Sigmoid函數
我們想定義一個函數,即能夠接受所有特徵輸入(自變量)然後預測出類別(因變量)。在二分類的情況下,可以定義輸出爲0和1。比如要預測一個動物是不是鳥類,是則爲1,不是則爲0。具有這種性質的函數,比較簡單的就是單位階躍函數(Heaviside step function)。但是該函數在處從0瞬間跳變到1,這樣就很難處理。換句話講,階躍函數在處不可微,這就不利於後面使用梯度上升或下降的方法。此時另一個函數就滿足類似的性質,即可以輸出0或1,這就是Sigmoid函數,如下
如圖5-1,當時,Sigmoid函數值爲0.5,隨着增大,對應的值將逼近於1;而隨着減小,Sigmoid值將逼近於0。如果橫座標刻度足夠大,如圖5-1下圖,Sigmoid函數看起來就很像一個階躍函數。
Logistic迴歸
而Logistic迴歸就是上面Sigmoid函數的輸入定義爲以下形式:
其中是輸入的特徵即自變量,就是特徵對應的權重,或者叫迴歸係數,而通常是偏移量設爲1,上面公式可以簡寫爲:
即Logistic迴歸的模型,剩下的我們只需要求出參數和。
梯度上升法
怎麼求出參數和呢?書中給出了梯度上升法,隨機梯度上升以及改進的隨機梯度上升,梯度上升跟下降類似,只不過前者就局部最大值,後者求的是最小值。原理的雛形可結合導數與極值的關係,比較容易理解,參考:
隨機梯度下降(Stochastic gradient descent)和 批量梯度下降(Batch gradient descent )的公式對比、實現對比
需要理解批量梯度,也就是書中給出了第一種梯度上升,以及mini-batch梯度下降,和隨機梯度下降,簡單來講就是隨機梯度一次僅用一個樣本點來更新迴歸係數,mini-batch使用一小部分,批量梯度則是全部,這樣的話訓練速度更新會很慢,所以隨機梯度比較流行。並且隨機梯度是一個在線算法,可以在新數據到來時就完成參數更新,而不需要重新讀取整個數據集來進行批處理運算。
代碼
以下是基於梯度上升的Logistic迴歸算法,其中alpha就是機器學習中常講的學習率,也就是機器學習實戰這本書所講的步長。
import numpy as np
def sigmoid(inX):
'''sigmoid函數
'''
return 1.0/(1+np.exp(-inX))
def gradAscent(dataMat,labelMat):
'''批量梯度上升
'''
dataMat=np.mat(dataMat)
labelMat=np.mat(labelMat).transpose()
m,n=np.shape(dataMat) # m cannot be deleted
alpha=0.001
maxCycles=500
weights=np.ones((n,1)) #weights[3*1]
for k in range(maxCycles):
h=sigmoid(dataMat*weights)
error=(labelMat-h) #error[100*1]
weights=weights+alpha*dataMat.transpose()*error
print(weights)
return weights
def stocGradAscent0(dataMat,labelMat):
'''隨機梯度上升
'''
m,n=np.shape(dataMat) #dataMat[100*3]
alpha=0.01
weights=np.ones(n) #weights[1*3]
dataArr=np.array(dataMat)
for i in range(m):
h=sigmoid(sum(dataMat[i]*weights)) # dataMat[i]表示一個樣本
error=labelMat[i]-h
weights=weights+alpha*error*dataArr[i]
return weights
def stocGradAscent1(dataMat,labelMat,iteration=150):
'''改進的隨機梯度上升
'''
m,n=np.shape(dataMat)
weights=np.ones(n)
dataArr=np.array(dataMat)
for j in range(iteration):
dataIndex=dataMat.copy() # initially dataIndex=range(m),but a range cannot be operated by del() at line 75
for i in range(m):
alpha=4/(1.0+j+i)+0.01 #apha decreases with iteration, does not
randIndex=int(np.random.uniform(0,len(dataIndex))) #go to 0 because of the constant
h=sigmoid(sum(dataMat[randIndex]*weights))
error=labelMat[randIndex]-h
weights=weights+alpha*error*dataArr[randIndex]
del(dataIndex[randIndex])
return weights
def classifyVector(inX,weights):
prob=sigmoid(sum(inX*weights))
if prob>0.5: return 1.0
else: return 0.0
相關問題
以下問題提供思考:
- Logistic迴歸與多重線性迴歸的區別?