機器學習–邏輯斯谛回歸(Logistic Regression)
基本概念
邏輯斯谛回歸(Logistic Regression)雖然帶回歸,卻是經典的分類方法。邏輯斯谛回歸模型屬于對數線性模型。它線上性模型的基礎上,使用 Sigmoid 函數,将線性模型的結果映射到 [0, 1] 之間,實作了具體值到機率的轉換。
線性回歸:
f ( x ) = w T x + b f(x)=w^Tx + b f(x)=wTx+b
Sigmoid:
S ( x ) = 1 1 + e − x S(x) = \frac{1}{1 + e^{-x}} S(x)=1+e−x1
l邏輯斯谛回歸:
f ( x ) = S ( w T x ) = 1 1 + e − w T x + b f(x)=S(w^Tx)=\frac{1}{1+e^{-w^Tx +b}} f(x)=S(wTx)=1+e−wTx+b1
邏輯斯谛分布
設 X X X 是連續随機變量,當 X X X 服從邏輯斯谛分布時, X X X 的分布函數和密度函數可以表示為(《統計機器學習》):
F ( x ) = P ( X ≤ x ) = 1 1 + e − ( x − μ ) / γ F(x)=P(X\le x)=\frac{1}{1 + e^{-(x-\mu)/ \gamma}} F(x)=P(X≤x)=1+e−(x−μ)/γ1
f ( x ) = F ′ ( x ) = e − ( x − μ ) / γ γ ( 1 + e − ( x − μ ) / γ ) 2 f(x)=F^{'}(x)=\frac{e^{-(x-\mu)/\gamma}}{\gamma(1+e^{-(x-\mu)/\gamma})^2} f(x)=F′(x)=γ(1+e−(x−μ)/γ)2e−(x−μ)/γ
其中, μ \mu μ 為位置參數, γ > 0 \gamma > 0 γ>0 為形狀參數。
二項邏輯斯谛回歸
二項邏輯斯谛回歸模型(binomial logistic regression model)是一種分類模型。并且分類結果隻有0和1兩種。
P ( Y = 1 ∣ x ) = e w T x + b 1 + e w T x + b P(Y=1|x)=\frac{e^{w^Tx + b}}{1+e^{w^Tx + b}} P(Y=1∣x)=1+ewTx+bewTx+b
P ( Y = 0 ∣ x ) = 1 1 + e w T x + b P(Y=0|x)=\frac{1}{1+e^{w^Tx + b}} P(Y=0∣x)=1+ewTx+b1
在求得兩個機率之後,邏輯斯谛回歸模型比較這兩個條件機率值的大小,将執行個體 x x x 分到機率值較大的那一類。
邏輯斯谛回歸模型的特點:一個事件的幾率是指該事件發生的機率與該時間不發生的機率的比值。對于邏輯斯谛回歸而言, P ( Y = 1 ∣ x ) P(Y=1|x) P(Y=1∣x) 發生的對數幾率是:
l o g P ( Y = 1 ∣ x ) 1 − P ( Y = 1 ∣ x ) = w T x + b log\frac{P(Y=1|x)}{1-P(Y=1|x)}=w^Tx+b log1−P(Y=1∣x)P(Y=1∣x)=wTx+b
這表明,在邏輯斯谛回歸模型中,輸出 Y = 1 的對數幾率是輸入 x x x 的線性函數。另一種說法是,輸出 Y = 1 的對數幾率是由輸入的線性函數表示的模型,即邏輯斯谛回歸模型。
代價函數
如果我們使用線性回歸中的代價函數進行梯度下降法計算,有可能得到局部最優解,無法求得最優的參數值,是以我們使用極大似然估計 求得代價函數。
我們以二分類為例(二項邏輯斯谛回歸)。
令:
P ( Y = 1 ∣ x ) = π ( x ) , P ( Y = 0 ∣ x ) = 1 − π ( x ) P(Y=1|x)=\pi(x),\ P(Y=0|x)=1-\pi(x) P(Y=1∣x)=π(x), P(Y=0∣x)=1−π(x)
可以得到似然函數為:
∏ i = 1 N [ π ( x i ) ] y i [ 1 − π ( x i ) ] 1 − y i \prod_{i=1}^N[\pi(x_i)]^{y_i}[1-\pi(x_i)]^{1-y_i} i=1∏N[π(xi)]yi[1−π(xi)]1−yi
取對數
L ( w ) = ∑ i = 1 N [ y i l o g π ( x i ) + ( 1 − y i ) l o g ( 1 − π ( x i ) ) ] = ∑ i = 1 N [ y i l o g π ( x i ) 1 − π ( x i ) + l o g ( 1 − π ( x i ) ) ] = ∑ i = 1 N [ y i ( w T x i + b ) − l o g ( 1 + e w T x i + b ) ] L(w)=\sum_{i=1}^N[y_i log \pi(x_i) + (1-y_i)log(1-\pi(x_i))] \\ \ \ \ \ =\sum_{i=1}^N [y_ilog\frac{\pi(x_i)}{1-\pi(x_i)}+log(1-\pi(x_i))]\\ =\sum_{i=1}^N[y_i(w^T x_i+b)-log(1+e^{w^Tx_i+b})] \ \ \ \ \ \ \ L(w)=i=1∑N[yilogπ(xi)+(1−yi)log(1−π(xi))] =i=1∑N[yilog1−π(xi)π(xi)+log(1−π(xi))]=i=1∑N[yi(wTxi+b)−log(1+ewTxi+b)]
對 L ( w ) L(w) L(w) 求極大值,得到 w w w 的估計值。
令代價函數為
J ( w ) = − L ( w ) J(w)=-L(w) J(w)=−L(w)
接下來用梯度下降法或牛頓法來求解參數。我們先求出偏導數 ∂ J ( w ) ∂ w \frac{\partial J(w)}{\partial w} ∂w∂J(w) 和 ∂ J ( w ) ∂ b \frac{\partial J(w)}{\partial b} ∂b∂J(w):
∂ J ( w ) ∂ w = 1 N x i ( w T x i + b − y i ) \frac{\partial J(w)}{\partial w}=\frac{1}{N}x_i(w^Tx_i+b-y_i) ∂w∂J(w)=N1xi(wTxi+b−yi)
∂ J ( w ) ∂ b = 1 N ∑ i = 1 N ( w T x i + b − y i ) \frac{\partial J(w)}{\partial b}=\frac{1}{N}\sum_{i=1}^N(w^Tx_i+b-y_i) ∂b∂J(w)=N1i=1∑N(wTxi+b−yi)
在求得偏導數之後,我們對參數進行疊代更新
w = w − l r ∗ ∂ J ( w ) ∂ w w=w-lr*\frac{\partial J(w)}{\partial w} w=w−lr∗∂w∂J(w)
b = b − l r ∗ ∂ J ( w ) ∂ b b=b-lr*\frac{\partial J(w)}{\partial b} b=b−lr∗∂b∂J(w)
經過多次疊代後,我們的模型能學習到一個很好的參數。
執行個體
# coding=utf-8
from sklearn.datasets import make_classification
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
import matplotlib.pyplot as plt
def load_data():
X, y = make_classification(n_samples=10000, n_features=10, n_redundant=3, n_informative=3, n_classes=2,
n_clusters_per_class=1, random_state=42)
return X, y
class LogisticRegression:
def __init__(self, lr=0.01, epoch=1000):
# 學習率
self.lr = lr
# 疊代次數
self.epochNum = epoch
self.train_loss = []
# 定義 sigmoid 函數
def sigmoid(self, z):
return 1 / (1 + np.exp(-z))
# 用來計算梯度 dw 和 db
def gradient(self, X, y):
h = self.sigmoid(np.dot(X, self.w) + self.b)
dw = np.dot(X.T, (h - y)) / X.shape[0]
db = np.sum(h - y) / X.shape[0]
return dw, db
# 計算損失
def loss(self, X, y):
m = len(y)
h = self.sigmoid(np.dot(X, self.w) + self.b)
# 參考公式
cost = (-1 / m) * (np.dot(y.T, np.log(h)) + np.dot((1 - y).T, np.log(1 - h)))
cost = cost.squeeze()
# 帶有 L2 正則化項
reg = (self.lr / 2) * np.sum(np.dot(self.w.T, self.w))
return cost + reg
# 拟合函數
def fit(self, X, y):
# 輸入要為二維,将标簽增維
y = y.reshape(-1, 1)
# 初始化參數 w 和 b
self.w = np.zeros((X.shape[1], 1))
self.b = np.zeros((X.shape[0], 1))
for epoch in range(self.epochNum):
# 計算損失和梯度
loss = self.loss(X, y)
dw, db = self.gradient(X, y)
# 更新參數 w 和 b
self.w = self.w - self.lr * dw
self.b = self.b - self.lr * db
self.train_loss.append(loss)
def show_parameters(self):
print('w:', self.w)
def predict(self, x_test):
prediction =self.sigmoid(np.dot(x_test, self.w))
prediction = prediction > 0.5
prediction = prediction.astype(int)
return prediction
# 繪圖
def plot_loss(self):
plt.figure()
plt.plot(range(len(self.train_loss)), self.train_loss, 'r')
plt.title("Convergence Graph")
plt.xlabel("Epochs")
plt.ylabel("Train Loss")
plt.show()
if __name__ == '__main__':
X, y = load_data()
x_train, x_test, y_train, y_test = train_test_split(X, y, test_size=0.3)
model = LogisticRegression()
model.fit(x_train, y_train)
model.plot_loss()
pre = model.predict(x_test)
acc = accuracy_score(y_test, pre)
print(acc)
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiI2EzX4xSZz91ZsAzNfRHLGZkRGZkRfJ3bs92YsYTMfVmepNHL90zdaVHbXNmb1cVY4VzVZlnVINVQClGVF5UMR9Fd4VGdsATNfd3bkFGazxSUhxGatJGbwhFT1Y0Mk9VZwlHdssmch1mclRXY39CXldWYtlWPzNXZj9mcw1ycz9WL49zZuBnLkljZiBzYyY2NiJDM3UmMhJDMiRzN4Q2Y4IDOzkzNyQ2Lc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)