机器学习实战python3 Logistic Regression
代码及数据:https://github.com/zle1992/MachineLearningInAction
logistic regression
优点:计算代价不高,易于理解实现,线性模型的一种。
缺点:容易欠拟合,分类精度不高。但是可以用于预测概率。
适用数据范围:数值型和标称型。
准备数据:
1 def loadDataSet(): 2 dataMat,labelMat = [],[] 3 with open(filename,"r") as fr: #open file 4 for line in fr.readlines(): 5 lineArr = line.split() #split each line 6 dataMat.append([1.0,float(lineArr[0]),float(lineArr[1])]) #创建2维list 7 labelMat.append(int(lineArr[2])) 8 return dataMat,labelMat
1 基于Logistic回归和Sigmoid函数的分类
Sigmoid函数:
1 def sigmoid(inX): 2 return 1.0/(1+np.exp(-inX))
2基于最优化方法的最佳回归系数确定
梯度上升法:
梯度上升法的伪代码如下:
每个回归系数初始化为1
重复R次:
计算整个数据集的梯度
使用alpha x gradient更新回归系数的向量
返回回归系数
代码:
1 def sigmoid(inX): 2 return 1.0/(1+np.exp(-inX)) 3 4 def gradAscent(dataMat,labelMat): 5 dataMatrix = np.mat(dataMat) #translate list to matrix 6 labelMatrix = np.mat(labelMat).transpose() #转置 7 m,n = np.shape(dataMatrix) #100 rows 3 coulums 8 alpha = 0.001 #步长 or 学习率 9 maxCyclse = 500 10 weight = np.ones((n,1)) #初始值随机更好吧 11 #weight = np.random.rand(n,1) 12 for k in range(maxCyclse): 13 h = sigmoid(dataMatrix * weight) # h 是向量 14 error = (labelMatrix - h) #error 向量 15 weight = weight + alpha * dataMatrix.transpose() *error #更新 16 # print(k," ",weight) 17 return weight
3分析数据:画出决策边界
1 def plotfit(wei): 2 import matplotlib.pyplot as plt 3 weight = np.array(wei) #???????? #return array 4 dataMat ,labelMat = loadDataSet() 5 dataArr = np.array(dataMat) 6 n = np.shape(dataArr)[0] #row 7 fig = plt.figure() #plot 8 ax = fig.add_subplot(111) 9 ax.scatter(dataArr[:,1],dataArr[:,2],s =50, c = np.array(labelMat)+5) #散点图 #参考KNN 的画图 10 x = np.arange(-3.0,3.0,0.1) #画拟合图像 11 y = (-weight[0] - weight[1] *x ) / weight[2] 12 ax.plot(x,y) 13 plt.xlabel("x1") 14 plt.ylabel("x2") 15 plt.show()
4训练算法:随机梯度上升
伪代码:
所有回归系数初始化为1
对数据集中每个样本
计算该样本的梯度
使用alpha x gradient更新回归系数值
返回回归系数值
原始梯度上升计算数据集的梯度,涉及的是矩阵运算。h,error都是向量
随机梯度算法计算的是数据集中每个样本的梯度,s计算量减小,h,error都是数值
1 ef stocGradAscent0(dataMatrix,labelMatrix): 2 m,n = np.shape(dataMatrix) 3 alpha = 0.1 4 weight = np.ones(n) 5 for i in range(m): 6 h = sigmoid(sum(dataMatrix * weight)) 7 error = labelMatrix[i] - h 8 weight = weight + alpha * error * dataMatrix[i] 9 return weight
上面的算法是固定的步长,固定的步长,不稳定,会产生震荡,所以下面的算法采用不固定的步长。
距离目标值远的时候,步长大,距离目标值近的时候,步长小。
1 def stocGradAscent1(dataMat,labelMat,numIter = 150): 2 dataMatrix = np.mat(dataMat) #translate list to matrix 3 labelMatrix = np.mat(labelMat).transpose() #转置 4 m,n = np.shape(dataMat) 5 alpha = 0.1 6 weight = np.ones(n) #float 7 #weight = np.random.rand(n) 8 for j in range(numIter): 9 dataIndex = list(range(m)) #range 没有del 这个函数 所以转成list del 见本函数倒数第二行 10 for i in range(m): 11 alpha = 4/(1.0 +j + i) + 0.01 12 randIndex = int(np.random.uniform(0,len(dataIndex))) #random.uniform(0,5) 生成0-5之间的随机数 13 #生成随机的样本来更新权重。 14 h = sigmoid(sum(dataMat[randIndex] * weight)) 15 error = labelMat[randIndex] - h 16 weight = weight + alpha * error * np.array(dataMat[randIndex]) #!!!!一定要转成array才行 17 #dataMat[randIndex] 原来是list list *2 是在原来的基础上长度变为原来2倍, 18 del(dataIndex[randIndex]) #从随机list中删除这个 19 return weight
5从病气病症预测病马的死亡率
1 def classifyVector(inX,weight): #输入测试带测试的向量 返回类别 2 prob = sigmoid(sum(inX * weight)) 3 if prob > 0.5 : 4 return 1.0 5 else: return 0.0 6 def colicTest(): 7 trainingSet ,trainingSetlabels =[],[] 8 with open("horseColicTraining.txt") as frTrain: 9 for lines in frTrain.readlines(): 10 currtline = lines.strip().split('\t') # strip()remove the last string('/n') in everyline 11 linearr = [] #每行临时保存str 转换float的list 12 for i in range(21): #将读进来的每行的前21个str 转换为float 13 linearr.append(float(currtline[i])) 14 trainingSet.append(linearr) #tianset 是2维的list 15 trainingSetlabels.append(float(currtline[21]))#第22个是类别 16 trainWeights = stocGradAscent1(trainingSet,trainingSetlabels,500) 17 errorCount = 0 18 numTestVec = 0.0 19 with open("horseColicTest.txt") as frTrain: 20 for lines in frTrain.readlines(): 21 numTestVec += 1.0 22 currtline = lines.strip().split('\t') # strip()remove the last string('/n') in everyline 23 linearr = [] #测试集的每一行 24 for i in range(21): 25 linearr.append(float(currtline[i]))#转换为float 26 if int(classifyVector(np.array(linearr),trainWeights)) != int(currtline[21]) : 27 errorCount += 1 #输入带分类的向量,输出类别,类别不对,errorCount ++ 28 errorRate = float(errorCount)/numTestVec 29 print("the error rate of this test is : %f"%errorRate) 30 return errorRate 31 def multiTest(): #所有测试集的错误率 32 numTests = 10 33 errorSum = 0.0 34 for k in range(numTests): 35 errorSum +=colicTest() 36 print("after %d iterations the average error rate is : %f" %(numTests,errorSum/float(numTests)))
主函数:
1 if __name__ == '__main__': 2 filename = "testSet.txt" 3 dataMat,labelMat = loadDataSet() 4 #weight = gradAscent(dataMat,labelMat) 5 weight = stocGradAscent1(dataMat,labelMat) 6 print(weight) 7 plotfit(weight)#画分类图像在小数据集上 8 multiTest() #真实数据集上测试