关于这两者的详细介绍我在以前整理的听课笔记中有写到,这里我就不做相关的详细叙述了
Machine Learning-3
本文分别使用python与matlab实现Logistic回归算法以及优化函数
源码以及数据集
Logistic回归
一般过程
- 收集数据:采用任何方法收集数据
- 准备数据:由于需要进行距离计算,因此要求数据类型为数值型。另外,结构化数据格式最佳
- 分析数据:采用任何方法对数据进行分析
- 训练算法:大部分时间将用与训练,训练的目的是为了找到最佳的分类回归函数
- 测试算法:一旦训练步骤完成,分类将会很快
- 使用算法:首先我们需要输入一些数据,并将其转换为结构化数值;接着,基于训练后的回归函数就可以对数值进行简单的回归计算,判定它们属于哪个类别;在这之后,我们就可以在输出类别上做一些其他分析工作
优点:计算代价不高,易于理解和实现
缺点:容易欠拟合,分类精度可能不高
试用数据类型:数值型和标称型数据
python实现
首先先导入数据
- 打开文件读取数据
- 每行前两个值分别为X1、X2,第三个值是数据对应的类别标签
- 第0维特征X0 = 1
1 2 3 4 5 6 7 8
| def loadDataSet(): dataMat = []; labelMat = [] fr = open('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])) return dataMat, labelMat
|
Sigmord实现
Sigmord函数就一行代码,具体函数形式可以点击文章开始的链接,里面详细介绍了Sigmord函数以及Logistic函数的代价函数
1 2
| def sigmoid(inX): return 1.0/(1+exp(-inX))
|
梯度上升算法
梯度上升方法与梯度下降算法
两者不同在于只是将公式中的加号变为减号
前者求最大值,后者求最小值
使用梯度上升找到最佳参数
dataMatIn: 2维Numpy数组,每列分别代表每个不同的特征,每行代表每个训练样本
classLabels: 类别标签,一组一维行向量
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| def gradAscent(dataMatIn, classLabels): # 转换为矩阵类型 dataMatrix = mat(dataMatIn) # 为便于计算,将类别标签转置 labelMat = mat(classLabels).transpose() m, n = shape(dataMatrix) alpha = 0.001 # 目标移动的步长 maxCycles = 500 # 迭代次数 weights = ones((n,1)) for k in range(maxCycles): # 矩阵相乘 h = sigmoid(dataMatrix * weights) # 计算真实类别与预测类型的差值 error = (labelMat - h) weights = weights + alpha * dataMatrix.transpose() * error return weights
|
画出数据集合Logistic回归最佳拟合直线的函数
使用的还是matplotlib模块绘图,具体安装方法我在这篇文章里详细介绍了matplotlib安装,具体位置在这篇文章的中心部分
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| def plotBestFit(weights): import matplotlib.pyplot as plt 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=10, 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()
|
随机梯度上升算法
代码与前面的梯度上升很像,但是这里计算weights时是用的是向量,而非数值;而且前者没有使用矩阵转换,使用的是Numpy数组
随机梯度上升算法相较于梯度上升算法的好处:
两者效果相当但是前者会占用比较少的计算机资源
此外前者是一个在线算法,即可以在新数据到来时就完成数据的更新,而不用重新读取整个数据集重新进行批处理
1 2 3 4 5 6 7 8 9
| def stocGradAscent0(dataMatrix, classLabels): m,n = shape(dataMatrix) alpha = 0.01 weights = ones(n) for i in range(m): h = sigmoid(sum(dataMatrix[i]*weights)) error = classLabels[i] - h weights = weights + alpha * error * dataMatrix[i] return weights
|
随机梯度上升改进版
我在这里规定迭代次数为150次
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| def stocGradAscent1(dataMatrix, classLabels, numInter = 150): m,n = shape(dataMatrix) weights = ones(n) for j in range(numInter): dataIndex = range(m) for i in range(m): # alpha 在每次迭代时需要调整,一避免参数的严格下降 alpha = 4/(1.0 + j + i) + 0.01 # 随机选取更新,以减少周期性的波动 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
|
Matlab实现
同样先是Sigmord函数,也是很简单的一行代码
1 2 3 4 5 6 7
| function g = sigmoid(z) %SIGMOID Compute sigmoid functoon % J = SIGMOID(z) computes the sigmoid of z.
g = 1.0 ./ (1.0 + exp(-z));
end
|
然后是计算Logistic的cost函数,即上面的weights
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| function [J, grad] = lrCostFunction(theta, X, y, lambda) %LRCOSTFUNCTION Compute cost and gradient for logistic regression with %regularization
% Initialize some useful values m = length(y); % number of training examples
J = 0; grad = zeros(size(theta));
htheta = sigmoid(X\*theta); J = 1/m\*sum(-y .* log(htheta) - (1-y) .* log(1-htheta)) + lambda/(2\*m)* sum(theta(2:end) .^ 2);
temp = theta; temp(1) = 0; grad = 1/m\*(X' * (htheta - y) + lambda*temp);
grad = grad(:);
end
|
总结
说是总结其实不过是把在本文开头的那篇关于Logistic的听课笔记翻译为中文然后挑些有关Logistic的干货
Logistic回归是为了寻找一个非线性函数sigmord的最佳拟合函数,求解算法可使用最优化算法完成
最优化算法使用随机梯度上升算法
最后则是个补充
处理数据中的缺失值
想学好任何一门技能都要大量的练习,而机器学习的练习则需要大量的无误的数据作为基础
网上有很多开源的大型数据集,上网随便找一下就可以了,而且很多大学的数据集都是开源的,比如布朗大学的人脸数据库
除去寻找合适的数据集外,还需要注意的就是如何处理数据中缺失的值
coursera上斯坦福的机器学习课程我记得就在前几节的样子,告诉我们如何处理。可见如何处理数据中的缺失值也是很重要的过程
主要方法就是一下几种,选取处理方式时要根据使用的算法来决定。比如你使用本文介绍的Logistic算法最简单就是将缺失的那条数据丢弃,然而如果你使用我再前面几篇文章中介绍的k-means算法的话就不行了
- 使用可用特征的均值来填补缺失值
- 使用特殊值来填补空缺
- 忽略有缺失的样本
- 使用相似样本的均值填补缺失值
- 使用另外的机器学习算法预测缺失值
如果你有一个很好的算法的话,最后一个方法则是最好的方法