邏輯回歸(Logistic Regression)是一種用于分類(lèi)問(wèn)題的算法。
建立一個(gè)Logistic Regression模型,需要以下三部分工作:
- 構(gòu)造預(yù)測(cè)函數(shù)
- 構(gòu)建損失函數(shù)
- 最小化損失函數(shù),求解θ
1.構(gòu)造預(yù)測(cè)函數(shù)
邏輯回歸和線(xiàn)性回歸都是廣義的線(xiàn)性模型,而邏輯回歸的本質(zhì)就是由線(xiàn)性回歸變化而來(lái)的。這里簡(jiǎn)單介紹下線(xiàn)性回歸模型:

θ統(tǒng)稱(chēng)為模型的參數(shù),其中θ0為截距,θ1-θn是模型的系數(shù)。
線(xiàn)性回歸的任務(wù)就是構(gòu)造一個(gè)預(yù)測(cè)函數(shù)z來(lái)映射輸入的特征矩陣x和標(biāo)簽y的線(xiàn)性關(guān)系,而構(gòu)造預(yù)測(cè)函數(shù)的核心就是找出模型的參數(shù)θ,線(xiàn)性回歸模型通常用最小二乘法來(lái)求解參數(shù)。
但是在二分類(lèi)問(wèn)題中,我們想要函數(shù)輸出0或1,那么就需要用到聯(lián)系函數(shù)(link function),將線(xiàn)性回歸方程z變換為g(z),并且使得g(z)的值分布在(0,1)之間,且當(dāng)g(z)接近0時(shí)樣本的標(biāo)簽為類(lèi)別0,當(dāng)g(z)接近1時(shí)樣本的標(biāo)簽為類(lèi)別1,這樣就得到了一個(gè)分類(lèi)模型。這個(gè)聯(lián)系函數(shù)對(duì)于邏輯回歸來(lái)說(shuō)就是Sigmoid函數(shù):


Sigmoid函數(shù)是一個(gè)S型的函數(shù),當(dāng)自變量z趨于正無(wú)窮時(shí),因變量g(z)趨近于1,當(dāng)自變量z趨于負(fù)無(wú)窮時(shí),g(z)趨近于0,它可以將任意實(shí)數(shù)映射到(0,1)區(qū)間。
通過(guò)將線(xiàn)性回歸模型與Sigmoid函數(shù)相結(jié)合,就可以得到邏輯回歸模型的一般形式:

其中,g(z)就是邏輯回歸返回的標(biāo)簽值,此時(shí)y(x)的取值都在(0,1)之間。令y(x)除以1-y(x)就得到了形似幾率odds(一個(gè)事件的odds指的是該事件發(fā)生的概率與不發(fā)生的概率之比),在此基礎(chǔ)上取對(duì)數(shù)可以得到:

從公式1-4可看出g(z)的形似幾率取對(duì)數(shù)的本質(zhì)就是線(xiàn)性回歸z,實(shí)際上我們是對(duì)線(xiàn)性回歸模型的預(yù)測(cè)結(jié)果取對(duì)數(shù)幾率來(lái)讓其結(jié)果無(wú)限逼近0和1。因此,這個(gè)模型也被稱(chēng)為“對(duì)數(shù)幾率回歸”(logistic regression),也就是邏輯回歸。
2.構(gòu)建損失函數(shù)
yθ(x)函數(shù)的值有特殊的含義,它表示預(yù)測(cè)結(jié)果為1的概率。因此對(duì)于輸入項(xiàng)x,預(yù)測(cè)分類(lèi)結(jié)果為1和0的概率分別為:


取似然函數(shù)為:

對(duì)數(shù)似然函數(shù)為:

最大似然函數(shù)就是求使l(θ)取最大值時(shí)的θ,這里可以通過(guò)梯度上升算法求解,得到的θ就是最佳參數(shù)。但是在Andrew Ng的課程中將損失函數(shù)J(θ)取為下式:

因?yàn)槌肆讼禂?shù)-1/m,所以使J(θ)取最小值的θ就為最佳參數(shù)。
3.最小化損失函數(shù),求解θ
使用梯度下降算法(Gradient descent)求解使得損失函數(shù)J(θ)取最小值的θ,由梯度下降算法可得θ的更新過(guò)程如下:

其中j表示樣本的第j個(gè)特征,α表示步長(zhǎng)(也稱(chēng)為學(xué)習(xí)率),后半部分對(duì)J(θ)的參數(shù)求偏導(dǎo)并以向量形式表示,就是損失函數(shù)的梯度。
對(duì)J(θ)求偏導(dǎo):

其中

所以θ的更新過(guò)程可以寫(xiě)成(i表示第i個(gè)樣本,j表示樣本的第j個(gè)特征,α表示步長(zhǎng)):

對(duì)該公式進(jìn)行迭代,直到收斂(J(θ)在每一步的迭代中都會(huì)減小,如果某一步J(θ)減小的值小于一個(gè)很小的值ε(例如0.001),則判定收斂)或者達(dá)到某個(gè)停止條件為止(比如達(dá)到指定的迭代次數(shù))
3.1 梯度下降算法的實(shí)例
3.1.1 單變量函數(shù)的梯度下降
假設(shè)單變量函數(shù)J(θ)=θ^2,J'(θ)=2θ即函數(shù)的梯度,初始化起點(diǎn)為θ0=1,步長(zhǎng)α為0.4,那么根據(jù)梯度下降的迭代公式進(jìn)行計(jì)算可得到:
θ0=1
θ1=θ0-αJ'(θ0)=1-0.42=0.2
θ2=θ1-αJ'(θ1)=0.2-0.40.4=0.04
θ3=θ2-αJ'(θ2)=0.04-0.40.08=0.008
θ4=θ3-αJ'(θ3)=0.008-0.40.016=0.0016
...
我們發(fā)現(xiàn)進(jìn)行了四次迭代,已經(jīng)接近函數(shù)的最小值點(diǎn)0了。
3.1.2 多變量函數(shù)的梯度下降
假設(shè)目標(biāo)函數(shù)為J(θ)= θ1^2 + θ2^2,通過(guò)梯度下降算法計(jì)算該函數(shù)的最小值。函數(shù)的梯度為<2θ1,2θ2>,假設(shè)初始起點(diǎn)為(1,3),初始化步長(zhǎng)為0.1,進(jìn)行迭代:
θ0=(1,3)
θ1=(1,3)-0.1(2,6)=(0.8,2.4)
θ2=(0.8,2.4)-0.1(0.16,4.8)=(0.64,1.92)
θ3=(0.64,1.92)-0.1*(1.28,3.84)=(0.512,1.536)
...
隨著迭代的不斷進(jìn)行,已經(jīng)越來(lái)越接近該函數(shù)的最小值點(diǎn)(0,0)了。
3.2 批量梯度下降法(Batch Gradient Descent)
批量梯度下降算法是梯度下降算法的最常用形式,即在更新參數(shù)時(shí)利用所有的樣本來(lái)進(jìn)行更新,上面公式3-4就是邏輯回歸的批量梯度下降算法,由于1/m是一個(gè)常量,α也是一個(gè)常量,所以可省略1/m,故參數(shù)的更新過(guò)程可寫(xiě)成:

由于有m個(gè)樣本,所以求梯度的時(shí)候就用了所有m個(gè)樣本的梯度數(shù)據(jù)。
此外,梯度下降算法還包括隨機(jī)梯度下降法(Stochastic Gradient Descent)、小批量梯度下降法(Mini-batch Gradient Descent),這里就不展開(kāi)了,下次再比較一下這幾個(gè)算法的區(qū)別吧。
4.邏輯回歸的代碼實(shí)現(xiàn)
接下來(lái)用python實(shí)現(xiàn)一個(gè)簡(jiǎn)單的邏輯回歸算法。
首先加載數(shù)據(jù):
def loaddata(filename):
dataSet = pd.read_table(filename, header=None)
dataSet.columns = ['X1', 'X2', 'label']
dataSet.insert(0, 'X0', 1) #增加常量列并賦值為1,對(duì)應(yīng)θ0
columns = [i for i in dataSet.columns if i != 'label']
data_x = dataSet[columns]
data_y = dataSet[['label']]
return data_x,data_y
構(gòu)造預(yù)測(cè)函數(shù)和損失函數(shù),最后利用批量梯度下降法求參數(shù)θ:
#sigmoid函數(shù)
def sigmoid(y):
s = 1.0/(1.0+np.exp(-y))
return s
def cost(xMat,weights,yMat):
m, n = xMat.shape
hypothesis = sigmoid(np.dot(xMat, weights)) # 預(yù)測(cè)值
cost = (-1.0 / m) * np.sum(yMat.T * np.log(hypothesis) + (1 - yMat).T * np.log(1 - hypothesis)) # 損失函數(shù)
return cost
def BGD_LR(data_x,data_y,alpha=0.1,maxepochs=10000,epsilon=0.0001):
xMat = np.mat(data_x)
yMat = np.mat(data_y)
m,n = xMat.shape
weights = np.ones((n,1)) #初始化模型參數(shù)
epochs_count = 0
while epochs_count < maxepochs:
loss = cost(xMat,weights,yMat)
hypothesis = sigmoid(np.dot(xMat,weights))
error = hypothesis -yMat #預(yù)測(cè)值與實(shí)際值誤差
print(loss)
grad = (1.0/m)*np.dot(xMat.T,error) #損失函數(shù)的梯度
last_weights = weights #上一輪迭代的參數(shù)
weights = weights - alpha*grad #參數(shù)更新
if (abs(cost(xMat, weights, yMat) - cost(xMat,last_weights,yMat))) < epsilon: #終止條件
break
epochs_count += 1
print('迭代到第{}次,結(jié)束迭代!'.format(epochs_count))
return weights
計(jì)算模型預(yù)測(cè)準(zhǔn)確率:
def acc(weights, test_x, test_y):
xMat_test = np.mat(test_x)
m, n = xMat_test.shape
result = []
for i in range(m):
proba = sigmoid(np.dot(xMat_test[i,:], weights))
if proba < 0.5:
preict = 0
else:
preict = 1
result.append(preict)
test_x_ = test_x.copy()
test_x_['predict'] = result
acc = (test_x_['predict']==test_y['label']).mean()
return acc

當(dāng)設(shè)置步長(zhǎng)為0.1,損失精度為0.0001時(shí),最終當(dāng)?shù)恋?71次時(shí),損失精度已經(jīng)小于0.0001了,訓(xùn)練集的準(zhǔn)確率達(dá)到了0.96。至此,一個(gè)簡(jiǎn)單的邏輯回歸模型就完成了~
本文代碼地址:https://github.com/DaHuangTyro/Daily_Machine_Learning
參考
https://blog.csdn.net/xiaoxiangzi222/article/details/55097570
http://www.itdecent.cn/p/c7e642877b0e