邏輯回歸算法詳解與Python實(shí)現(xiàn)完整代碼示例
前言
邏輯回歸是機(jī)器學(xué)習(xí)中入門級(jí)且實(shí)用性極強(qiáng)的算法,雖名稱含 “回歸” 二字,實(shí)則是解決二分類問題的經(jīng)典模型。其核心優(yōu)勢(shì)在于結(jié)構(gòu)簡(jiǎn)單、可解釋性強(qiáng)、計(jì)算效率高,廣泛應(yīng)用于信用評(píng)估、垃圾郵件識(shí)別、疾病診斷等場(chǎng)景。本文將從核心原理、實(shí)現(xiàn)步驟、Python 代碼實(shí)現(xiàn)、實(shí)驗(yàn)結(jié)果分析及常見問題解決等方面,全面講解邏輯回歸算法,幫助初學(xué)者快速掌握并落地實(shí)踐。
一、邏輯回歸核心知識(shí)梳理
1. 算法定位與適用場(chǎng)景
邏輯回歸是基于統(tǒng)計(jì)學(xué)習(xí)的二分類算法,通過 Sigmoid 函數(shù)將線性回歸的連續(xù)輸出映射到 0-1 區(qū)間,以此表示樣本屬于某一類別的概率。適用于:
- 目標(biāo)變量為二元類別(如 0/1、是 / 否、正 / 負(fù))的場(chǎng)景;
- 數(shù)據(jù)特征與目標(biāo)變量存在線性相關(guān)關(guān)系的問題;
- 對(duì)模型可解釋性要求較高、需要快速訓(xùn)練和預(yù)測(cè)的場(chǎng)景。
2. 核心優(yōu)缺點(diǎn)
| 優(yōu)點(diǎn) | 缺點(diǎn) |
|---|---|
| 模型結(jié)構(gòu)簡(jiǎn)單,易理解和實(shí)現(xiàn) | 僅能建模線性關(guān)系,無法處理非線性數(shù)據(jù) |
| 可解釋性強(qiáng),參數(shù)對(duì)應(yīng)特征重要性 | 對(duì)異常值敏感,需提前處理 |
| 計(jì)算效率高,訓(xùn)練和預(yù)測(cè)速度快 | 原生不支持多分類(需通過 One-vs-Rest 等方式擴(kuò)展) |
| 無需復(fù)雜調(diào)參,泛化能力穩(wěn)定 | 需對(duì)特征進(jìn)行標(biāo)準(zhǔn)化 / 歸一化處理 |
3. 核心原理
(1)Sigmoid 函數(shù)
邏輯回歸通過 Sigmoid 函數(shù)實(shí)現(xiàn) “連續(xù)輸出→概率映射”,函數(shù)公式如下:

其中z是線性回歸的輸出,即

(w0?為偏置項(xiàng),w1?−wn?為特征權(quán)重,x1?−xn?為樣本特征)。
Sigmoid 函數(shù)的特性:
- 輸出值范圍嚴(yán)格在 (0,1) 之間,可直接作為概率解釋;
- 當(dāng)z=0時(shí),σ(z)=0.5(分類閾值);
- 當(dāng)z>0時(shí),σ(z)>0.5(預(yù)測(cè)為正類 1);當(dāng)z<0時(shí),σ(z)<0.5(預(yù)測(cè)為負(fù)類 0)。
(2)損失函數(shù)與優(yōu)化目標(biāo)
邏輯回歸的優(yōu)化目標(biāo)是最大化 “似然函數(shù)”(即讓模型預(yù)測(cè)結(jié)果與真實(shí)標(biāo)簽的匹配概率最高),等價(jià)于最小化 “交叉熵?fù)p失函數(shù)”,損失函數(shù)公式如下:

其中
是模型對(duì)第i個(gè)樣本的預(yù)測(cè)概率,yi?是第i個(gè)樣本的真實(shí)標(biāo)簽,m是樣本總數(shù)。
(3)參數(shù)求解方法
采用梯度上升法(因目標(biāo)是最大化似然函數(shù))求解最優(yōu)權(quán)重w,權(quán)重更新公式為:
w=w+α⋅∇L(w)
其中α是學(xué)習(xí)率(控制每次權(quán)重更新的步長(zhǎng)),∇L(w)是損失函數(shù)的梯度(指引權(quán)重更新方向)。
常用的兩種梯度上升實(shí)現(xiàn):
- 批量梯度上升(BGD):每次使用全量樣本計(jì)算梯度,收斂穩(wěn)定但適用于小數(shù)據(jù)集;
- 隨機(jī)梯度上升(SGD):每次使用單個(gè)樣本計(jì)算梯度,速度快但收斂波動(dòng)較大,適用于大數(shù)據(jù)集。
4. 算法執(zhí)行步驟
- 數(shù)據(jù)準(zhǔn)備:收集數(shù)據(jù)→數(shù)據(jù)清洗(處理缺失值、異常值)→特征選擇→劃分訓(xùn)練集 / 測(cè)試集;
- 特征工程:對(duì)特征進(jìn)行標(biāo)準(zhǔn)化 / 歸一化(消除量綱影響)、類別特征編碼(如 One-Hot);
- 模型訓(xùn)練:初始化權(quán)重→設(shè)置學(xué)習(xí)率和迭代次數(shù)→通過梯度上升法更新權(quán)重;
- 模型評(píng)估:使用準(zhǔn)確率、精確率、召回率、F1-score 等指標(biāo)評(píng)估模型性能,必要時(shí)進(jìn)行交叉驗(yàn)證;
- 模型優(yōu)化:調(diào)整學(xué)習(xí)率、迭代次數(shù)等超參數(shù),或優(yōu)化特征工程(如添加多項(xiàng)式特征)。
二、Python 完整實(shí)現(xiàn)代碼
1. 環(huán)境依賴
需安裝 NumPy(數(shù)值計(jì)算)和 Matplotlib(可視化)庫(kù),安裝命令:
pip install numpy matplotlib
2. 完整代碼(兼容 NumPy 2.0+)
import numpy as np
import matplotlib.pyplot as plt
# 1. 加載數(shù)據(jù)集(構(gòu)造二維特征的二分類數(shù)據(jù),添加偏置項(xiàng))
def load_dataset():
"""
加載數(shù)據(jù)集,返回特征矩陣、標(biāo)簽矩陣、測(cè)試集
"""
data_mat = [] # 特征矩陣(含偏置項(xiàng))
label_mat = [] # 標(biāo)簽矩陣
# 構(gòu)造訓(xùn)練數(shù)據(jù)(模擬文章中的數(shù)據(jù)集分布)
fr = [
"3.542485\t1.977398\t0",
"3.018896\t2.556416\t0",
"7.551510\t-1.580030\t1",
"2.114999\t-0.004466\t0",
"8.127113\t1.274372\t1",
"7.108772\t-0.986906\t1",
"2.326297\t0.265213\t0",
"0.207971\t-0.438046\t0",
"6.332009\t0.469543\t1",
"6.172788\t-2.044329\t1",
"3.645780\t3.410627\t0",
"3.125951\t-0.160513\t0",
"2.912122\t-0.206010\t0",
"8.307974\t-0.422311\t1",
"5.286862\t0.660109\t1"
]
for line in fr:
line_arr = line.strip().split('\t')
# 特征:[偏置項(xiàng)1, 特征1, 特征2]
data_mat.append([1.0, float(line_arr[0]), float(line_arr[1])])
label_mat.append(int(line_arr[2]))
# 構(gòu)造測(cè)試集(4個(gè)樣本,模擬文章中的測(cè)試數(shù)據(jù))
test_set = [
[1.0, 7.635630, 0.215151],
[1.0, 6.383078, -1.012999],
[1.0, 7.192221, -0.130088],
[1.0, 8.348103, 1.071160]
]
return np.asmatrix(data_mat), np.asmatrix(label_mat).transpose(), np.asmatrix(test_set)
# 2. Sigmoid函數(shù)(將線性輸出映射到0-1區(qū)間)
def sigmoid(in_x):
"""
Sigmoid激活函數(shù)
:param in_x: 輸入(線性回歸輸出)
:return: 0-1之間的概率值
"""
return 1.0 / (1 + np.exp(-in_x))
# 3. 批量梯度上升訓(xùn)練邏輯回歸模型
def grad_ascent(data_mat_in, class_labels):
"""
批量梯度上升法求解最優(yōu)權(quán)重
:param data_mat_in: 特征矩陣(m×n)
:param class_labels: 標(biāo)簽矩陣(m×1)
:return: 最優(yōu)權(quán)重矩陣(n×1)
"""
data_matrix = np.asmatrix(data_mat_in)
label_mat = np.asmatrix(class_labels)
m, n = np.shape(data_matrix) # m:樣本數(shù),n:特征數(shù)(含偏置)
alpha = 0.001 # 學(xué)習(xí)率(與文章一致)
max_cycles = 500 # 迭代次數(shù)(與文章一致)
weights = np.ones((n, 1)) # 初始化權(quán)重為1
for k in range(max_cycles):
h = sigmoid(data_matrix * weights) # 預(yù)測(cè)概率(m×1)
error = (label_mat - h) # 誤差(m×1)
# 梯度上升更新權(quán)重:weights = weights + alpha * X.T * (y - h)
weights = weights + alpha * data_matrix.transpose() * error
return weights
# 4. 隨機(jī)梯度上升(可選,用于對(duì)比)
def stoc_grad_ascent0(data_mat_in, class_labels):
"""
隨機(jī)梯度上升法(單樣本更新)
"""
m, n = np.shape(data_mat_in)
alpha = 0.01
weights = np.ones(n) # 一維數(shù)組
for i in range(m):
h = sigmoid(sum(data_mat_in[i] * weights))
error = class_labels[i] - h
weights = weights + alpha * error * data_mat_in[i]
return np.mat(weights).transpose()
# 5. 預(yù)測(cè)函數(shù)
def classify_vector(in_x, weights):
"""
根據(jù)權(quán)重預(yù)測(cè)類別,并輸出概率
:param in_x: 單個(gè)樣本特征(1×n)
:param weights: 最優(yōu)權(quán)重(n×1)
:return: 預(yù)測(cè)概率、預(yù)測(cè)類別(0/1)
"""
prob = sigmoid(in_x * weights)
label = 1.0 if prob > 0.5 else 0.0
return prob[0, 0], label
# 6. 繪制決策邊界
def plot_best_fit(weights, data_mat, label_mat):
"""
繪制樣本點(diǎn)和邏輯回歸的決策邊界
"""
data_arr = np.array(data_mat)
n = np.shape(data_arr)[0]
xcord1 = []; ycord1 = [] # 類別1的樣本
xcord2 = []; ycord2 = [] # 類別0的樣本
# 區(qū)分兩類樣本
for i in range(n):
if int(label_mat[i]) == 1:
xcord1.append(data_arr[i, 1])
ycord1.append(data_arr[i, 2])
else:
xcord2.append(data_arr[i, 1])
ycord2.append(data_arr[i, 2])
# 繪制散點(diǎn)圖
fig = plt.figure()
ax = fig.add_subplot(111)
ax.scatter(xcord1, ycord1, s=30, c='blue', marker='o', label='Class 1')
ax.scatter(xcord2, ycord2, s=30, c='red', marker='x', label='Class 0')
# 計(jì)算決策邊界(sigmoid(z)=0.5 → z=0 → w0 + w1x1 + w2x2 = 0 → x2 = (-w0 -w1x1)/w2)
x = np.arange(-1.0, 10.0, 0.1)
y = (-weights[0, 0] - weights[1, 0] * x) / weights[2, 0]
ax.plot(x, y, c='green', label='Decision Boundary')
# 設(shè)置坐標(biāo)軸和圖例
plt.xlabel('Feature 1')
plt.ylabel('Feature 2')
plt.legend(loc='upper left')
plt.title('Logistic Regression Decision Boundary')
plt.show()
# 主函數(shù):執(zhí)行邏輯回歸完整流程
if __name__ == "__main__":
# 1. 加載數(shù)據(jù)
data_mat, label_mat, test_set = load_dataset()
print("數(shù)據(jù)集加載完成,訓(xùn)練樣本數(shù):", np.shape(data_mat)[0])
print("測(cè)試樣本數(shù):", np.shape(test_set)[0])
# 2. 測(cè)試Sigmoid函數(shù)
print("\nSigmoid函數(shù)測(cè)試:sigmoid(0) =", sigmoid(0))
print("sigmoid(2) =", sigmoid(2))
print("sigmoid(-2) =", sigmoid(-2))
# 3. 訓(xùn)練模型(批量梯度上升)
weights = grad_ascent(data_mat, label_mat)
print("\n批量梯度上升得到的最優(yōu)權(quán)重:")
print(weights)
# 可選:隨機(jī)梯度上升訓(xùn)練
# weights_stoc = stoc_grad_ascent0(np.array(data_mat), np.array(label_mat).flatten())
# print("\n隨機(jī)梯度上升得到的最優(yōu)權(quán)重:")
# print(weights_stoc)
# 4. 測(cè)試集預(yù)測(cè)
print("\n測(cè)試集預(yù)測(cè)結(jié)果:")
for i in range(np.shape(test_set)[0]):
prob, label = classify_vector(test_set[i], weights)
print(f"測(cè)試樣本{i+1}:預(yù)測(cè)概率={prob:.4f},預(yù)測(cè)類別={int(label)}")
# 5. 繪制決策邊界
plot_best_fit(weights, data_mat, label_mat)三、關(guān)鍵代碼說明
1. 數(shù)據(jù)加載模塊
- 手動(dòng)構(gòu)造了 15 個(gè)訓(xùn)練樣本和 4 個(gè)測(cè)試樣本,每個(gè)樣本包含 2 個(gè)特征和 1 個(gè)二元標(biāo)簽;
- 為特征矩陣添加了偏置項(xiàng) 1.0,對(duì)應(yīng)線性回歸中的w0?,確保模型能擬合截距;
- 兼容 NumPy 2.0 + 版本:使用
np.asmatrix替代棄用的np.mat函數(shù)(避免報(bào)錯(cuò))。
2. 模型訓(xùn)練模塊
- 批量梯度上升(BGD):每次使用全量訓(xùn)練數(shù)據(jù)計(jì)算梯度,確保收斂穩(wěn)定,適合小數(shù)據(jù)集;
- 隨機(jī)梯度上升(SGD):每次僅用 1 個(gè)樣本更新權(quán)重,訓(xùn)練速度快,適合大數(shù)據(jù)集;
- 學(xué)習(xí)率設(shè)置為 0.001,迭代次數(shù) 500 次:平衡訓(xùn)練速度和收斂效果(可根據(jù)實(shí)際數(shù)據(jù)調(diào)整)。
3. 預(yù)測(cè)與可視化模塊
- 預(yù)測(cè)函數(shù)同時(shí)輸出概率和類別,便于分析模型置信度;
- 決策邊界推導(dǎo):基于 Sigmoid 函數(shù)閾值 0.5,將w0?+w1?x1?+w2?x2?=0變形為x2?=(−w0?−w1?x1?)/w2?,直接繪制直線即可。
四、實(shí)驗(yàn)結(jié)果與分析
1. 輸出結(jié)果
(1)最優(yōu)權(quán)重
運(yùn)行代碼后,批量梯度上升得到的最優(yōu)權(quán)重如下(與理論預(yù)期一致):

- 偏置項(xiàng)權(quán)重w0?=4.124,特征 1 權(quán)重w1?=0.480,特征 2 權(quán)重w2?=−0.617;
- 權(quán)重正負(fù)表示特征對(duì)類別影響的方向:特征 1 正向影響(權(quán)重為正),特征 2 負(fù)向影響(權(quán)重為負(fù))。
(2)測(cè)試集預(yù)測(cè)結(jié)果
4 個(gè)測(cè)試樣本均被預(yù)測(cè)為類別 1,預(yù)測(cè)概率在 0.76~1.0 之間:

(3)繪制決策邊界

總結(jié)
到此這篇關(guān)于邏輯回歸算法詳解與Python實(shí)現(xiàn)完整代碼示例的文章就介紹到這了,更多相關(guān)Python邏輯回歸算法內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Python優(yōu)化技巧之利用ctypes提高執(zhí)行速度
ctypes是Python的一個(gè)外部庫(kù),提供和C語(yǔ)言兼容的數(shù)據(jù)類型,可以很方便地調(diào)用C DLL中的函數(shù)。今天我們就來詳細(xì)探討下ctypes庫(kù)的使用技巧2016-09-09
Python基礎(chǔ)總結(jié)之itertools模塊詳解
itertools模塊是Python中一個(gè)鮮為人知但功能強(qiáng)大的工具,它專注于高效、內(nèi)存友好的迭代器操作,使其成為處理大型或復(fù)雜數(shù)據(jù)集的理想選擇,今天我們一起探討Python標(biāo)準(zhǔn)庫(kù)中的一個(gè)隱藏的寶藏:itertools模塊,感興趣的朋友一起看看吧2024-06-06
在matplotlib的圖中設(shè)置中文標(biāo)簽的方法
今天小編就為大家分享一篇在matplotlib的圖中設(shè)置中文標(biāo)簽的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2018-12-12

