深入解析:【機器學習學習筆記】邏輯回歸實現與應用
零基礎入門邏輯回歸:從原理到實戰
邏輯回歸是機器學習里超基礎、超常用的分類方法(劃重點!它不是回歸方法),比如判斷郵件是不是垃圾郵件、用戶會不會點擊廣告,都能用它解決。下面用大白話拆解它的核心邏輯和實戰步驟,零基礎也能看懂。
一、先搞懂:為什么需要邏輯回歸?(從線性回歸的 “缺點” 說起)
我們先從熟悉的 “線性回歸” 入手,看看它處理分類問題時的不足 —— 這也是邏輯回歸存在的意義。
1. 一個簡單的分類問題
比如用 “學習時長” 判斷 “是否通過考試”:
- 特征(輸入):學習時長(1 小時、2 小時…10 小時)
- 標簽(輸出):是否通過(0 = 不通過,1 = 通過)
這是典型的 “二分類問題”(結果只有 2 種)。
2. 試試用線性回歸解決?
線性回歸的核心是 “擬合一條直線”,比如用直線 y = 系數×時長 + 截距 預測結果。我們可以約定:
- 若預測值
y > 0.5,就判斷 “通過”(1) - 若
y ≤ 0.5,就判斷 “不通過”(0)
但這樣做有個大問題:線性回歸的預測值可能超出 0-1 范圍。比如學習時長特別短(比如 - 1 小時,雖然實際不存在),預測值可能是負數;時長特別長,預測值可能大于 1。但 “是否通過” 的概率只能在 0-1 之間,顯然線性回歸不適合直接做分類。
二、邏輯回歸的 “核心 trick”:用 Sigmoid 函數 “壓縮” 范圍
邏輯回歸的關鍵,是給線性回歸加了一個 “轉換工具”——Sigmoid 函數,把線性回歸輸出的 “任意數”,壓縮到 0-1 之間(剛好對應 “概率”)。
1. Sigmoid 函數長什么樣?
它的公式不用記,只需記住形狀:像一條 “S 型曲線”,特點是:
- 輸入(比如線性回歸的結果)不管是多大的正數,輸出都無限接近 1;
- 輸入不管是多小的負數,輸出都無限接近 0;
- 輸入 = 0 時,輸出正好是 0.5。
這簡直是為二分類量身定做的!我們可以直接用它的輸出當 “概率”:
- 若 Sigmoid 輸出 > 0.5,判斷為 “是”(標簽 1,比如通過考試);
- 若 ≤ 0.5,判斷為 “否”(標簽 0,比如不通過)。
2. 邏輯回歸的完整公式(大白話版)
邏輯回歸其實是 “線性回歸 + Sigmoid 轉換” 的組合,分兩步:
第一步:算線性結果
跟線性回歸一樣,把特征(比如學習時長 x)和系數(w)相乘再加截距(b),得到z = w×x + b(如果有多個特征,就是z = w1×x1 + w2×x2 + ... + b)。
這里的z可以理解為 “分類邊界的基礎”。第二步:用 Sigmoid 壓縮
把z代入 Sigmoid 函數,得到最終的 “概率”:概率 = 1 / (1 + e^(-z))(e 是數學里的常數,約等于 2.718)。
比如:
- 當
z很大(比如 10),e^(-10)幾乎是 0,概率≈1/1=1(幾乎肯定是 1 類); - 當
z很小(比如 - 10),e^(-(-10))=e^10很大,概率≈1/(1 + 大數字)≈0(幾乎肯定是 0 類)。
三、邏輯回歸怎么 “學” 到最優參數?(損失函數 + 梯度下降)
模型要 “學習” 的,就是線性部分的系數 w 和截距 b。怎么判斷參數好不好?需要兩個關鍵工具:損失函數(判斷誤差)和梯度下降(調整參數減小誤差)。
1. 損失函數:給 “誤差” 打分
損失函數的作用是:計算模型預測結果和真實標簽的差距有多大。差距越小,損失值越小,模型越好。
邏輯回歸不用線性回歸的 “平方損失”(會導致參數難優化),而是用對數損失函數。不用記公式,只需理解核心:
- 如果真實標簽是 1,模型預測的概率越接近 1,損失越小;越接近 0,損失越大(比如預測錯了,罰得狠);
- 如果真實標簽是 0,模型預測的概率越接近 0,損失越小;越接近 1,損失越大。
2. 梯度下降:“一步步找最優參數”
有了損失函數,怎么找到讓損失最小的 w 和 b?靠 “梯度下降”,原理像 “下山找最低點”:
- 梯度:可以理解為 “當前位置下山最快的方向”;
- 學習率:每一步走多大(步太大容易跨過最低點,步太小走得慢);
- 迭代:重復 “算梯度→往梯度反方向走一步→更新參數”,直到損失不再減小(找到山腳)。
簡單說,梯度下降就是讓模型 “一點點調整參數”,最終找到讓損失最小的最優參數。
四、實戰:用代碼實現邏輯回歸(兩種方式)
下面用真實數據集(特征 X0、X1,標簽 Y=0 或 1),分別手動實現邏輯回歸,再用 sklearn (機器學習庫)快速實現,直觀感受過程。
方式 1:手動實現(理解核心步驟)
我們把前面的邏輯(Sigmoid、損失函數、梯度下降)寫成代碼,步驟如下:
1. 導入工具庫
import numpy as np # 做數學計算
import pandas as pd # 處理數據
import matplotlib.pyplot as plt # 畫圖
2. 加載數據并可視化
先看看數據長什么樣:
# 加載數據集(網上可直接獲取)
df = pd.read_csv("https://labfile.oss.aliyuncs.com/courses/1081/course-8-data.csv")
# 畫散點圖:X0是橫軸,X1是縱軸,顏色區分標簽Y(0=深藍,1=黃色)
plt.figure(figsize=(10,6))
plt.scatter(df['X0'], df['X1'], c=df['Y'])
plt.show()
會看到兩類點分布在圖上,我們要找一條線把它們分開。
3. 定義核心函數(Sigmoid、損失、梯度)
# 1. Sigmoid函數:壓縮到0-1
def sigmoid(z):
return 1 / (1 + np.exp(-z))
# 2. 對數損失函數:計算誤差
def calculate_loss(h, y):
# h是預測概率,y是真實標簽(0或1)
return (-y * np.log(h) - (1 - y) * np.log(1 - h)).mean()
# 3. 計算梯度:找下山方向
def calculate_gradient(X, h, y):
# X是特征,h是預測概率,y是真實標簽
return np.dot(X.T, (h - y)) / y.shape[0]
4. 實現邏輯回歸的訓練過程
def logistic_regression(X, y, learning_rate=0.01, num_iterations=30000):
"""
邏輯回歸模型訓練函數,通過梯度下降法尋找最優參數
參數:
X: 特征數據,形狀為 (樣本數, 特征數) 的numpy數組
y: 標簽數據,形狀為 (樣本數,) 的numpy數組,值為0或1
learning_rate: 學習率,控制梯度下降的步長,默認0.01
num_iterations: 迭代次數,控制梯度下降的迭代輪數,默認30000
返回:
w: 訓練好的參數,包含截距項,形狀為 (特征數+1,) 的numpy數組
"""
# 步驟1:給特征矩陣添加截距列(全為1)
# 這是為了將截距項b整合到參數w中,相當于給每個樣本增加一個恒為1的特征x0
# 此時模型變為 z = w0*x0 + w1*x1 + ... + wn*xn,其中x0=1,w0即截距b
intercept = np.ones((X.shape[0], 1)) # 創建形狀為(樣本數, 1)的全1數組
X = np.concatenate((intercept, X), axis=1) # 按列拼接,新特征矩陣形狀為(樣本數, 特征數+1)
# 步驟2:初始化參數w
# 初始化為全0數組,長度等于新特征矩陣的列數(特征數+1)
# w[0]對應截距項b,w[1:]對應各個特征的系數
w = np.zeros(X.shape[1]) # 形狀為(特征數+1,)
# 步驟3:通過梯度下降法迭代優化參數
for i in range(num_iterations):
# 計算線性組合z = X·w(矩陣乘法)
# 形狀為(樣本數,),每個元素對應一個樣本的線性計算結果
z = np.dot(X, w)
# 計算Sigmoid函數值h,得到每個樣本的預測概率(0-1之間)
# 形狀為(樣本數,),h[i]表示第i個樣本預測為1的概率
h = sigmoid(z)
# 計算梯度(損失函數對參數w的偏導數)
# 形狀為(特征數+1,),每個元素表示對應參數的梯度方向
grad = calculate_gradient(X, h, y)
# 更新參數:沿梯度反方向移動,步長為learning_rate
# 這一步是梯度下降的核心,通過不斷調整參數減小損失
w -= learning_rate * grad
# 每1000次迭代打印一次損失值,監控訓練過程
# 損失值逐漸減小說明模型在優化,趨于穩定說明接近最優解
if i % 1000 == 0:
loss = calculate_loss(h, y) # 計算當前的平均損失
print(f"迭代第{i}次,損失:{loss:.4f}") # 保留4位小數打印
return w # 返回訓練好的參數,包含截距項和各特征系數
5. 訓練模型并畫分類邊界
# 準備數據:特征X(X0、X1),標簽y(Y)
X = df[['X0', 'X1']].values
y = df['Y'].values
# 訓練模型
trained_w = logistic_regression(X, y)
# 畫分類邊界(紅線就是分開兩類點的線)
plt.figure(figsize=(10,6))
plt.scatter(df['X0'], df['X1'], c=df['Y'])
# 生成網格點(覆蓋整個圖的范圍)
x1_min, x1_max = df['X0'].min(), df['X0'].max()
x2_min, x2_max = df['X1'].min(), df['X1'].max()
xx1, xx2 = np.meshgrid(np.linspace(x1_min, x1_max), np.linspace(x2_min, x2_max))
# 計算每個網格點的預測結果(判斷在邊界哪一側)
grid = np.c_[xx1.ravel(), xx2.ravel()] # 把網格點轉成特征格式
# 加截距列(1),算線性結果z
z = np.dot(np.c_[np.ones(grid.shape[0]), grid], trained_w)
# 畫邊界:z=0的地方就是分類線(Sigmoid(z)=0.5的位置)
plt.contour(xx1, xx2, z.reshape(xx1.shape), levels=[0], colors='red', linewidths=2)
plt.show()
運行后會看到一條紅線,能較好地把兩類點分開 —— 這就是邏輯回歸找到的 “分類邊界”。
方式 2:用 sklearn 快速實現(實際工作常用)
手動實現是為了理解原理,實際工作中直接用 sklearn 庫,幾行代碼就能搞定:
from sklearn.linear_model import LogisticRegression
# 1. 初始化模型(設置參數:迭代次數足夠多,確保收斂)
model = LogisticRegression(max_iter=10000, solver='liblinear')
# 2. 訓練模型(直接喂特征X和標簽y)
model.fit(X, y)
# 3. 查看模型參數(系數w和截距b)
print("系數w:", model.coef_) # 對應X0、X1的系數
print("截距b:", model.intercept_) # 對應手動實現中的trained_w[0]
# 4. 計算準確率(模型在訓練集上的正確率)
accuracy = model.score(X, y)
print(f"模型準確率:{accuracy:.4f}") # 通常能達到0.9以上
# 5. 畫分類邊界(和手動實現類似,紅線分開兩類點)
plt.figure(figsize=(10,6))
plt.scatter(df['X0'], df['X1'], c=df['Y'])
z = np.dot(grid, model.coef_.T) + model.intercept_ # 算線性結果
plt.contour(xx1, xx2, z.reshape(xx1.shape), levels=[0], colors='red', linewidths=2)
plt.show()
sklearn 已經封裝好了所有復雜邏輯,我們只需調用接口,效率極高。
五、回到最初的問題:邏輯回歸為什么帶 “回歸” 二字?
現在能回答開頭的疑問了:
- “邏輯”:來自 “邏輯分布”(Sigmoid 函數是邏輯分布的核心),代表 “是 / 否” 的二分類邏輯;
- “回歸”:因為它的核心是用線性模型(和線性回歸一樣的 w×X + b)構建分類邊界,本質是 “線性模型的分類應用”,所以保留了 “回歸” 的名字。
六、總結:邏輯回歸的核心要點
- 本質:二分類模型,用 “線性模型 + Sigmoid” 實現概率預測;
- 關鍵工具:
- Sigmoid 函數:壓縮輸出到 0-1(概率);
- 對數損失函數:衡量預測誤差;
- 梯度下降:找到最優參數(w 和 b);
- 優勢:簡單、高效、易解釋,適合處理二分類問題(如垃圾郵件識別、疾病初篩);
- 實戰:手動實現理解原理,sklearn 快速落地。
只要記住 “線性回歸做基礎,Sigmoid 來轉換,梯度下降找最優”,邏輯回歸的核心就掌握了!

浙公網安備 33010602011771號