自己动手写Logistic回归算法
假设一个数据集有n个样本,每个样本有m个特征,样本标签y为{0, 1}。
数据集可表示为:
其中,x(ij)为第i个样本的第j个特征值,y(i)为第i个样本的标签。
X矩阵左侧的1相当于回归方程的常数项。
每个特征有一个权重(或系数),权重矩阵为:
开始可以将权重均初始化为1。
将特征及权重分别相乘得到Xw (即特征的线性组合,为n维列向量)。
经过Sigmoid函数处理得到预测值:
y为预测值(取值范围0-1),为n维列向量。
对于一个样本i,y(i)取值为1和0的概率分别是:
其中x(i)为第i个样本的特征向量,为m+1维行向量。
为了学习得到最佳的权重矩阵w,需要定义损失函数来优化。一个直观的想法是使用预测值y与观测值Y之间的误差平方和,但是这个损失函数是非凸函数,用梯度下降法不能得到全局极小值。所以我们采用最大似然法。
对于每一个样本,出现的概率为:
假设n个样本相互独立,概率相乘。似然函数为:
取对数,变乘法为加法,得到对数似然函数:
这就是我们需要最大化的目标函数。
梯度法
如采用梯度法,首先要对w求导:
其中,σ为Sigmoid函数。
最后使用梯度上升来更新权重:
其中α为步长。经过多次迭代后,求得似然函数的最大值及相应的w。
牛顿法
如采用牛顿法,需要计算二阶导数:
这是一个m×m的矩阵,称为Hessian矩阵,用H表示。
如果定义:
则:
根据牛顿迭代公式:
经过有限次迭代,达到收敛。
预测分类
如果用来预测分类,进行如下运算:
如y(i) > 0.5 判定为1,如y(i) < 0.5,判定为0
权重系数与OR的关系
下面讨论一下权重w与OR的关系。
根据OR的定义:
当其他特征值不变的情况下,某x(i)增加1,相应的和xw增加w(i),OR值变为原来的exp(w(i)) 倍。
Python程序代码
from numpy import * import matplotlib.pyplot as plt # 加载数据 def loadDataSet(): dataMat = [] labelMat = [] fr = open ( 'data/testSet.txt' ) for line in fr.readlines(): lineArr = line.strip().split( ',' ) dataMat.append([ 1.0 , float (lineArr[ 0 ]), float (lineArr[ 1 ])]) labelMat.append( int (lineArr[ 2 ])) fr.close() return dataMat, labelMat # Sigmoid函数,注意是矩阵运算 def sigmoid(inX): return 1.0 / ( 1 + exp( - inX)) # 梯度上升算法 def gradAscent(dataMatIn, classLabels): dataMat = mat(dataMatIn) labelMat = mat(classLabels).transpose() m,n = shape(dataMat) alpha = 0.01 maxCycles = 500 weights = mat(ones((n, 1 ))) weightsHis = [mat(ones((n, 1 )))] # 权重的记录,主要用于画图 for k in range (maxCycles): h = sigmoid(dataMat * weights) error = labelMat - h weights = weights + alpha * dataMat.transpose() * error weightsHis.append(weights) return weights,weightsHis # 简单的随机梯度上升,即一次处理一个样本 def stocGradAscent0(dataMatIn, classLabels): dataMat = mat(dataMatIn) labelMat = mat(classLabels).transpose() m,n = shape(dataMat) alpha = 0.01 weights = mat(ones((n, 1 ))) weightsHis = [mat(ones((n, 1 )))] # 权重的记录,主要用于画图 for i in range (m): h = sigmoid(dataMat[i] * weights) error = labelMat[i] - h weights = weights + alpha * dataMat[i].transpose() * error weightsHis.append(weights) return weights,weightsHis # 改进的随机梯度算法 def stocGradAscent1(dataMatIn, classLabels, numIter): dataMat = mat(dataMatIn) labelMat = mat(classLabels).transpose() m,n = shape(dataMat) alpha = 0.001 weights = mat(ones((n, 1 ))) weightsHis = [mat(ones((n, 1 )))] # 权重的记录,主要用于画图 for j in range (numIter): dataIndex = list ( range (m)) for i in range (m): alpha = 4 / ( 1.0 + j + i) + 0.001 # 动态调整alpha randIndex = int (random.uniform( 0 , len (dataIndex))) # 随机选择样本 h = sigmoid(dataMat[randIndex] * weights) error = labelMat[randIndex] - h weights = weights + alpha * dataMat[randIndex].transpose() * error del (dataIndex[randIndex]) weightsHis.append(weights) return weights,weightsHis # 牛顿法 def newton(dataMatIn, classLabels, numIter): dataMat = mat(dataMatIn) labelMat = mat(classLabels).transpose() m,n = shape(dataMat) # 对于牛顿法,如果权重初始值设定为1,会出现Hessian矩阵奇异的情况. # 原因未知,谁能告诉我 # 所以这里初始化为0.01 weights = mat(ones((n, 1 ))) - 0.99 weightsHis = [mat(ones((n, 1 )) - 0.99 )] # 权重的记录,主要用于画图 for _ in range (numIter): A = eye(m) for i in range (m): h = sigmoid(dataMat[i] * weights) hh = h[ 0 , 0 ] A[i,i] = hh * ( 1 - hh) error = labelMat - sigmoid(dataMat * weights) H = dataMat.transpose() * A * dataMat # Hessian矩阵 weights = weights + H * * - 1 * dataMat.transpose() * error weightsHis.append(weights) return weights,weightsHis def plotWeights(w): w = array(w) def f1(x): return w[x, 0 , 0 ] def f2(x): return w[x, 1 , 0 ] def f3(x): return w[x, 2 , 0 ] k = len (w) x = range ( 0 ,k, 1 ) plt.plot(x,f1(x),' ',x,f2(x),' ',x,f3(x),' ') plt.show() # 画出分类边界 def plotBestFit(wei): weights = wei.getA() dataMat, labelMat = loadDataSet() dataArr = array(dataMat) n = shape(dataArr)[ 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' ) ax.scatter(xcord2, ycord2, s = 30 , c = 'green' ) x = arange( - 3.0 , 3.0 , 0.1 ) y = ( - weights[ 0 ] - weights[ 1 ] * x) / weights[ 2 ] ax.plot(x,y) plt.xlabel( 'x1' ) plt.ylabel( 'x2' ) plt.show() # 测试 data, labels = loadDataSet() #weights,weightsHis = gradAscent(data, labels) #weights0, weightsHis0 = stocGradAscent0(data, labels) #weights1, weightsHis1 = stocGradAscent1(data, labels, 500) weights3, weightsHis3 = newton(data, labels, 10 ) plotBestFit(weights3) print (weights3) plotWeights(weightsHis3) |
运行结果:
2、随机梯度法迭代500次的分类边界及权重收敛情况
3、牛顿法迭代10次的分类边界及权重收敛情况,可以牛顿法要快很多。
自己动手写Logistic回归算法的更多相关文章
- Logistic回归算法梯度公式的推导
最近学习Logistic回归算法,在网上看了许多博文,笔者觉得这篇文章http://blog.kamidox.com/logistic-regression.html写得最好.但其中有个关键问题没有讲 ...
- 机器学习之Logistic 回归算法
1 Logistic 回归算法的原理 1.1 需要的数学基础 我在看机器学习实战时对其中的代码非常费解,说好的利用偏导数求最值怎么代码中没有体现啊,就一个简单的式子:θ= θ - α Σ [( hθ( ...
- 机器学习之logistic回归算法与代码实现原理
Logistic回归算法原理与代码实现 本文系作者原创,转载请注明出处:https://www.cnblogs.com/further-further-further/p/10033567.html ...
- 机器学习算法-logistic回归算法
Logistic回归算法调试 一.算法原理 Logistic回归算法是一种优化算法,主要用用于只有两种标签的分类问题.其原理为对一些数据点用一条直线去拟合,对数据集进行划分.从广义上来讲这也是一种多元 ...
- 机器学习算法( 五、Logistic回归算法)
一.概述 这会是激动人心的一章,因为我们将首次接触到最优化算法.仔细想想就会发现,其实我们日常生活中遇到过很多最优化问题,比如如何在最短时间内从A点到达B点?如何投入最少工作量却获得最大的效益?如何设 ...
- matlib实现logistic回归算法(序一)
数据下载:http://archive.ics.uci.edu/ml/datasets/Adult 数据描述:http://archive.ics.uci.edu/ml/machine-learnin ...
- logistic回归算法及其matlib实现
一般来说,回归不用在分类问题上,因为回归是连续型模型,而且受噪声影响比较大.如果非要使用回归算法,可以使用logistic回归. logistic回归本质上是线性回归,只是在特征到结果的映射中多加入了 ...
- 《转》Logistic回归 多分类问题的推广算法--Softmax回归
转自http://ufldl.stanford.edu/wiki/index.php/Softmax%E5%9B%9E%E5%BD%92 简介 在本节中,我们介绍Softmax回归模型,该模型是log ...
- Logistic回归 python实现
Logistic回归 算法优缺点: 1.计算代价不高,易于理解和实现2.容易欠拟合,分类精度可能不高3.适用数据类型:数值型和标称型 算法思想: 其实就我的理解来说,logistic回归实际上就是加了 ...
随机推荐
- Spring Data JPA
转自: http://www.cnblogs.com/WangJinYang/p/4257383.html Spring 框架对 JPA 的支持 Spring 框架对 JPA 提供的支持主要体现在如下 ...
- 命名空间“System.Web”中不存在类型或命名空间名称“Optimization”(是否缺少程序集引用?)
今天,在.net4.5,mvc4下新建了个区域,运行起来就报这个错误: 命名空间"System.Web"中不存在类型或命名空间名称"Optimization"( ...
- Spark on Yarn:任务提交参数配置
当在YARN上运行Spark作业,每个Spark executor作为一个YARN容器运行.Spark可以使得多个Tasks在同一个容器里面运行. 以下参数配置为例子: spark-submit -- ...
- 添加右键菜单命令 在此处打开命令窗口(E)(带图标)
@color 0A @title 添加右键菜单命令 在此处打开命令窗口(^&E)(带图标) by wjshan0808 @echo off reg add HKCR\Directory\Bac ...
- 自定义cell侧滑删除
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath { return Y ...
- 。。。IO流的学习之一。。。
文件写入流FileWriter的使用: import static org.junit.Assert.*; import java.io.File; import java.io.FileWriter ...
- Asp.net MVC5 框架揭秘 S412 实例解析 – 绝妙的扩展 模式的胜利
Asp.net MVC5 框架是个 开源的,处处可扩展的框架. 蒋先生 在他的这本书里 对如何理解框架,如何扩展框架, 给出了大量的说明和实例. 先上效果图 大部分做传统BS 的同学看到这个页面,脑海 ...
- 验证控件,解决用于ajax提交前的验证,不是submit提交的验证
//解决ajax提交前的验证问题,主要用于onclick事件时对某一区域中(可以是form,div,table中的等)控件的验证.(function ($) { var v; //Create a n ...
- IP釋放、清除、以及刷新DNS
Windows 10 於桌面按住 Windows + X 按鍵. 選擇 Command Prompt (以管理員執行). 在彈跳視窗中輸入 ipconfig /release. 等待數秒回報此 IP ...
- VIM 常用快捷键
一,光标移动 大家不要觉得光标移动不重要,其实它是基础,更好的光标移动,复制,粘贴,删除等才能更加的得心应手,进入了编辑器里面后,鼠标就不能用了. 光标移动 h 或 向左箭头键(←) 20h或者20( ...