Logistic回归:
import numpy as np
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])) #添加标签
fr.close() #关闭文件
return dataMat, labelMat #返回
def sigmoid(inX):
return 1.0/(1+np.exp(-inX))
#梯度上升算法
def gradAscent(dataMatIn, classLabels): #dataMatIn 每列代表不同的特征,每行代表每个训练样本
dataMarix = np.mat(dataMatIn)#创造矩阵
labelMat = np.mat(classLabels).transpose() #转置
m,n = np.shape(dataMarix) #获得维数
alpha = 0.001 #向目标移动的步长
maxCycles = 500 #迭代次数
weights = np.ones((n,1))
for k in range(maxCycles):
h = sigmoid(dataMarix*weights) #梯度上升矢量化公式
error = (labelMat - h) #h是一个列向量
weights = weights + alpha + dataMarix.transpose()* error #权重
return weights
画出数据集和Logistic回归最佳拟合直线的函数:
def plotBestFit(weights):
dataMat, labelMat = loadDataSet() #加载数据集
dataArr = np.array(dataMat) #转换成numpy的array数组
n = np.shape(dataMat)[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]) #1为正样本
else:
xcord2.append(dataArr[i,1]); ycord2.append(dataArr[i,2]) #0为负样本
fig = plt.figure()
ax = fig.add_subplot(111) #添加子图一行一列画在第一块
ax.scatter(xcord1, ycord1, s = 20, c = 'red', marker = 's',alpha=.5)#绘制正样本
ax.scatter(xcord2, ycord2, s = 20, c = 'green',alpha=.5) #绘制负样本
x = np.arange(-3.0, 3.0, 0.1)
y = (-weights[0] - weights[1] * x) / weights[2]
ax.plot(x, y)
plt.title('BestFit') #绘制title
plt.xlabel('X1'); plt.ylabel('X2') #绘制label
plt.show()
if __name__ == '__main__':
dataMat, labelMat = loadDataSet()
weights = gradAscent(dataMat, labelMat)
plotBestFit(weights)
随机梯度上升:
梯度上升算在每次更新回归系数时都需要遍历整个数据集,一种改进方法是一次仅用一个样本点来更新回归系数,该方法称为 随机梯度上升算法。由于可以在新样本到来时对分类器进行增量式更新,因而随机梯度上升算法是一个在线学习算法。与“在线学习”相对应,一次处理所有数据被称作是“批处理”。
def stocGradAscent1(dataMatrix, classLabels, numIter=150):
m,n = np.shape(dataMatrix) #返回dataMatrix的大小。m为行数,n为列数。
weights = np.ones(n) #参数初始化
for j in range(numIter):
h = sigmoid(dataMatrix[i]*weights))
error = classLabels[i] - h
weights = weights + alpha * error * dataMatrix[i]
return weights
随机梯度上升算法与梯度上升算法在代码上很相似,但也有些区别:第一,后者的变量h和误差error都是向量,而前者则全是数值;第二,前者没有矩阵的转换过程,所有变量的数据类型都是Numpy数组。
# 函数说明:改进的随机梯度上升算法
#numIter为迭代次数
def stocGradAscent1(dataMatrix, classLabels, numIter=150):
m,n = np.shape(dataMatrix) #返回dataMatrix的大小。m为行数,n为列数。
weights = np.ones(n) #参数初始化
for j in range(numIter):
dataIndex = list(range(m))
for i in range(m):
alpha = 4/(1.0+j+i)+0.01 #降低alpha的大小,每次减小1/(j+i),但是alpha不会减小到0因为有常数项,当j<<max(i)时,alpha不是严格下降的
randIndex = int(random.uniform(0,len(dataIndex))) #随机选取样本更新回归系数
h = sigmoid(sum(dataMatrix[randIndex]*weights)) #选择随机选取的一个样本,计算h
error = classLabels[randIndex] - h #计算误差
weights = weights + alpha * error * dataMatrix[randIndex]#更新回归系数
del(dataIndex[randIndex]) #删除已经使用的样本
return weights
实例:从疝气病症预测病马的死亡率
1.准备数据:处理数据中的缺失值
所有缺失值用一个实数值替换,这里取0恰好适用于Logistic回归
如果在测试数据集中发现了一条数据的类别标签已经缺失,那么我们的简单做法是将该条数据丢弃,采用Logistic回归进行分类时这种做法是合理的,而如果采用类似kNN的方法就可能不太行
2.测试数据:用Logistic回归进行回归
from sklearn.linear_model import LogisticRegression
函数说明:使用Sklearn构建Logistic回归分类器
#打开训练集和训练集,并对数据进行格式化处理的函数
def colicSklearn():
frTrain = open('horseColicTraining.txt') #打开训练集
frTest = open('horseColicTest.txt') #打开测试集
trainingSet = []; trainingLabels = []
testSet = []; testLabels = []
for line in frTrain.readlines():
currLine = line.strip().split('\t')
lineArr = []
for i in range(len(currLine)-1):
lineArr.append(float(currLine[i]))
trainingSet.append(lineArr)
trainingLabels.append(float(currLine[-1]))
for line in frTest.readlines():
currLine = line.strip().split('\t')
lineArr =[]
for i in range(len(currLine)-1):
lineArr.append(float(currLine[i]))
testSet.append(lineArr)
testLabels.append(float(currLine[-1]))
classifier = LogisticRegression(solver='liblinear',max_iter=10).fit(trainingSet, trainingLabels)
test_accurcy = classifier.score(testSet, testLabels) * 100
print('正确率:%f%%' % test_accurcy)
if __name__ == '__main__':
colicSklearn()