代碼及數據: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() #真實數據集上測試