#【Logistc-回归】
文章目录
1.难点说明
1.plotBestFit(weights.getA())
getA()将weights矩阵转换为数组,getA()函数与mat()函数的功能相反
如果是矩阵会报错:
x and y must have same first dimension, but have shapes (60,) and (1, 60)
x = arange(-3.0, 3.0, 0.1),len(x) = [3-(-3)]/0.1 = 60
weights是矩阵的话,y = (-weights[0]-weights[1]*x)/weights[2],len(y) = 1
2. del 修改
del那句改成del(list(dataIndex)[randIndex])
3.RuntimeWarning: overflow encountered in exp
当参数 inx 很大时,exp(inx)可能会发生溢出
????????
def sigmoid(inx):
'''定义sigmoid函数'''
if inx >=0:
return 1.0/(1+np.exp(-inx))
else:
return np.exp(inx)/(1+np.exp(inx))
2.基于Logistic 回归和Sigmoid 函数的分类
logRegres.py and logRegres_1.py
梯度上升伪代码
所有回归系数初始化为1
重复 R 次
计算整个数据集的梯度
使用alpha*gradient更新回顾系数值
返回回归系数值
随机梯度上升
所有回归系数初始化为1
对数据集每个样本
计算该样本的梯度
使用alpha*gradient更新回顾系数值
返回回归系数值
import numpy as np
import matplotlib.pyplot as plt
def loadDataSet():
'''读取数据
输出:dataMat 数据集
lalelMat 数据标签'''
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])]) #特征 + x0=1.0
labelMat.append(int(lineArr[2]))
return dataMat, labelMat
def sigmoid(inx):
'''定义sigmoid函数'''
return 1.0/(1+np.exp(-inx))
def gradAscent(dataMatIn, classLabels):
'''梯度上升法更新拟合参数
@ dataMatIn 数据集
@ classLabels 数据标签
'''
dataMatrix = np.mat(dataMatIn) #将数据集list>>matrix
labelMat = np.mat(classLabels).transpose() #将标签转换,并转置
m, n = np.shape(dataMatrix) #获取数据集的行和列
alpha = 0.001 # 学习步长
maxCycles = 500 # 最大迭代次数
weights = np.ones((n,1)) #初始化权值参数向量每个维度均为1.0
for k in range(maxCycles):
h = sigmoid(dataMatrix*weights) # 当前的sigmoid函数预测概率
'''逻辑回归的更新方式'''
error = (labelMat - h)
weights = weights + alpha*dataMatrix.transpose()*error
return weights
def plotBestFit(weights):
'''绘制图像
@ weights 权重'''
dataMat, labelMat = loadDataSet() #导入数据和标签
dataArr = np.array(dataMat) #转化为矩阵
n = np.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) # 创建一个或多个子图(subplot)
ax.scatter(xcord1,ycord1,c='red', marker='s')
ax.scatter(xcord2,ycord2, c='green')
x = np.arange(-3.0,3.0,0.1)
y = (-weights[0]-weights[1]*x)/weights[2] # 绘制直线
y = y.reshape((60,1))
ax.plot(x,y)
plt.xlabel('X1')
plt.ylabel('X2')
plt.show()
if __name__=='__main__':
dataArr, labelMat = loadDataSet()
weights = gradAscent(dataArr,labelMat)
plotBestFit(weights.getA())
import numpy as np
import logRegres
def stocGradAscent0(dataMatrix,classLabels):
'''随机梯度上升算法'''
dataMat = np.array(dataMatrix) #为便于计算,转为Numpy数组
m,n = np.shape(dataMatrix) #获取数据集的行数和列数
weights = np.ones(n) #初始化权值向量各个参数为1.0
alpha = 0.01 #设置步长为0.01
#循环m次,每次选取数据集一个样本更新参数
for i in range(m):
h = logRegres.sigmoid(np.sum(dataMatrix[i]*weights)) # 计算当前样本的sigmoid函数值
error=classLabels[i]-h
#更新权值参数
weights=weights+alpha*error*dataMat[i]
return weights
def stocGradAscent1(dataMatrix,classLabels,numIter=150):
'''改进的随机梯度上升算法'''
dataMat = np.array(dataMatrix) #将数据集列表转为Numpy数组
m,n = np.shape(dataMat) #获取数据集的行数和列数
weights = np.ones(n) #初始化权值参数向量每个维度均为1
for j in range(numIter): #循环每次迭代次数
dataIndex = range(m) #获取数据集行下标列表
for i in range(m): #遍历行列表
#每次更新参数时设置动态的步长,且为保证多次迭代后对新数据仍然具有一定影响
#添加了固定步长0.1
alpha = 4/(1.0+j+i)+0.1
randomIndex = int(np.random.uniform(0,len(dataIndex))) #随机获取样本
h = logRegres.sigmoid(np.sum(dataMat[randomIndex]*weights)) #计算当前sigmoid函数值
error = classLabels[randomIndex]-h
weights=weights + alpha*error*dataMat[randomIndex]
'''选取该样本后,将该样本下标删除,确保每次迭代时只使用一次'''
del(list(dataIndex)[randomIndex])
return weights
if __name__=='__main__':
dataArr, labelMat = logRegres.loadDataSet()
weights = stocGradAscent0(dataArr,labelMat)
logRegres.plotBestFit(weights)
3.示例:从疝气病预测病马的死亡率(logRegres_2.py)
import logRegres
import logRegres_1
def clasifyVector(inX,weights):
'''分类决策函数'''
prob = logRegres.sigmoid(np.sum(inX*weights)) #计算logistic回归预测概率
# 判断
if prob > 0.5:
return 1.0
else:
return 0.0
def colicTest():
'''logistic回归预测算法'''
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])) #将该样本标签存入标签列表
'''调用随机梯度上升法更新logistic回归的权值参数'''
trainWeights = logRegres_1.stocGradAscent1(trainingSet,trainingLabels,500)
'''测试'''
errorCount=0;numTestVec=0.0
for line in frTest.readlines():
numTestVec += 1.0 #样本总数加1
currLine=line.strip().split('\t') #对当前行进行处理,分割出各个特征及样本标签
lineArr=[] #新建特征向量
for i in range(21): #将各个特征构成特征向量
lineArr.append(float(currLine[i]))
#利用分类预测函数对该样本进行预测,并与样本标签进行比较
if(clasifyVector(lineArr,trainWeights) != int(currLine[21])):
errorCount += 1 #如果预测错误,错误数加1
errorRate=(float(errorCount)/numTestVec) #计算测试集总的预测错误率
print('测试集的错误率为: %f' %(errorRate))
return errorRate
def multTest():
'''多次测试算法求取预测误差平均值'''
#设置测试次数为10次,并统计错误率总和
numTests=10;errorRateSum=0.0
#每一次测试算法并统计错误率
for k in range(numTests):
errorRateSum+=colicTest()
print('经过 %d 次迭代后,错误率的平均值: %f' %(numTests,errorRateSum/float(numTests)))
if __name__=='__main__':
multTest()
测试集的错误率为: 0.388060
测试集的错误率为: 0.358209
测试集的错误率为: 0.253731
测试集的错误率为: 0.328358
测试集的错误率为: 0.462687
测试集的错误率为: 0.298507
测试集的错误率为: 0.253731
测试集的错误率为: 0.283582
测试集的错误率为: 0.507463
测试集的错误率为: 0.283582
经过 10 次迭代后,错误率的平均值: 0.341791