Logistic回归是入门机器学习时所学的几个基本回归算法之一
其主要思想是:根据现有数据对分类边界线建立回归公式,以此进行分类。
其训练过程其实也就是一个调参过程,用详细的语言描述为:寻找最佳拟合参数,在这其中使用的是最优化算法。
示例:从疝气病症预测病马的死亡率
数据包含368个样本和28个特征。疝病是描述马胃肠痛的术语。然而,这种病不一定源自马的胃肠问题,其他问题也可能引发马疝病。
该数据集中包含了医院检测马疝病的一些指标,有的指标比较主观,有的指标难以测量,例如马的疼痛级别。除此之外,还存在一个问题,数据集中有30%的值是缺失的。
下面将首先介绍如何处理数据集中的数据缺失问题,然后再利用Logistic回归和随机梯度上升算法来预测病马的生死。
一、准备数据:处理数据中的缺失值
可选做法:
●使用可用特征的均值来填补缺失值
●使用特殊值来填补缺失值,如-1
●忽略有缺失值的样本
●使用相似样本的均值添补缺失值
●使用另外的机器学习算法预测缺失值
数据预处理阶段:
1、所有缺失值必须用一个实数值来替换,因为numpy数据类型不允许包含缺失值(这里选择0来替换所有缺失值,恰好能适用于Logistic回归)。
回归系数的更新公式如下:
weights = weights + alpha * error * dataMatrix[randIndex]
如果dataMatrix的某特征对应值为0,那么该特征的系数将不做更新,即:
weights = weights
由于sigmoid(0)=0.5,即它对结果的预测不具任何倾向性,因此不会对误差项造成任何影响。
2、如果在测试集中发现了一条数据的类别标签已经缺失,那么简单做法是将该条数据丢弃。
“干净”可用的数据集 + 一个不错的优化算法————>分类器————> 预测病马的生死问题
其中数据集下载链接如下:
http://archive.ics.uci.edu/ml/datasets/Horse+Colic
二、测试算法:用Logistic回归进行分类
Logistic回归方法:所需的只是把测试集上每个特征向量乘以最优化方法得来的回归系数,再将该乘积结果求和,最后输入到Sigmoid函数中。
如果对应的Sigmoid值大于0.5,就预测类别标签为1,否则为0。
Logistic回归分类函数代码如下:
import numpy as np
import matplotlib.pyplot as plt
import matplotlib
def stocGradAscent1(dataMatrix, classLabels, numIter=150):
m,n = np.shape(dataMatrix)
weights = np.ones(n) #initialize to all ones
for j in range(numIter):
dataIndex = list(range(m))
for i in range(m):
# alpha = 0.001
alpha = 4/(1.0+j+i)+0.01 #alpha每次迭代时需要调整
randIndex = int(np.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
def sigmoid(inx):
if inx>0:
return 1.0/(1+ np.exp(-inx))
else:
return np.exp(inx)/(1+ np.exp(inx))
# Logistic回归分类函数
def classifyVector(inX,weights):
prob = sigmoid(sum(inX*weights)) #计算logistic回归预测概率
if prob>0.5: #大于0.5预测为1,否则预测为0
return 1.0
else:
return 0.0
# logistic回归预测算法
def colicTest():
frTrain = open('horseColicTraining.txt') # 打开训练数据集
frTest = open('horseColicTest.txt') # 打开测试数据集
trainingSet = [];
trainingLabels = [] # 新建两个孔列表,用于保存训练数据集和标签
for line in frTrain.readlines(): # 读取训练集文档的每一行
currLine = line.strip().split('\t') # 对当前行进行特征分割
lineArr = [] # 新建列表存储每个样本的特征向量
for i in range(21): # 遍历每个样本的特征
lineArr.append(float(currLine[i])) # 将该样本的特征存入lineArr列表
trainingSet.append(lineArr) # 将该样本的特征向量添加到数据集列表
trainingLabels.append(float(currLine[21])) # 将该样本标签存入标签列表
trainWeights = stocGradAscent1(np.array(trainingSet), trainingLabels, 1000) # 调用随机梯度上升法更新logistic回归的权值参数
errorCount = 0;
numTestVec = 0.0 # 统计测试数据集预测错误样本数量和样本总数
for line in frTest.readlines(): # 遍历测试集的每个样本
numTestVec += 1.0 # 样本总数统计
currLine = line.strip().split('\t') # 对当前行进行处理,分割出各个特征及样本标签
lineArr = [] # 新建特征向量
for i in range(21): # 将各个特征构成特征向量
lineArr.append(float(currLine[i]))
if int(classifyVector(np.array(lineArr), trainWeights)) != int(currLine[21]): # 利用分类预测函数对该样本进行预测,并与样本标签进行比较
errorCount += 1 # 如果预测错误,错误数加1
errorRate = (float(errorCount) / numTestVec) # 计算测试集总的预测错误率
print('the error rate of this test is: %f' % (errorRate)) # 打印错误率大小
return errorRate # 返回错误率
# 多次测试算法求取预测误差平均值
def multiTest():
numTests = 10;
errorRateSum = 0.0 # 设置测试次数为10次,并统计错误率总和
for k in range(numTests): # 每一次测试算法并统计错误率
errorRateSum += colicTest()
print('after %d iterations the average error rate is: %f' % (
numTests, errorRateSum / float(numTests))) # 打印出测试10次预测错误率平均值
def main():
multiTest()
main()