目录

一.线性模型及回归:

1.一维数据线性模型:

2.多维数据:

二.对数线性回归:

三.Logistic回归:

1.极大似然估计:

2.梯度下降:

三.本次实验数据集介绍:

1.数据集信息介绍:

2.采用算法:

3.训练数据:(其中第二栏的性别男性为1,女性为 0)

4.代码和代码实现:


一.线性模型及回归:

  线性模型的一般形式:
        
其中x=(x1, x2, ..., xd)是由d维属性描述的样本,其中 xix 在第 i 个属性上的取值。
向量形式可记为:

1.一维数据线性模型:

给定数据集:

一维数据线性模型最终需要得到:

这样可以准确的预测出该线性模型在xi处的值;

即我们需要将误差尽可能的减少;

下面我们将用到最小二乘法,即利用均方误差最小化来求解参数

该函数已被证明为凸函数,由于凸函数的性质我们可以通过求取极值点来求取极小值

分别对这两个参数求偏导数,并且令这两个偏导数为0;

最终得到w和b的值:

通过上述公式,我们可以通过已知的数值算出最终一维数据线性模型的w和b的值。

2.多维数据:

多维数据集:

我们想通过:

在多维数据集中,我们可以将其表示为向量模式:

同样通过最小二乘法,求取最小误差:

二.对数线性回归:

通过上面的线性模型回归,我们知道可以通过

来得到接近真实数据的预测值,那么对于非线性的函数我们是怎样进行预测的呢?

我们可以将线性回归推广为:

如下图,其中g是单调可微函数:

三.Logistic回归:

logistic回归就是一种广义线性回归:

单调可微、任意阶可导;(Sigmoid 函数)

为了实现Logistic回归分类器,我们可以将每个属性乘上一个回归系数,再把所有结果之相加,将这个综合代入Sigmoid函数中,得到值域为[0,1]。

1.极大似然估计:

求解过程:

确定待求解的未知参数,如均值、方差或特定分布函数的参数等
计算每个样本X1,X2,...,Xn的概率密度f(Xi)

样本作为正例的相对可能性的对数:

所以有:

假定样本,则可根据样本的概率密度累乘构造似然函数:

通过似然函数最大化(求导为零),最终求解出未知参数.

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回归相关推荐

  1. 机器学习-Logistic回归原理及实战

    Logistic回归 回归 在介绍Logistic回归之前,先容我介绍一下什么是回归 回归,指研究一组随机变量(Y1 ,Y2 ,-,Yi)和另一组(X1,X2,-,Xk)变量之间关系的统计分析方法,又 ...

  2. [机器学习]Logistic回归

    目录 什么是逻辑斯蒂(Logistic)回归? 1.线性回归函数 2.  逻辑函数(Sigmoid函数) 3. Logistic回归函数 Logistic回归分类器 梯度上升算法 python实现梯度 ...

  3. 机器学习——logistic回归

    何为回归?假设有一系列数据点,我们使用一条直线对这些点进行拟合(该线称为最佳拟合直线),这个拟合过程就称为回归.利用Logistic回归进行分类的主要思想是:根据现有数据对分类边界线建立回归公式,并以 ...

  4. 机器学习--Logistic回归

    一.前言 logistic回归又称logistic回归分析,是一种广义的线性回归分析模型,常用于数据挖掘,疾病自动诊断,经济预测等领域.例如,探讨引发疾病的危险因素,并根据危险因素预测疾病发生的概率等 ...

  5. 机器学习--logistic回归和softmax回归

    logistic回归和softmax回归放在一起总结一下,其实softmax就是logistic的推广,logistic一般用于二分类,而softmax是多分类. logistic回归虽然也是叫回归, ...

  6. 吴恩达机器学习logistic回归作业(python实现)

    1. Logistic regression 在这部分的练习中,你将建立一个逻辑回归模型来预测一个学生是否能进入大学.假设你是一所大学的行政管理人员,你想根据两门考试的结果,来决定每个申请人是否被录取 ...

  7. logistic回归预测_使用Apache Spark机器学习Logistic回归预测乳腺癌

    logistic回归预测 在此博客文章中,我将帮助您开始使用Apache Spark的spark.ml Logistic回归来预测癌症恶性程度. Spark的spark.ml库目标是在DataFram ...

  8. 机器学习:多分类的logistic回归

    机器学习:多分类的logistic回归 Multi-Class Logistic(多分类的Logistic问题) 它适用于那些类别数大于2的分类问题,并且在分类结果中,样本x不是一定只属于某一个类可以 ...

  9. 机器学习算法(优化)之一:梯度下降算法、随机梯度下降(应用于线性回归、Logistic回归等等)...

    本文介绍了机器学习中基本的优化算法-梯度下降算法和随机梯度下降算法,以及实际应用到线性回归.Logistic回归.矩阵分解推荐算法等ML中. 梯度下降算法基本公式 常见的符号说明和损失函数 X :所有 ...

最新文章

  1. jquery插件,nocube
  2. 记住,永远不要在MySQL中使用“utf8”-转
  3. 高级线性表——静态链表(最全静态链表解读)
  4. Linux下的简单好用的计算器bc
  5. 阿里云江岑:云原生在边缘形态下的升华
  6. 沉浸式视频技术应用与挑战
  7. JWT认证原理、整合springboot实战应用
  8. KANO模型,一个能解决你工作中90%烦恼的需求分析神器
  9. Google 发布全新绘画工具 AutoDraw
  10. java证书不见了_java – 找不到证书链
  11. 谷歌Chrome浏览器如何截图长图
  12. VC编程使计算机休眠
  13. [FAQ21153]MT6761/MT6762/MT6765平台搭配LPDDR4 注意事项
  14. 美团外卖uml流程图_以美团外卖为例,区别业务流程图和页面流程图 | 人人都是产品经理...
  15. 过滤器(Filter)应用:全站压缩----Gzip网页压缩输出
  16. 快乐牛牛终极板creator1.82 shader 挫牌代码
  17. Team Tic Tac Toe--数据结构set的妙用
  18. krait和kryo_高通kryo架构还是arm吗
  19. 前端面试题 Doctype作用是什么?严格模式与混杂模式如何区分?他们之间有何意义?
  20. 3500字归纳总结:一名合格的软件测试工程师需要掌握的技能大全

热门文章

  1. Ubuntu安装anaconda做英文词云
  2. java按位异或的运算是,深入理解按位异或运算符
  3. 【Guacamole中文文档】二、用户指南 —— 3.用Docker安装Guacamole
  4. SpringBoot+Vue项目实例开发及部署
  5. Linux - uptime命令平均负载详解
  6. 5年为山西提供超5万岗位,2000万互联网众包用户,百度智能云数据众包高速增长
  7. 全连接层介绍以及简单实现
  8. php pusher,php – Pusher没有接收来自Laravel 5.2广播的事件
  9. 射频百科|巴伦(balun)的基本原理与应用
  10. php单页应用,前端单页应用的路由系统 – 介绍篇