01 logisitic回歸與梯度下降法
logisitic回歸是因變量是分類的回歸模型或算法,它實際上是一種分類方法础淤,主要用于兩分類問題(即輸出只有兩種,分別代表兩個類別),所以利用了Logistic函數(shù)(或稱為Sigmoid函數(shù))罐盔,函數(shù)形式為:
Paste_Image.png
z={\theta }_{0}{x }_{0}+{\theta }_{1}{x }_{1}+...+{\theta }_{n}{x }_{n}
Z={\Theta}^{T}X
梯度下降法則是一種最優(yōu)化算法壁熄,它是用迭代的方法求解目標(biāo)函數(shù)得到最優(yōu)解帚豪,是在最小二乘法cost function(成本函數(shù))的基礎(chǔ)上,利用梯度迭代求出局部最優(yōu)解草丧。在這里關(guān)于梯度下降法不做過多介紹狸臣,相關(guān)資料已經(jīng)很多且后邊還會分析,對其的理解借用一位網(wǎng)友的描述吧:
梯度下降法被比喻成一種方法昌执,一個人蒙著眼睛去找從山坡到溪谷最深處的路烛亦。 他看不到地形圖,所以只能沿著最陡峭的方向一步一步往前走懂拾。每一步的大忻呵荨(也就是梯度)與地勢陡峭的程度成正比。 如果地勢很陡峭岖赋,他就走一大步檬果,因為他相信他仍在高出,還沒有錯過溪谷的最低點唐断。如果地勢比較平坦选脊,他就走一小步。這時如果再走大步脸甘,可能會與最低點失之交臂恳啥。 如果真那樣,他就需要改變方向丹诀,重新朝著溪谷的最低點前進钝的。 他就這樣一步一步的走啊走,直到有一個點走不動了铆遭,因為路是平的了硝桩,于是他卸下眼罩,已經(jīng)到了谷底深處疚脐。
02 用梯度下降法求解logisitic回歸
用梯度下降法求解logisitic回歸的步驟為:
(1)構(gòu)建損失函數(shù)
預(yù)測函數(shù)為:
注:在這里為什么加了個系數(shù)-1/m痕支,編者翻閱了相關(guān)資料颁虐,因為不加的話,說是不能用梯度下降法(而是梯度上升法)卧须,所以要加負(fù)號另绩,而1/m代表了樣本平均。
最終得到:
采用與線性回歸中一樣的梯度下降法來確定θ的值花嘶,即設(shè)置一個合適的學(xué)習(xí)率α之后笋籽,同步更新所有j=1 to n:
03 python代碼的實現(xiàn)
在這里采用了python2.7 版本车海,并分為兩大步驟:構(gòu)建梯度下降法函數(shù)與創(chuàng)建數(shù)據(jù)函數(shù)。而經(jīng)過上面的推導(dǎo)隘击,對我們編程最有用的不是那些過程侍芝,而是得到的結(jié)果,即最后一個公式埋同,因此州叠,將圍繞最后得到的梯度下降法求解公式來構(gòu)建函數(shù)。
-*- coding: UTF-8 -*-
import numpy as np #科學(xué)計算(矩陣)包
import random #生成隨機數(shù)的包
#梯度下降算法函數(shù),x/y是輸入變量凶赁,theta是參數(shù)咧栗,alpha是學(xué)習(xí)率,m是實例哟冬,numIterations梯度下降迭代次數(shù)
def gradientDescent(x, y, theta, alpha, m, numIterations):
xTrans = x.transpose() #矩陣轉(zhuǎn)置
#在1-numIterations之間for循環(huán)
for i in range(0,numIterations):
hypothesis = np.dot(x,theta) #矩陣相乘
loss = hypothesis - y #預(yù)測值減去實際值
# avg cost per example (the 2 in 2*m doesn't really matter here.
# But to be consistent with the gradient, I include it)
cost = np.sum(loss **2)/(2 * m)
#成本函數(shù):loss方差的平均加總楼熄,在這里采用了常用的成本函數(shù),而非logistic特有的
print("Iteration %d | Cost: %f" % (i, cost))
# avg gradient per example
gradient = np.dot(xTrans, loss) / m #計算梯度
# update
theta = theta - alpha * gradient #參數(shù)theta的計算浩峡,即更新法則
return theta
#創(chuàng)建數(shù)據(jù)可岂,numPoints實例數(shù),bias加一些偏倚或偏差翰灾,variance:方差
def genData(numPoints,bias,variance):
x = np.zeros(shape=(numPoints,2)) #生成0矩陣缕粹,shape表示矩陣的形狀,參數(shù)1是行纸淮,后邊是列
y = np.zeros(shape=(numPoints))
#對x平斩、y的0矩陣填充數(shù)值
for i in range(0,numPoints):
x[i][0] = 1 #第i行第1列全部等于1
x[i][1] = i # 第i行第2列等于i
y[i] = (i + bias) + random.uniform(0,1) * variance # 第i行第2列等于i+bias(偏倚),再加,0-1的隨機數(shù)咽块,以及方差
return x, y
x, y = genData(100, 25, 10) #傳入?yún)?shù)
print "x:"
print x
print "y:"
print y
m, n = np.shape(x) #檢查x的行列數(shù)绘面,是否一致
numIterations = 100000
alpha = 0.0005 #學(xué)習(xí)率,不能太大也不能太小
theta = np.ones(n) #初始化
theta = gradientDescent(x, y, theta, alpha, m, numIterations)
print(theta)
可以根據(jù)不同的數(shù)據(jù),利用gradientDescent()函數(shù)來求解揭璃。