实例背景
使用Logistic回归来预测患疝气病的马的存活问题。数据包含了368个样本和28个特征。这种病不一定源自马的肠胃问题,其他问题也可能引发马疝病。
该数据集中包含了医院检测马疝病的一些指标,有的指标比较主观,有的指标难以测量,例如马的疼痛级别。另外需要说明的是,除了部分指标主观和难以测量外,该数据还存在一个问题,数据集中有30%的值是缺失的。
准备数据
如何处理数据中的缺失值?
- 使用可用特征的均值来填补缺失值;
- 使用特殊值来填补缺失值,如-1;
- 忽略有缺失值的样本;
- 使用相似样本的均值添补缺失值;
- 使用另外的机器学习算法预测缺失值。
案例中预处理数据:
- 如果一 条数据的特征值已经缺失——选择实数0来替换所有缺失。(sigmoid(0)=0.5,即它对结果的预测不具有任何倾向性,因此这样做不会影响回归系数的值)
- 如果一 条数据的类别标签已经缺失——将该类别数据丢弃。
原始的数据集经过处理,保存为两个文件: horseColicTest.csv和horseColicTraining.csv
加载数据
import numpy as np
import pandas as pd
# 加载数据
def loadDataSet(filename):
data = pd.read_csv(filename)
xArr = data.iloc[:, :-1].values
labelMat = data. iloc[:, -1].values
data_num, features_num = np.shape(xArr)
dataMat = np.ones((data_num, features_num + 1))
dataMat[:, 1:] = np.mat(xArr)
return dataMat, labelMat
Parameters:
filename – 文件名
Returns:
dataMat – 数据列表
labelMat – 标签列表
sigmoid函数
# sigmoid函数
def sigmoid(inX):
if inX >= 0:
return 1.0 / (1 + np.exp(-inX))
else:
return np.exp(inX) / (1 + np.exp(inX))
Parameters:
inX – 数据
Returns:
sigmoid函数
改进的随机梯度上升算法
# 改进的随机梯度上升算法
def stocGradAscent(dataMatrix, classLabels, numlter=150):
m, n = np.shape(dataMatrix)
weights = np.ones(n)
for j in range(numlter):
randnums = np.random.permutation(m)
i = 0
for index in randnums:
alpha = 4/(1.0+j+i)+0.01
h = sigmoid(sum(dataMatrix[index]*weights))
error = classLabels[index] - h
weights = weights + alpha * error * dataMatrix[index]
i += 1
return weights
Parameters:
dataMatrix – 数据数组
classlabels – 数据标签
numlter – 迭代次数
Returns:
weights – 求得的回归系数数组(最优参数)
分类函数
# 分类函数
def classifyVector(inX, weights, p=0.5):
prob = sigmoid(sum(inX*weights))
if prob > p:
return 1.0
else:
return 0.0
Parameters:
inX – 特征向量
weights – 回归系数
Returns:
分类结果
循环预测,得出最优回归系数和最小错误率
# 对测试数据进行预测,计算出错误率
def colicTest():
dataMat1, labelMat1 = loadDataSet("horseColicTraining.csv")
dataMat2, labelMat2 = loadDataSet("horseColicTest.csv")
re0 = []
re1 = []
for j in range(50):
weights = stocGradAscent(dataMat1, labelMat1)
total = len(dataMat2)
err = 0.0
for i in range(total):
res = classifyVector(dataMat2[i], weights)
if res - labelMat2[i] != 0:
err += 1
re0.append(err/total)
re1.append(weights)
print("循环执行50次后,")
print("最小的错误率为:", end=" ")
print(min(re0))
print("对应的回归系数为:",)
print(re1[re0.index(min(re0))])
做出以上处理后,大致的结果如下:
