[机器学习]Logistic回归
目录
什么是逻辑斯蒂(Logistic)回归?
1.线性回归函数
2. 逻辑函数(Sigmoid函数)
3. Logistic回归函数
Logistic回归分类器
梯度上升算法
python实现梯度上升算法
1.普通梯度上升算法(在每次更新回归系数(最优参数)时,都需要遍历整个数据集。)
2.随机梯度上升算法
【实战】用Logistic回归模型诊断糖尿病
Logistic回归的一般过程
数据样本收集
数据处理
Sigmoid函数
梯度上升算法寻找最佳优化系数
训练Logistic回归模型并测试
计算测试结果的正确率
设置步长、迭代次数等参数开始测试
测试结果
Logistic回归模型总结
什么是逻辑斯蒂(Logistic)回归?
由于逻辑斯蒂回归的原理是用逻辑函数把线性回归的结果(-∞,∞)映射到(0,1),故先介绍线性回归函数和逻辑函数。
1.线性回归函数
线性回归函数的数学表达式:
其中xi是自变量,y是因变量,y的值域为(-∞,∞),θ0是常数项,θi(i=1,2,...,n)是待求系数,不同的权重θi反映了自变量对因变量不同的贡献程度。我们初中学过的一元一次方程:y=a+bx,这种只包括一个自变量和一个因变量的回归分析称为一元线性回归分析。初中学过的二元一次方程:y = a+b1x1+b2x2,三元一次方程:y = a+b1x1+b2x2+b3x3,这种回归分析中包括两个或两个以上自变量的回归分析,称为多元线性回归分析。不管是一元线性回归分析还是多元线性回归分析,都是线性回归分析。
2. 逻辑函数(Sigmoid函数)
Sigmoid函数数学表达式:
Sigmoid函数的图像:
从图像可以看到当x为0时,Sigmoid函数值为0.5。随着x的增大,对应的Sigmoid函数的值将逼近于1;而随着x的减小,Sigmoid函数的值将逼近于0,而Sigmoid函数的值域在(0,1)之间,而概率P也是在0到1之间,因此我们可以把Sigmoid的值域和概率联系起来
3. Logistic回归函数
Logistic回归的原理是用Sigmoid函数把线性回归的结果从(-∞,∞)映射到(0,1)。我们用公式描述上面这句话:
把线性回归函数的结果y,放到sigmod函数中去,就构造了Logistic回归函数。 由y的值域和sigmod函数的值域知,在Logistic回归函数中用sigmod函数把线性回归的结果(-∞,∞)映射到(0,1),得到的这个结果类似一个概率值。
我们转换一下逻辑回归函数,过程如下:
因此Logistic回归属于对数线性模型,也被称为对数几率回归。
Logistic回归分类器
为了实现logistic回归分类器,我们可以在每个分类特征上都乘以一个回归系数,然后把所有的结果值相加,将这个总和带入sigmoid函数中。进而得到一个范围在0-1之间的数值。最后设定一个阈值,在大于阈值时判定为1,否则判定为0。以上便是逻辑斯谛回归算法是思想,公式就是分类器的函数形式。 确定了logistic分类函数,有了分类函数,我们输入特征向量就可以得出实例属于某个类别的概率。但这里有个问题,权重(回归系数)我们是不确定的。我们需要求得最佳的回归系数,从而使得分类器尽可能的精确。 最佳回归系数的确定,可以用极大似然法、牛顿法、最优化方法(也就是梯度上升和梯度下降法)。下面重点介绍梯度上升法实现Logistic回归分类。
梯度上升算法
梯度上升法基于的思想是:要找到某函数的最大值,最好的方法是沿着该函数的梯度方向探寻。如果梯度记为∇ ,则函数f(x,y)的梯度由下式表示:
这个梯度意味着要沿x的方向移动,沿y的方向移动其中,函数f(x,y)必须要在待计算的点上有定义并且可微。一个具体的函数例子见下图。
梯度上升算法到达每个点后都会重新估计移动的方向。从P0开始,计算完该点的梯度,函数就根据梯度移动到下一点P1。在P1点,梯度再次被重新计算,并沿新的梯度方向移动到P2.如此循环迭代,知道满足通知条件。迭代的过程中,梯度算子总是保证我们能选取到最佳的移动方向
上图中的梯度上升算法沿梯度方向移动了一步。可以看到,梯度算子总是指向函数值增长最快的方向。这里所说的是移动方向,而未提到移动量的大小。该量值称为步长,记作α \alphaα。用向量来表示的话,梯度上升算法的迭代公式如下:
该公式将一直迭代执行,直至达到某个停止条件为止,b比如迭代次数达到某个值或者算法达到某个可以允许的误差范围。如果是梯度下降法,那就是按梯度上升的反方向迭代公式即可,对应的公式如下:
python实现梯度上升算法
1.普通梯度上升算法(在每次更新回归系数(最优参数)时,都需要遍历整个数据集。)
def gradAscent(dataMatIn, classLabels):#梯度上升:dataMatIn:2维NumPy数组,100*3矩阵;classLabels:类别标签,1*100行向量dataMatrix = mat(dataMatIn)#特征矩阵labelMat = mat(classLabels).transpose()#类标签矩阵:100*1列向量m,n = shape(dataMatrix)alpha = 0.001#向目标移动的步长maxCycles = 500#迭代次数weights = ones((n,1))#n*1列向量:3行1列for k in range(maxCycles):h = sigmoid(dataMatrix*weights)#100*3*3*1=100*1,dataMatrix * weights代表不止一次乘积计算,事实上包含了300次乘积error = (labelMat - h)#真实类别与预测类别的差值weights = weights + alpha * dataMatrix.transpose()* error#w:=w+α▽wf(w)return weights
2.随机梯度上升算法
普通梯度上升算法,在每次更新回归系数时都需要遍历整个数据集,在数十亿样本上该算法复杂度太高。改进方法:随机梯度上升算法:一次仅用一个样本点更新回归系数。)
def stocGradAscent0(dataMatrix, classLabels):m, n = shape(dataMatrix)alpha = 0.01weights = ones(n)for i in range(m):h = sigmoid(sum(dataMatrix[i] * weights))error = classLabels[i] - hweights = weights + alpha * error * dataMatrix[i]return weights
现在我们用一个简单的数据集测试一下这两个算法的分类效果。
数据集testSet有100条样本,两个属性x1,x2
完整测试代码
#coding:utf-8
from numpy import *
import matplotlib.pyplot as pltclass func:def loadDataSet(self):dataMat = []labelMat = []fr = open('testSet.txt')for line in fr.readlines():# 矩阵的格式【标签,X1,X2】lineArr = line.strip().split()#插入X1,X2,以及初始化的回归系数(权重),全部设为1.0dataMat.append([1.0,float(lineArr[0]),float(lineArr[1])])#插入标签,#必须转换成int类型,因为只有两类labelMat.append(int(lineArr[2]))return dataMat,labelMat# 使用sigmoid函数进行分类def sigmoid(self,inX):return 1.0/(1+exp(-inX))#普通梯度上升#使用梯度上升算法进行优化,找到最佳优化系数#dataMatIn是训练集,三维矩阵,(-0.017612 14.053064 0)#classLabels是类别标签,数值型行向量,需要转置为列向量,取值是0,1def gradAscent(self,dataMatIn,classLabels):dataMatrix = mat(dataMatIn) #转换为Numpy矩阵数据类型labelMat = mat(classLabels).transpose() #转置矩阵,便于加权相乘m,n = shape(dataMatrix) #得到矩阵的行列数,便于设定权重向量的维度alpha = 0.001maxCycles = 500weights = ones((n,1)) #返回一个被1填满的 n * 1 矩阵,作为初始化权重for k in range(maxCycles):h = self.sigmoid(dataMatrix*weights)erro = (labelMat - h) #labelMat是使用当前回归系数得到的的标签,labelMat是训练集的标签,取值是0,1weights = weights + alpha * dataMatrix.transpose( ) * erro #根据使用当前权重计算的值与初始值的误差,更改weight,#按照误差的方向调整回归系数return weights#随机梯度上升def stocGradAscent0(dataMatrix, classLabels):m, n = shape(dataMatrix)alpha = 0.01weights = ones(n)for i in range(m):h = sigmoid(sum(dataMatrix[i] * weights))error = classLabels[i] - hweights = weights + alpha * error * dataMatrix[i]return weightsdef plotBestFit(self,wei):weights = wei.getA()dataMat,labelMat = self.loadDataSet()dataArr = array(dataMat)n = shape(dataMat)[0]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') #scatter散开ax.scatter(xcord2,ycord2,s=30,c='green')x = arange(-3.0,3.0,1)y = (-weights[0]-weights[1]*x)/weights[2]ax.plot(x,y)plt.xlabel('x1')plt.ylabel('x2')plt.show()if __name__=="__main__":#普通梯度上升logRegres = func()dataArr,labelMat = logRegres.loadDataSet()weights = logRegres.gradAscent(dataArr,labelMat)logRegres.plotBestFit(weights)#随机梯度上升logRegres = func()dataArr,labelMat = logRegres.loadDataSet()weights =stocGradAscent0(array(dataArr),labelMat)plotBestFit(weights)
运行结果
普通梯度上升
分类结果是很不错,虽然这里是简单且数据集很小,但是这个方法却需要大量的计算(300次乘法)。
随机梯度上升
拟合效果没有普通梯度上升算法好。这里的分类器错分了三分之一的样本。但是普通梯度上升算法的计算量较大,时间较长,其结果是在整个数据集上迭代了500次才能得到的。而随机梯度上升在整个数据集上只需迭代200次,所以现在还不能分辨哪个算法更好。 通常判断优化算法优劣的可靠方法是看它是否收敛,也就是说参数是否达到稳定值,是否不断地变化。下图展示随机梯度上升算法在 200 次迭代过程中回归系数的变化情况。其中的系数2,也就是 X2 只经过了 50 次迭代就达到了稳定值,但系数 1 和 0 则需要更多次的迭代。
针对欠拟合这个问题,我们对随机梯度上升算法进行优化
# 随机梯度上升算法(优化)
def stocGradAscent1(dataMatrix, classLabels, numIter=150):m,n = shape(dataMatrix)weights = ones(n) for j in range(numIter):# [0, 1, 2 .. m-1]dataIndex = list(range(m))for i in range(m):alpha = 4/(1.0+j+i)+0.0001 randIndex = int(random.uniform(0,len(dataIndex)))# sum(dataMatrix[i]*weights)为了求 f(x)的值, f(x)=a1*x1+b2*x2+..+nn*xnh = sigmoid(sum(dataMatrix[randIndex]*weights))error = classLabels[randIndex] - h# print weights, '__h=%s' % h, '__'*20, alpha, '__'*20, error, '__'*20, dataMatrix[randIndex]weights = weights + alpha * error * dataMatrix[randIndex]del(dataIndex[randIndex])return weights
运行后效果
现在随机的alpha比固定的alpha收敛速度更快。主要归功于:1.stocGradAscent1()的样本随机机制避免周期性波动;2.stocGradAscent1()收敛更快。这次的随机梯度上升算法仅对数据集做了20次遍历,而之前的普通梯度上升算法是500次。
因此,通常数据集较小时,选用梯度上升算法就能达到我们想要的数据分类效果;当数据集较大时,为有效地减少了计算量,提高收敛速度,我们选用随机梯度上升算法。
【实战】用Logistic回归模型诊断糖尿病
Logistic回归的一般过程
(1)收集数据: 可以使用任何方法。
(2)准备数据: 由于需要进行距离计算,因此要求数据类型为数值型。当然,结构化数据格式最佳。
(3)分析数据: 采用任意方法对数据进行分析。
(4)训练算法: 大部分时间将用于训练,训练的目的是为了找到最佳的分类回归系数。
(5)测试算法: 一旦训练阶段完成,分类将很快完成。
(6)使用算法: 首先,需要输入一些数据,并将其转换成对应的结构化数值;然后,基于训练好的回归系数就可以对这些数值进行简单的回归计算,判定它们属于哪个类别;最后,可以在输出的类别上做一些其他分析工作。
数据样本收集
本次数据集一共765条样本,每条数据样本记录着健康人员和糖尿病患者的8个身体状况特征值,接下来我们使用Logistic回归模型对样本进行分类。 数据收集来源:http://archive.ics.uci.edu/ml/index.php) 1是糖尿病患者,0是健康人员。
数据处理
我们将样本数据分成五组,分别用这五组样本作为测试集,当某组作为测试集时,就用除该组以外的样本作训练集,然后计算出五组样本的正确率,最后取平均正确率
from random import seed
from random import randrange
from csv import reader
from math import expdef load_csv(filename):dataset = list()with open(filename, 'r') as f: #读取样本数据保存到dataset中csv_reader = reader(f)for row in csv_reader:if not row:continueelse:dataset.append(row)return datasetdef str_column_to_float(dataset,column): #将样本数据转换成float类型for row in dataset:row[column] = float(row[column].strip())def dataset_minmax(dataset):minmax = list()for i in range(len(dataset[0])):col_values = [row[i] for row in dataset]value_min = min(col_values)value_max = max(col_values)minmax.append([value_min, value_max])return minmaxdef normalize_dataset(dataset, minmax): #归一化处理样本数据for row in dataset:for i in range(len(row)):row[i] = (row[i] - minmax[i][0])/(minmax[i][1] - minmax[i][0])def cross_validation_split(dataset, n_folds): #将数据样本分成n_folds组dataset_split = list()dataset_copy = list(dataset)fold_size = int(len(dataset) / n_folds)for i in range(n_folds):fold = list()while len(fold) < fold_size:index = randrange(len(dataset_copy))fold.append(dataset_copy.pop(index))dataset_split.append(fold)return dataset_split
Sigmoid函数
def predict(row, coefficients): #Sigmoid函数变形yhat = coefficients[0]for i in range(len(row)-1):yhat += coefficients[i + 1] * row[i]return 1.0 / (1.0 + exp(-yhat))
梯度上升算法寻找最佳优化系数
def logistic_regression(train, test, l_rate, n_epoch):predictions = list()coef = coefficients_sgd(train, l_rate, n_epoch)for row in test:yhat = predict(row, coef)yhat = round(yhat)predictions.append(yhat)return(predictions)def coefficients_sgd(train, l_rate, n_epoch): #使用梯度下降算法进行优化,找到最佳优化系数coef = [0.0 for i in range(len(train[0]))]for epoch in range(n_epoch):for row in train:yhat = predict(row, coef)error = row[-1] - yhatcoef[0] = coef[0] + l_rate * error * yhat * (1.0 - yhat)for i in range(len(row)-1):coef[i + 1] = coef[i + 1] + l_rate * error * yhat * (1.0 - yhat) * row[i]return coef
训练Logistic回归模型并测试
def evaluate_algorithm(dataset, algorithm, n_folds, *args): #训练Logistic回归模型folds = cross_validation_split(dataset, n_folds)scores = list()for fold in folds:train_set = list(folds)train_set.remove(fold)train_set = sum(train_set, [])test_set = list()for row in fold:row_copy = list(row)test_set.append(row_copy)row_copy[-1] = Nonepredicted = algorithm(train_set, test_set, *args)actual = [row[-1] for row in fold]accuracy = accuracy_metric(actual, predicted)scores.append(accuracy)return scores
计算测试结果的正确率
def accuracy_metric(actual, predicted): #计算Logistic回归模型分类正确率correct = 0for i in range(len(actual)):if actual[i] == predicted[i]:correct += 1return correct / float(len(actual)) * 100.0
设置步长、迭代次数等参数开始测试
if __name__=="__main__":seed(1)filename = 'pima-indians-diabetes.csv' #数据样本名称
dataset = load_csv(filename)
for i in range(len(dataset[0])):str_column_to_float(dataset, i)
minmax = dataset_minmax(dataset)
normalize_dataset(dataset, minmax)
n_folds = 5 #样本分组
l_rate = 0.1 #移动步长,也就是学习速率,控制更新的幅度
n_epoch = 1000 #最大迭代次数
scores = evaluate_algorithm(dataset, logistic_regression, n_folds, l_rate, n_epoch)
print('五组测试样本的正确率: %s' % scores)
print('平均正确率: %.3f%%' % (sum(scores)/float(len(scores))))
测试结果
该Logistic回归模型诊断糖尿病的正确率是:78.301%
Logistic回归模型总结
优点:
- 原理简单,模型清晰,操作高效,背后的概率的推导过程经得住推敲,在研究中,通常以 Logistic 回归模型作为基准,再尝试使用更复杂的算法,可以在大数据场景中使用。
- 使用online learning的方式更新轻松更新参数,不需要重新训练整个模型。
- 基于概率建模,输出值落在0到1之间,并且有概率意义。
- 求出来的参数θi 代表每个特征对输出的影响,可解释性强。
- 无需事先假设数据分布 ,可得到“类别”的近似概率预测(概率值还可用于后续应 用),可直接应用现有数值优化算法(如牛顿法)求取最优解, 具有快速、高效的特点
缺点:
- 对数据依赖性强,很多时候需要做特征工程,且主要用来解决线性可分问题。
- 因为它本质上是一个线性的分类器,所以处理不好特征之间相关的情况,对模型中自变量多重共线性较为敏感,例如两个高度相关自变量同时放入模型,可能导致较弱的一个自变量回归符号不符合预期,符号被扭转,正好变负号。
- logit变换过程是非线性的,在两端随着变化率微乎其微,而中间的变化很大,很敏感。 导致很多区间的变量变化对目标概率的影响没有区分度,很难确定阀值。
- 当特征空间很大时,性能不好。
- 容易欠拟合,精度不高。
应用场景:
- 在P2P,汽车金融等领域,根据申请人的提供的资料,预测其违约的可能性大小,进而决定是否给其贷款。
- 电商平台根据用于购买记录预测用户下一次是否会购买某件商品。
- (天涯,bbs,微博,豆瓣短评等舆论平台做情感分类器。如根据某网友对某些特定主题的历史评论数据,预测其下次对某类型的主题是否会给出正面的评论。
- 在医疗领域,根据病人症状,预测其肿瘤是良性的还是恶性的。
- 根据CT,流行病学,旅行史,检测试剂结果等特点预测某位疑似病人是否真感染新型冠状病毒。
- 在精准营销领域,预测某个产品的收益。
[机器学习]Logistic回归相关推荐
- 机器学习-Logistic回归原理及实战
Logistic回归 回归 在介绍Logistic回归之前,先容我介绍一下什么是回归 回归,指研究一组随机变量(Y1 ,Y2 ,-,Yi)和另一组(X1,X2,-,Xk)变量之间关系的统计分析方法,又 ...
- 机器学习——logistic回归
何为回归?假设有一系列数据点,我们使用一条直线对这些点进行拟合(该线称为最佳拟合直线),这个拟合过程就称为回归.利用Logistic回归进行分类的主要思想是:根据现有数据对分类边界线建立回归公式,并以 ...
- 机器学习 Logistic回归
目录 一.线性模型及回归: 1.一维数据线性模型: 2.多维数据: 二.对数线性回归: 三.Logistic回归: 1.极大似然估计: 2.梯度下降: 三.本次实验数据集介绍: 1.数据集信息介绍: ...
- 机器学习--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 :所有 ...
最新文章
- 使用phpMyAdmin时出现PHP 5.3+is required的解决方案
- 按钮在执行frame动画的时候怎么响应触发事件?
- struts2教程(5)--请求参数校验
- 什么是大数据,怎么理解和应对大数据时代
- 程序员面试金典 - 面试题 01.01. 判定字符是否唯一(位运算,牛)
- [6] ADB 文件管理
- 客户端序列码生成_Django REST Framework教程(2): 序列化器介绍及开发基于函数视图的API...
- Web前端笔记(9) flex布局
- 统计出每个班分别有男女生各多少名
- 01.00 简单工厂模式
- 总结的比较好的OpenGL教程
- 佳能Canon imageCLASS MF236n 一体机驱动
- VTK笔记——医学图像等值面提取(Marching Cubes)
- 应届生 实习生 社招最常用招聘网站
- 29.Silverlight碰撞测试、检测自定义控件碰撞,雷达扫描图之扫描雷达点状态
- 远程计算机或设备将不接受连接 解决方案
- vue的过渡动画(有vue的动画库和ui库的介绍)
- 乱码html文档怎么恢复,乱码word文档怎么恢复
- 2022年国庆红旗头像制作微信小程序源码
- Leecode159:至多包含两个不同字符的最长子串