由于近期学业繁重 QAQ,所以我就不说废话了,直接上代码~
Logistic 回归进行分类
分类效果
Logistic 回归预测病马的死亡率
预测结果
全部代码
from numpy import *
import matplotlib.pyplot as plt
# 使用梯度上升法找到最佳参数
#使用梯度上升法找到最佳回归系数,
#也就是拟合 Logistic 回归模型的最佳参数
#Logistic 归回梯度上升优化算法
#加载文件
def loadDataSet():
dataMat=[];labelMat=[]
#打开文本文件
fr=open(‘testSet.txt’)
#逐行读取
for line in fr.readlines():
lineArr=line.strip().split()
#为了方便计算,将 x0 设为 1,后面的 x1,x2 是文本中每行的前两个值
dataMat.append([1.0, float(lineArr[0]), float(lineArr[1])])
#文本中每行的第三个值为数据对应的标签
labelMat.append(int(lineArr[2]))
return dataMat,labelMat
#sigmiod 函数
def sigmoid(inX):
return 1.0/(1+exp(-inX))
# 梯度上升算法
#第一个参数是一个 2 维的 Numpy 数组
#每列表示不同的特征
#每行表示每个训练样本
#我们采用 100 个样本,包含两个 x1,x2 特征
#再加上第 0 维特征 x0,所以 dataMatIn 是一个 100X3 的矩阵
#第二个参数是类别标签,是一个 1X100 的行向量
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 循环结束之后,将返回训练好的回归系数
for k in range(maxCycles):
#注:此处是矩阵相乘
#h 是一个列向量,元素的个数等于样本的个数
h=sigmoid(dataMatrix*weights)
#真实类别与预测类别的差别
error=(labelMat-h)
#按照该差别的方向调整回归系数
weights=weights+alpha*dataMatrix.transpose()*error
#返回回归系数——确定了不同类别数据之间的分割线
return weights
# 画出决策边界
#画出数据集和 Logistic 回归最佳拟合直线的函数
#X1 表示一个特征,X2 表示另一个特征
def plotBestFit(weights):
#得到数据集与标签
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)
#根据 gradAscent 得到的回归系数绘制分割线
y = (-weights[0]-weights[1]*x)/weights[2]
#print(x)
#print(y)
ax.plot(x, y)
plt.xlabel(‘X1’); plt.ylabel(‘X2’);
plt.show()
# 梯度上升方法在每次更新回归系数时都需要遍历整个数据集
#改进方法:一次仅使用一个样本点来更新回归系数——随机梯度上升算法
#由于可以在新样本到来时对分类器进行增量式更新,因此随机梯度上升
#算法是一个在线学习算法
#与“在线学习”相对应,一次数里所有数据被称作“批处理”
#随机梯度上升算法
def stocGradAscent0(dataMatrix,classLabels):
#得到矩阵的大小
m,n=shape(dataMatrix)
#向目标移动的步长
alpha=0.01
weights=ones(n)
for i in range(m):
#h 为向量
h=sigmoid(sum(dataMatrix[i]*weights))
#error 为向量
error=classLabels[i]-h
weights=weights+alpha*error*dataMatrix[i]
return weights
# 由于经过测试,多次迭代后,X0,X1 收敛速度较小
#且存在一些小的周期性的波动,因此及逆行改进
#改进随机梯度上升算法
#第三个参数为迭代次数
def stocGradAscent1(dataMatrix,classLabels,numIter=150):
m,n=shape(dataMatrix)
weights=ones(n)
for j in range(numIter):
dataIndex=list(range(m))
for i in range(m):
#改进 1: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
#Logistic 回归预测病马的死亡率
#对于缺失数据,我们选择用 0 来替换
#因为这样不会影响系数 weights 的值
#对于标签已经丢失的,我们将这条数据丢弃
#使用 Logistic 回归进行分类的主要思路:
#把测试集上每个特征向量乘最优方法得到的回归系数
#再将该乘积结果求和,最后输入 Sigmoid 函数中即可,
#若对应的 sigmoid 值 >0.5 预测类别标签为 1,否则为 0
#Logistic 回归分类函数
def classifyVector(inX,weights):
#以回归系数和特征向量作为输入来计算对应的 Sigmoid 值
prob=sigmoid(sum(inX*weights))
if prob>0.5:return 1.0
else:return 0.0
# 打开测试集和训练集,并对数据进行格式化处理
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]))
trainingSet.append(lineArr)
#最后一列为类别标签
trainingLabels.append(float(currLine[21]))
#计算回归系数向量
trainWeights=stocGradAscent1(array(trainingSet),trainingLabels,500)
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(array(lineArr),trainWeights))!=int(currLine[21]):
errorCount+=1
#计算错误率
errorRate=(float(errorCount)/numTestVec)
print(“the error rate of this test is: %f”%errorRate)
return errorRate
# 调用 colicTest 函数 10 次,并且结果的平均值
def multiTest():
numTests=10
errorSum=0.0
for k in range(numTests):
errorSum+=colicTest()
print(“after %d iterations the average error rate is: %f”%(numTests,errorSum/float(numTests)))
def main():
#dataArr,labelMat=loadDataSet()
#weights=gradAscent(dataArr,labelMat)
#print(weights)
#plotBestFit(weights.getA())
#weights=stocGradAscent0(array(dataArr),labelMat)
#weights=stocGradAscent1(array(dataArr),labelMat)
#plotBestFit(weights)
multiTest()
if __name__==’__main__’:
main()