機器學習之邏輯回歸 純python實現

2021-09-11 15:12:19 字數 4477 閱讀 3213

logistic回歸是一種廣義的線性回歸,通過構造回歸函式,利用機器學習來實現分類或者**。

上一文簡單介紹了線性回歸,與邏輯回歸的原理是類似的。

**函式(h)。該函式就是分類函式,用來**輸入資料的判斷結果。過程非常關鍵,需要**函式的「大概形式」, 比如是線性還是非線性的。 本文參考機器學習實戰的相應部分,看一下資料集。

// 兩個特徵

-0.017612 14.053064 0

-1.395634 4.662541 1

-0.752157 6.538620 0

-1.322371 7.152853 0

0.423363 11.054677 0

0.406704 7.067335 1

複製**

如上圖,紅綠代表兩種不同的分類。可以**分類函式大概是一條直線。

cost函式(損失函式):該函式**的輸出h和訓練資料類別y之間的偏差,(h-y)或者其他形式。綜合考慮所有訓練資料的cost, 將其求和或者求平均,極為j函式, 表示所有訓練資料**值和實際值的偏差。

顯然,j函式的值越小,表示**的函式越準確(即h函式越準確),因此需要找到j函式的最小值。有時需要用到梯度下降。

構造**函式

邏輯回歸名為回歸,實際為分類,用於兩分類問題。 這裡直接給出sigmoid函式。

接下來確定分類的邊界,上面有提到,該資料集需要乙個線性的邊界。 不同資料需要不同的邊界。

確定了分類函式,將其輸入記做z ,那麼

向量x是特徵變數, 是輸入資料。此資料有兩個特徵,可以表示為z = w0x0 + w1x1 + w2x2。w0是常數項,需要構造x0等於1(見後面**)。 向量w是回歸係數特徵,t表示為列向量。 之後就是確定最佳回歸係數w(w0, w1, w2)。

cost函式

綜合以上,**函式為:

這裡不做推導,可以參考文章

logistic回歸總結

有了上述的cost函式,可以使用梯度上公升法求函式j的最小值。推導見上述鏈結。

綜上:梯度更新公式如下:

接下來是python**實現:

# sigmoid函式和初始化資料

def sigmoid(z):

return 1 / (1 + np.exp(-z))

def init_data():

data = np.loadtxt('data.csv')

datamatin = data[:, 0:-1]

classlabels = data[:, -1]

datamatin = np.insert(datamatin, 0, 1, axis=1) #特徵資料集,新增1是構造常數項x0

return datamatin, classlabels

複製**

//  梯度上公升

def grad_descent(datamatin, classlabels):

datamatrix = np.mat(datamatin) #(m,n)

labelmat = np.mat(classlabels).transpose()

m, n = np.shape(datamatrix)

weights = np.ones((n, 1)) #初始化回歸係數(n, 1)

alpha = 0.001 #步長

maxcycle = 500 #最大迴圈次數

for i in range(maxcycle):

h = sigmoid(datamatrix * weights) #sigmoid 函式

weights = weights + alpha * datamatrix.transpose() * (labelmat - h) #梯度

return weights

複製**

// 計算結果

if __name__ == '__main__':

datamatin, classlabels = init_data()

r = grad_descent(datamatin, classlabels)

print(r)

複製**

輸入如下:

[[ 4.12414349]

[ 0.48007329]

[-0.6168482 ]]

複製**

上述w就是所求的回歸係數。w0 = 4.12414349, w1 = 0.4800, w2=-0.6168 之前**的直線方程0 = w0x0 + w1x1 + w2x2, 帶入回歸係數,可以確定邊界。 x2 = (-w0 - w1*x1) / w2

畫出函式影象:

def plotbestfit(weights):

datamatin, classlabels = init_data()

n = np.shape(datamatin)[0]

xcord1 =

ycord1 =

xcord2 =

ycord2 =

for i in range(n):

if classlabels[i] == 1:

else:

fig = plt.figure()

ax = fig.add_subplot(111)

ax.scatter(xcord1, ycord1,s=30, c='red', marker='s')

ax.scatter(xcord2, ycord2, s=30, c='green')

x = np.arange(-3, 3, 0.1)

y = (-weights[0, 0] - weights[1, 0] * x) / weights[2, 0] #matix

ax.plot(x, y)

plt.xlabel('x1')

plt.ylabel('x2')

plt.show()

複製**

如下:

隨機梯度上公升

上述演算法中,每次迴圈矩陣都會進行m * n次乘法計算,時間複雜度是maxcycles* m * n。當資料量很大時, 時間複雜度是很大。 這裡嘗試使用隨機梯度上公升法來進行改進。隨機梯度上公升法的思想是,每次只使用乙個資料樣本點來更新回歸係數。這樣就大大減小計算開銷。演算法如下:

def stoc_grad_ascent(datamatin, classlabels):

m, n = np.shape(datamatin)

alpha = 0.01

weights = np.ones(n)

for i in range(m):

h = sigmoid(sum(datamatin[i] * weights)) #數值計算

error = classlabels[i] - h

weights = weights + alpha * error * datamatin[i]

return weights

複製**

進行測試:

隨機梯度上公升的改進

def stoc_grad_ascent_one(datamatin, classlabels, numiter=150):

m, n = np.shape(datamatin)

weights = np.ones(n)

for j in range(numiter):

dataindex = list(range(m))

for i in range(m):

alpha = 4 / (1 + i + j) + 0.01 #保證多次迭代後新資料仍然有影響力

randindex = int(np.random.uniform(0, len(dataindex)))

h = sigmoid(sum(datamatin[i] * weights)) # 數值計算

error = classlabels[i] - h

weights = weights + alpha * error * datamatin[i]

del(dataindex[randindex])

return weights

複製**

可以對上述三種情況的回歸係數做個波**。 可以發現第三種方法收斂更快。評價演算法優劣勢看它是或否收斂,是否達到穩定值,收斂越快,演算法越優。

這裡用到的梯度上公升和梯度下降是一樣的,都是求函式的最值, 符號需要變一下。 梯度意味著分別沿著x, y的方向移動一段距離。(cost分別對x, y)的導數。

完整**請檢視: github: logistic regression

參考文章: 機器學習之logistic回歸與python實現

機器學習筆記:logistic回歸總結

機器學習基本演算法系列之邏輯回歸

機器學習之邏輯回歸

什麼叫邏輯回歸?簡單來講便是目標值只有,而線性回歸的目標值卻是乙個區域 0,1 可以代表得病沒得病,正確錯誤,etc.那麼怎麼才能把給定的輸入值正確的分類到呢,下面就介紹乙個特別的函式 sigmoid函式,g z 1 1 exp z 啥都不說先上圖。上圖便是sigmoid函式圖了,之所以引用這個函式...

機器學習之 邏輯回歸

邏輯回歸又稱logistic回歸,邏輯斯諦回歸,是一種廣義的線性回歸分析模型。sigmoid函式也是神經網路中常用的函式,用於把x從負無窮到正無窮壓縮到y從0到1之間。畫出來就是一條s型曲線,如下圖中的藍色曲線 它以0點為中心對稱,公式如下 當x值接近負無窮時,分母很大,s x 接近0,當x接近正無...

機器學習之邏輯回歸

邏輯回歸 logistic regression 最初是為了解決二分類問題。對於線性模型要想進行如二分類任務,最簡單的辦法就是通過階躍函式 unit step function 即將線性模型的輸出值套上乙個函式進行分割,大於z的判定為0,小於z的判定為1。如下圖左所示 但這有個問題是,分段函式不連續...