机器学习 Logistic回归
目录
一.线性模型及回归:
1.一维数据线性模型:
2.多维数据:
二.对数线性回归:
三.Logistic回归:
1.极大似然估计:
2.梯度下降:
三.本次实验数据集介绍:
1.数据集信息介绍:
2.采用算法:
3.训练数据:(其中第二栏的性别男性为1,女性为 0)
4.代码和代码实现:
一.线性模型及回归:
1.一维数据线性模型:
一维数据线性模型最终需要得到:
这样可以准确的预测出该线性模型在xi处的值;
即我们需要将误差尽可能的减少;
下面我们将用到最小二乘法,即利用均方误差最小化来求解参数
该函数已被证明为凸函数,由于凸函数的性质我们可以通过求取极值点来求取极小值
分别对这两个参数求偏导数,并且令这两个偏导数为0;
最终得到w和b的值:
通过上述公式,我们可以通过已知的数值算出最终一维数据线性模型的w和b的值。
2.多维数据:
多维数据集:
我们想通过:
在多维数据集中,我们可以将其表示为向量模式:
同样通过最小二乘法,求取最小误差:
二.对数线性回归:
通过上面的线性模型回归,我们知道可以通过
来得到接近真实数据的预测值,那么对于非线性的函数我们是怎样进行预测的呢?
我们可以将线性回归推广为:
如下图,其中g是单调可微函数:
三.Logistic回归:
logistic回归就是一种广义线性回归:
单调可微、任意阶可导;(Sigmoid 函数)
为了实现Logistic回归分类器,我们可以将每个属性乘上一个回归系数,再把所有结果之相加,将这个综合代入Sigmoid函数中,得到值域为[0,1]。
1.极大似然估计:
求解过程:
所以有:
假定样本,则可根据样本的概率密度累乘构造似然函数:
通过似然函数最大化(求导为零),最终求解出未知参数.
2.梯度下降:
基本思想:沿着某函数的梯度方向探寻找到该函数的最大值。
梯度下降算法到达每个点后都会重新估计移动的方向。从 P0 开始,计算完该点的梯度,函数就根据梯度移动到下一点 P1。在 P1 点,梯度再次被重新计算,并沿着新的梯度方向移动到 P2 。如此循环迭代,直到满足停止条件。迭代过程中,梯度算子总是保证我们能选取到最佳的移动方向。梯度算子总是指向函数值下降最快的方向。
三.本次实验数据集介绍:
1.数据集信息介绍:
本次数据集是印度肝脏病人数据,该数据集包含10个变量,即年龄、性别、总胆红素、直接胆红素、总蛋白、白蛋白、A/G比值、SGPT、SGOT和碱性磷酸酶。
该数据集包含416份肝脏病人(1)记录和167份非肝脏病人(0)记录,数据集来自印度安得拉邦东北部。选择器是一个类标签,用于分组(不管是否有肝脏病人)。这套数据包括441份男性病历和142份女性病历。任何年龄超过89岁的病人都被列为“90岁”。数据来源于UCI Machine Learning Repository: Data Sets。
2.采用算法:
使用梯度上升找到最佳参数,通过梯度上升法找到最佳回归系数,也就是拟合出Logistic回归模型的最佳参数。
设数据集有100个样本点,每个点包含两个数值型特征:X1和X2。在此数据集上通过梯度上升算法找到最佳回归系数,也就是拟合出Logstic回归模型的最佳参数。
#Logistic回归梯度上升优化算法
def loadDataSet():'''函数说明:打开文件并逐行读取:return: 数据集列表和类标签列表'''dataMat = []labelMat = []fr = open('./data/testSet.txt')for line in fr.readlines():lineArr = line.strip().split()#每行的前两个值是X1和X2dataMat.append([1.0, float(lineArr[0]), float(lineArr[1])])#对应的类标签labelMat.append(int(lineArr[2]))return dataMat,labelMat#sigmoid()函数定义,x=0时,Sigmoid函数值为0.5;
#随着x的增大,Sigmoid函数值将逼近于1,随着x的减小,Sigmoid函数值将逼近于0
def sigmoid(inX):return 1.0/(1+exp(-inX))#Logistic回归梯度上升优化算法
'''
梯度上升法的伪代码:
每个回归系数初始化为1
重复R次:计算整个数据集的梯度使用alpha*gradient更新回归系数的向量返回回归系数
dataMatIn:2维NumPy数组,每列分别代表每个不同的特征,每行则代表每个训练样本
classLabels:数据集类别标签向量
'''
def gradAscent(dataMatIn, classLabels):#将输入数据转换成矩阵dataMatrix = mat(dataMatIn)#将类别标签矩阵进行转置labelMat = mat(classLabels).transpose()#获得dataMatrix矩阵大小m,n = shape(dataMatrix)#向目标移动的步长alpha = 0.001#迭代次数,for循环迭代完成后返回训练好的回归系数maxCycles = 500weights = ones((n,1))for k in range(maxCycles):#h为一个列向量,元素个数等于样本个数;[m,n]*[n,1] = [m,1],包含了m*n次乘积h = sigmoid(dataMatrix*weights)#真实值与预测值之差error = (labelMat - h)weights = weights + alpha * dataMatrix.transpose()* errorreturn weights
画出数据集和Logistic回归最佳拟合直线的函数:
#画出数据集和Logistic回归最佳拟合直线的函数(输入wei为矩阵)
def plotBestFit(weights):# 矩阵.getA()是把矩阵变成数组array类型#weights = wei.getA()#得到数据集列表和类标签列表dataMat,labelMat=loadDataSet()print("dataMat:",dataMat)#将由列表存储的数据集转换为array(数组)类型,方便后面数组访问 dataArr[i,j]dataArr = array(dataMat)print("dataArr:",dataArr)#dataArr数据集的行数,即样本的个数n = shape(dataArr)[0]# 定义两个空数组,用来存放不同label的x1和x2值xcord1 = []; ycord1 = []xcord2 = []; ycord2 = []for i in range(n):if int(labelMat[i])== 1:xcord1.append(dataArr[i,1]); ycord1.append(dataArr[i,2])else:xcord2.append(dataArr[i,1]); ycord2.append(dataArr[i,2])fig = plt.figure()ax = fig.add_subplot(111)ax.scatter(xcord1, ycord1, s=30, c='red', marker='s')ax.scatter(xcord2, ycord2, s=30, c='green')# 画出最佳拟合直线x = arange(-3.0, 3.0, 0.1)# 设置sigmoid函数为0,0=W0X0+W1X1+W2X2,解出X1,X2的关系式得到分割线方程(为方便计算,X0=1)y = (-weights[0]-weights[1]*x)/weights[2]ax.plot(x, y)plt.xlabel('X1'); plt.ylabel('X2');plt.show()
拟合结果如下:
在上图中,分错了差不多两个点,算法实现分类比较好,但是梯度上升算法在每次更新回归系数时都要遍历整个数据集,当样本比较大时,方法的计算复杂度就太高了。
改进:随机梯度上升算法:一次仅用一个样本点更新回归系数。
#随机梯度上升算法
'''
伪代码:
所有回归系数初始化为1
对数据集中每个样本计算该样本的梯度使用alpha*gradient更新回归系数值
返回回归系数值
问题:存在每次迭代会引发系数的剧烈改变,效果不够好
'''
def stocGradAscent0(dataMatIn, classLabels):#将输入数据转换为矩阵dataMatrix = array(dataMatIn)#得到矩阵大小m,n = shape(dataMatrix)alpha = 0.01weights = ones(n) #创建n行1列的全为1的数组for i in range(m):h = sigmoid(sum(dataMatrix[i]*weights))error = classLabels[i] - hweights = weights + alpha * error * dataMatrix[i]return weights
拟合结果:
该图,分类器错分了大概三分之一的样本, 拟合效果没有梯度上升算法完美。原因是在非随机梯度上升算法,整个数据集上迭代了500次才得到结果,随机梯度上升只是迭代了m(矩阵)行数,非随机梯度上升算法迭代次数要远大于随机梯度上升方法,而判断优化算法优劣的可靠方法:看它是否收敛,也就是说参数是否达到稳定值,是否不断地变化。
3.训练数据:(其中第二栏的性别男性为1,女性为 0)
测试数据集:
第一列数据为X1轴上的值,第二列数据为X2轴上的值。而最后一列数据即为分类标签,利用训练数据来训练逻辑回归分类器,进而用训练好的模型来预测新的样本,即测试数据集,比对正确率;
4.代码和代码实现:
Logistic回归分类函数:
#Logistic回归分类函数def classifyVector(inX, weights):prob = sigmoid(sum(inX*weights))if prob > 0.5: return 1.0else: return 0.0
Sigmoid函数:
#sigmoid()函数定义,x=0时,Sigmoid函数值为0.5;
#随着x的增大,Sigmoid函数值将逼近于1,随着x的减小,Sigmoid函数值将逼近于0
def sigmoid(inX):if inX>=0: #对sigmoid函数的优化,避免了出现极大的数据溢出return 1.0/(1+exp(-inX))else: #这样做可以保证exp(inx)值始终小于1,避免极大溢出return exp(inX) / (1 + exp(inX))
读入训练集和测试集,并用测试集:
#读取数据集和测试集
def colicTest():trainingSet = []; trainingLabels = []TrainData = pd.read_csv('Indian Liver Patient Dataset (ILPD).csv')TrainData = TrainData.values.tolist()TestData = pd.read_csv('test.csv')TestData = TestData.values.tolist()for i in range(len(TrainData)):lineArr =[]for j in range(10):lineArr.append(TrainData[i][j])trainingSet.append(lineArr)trainingSet = array(trainingSet) #将列表转换成数组trainingSet = trainingSet.astype(float).tolist() #将数组中元素转换成floattrainingLabels.append(TrainData[i][10]) #将数组重新转为列表print(trainingSet)trainWeights = stocGradAscent1(array(trainingSet), trainingLabels, 1000)errorCount = 0; numTestVec = 0.0for i in range(len(TestData)):numTestVec += 1.0lineArr =[]for j in range(10):lineArr.append(TestData[i][j])if int(classifyVector(array(lineArr), trainWeights))!= int(TestData[i][10]):errorCount += 1errorRate = (float(errorCount)/numTestVec)print("此测试的错误率为: %f" % errorRate)return errorRate
测试次数调用函数:
#multiTest()调用colicTest()10次求结果的平均值
def multiTest():numTests = 10; errorSum=0.0for k in range(numTests):resultCount = colicTest()print("第%d次测试的错误率为: %f" % (k+1,resultCount))errorSum += resultCountprint("在%d次迭代之后,平均错误率为: %f" % (numTests, errorSum/float(numTests)))#主函数
import logRegres# 按间距中的绿色按钮以运行脚本。
if __name__ == '__main__':logRegres.multiTest()
运行结果:
无论使用哪种方法,错误率都为75%,可能是数据集选取有错;
下面重新选取了数据集:(UCI Machine Learning Repository: Heart failure clinical records Data Set)
新的数据集中包含299条心力衰竭临床记录数据;
全批量梯度上升算法测试结果:
随机梯度上升算法:
改进后随机梯度上升测试结果:
迭代1000次的结果:
通过上面的运行结果来看,未改进的随机梯度上升算法错误率较高,改进后的随机梯度上升算法很较为理想的,但是它的运行速度非常慢,这与赋给它的迭代次数和数据集相关。
整体代码:
from numpy import *
import matplotlib.pyplot as plt
import pandas as pd# Logistic回归梯度上升优化算法
def loadDataSet():'''函数说明:打开文件并逐行读取:return: 数据集列表和类标签列表'''dataMat = []labelMat = []fr = open('./data/testSet.txt')for line in fr.readlines():lineArr = line.strip().split()# 每行的前两个值是X1和X2dataMat.append([1.0, float(lineArr[0]), float(lineArr[1])])# 对应的类标签labelMat.append(int(lineArr[2]))return dataMat, labelMat# 用于全批量随机梯度上升算法的Sigmoid函数,因为传入值是一个向量,不能比较大小
def gradAscentSigmoid(inX):return 1.0 / (1 + exp(-inX))# sigmoid()函数定义,x=0时,Sigmoid函数值为0.5;
# 随着x的增大,Sigmoid函数值将逼近于1,随着x的减小,Sigmoid函数值将逼近于0
def sigmoid(inX):if inX >= 0: # 对sigmoid函数的优化,避免了出现极大的数据溢出return 1.0 / (1 + exp(-inX))else: # 这样做可以保证exp(inx)值始终小于1,避免极大溢出return exp(inX) / (1 + exp(inX))# 全批量梯度上升算法
'''
梯度上升法的伪代码:
每个回归系数初始化为1
重复R次:计算整个数据集的梯度使用alpha*gradient更新回归系数的向量返回回归系数
dataMatIn:2维NumPy数组,每列分别代表每个不同的特征,每行则代表每个训练样本
classLabels:数据集类别标签向量
'''def gradAscent(dataMatIn, classLabels):# 将输入数据转换成矩阵dataMatrix = mat(dataMatIn)# 将类别标签矩阵进行转置labelMat = mat(classLabels).transpose()# 获得dataMatrix矩阵大小m, n = shape(dataMatrix)# 向目标移动的步长alpha = 0.001# 迭代次数,for循环迭代完成后返回训练好的回归系数maxCycles = 500weights = ones((n, 1))for k in range(maxCycles):# h为一个列向量,元素个数等于样本个数;[m,n]*[n,1] = [m,1],包含了m*n次乘积h = gradAscentSigmoid(dataMatrix * weights)# 真实值与预测值之差error = (labelMat - h)weights = weights + alpha * dataMatrix.transpose() * errorreturn weights'''.......#分析数据:画出决策边界...... '''# 画出数据集和Logistic回归最佳拟合直线的函数(输入wei为矩阵)
def plotBestFit(weights):# 矩阵.getA()是把矩阵变成数组array类型# weights = wei.getA()# 得到数据集列表和类标签列表dataMat, labelMat = loadDataSet()print("dataMat:", dataMat)# 将由列表存储的数据集转换为array(数组)类型,方便后面数组访问 dataArr[i,j]dataArr = array(dataMat)print("dataArr:", dataArr)# dataArr数据集的行数,即样本的个数n = shape(dataArr)[0]# 定义两个空数组,用来存放不同label的x1和x2值xcord1 = [];ycord1 = []xcord2 = [];ycord2 = []for i in range(n):if int(labelMat[i]) == 1:xcord1.append(dataArr[i, 1]);ycord1.append(dataArr[i, 2])else:xcord2.append(dataArr[i, 1]);ycord2.append(dataArr[i, 2])fig = plt.figure()ax = fig.add_subplot(111)ax.scatter(xcord1, ycord1, s=30, c='red', marker='s')ax.scatter(xcord2, ycord2, s=30, c='green')# 画出最佳拟合直线x = arange(-3.0, 3.0, 0.1)# 设置sigmoid函数为0,0=W0X0+W1X1+W2X2,解出X1,X2的关系式得到分割线方程(为方便计算,X0=1)y = (-weights[0] - weights[1] * x) / weights[2]ax.plot(x, y)plt.xlabel('X1');plt.ylabel('X2');plt.show()# 随机梯度上升算法
'''
伪代码:
所有回归系数初始化为1
对数据集中每个样本计算该样本的梯度使用alpha*gradient更新回归系数值
返回回归系数值
问题:存在每次迭代会引发系数的剧烈改变,效果不够好
'''def stocGradAscent0(dataMatIn, classLabels):# 将输入数据转换为矩阵dataMatrix = array(dataMatIn)# 得到矩阵大小m, n = shape(dataMatrix)alpha = 0.01weights = ones(n) # 创建n行1列的全为1的数组for i in range(m):h = sigmoid(sum(dataMatrix[i] * weights))error = classLabels[i] - hweights = weights + alpha * error * dataMatrix[i]return weights# 改进的随机梯度上升算法
def stocGradAscent1(dataMatIn, classLabels, numIter=150):# 迭代次数若未给定,则默认迭代150次dataMatrix = array(dataMatIn)m, n = shape(dataMatrix)# print("m=:",m)weights = ones(n)for j in range(numIter):dataIndex = list(range(m))for i in range(m):# alpha每次迭代时需要调整alpha = 4 / (1.0 + j + i) + 0.0001# 随机选取样本更新回归系数# uniform() 方法将随机生成下一个实数,它在[0,len(dataIndex)]范围内randIndex = int(random.uniform(0, len(dataIndex)))h = sigmoid(sum(dataMatrix[randIndex] * weights))error = classLabels[randIndex] - h # 计算误差weights = weights + alpha * error * dataMatrix[randIndex]# 删除已使用的样本del (dataIndex[randIndex])return weights# Logistic回归分类函数
def classifyVector(inX, weights):prob = sigmoid(sum(inX * weights))if prob > 0.5:return 1.0else:return 0.0# 读取数据集和测试集
def colicTest():trainingSet = [];trainingLabels = []TrainData = pd.read_csv('heart_failure_clinical_records_dataset.csv')TrainData = TrainData.values.tolist()TestData = pd.read_csv('tttw.csv')TestData = TestData.values.tolist()for i in range(len(TrainData)):lineArr = []for j in range(12):lineArr.append(TrainData[i][j])trainingSet.append(lineArr)trainingSet = array(trainingSet) # 将列表转换成数组trainingSet = trainingSet.astype(float).tolist() # 将数组中元素转换成floattrainingLabels.append(TrainData[i][12]) # 将数组重新转为列表# trainWeights = gradAscent(trainingSet, trainingLabels)# trainWeights = stocGradAscent0(array(trainingSet), trainingLabels)trainWeights = stocGradAscent1(array(trainingSet), trainingLabels, 500)errorCount = 0;numTestVec = 0.0for i in range(len(TestData)):numTestVec += 1.0lineArr = []for j in range(12):lineArr.append(TestData[i][j])if int(classifyVector(array(lineArr), trainWeights)) != int(TestData[i][12]):errorCount += 1errorRate = (float(errorCount) / numTestVec)# print("此测试的错误率为: %f" % errorRate)return errorRate# multiTest()调用colicTest()10次求结果的平均值
def multiTest():numTests = 10;errorSum = 0.0for k in range(numTests):resultCount = colicTest()print("第%d次测试的错误率为: %f" % (k + 1, resultCount))errorSum += resultCountprint("在%d次测试之后,平均错误率为: %f" % (numTests, errorSum / float(numTests)))
机器学习 Logistic回归相关推荐
- 机器学习-Logistic回归原理及实战
Logistic回归 回归 在介绍Logistic回归之前,先容我介绍一下什么是回归 回归,指研究一组随机变量(Y1 ,Y2 ,-,Yi)和另一组(X1,X2,-,Xk)变量之间关系的统计分析方法,又 ...
- [机器学习]Logistic回归
目录 什么是逻辑斯蒂(Logistic)回归? 1.线性回归函数 2. 逻辑函数(Sigmoid函数) 3. Logistic回归函数 Logistic回归分类器 梯度上升算法 python实现梯度 ...
- 机器学习——logistic回归
何为回归?假设有一系列数据点,我们使用一条直线对这些点进行拟合(该线称为最佳拟合直线),这个拟合过程就称为回归.利用Logistic回归进行分类的主要思想是:根据现有数据对分类边界线建立回归公式,并以 ...
- 机器学习--Logistic回归
一.前言 logistic回归又称logistic回归分析,是一种广义的线性回归分析模型,常用于数据挖掘,疾病自动诊断,经济预测等领域.例如,探讨引发疾病的危险因素,并根据危险因素预测疾病发生的概率等 ...
- 机器学习--logistic回归和softmax回归
logistic回归和softmax回归放在一起总结一下,其实softmax就是logistic的推广,logistic一般用于二分类,而softmax是多分类. logistic回归虽然也是叫回归, ...
- 吴恩达机器学习logistic回归作业(python实现)
1. Logistic regression 在这部分的练习中,你将建立一个逻辑回归模型来预测一个学生是否能进入大学.假设你是一所大学的行政管理人员,你想根据两门考试的结果,来决定每个申请人是否被录取 ...
- logistic回归预测_使用Apache Spark机器学习Logistic回归预测乳腺癌
logistic回归预测 在此博客文章中,我将帮助您开始使用Apache Spark的spark.ml Logistic回归来预测癌症恶性程度. Spark的spark.ml库目标是在DataFram ...
- 机器学习:多分类的logistic回归
机器学习:多分类的logistic回归 Multi-Class Logistic(多分类的Logistic问题) 它适用于那些类别数大于2的分类问题,并且在分类结果中,样本x不是一定只属于某一个类可以 ...
- 机器学习算法(优化)之一:梯度下降算法、随机梯度下降(应用于线性回归、Logistic回归等等)...
本文介绍了机器学习中基本的优化算法-梯度下降算法和随机梯度下降算法,以及实际应用到线性回归.Logistic回归.矩阵分解推荐算法等ML中. 梯度下降算法基本公式 常见的符号说明和损失函数 X :所有 ...
最新文章
- jquery插件,nocube
- 记住,永远不要在MySQL中使用“utf8”-转
- 高级线性表——静态链表(最全静态链表解读)
- Linux下的简单好用的计算器bc
- 阿里云江岑:云原生在边缘形态下的升华
- 沉浸式视频技术应用与挑战
- JWT认证原理、整合springboot实战应用
- KANO模型,一个能解决你工作中90%烦恼的需求分析神器
- Google 发布全新绘画工具 AutoDraw
- java证书不见了_java – 找不到证书链
- 谷歌Chrome浏览器如何截图长图
- VC编程使计算机休眠
- [FAQ21153]MT6761/MT6762/MT6765平台搭配LPDDR4 注意事项
- 美团外卖uml流程图_以美团外卖为例,区别业务流程图和页面流程图 | 人人都是产品经理...
- 过滤器(Filter)应用:全站压缩----Gzip网页压缩输出
- 快乐牛牛终极板creator1.82 shader 挫牌代码
- Team Tic Tac Toe--数据结构set的妙用
- krait和kryo_高通kryo架构还是arm吗
- 前端面试题 Doctype作用是什么?严格模式与混杂模式如何区分?他们之间有何意义?
- 3500字归纳总结:一名合格的软件测试工程师需要掌握的技能大全
热门文章
- Ubuntu安装anaconda做英文词云
- java按位异或的运算是,深入理解按位异或运算符
- 【Guacamole中文文档】二、用户指南 —— 3.用Docker安装Guacamole
- SpringBoot+Vue项目实例开发及部署
- Linux - uptime命令平均负载详解
- 5年为山西提供超5万岗位,2000万互联网众包用户,百度智能云数据众包高速增长
- 全连接层介绍以及简单实现
- php pusher,php – Pusher没有接收来自Laravel 5.2广播的事件
- 射频百科|巴伦(balun)的基本原理与应用
- php单页应用,前端单页应用的路由系统 – 介绍篇