逻辑回归分类(LogisticRegression)算法详解
逻辑回归分类(LogisticRegression)算法详解
本文介绍了 scikit-learn 的 LogisticRegression 逻辑回归分类算法。虽然名称中带有“回归”,但它本质上是一个经典的分类模型,主要用于二分类任务,同时也能够扩展到多分类问题。文章将从算法原理、主要参数、代码示例、可视化分析以及适用场景几个方面展开,帮助读者系统理解 LogisticRegression 在 scikit-learn 中的使用方式与实践价值。
1. 算法背景
逻辑回归(Logistic Regression)是机器学习中最基础、最常用的监督学习算法之一。它的核心思想是:先对输入特征进行线性组合,再通过一个概率映射函数将输出压缩到 0 到 1 之间,从而得到样本属于某一类别的概率。由于这一输出结果具有明确的概率意义,因此逻辑回归不仅适合做分类任务,也常用于风险预测、转化分析、医疗诊断和金融风控等实际场景。
在 scikit-learn 中,逻辑回归由 sklearn.linear_model.LogisticRegression 实现。该模型具有实现简单、训练高效、可解释性较强等优点,在很多分类问题中都可以作为首选的基线模型。虽然逻辑回归结构简单,但在工程实践中依然具有非常重要的地位,尤其适合用来快速验证数据是否具有较好的线性可分性。
2. 逻辑回归的基本原理
逻辑回归的出发点仍然是线性模型。对于输入样本 xxx,模型首先计算一个线性组合:
z=w1x1+w2x2+⋯+wnxn+b z = w_1x_1 + w_2x_2 + \cdots + w_nx_n + b z=w1x1+w2x2+⋯+wnxn+b
其中,www 表示各个特征对应的权重,bbb 表示偏置项。这个线性结果本身只是一个实数,并不能直接表示类别概率,因此逻辑回归进一步引入了 Sigmoid 函数:
σ(z)=11+e−z \sigma(z) = \frac{1}{1 + e^{-z}} σ(z)=1+e−z1
经过 Sigmoid 映射之后,输出值就落在 0 到 1 之间,可以理解为样本属于正类的概率。通常情况下,当该概率大于 0.5 时,模型预测为正类;反之则预测为负类。
从决策边界的角度来看,逻辑回归学习到的本质上仍然是线性边界,因此它更适合处理线性可分或近似线性可分的数据。如果数据的真实边界非常复杂,逻辑回归的表达能力就会受到限制。
在模型训练过程中,逻辑回归并不是通过最小化均方误差来学习参数,而是通过最小化对数损失函数完成优化。为了降低过拟合风险,实际实现中通常还会结合正则化机制,使模型在训练集和测试集之间具备更好的泛化能力。
3. scikit-learn 中的 LogisticRegression
在 scikit-learn 中,逻辑回归的基本使用方式非常直接:
from sklearn.linear_model import LogisticRegression
# 创建逻辑回归模型
model = LogisticRegression()
# 使用训练集拟合模型
model.fit(X_train, y_train)
# 对测试集进行预测
y_pred = model.predict(X_test)
虽然调用形式看起来非常简单,但在实际建模过程中,逻辑回归通常不会单独使用,而是会和数据划分、特征标准化、模型评估以及可视化分析一起构成完整流程。特别是在数值型特征量纲差异较大的场景中,标准化往往会显著改善模型训练效果和收敛稳定性,因此这是逻辑回归实践中非常重要的一步。
4. 主要参数解析
在 scikit-learn 中,LogisticRegression 的常见构造形式如下:
from sklearn.linear_model import LogisticRegression
LogisticRegression(
penalty='l2', # 正则化类型:l1/L2/elasticnet/none,用于防止过拟合
*,
dual=False, # 对偶/原始形式求解,仅适用于l2正则+liblinear,样本数<特征数时用True
tol=0.0001, # 停止迭代的精度阈值,损失函数变化小于该值则提前收敛
C=1.0, # 正则化强度的倒数,值越小正则化越强
fit_intercept=True, # 是否拟合截距(偏置项b),False则模型无截距
intercept_scaling=1, # 仅solver=liblinear时有效,截距的缩放系数
class_weight=None, # 类别权重,balanced自动根据样本数量平衡权重
random_state=None, # 随机种子,保证多次运行结果可复现
solver='lbfgs', # 优化算法:lbfgs/liblinear/newton-cg/sag/saga
max_iter=100, # 最大迭代次数,不收敛时可适当调大
multi_class='deprecated', # 多分类方式,已废弃,由库自动处理
verbose=0, # 日志输出详细程度,0不输出,越大输出越多
warm_start=False, # 是否热启动,True则复用上次训练结果继续迭代
n_jobs=None, # 并行运算CPU核数,None=1,-1=使用全部CPU
l1_ratio=None, # 弹性网(elasticnet)混合比例,0=L2,1=L1,仅penalty=elasticnet时使用
)
虽然 LogisticRegression 提供了较多参数,但在实际使用中,最值得关注的通常还是 penalty、C、solver、max_iter 和 class_weight。
penalty 用于指定正则化方式,常见取值包括 l2、l1、elasticnet 和 None。其中,l2 是最常见也最稳定的选择;l1 可以得到更稀疏的系数结果,在一定程度上具有特征选择作用;elasticnet 则结合了 l1 和 l2 的特点。
C 表示正则化强度的倒数。C 越小,正则化越强,模型越简单;C 越大,正则化越弱,模型越倾向于拟合训练数据。实际调参时,C 往往是最核心的参数之一。
solver 表示优化算法。默认的 lbfgs 适合大多数中小规模数据;liblinear 更适合小规模数据,并支持 l1 正则;saga 则适合更大规模数据,同时支持 elasticnet。因此,penalty 与 solver 通常需要结合起来考虑。
max_iter 表示最大迭代次数,默认值为 100。如果模型训练时出现未收敛警告,通常可以适当增大这个参数。在实际示例中,常将它设置为 1000,以减少迭代次数不足带来的影响。
class_weight 用于设置类别权重,默认值为 None。当数据集存在明显类别不平衡时,可以设置为 'balanced',让模型根据类别分布自动调整权重,从而减轻多数类对训练过程的影响。
除上述参数外,fit_intercept 用于控制是否拟合截距项,通常保持默认值 True 即可;random_state 用于固定随机种子,便于实验复现;l1_ratio 只在 penalty='elasticnet' 时才有意义。至于 dual、intercept_scaling、verbose、warm_start 和 n_jobs 等参数,在一般教学和常规建模中并不是优先关注的重点。
总体来看,掌握 penalty、C、solver、max_iter 和 class_weight 这几个核心参数,已经足以应对大多数逻辑回归建模场景。
5. 二分类实战示例
下面以 scikit-learn 自带的乳腺癌数据集为例,演示逻辑回归的完整建模流程。案例包括数据加载、数据集分布观察、训练集和测试集划分、特征标准化、模型训练、预测评估以及可视化分析。
5.1 导入库并加载数据
import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
from sklearn.datasets import load_breast_cancer
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import accuracy_score, classification_report, confusion_matrix
# 设置主题
sns.set_theme(style="whitegrid", font="SimHei", rc={"axes.unicode_minus": False})
# 加载乳腺癌数据集
data = load_breast_cancer()
X = data.data
y = data.target
# 输出数据基本信息
print("特征维度:", X.shape)
print("类别名称:", data.target_names)
print("类别分布:", np.bincount(y))
特征维度: (569, 30)
类别名称: [‘malignant’ ‘benign’]
类别分布: [212 357]
5.2 二分类 类别分布可视化
# 将目标变量整理为 DataFrame,便于使用 seaborn 作图
target_df = pd.DataFrame({
"类别": y
})
# 绘制类别分布图
plt.figure(figsize=(7, 5))
sns.countplot(data=target_df, x="类别")
plt.title("乳腺癌数据集类别分布")
plt.xlabel("类别")
plt.ylabel("样本数量")
plt.tight_layout()
plt.show()

从类别分布图可以看出,该数据集中的两类样本数量并不完全一致,但整体差异并不算特别极端。这说明在本例中,模型可以先从默认设置开始训练,而不必一开始就对类别权重做过多干预。
5.3 划分训练集与测试集并进行标准化
# 划分训练集和测试集,并保持类别比例一致
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42, stratify=y
)
# 对特征进行标准化处理
scaler = StandardScaler()
X_train_std = scaler.fit_transform(X_train)
X_test_std = scaler.transform(X_test)
5.4 构建并训练模型
# 创建逻辑回归模型
model = LogisticRegression(
penalty='l2',
C=1.0,
solver='lbfgs',
max_iter=1000,
random_state=42
)
# 在标准化后的训练集上拟合模型
model.fit(X_train_std, y_train)
5.5 模型预测与评估
# 进行类别预测和概率预测
y_pred = model.predict(X_test_std)
y_prob = model.predict_proba(X_test_std)[:, 1]
# 输出模型评估结果
print("准确率:", accuracy_score(y_test, y_pred))
print("混淆矩阵:")
print(confusion_matrix(y_test, y_pred))
print("分类报告:")
print(classification_report(y_test, y_pred, target_names=data.target_names))
准确率: 0.9824561403508771
混淆矩阵:
[[41 1]
[ 1 71]]分类报告:
precision recall f1-score support
malignant 0.98 0.98 0.98 42
benign 0.99 0.99 0.99 72
accuracy 0.98 114macro avg 0.98 0.98 0.98 114
weighted avg 0.98 0.98 0.98 114
准确率可以帮助我们快速了解模型整体表现,而分类报告则进一步给出了精确率、召回率和 F1 值等指标。对于分类模型来说,仅仅看准确率往往还不够,还需要结合混淆矩阵进一步分析模型在哪些类别上更容易出现误判。
5.6 二分类 混淆矩阵热力图
# 计算混淆矩阵
cm = confusion_matrix(y_test, y_pred)
# 绘制热力图
plt.figure(figsize=(7, 5))
ax = sns.heatmap(
cm,
annot=True,
fmt="d",
cmap="Blues",
xticklabels=data.target_names,
yticklabels=data.target_names
)
plt.xlabel("预测类别")
plt.ylabel("真实类别")
plt.title("乳腺癌逻辑回归混淆矩阵热力图")
plt.tight_layout()
plt.show()

从混淆矩阵热力图可以更直观地看到模型分类结果的分布情况。热力图对角线上的数值表示被正确分类的样本数量,而非对角线上的数值则表示误分类样本。从图中通常可以观察到,大部分样本都集中在对角线位置,这说明逻辑回归在该数据集上的整体分类效果较好。与此同时,少量非对角线元素则揭示了模型仍然存在一定的混淆情况,这对于进一步优化模型具有参考价值。
5.7 特征系数可视化
# 将模型系数与特征名称整理到同一个表中
coef_df = pd.DataFrame({
"特征": data.feature_names,
"系数": model.coef_[0]
})
# 计算系数绝对值并筛选前 10 个重要特征
coef_df["系数绝对值"] = coef_df["系数"].abs()
top_coef_df = coef_df.sort_values("系数绝对值", ascending=False).head(10)
# 绘制条形图
plt.figure(figsize=(8, 6))
ax = sns.barplot(data=top_coef_df, x="系数", y="特征")
plt.title("逻辑回归前10重要特征系数")
plt.xlabel("系数值")
plt.ylabel("特征名称")
plt.tight_layout()
plt.show()

逻辑回归的一个重要优势在于模型具有较好的可解释性。通过特征系数条形图,可以观察哪些特征对最终分类结果影响更大。系数为正通常表示该特征增大时,样本更倾向于被预测为正类;系数为负则表示该特征增大时,更倾向于被预测为负类;而绝对值越大,通常说明该特征对决策边界的影响越明显。由于这里已经对特征做了标准化,因此不同特征系数之间的对比更具有参考意义。
6. 二维数据下的分类边界可视化
为了更直观地理解逻辑回归“线性分类器”的本质,下面构造一个二维分类数据集,并使用散点图展示样本分布情况。
6.1 导入库并构造二维数据
import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
from sklearn.datasets import make_classification
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
sns.set_theme(style="whitegrid", font="SimHei", rc={"axes.unicode_minus": False})
# 生成二维二分类样本
X_vis, y_vis = make_classification(
n_samples=300,
n_features=2,
n_redundant=0,
n_informative=2,
n_clusters_per_class=1,
random_state=42
)
# 整理为 DataFrame 便于可视化
vis_df = pd.DataFrame(X_vis, columns=["特征1", "特征2"])
vis_df["类别"] = y_vis
6.2 样本分布可视化
# 绘制二维样本散点图
plt.figure(figsize=(7, 5))
sns.scatterplot(
data=vis_df,
x="特征1",
y="特征2",
hue="类别",
palette="Set1"
)
plt.title("二维样本类别分布")
plt.xlabel("特征1")
plt.ylabel("特征2")
plt.tight_layout()
plt.show()

从散点图可以看出,两类样本在二维空间中呈现出较明显的分离趋势。这类数据非常适合逻辑回归建模,因为它本身更倾向于学习一条线性决策边界。如果样本分布呈现非常复杂的曲线状边界,那么逻辑回归的表达能力通常就会受到限制。
6.3 训练二维逻辑回归模型并绘制决策区域
# 对二维样本进行标准化
scaler_vis = StandardScaler()
X_vis_std = scaler_vis.fit_transform(X_vis)
# 训练二维逻辑回归模型
model_vis = LogisticRegression()
model_vis.fit(X_vis_std, y_vis)
# 构建网格点,用于绘制分类区域
x_min, x_max = X_vis_std[:, 0].min() - 1, X_vis_std[:, 0].max() + 1
y_min, y_max = X_vis_std[:, 1].min() - 1, X_vis_std[:, 1].max() + 1
xx, yy = np.meshgrid(
np.linspace(x_min, x_max, 300),
np.linspace(y_min, y_max, 300)
)
# 对网格点进行预测
grid = np.c_[xx.ravel(), yy.ravel()]
Z = model_vis.predict(grid).reshape(xx.shape)
# 整理标准化后的样本点
plot_df = pd.DataFrame({
"特征1": X_vis_std[:, 0],
"特征2": X_vis_std[:, 1],
"类别": y_vis
})
# 绘制决策区域与样本散点
plt.figure(figsize=(8, 6))
plt.contourf(xx, yy, Z, alpha=0.25, cmap="coolwarm")
sns.scatterplot(
data=plot_df,
x="特征1",
y="特征2",
hue="类别",
palette="Set1",
edgecolor="black"
)
plt.title("逻辑回归决策边界示意图")
plt.xlabel("特征1")
plt.ylabel("特征2")
plt.tight_layout()
plt.show()

从决策区域图可以更清楚地看到,逻辑回归最终学习到的是一条线性分界面。图中不同背景区域表示模型对不同类别的预测范围,而散点则是真实样本的位置分布。当样本大体可以用直线分开时,逻辑回归通常能够取得较好的效果;反之,如果样本之间呈现复杂非线性混杂关系,那么逻辑回归就可能出现明显欠拟合。
7 正则化参数对模型的影响
在逻辑回归中,C 参数直接影响正则化强度,因此也会影响模型复杂度和泛化能力。下面通过一个简单实验,观察不同 C 值下模型表现的变化。
7.1 导入库并计算不同 C 值下的准确率
import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
# 设置主题
sns.set_theme(style="whitegrid", font="SimHei", rc={"axes.unicode_minus": False})
# 加载乳腺癌数据集
data = load_breast_cancer()
# 转成 DataFrame
df = pd.DataFrame(data.data, columns=data.feature_names)
df["target"] = data.target
# 特征和标签
X = df.drop("target", axis=1)
y = df["target"]
# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42
)
# 标准化
scaler = StandardScaler()
X_train_std = scaler.fit_transform(X_train)
X_test_std = scaler.transform(X_test)
# 定义不同的 C 值
C_values = [0.01, 0.1, 1, 10, 100]
score_list = []
# 分别训练模型并记录准确率
for c in C_values:
model_c = LogisticRegression(C=c, max_iter=1000, random_state=42)
model_c.fit(X_train_std, y_train)
y_pred_c = model_c.predict(X_test_std)
score_list.append(accuracy_score(y_test, y_pred_c))
# 整理结果
result_df = pd.DataFrame({
"C值": C_values,
"准确率": score_list
})
print(result_df)
C值 准确率
0 0.01 0.964912
1 0.10 0.982456
2 1.00 0.973684
3 10.00 0.973684
4 100.00 0.938596
7.2 使用折线图观察参数变化趋势
# 绘制折线图
plt.figure(figsize=(7.5, 5.2))
ax = sns.lineplot(
data=result_df,
x="C值",
y="准确率",
marker="o",
linewidth=2.2,
markersize=7
)
# 设置对数坐标轴
plt.xscale("log")
plt.title("正则化强度 C 对逻辑回归准确率的影响", fontsize=14, pad=12)
plt.xlabel("C值(对数尺度)", fontsize=11)
plt.ylabel("准确率", fontsize=11)
# 设置网格样式
ax.grid(True, linestyle="--", alpha=0.45)
# 单独设置刻度字体,避免对数轴刻度显示问题
fp = FontProperties(family="DejaVu Sans")
for label in ax.get_xticklabels():
label.set_fontproperties(fp)
for label in ax.get_yticklabels():
label.set_fontproperties(fp)
plt.tight_layout()
plt.show()

从折线图中可以更直观地观察 C 对模型性能的影响。通常来说,当 C 较小时,正则化更强,模型会更简单,因此可能降低过拟合风险,但也可能因为过于保守而出现欠拟合;当 C 较大时,模型的拟合能力增强,但同时也可能带来泛化能力下降的风险。实际建模时,往往需要结合交叉验证来进一步寻找更合适的参数取值,而不是仅仅依赖单次测试结果。
8. 多分类任务中的逻辑回归
逻辑回归不仅适用于二分类问题,也可以用于多分类任务。下面以鸢尾花数据集为例,展示逻辑回归在多分类问题中的应用效果。
8.1 导入库并加载鸢尾花数据集
import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
from matplotlib.lines import Line2D
from sklearn.datasets import load_iris
from sklearn.decomposition import PCA
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score, classification_report, confusion_matrix
# 设置主题
sns.set_theme(style="whitegrid", font="SimHei", rc={"axes.unicode_minus": False})
# 加载鸢尾花数据集
iris = load_iris()
X_iris = iris.data
y_iris = iris.target
# 定义中文类别名称
iris_label_names = ["山鸢尾", "变色鸢尾", "维吉尼亚鸢尾"]
iris_label_map = {
0: "山鸢尾",
1: "变色鸢尾",
2: "维吉尼亚鸢尾"
}
# 整理为 DataFrame
iris_df = pd.DataFrame(X_iris, columns=iris.feature_names)
iris_df["类别"] = y_iris
iris_df["类别名称"] = iris_df["类别"].map(iris_label_map)

8.2 多分类 类别分布可视化
# 绘制类别分布图
plt.figure(figsize=(7, 5))
sns.countplot(
data=iris_df,
x="类别名称",
order=iris_label_names
)
plt.title("鸢尾花数据集类别分布")
plt.xlabel("类别名称")
plt.ylabel("样本数量")
plt.tight_layout()
plt.show()
从类别分布图可以看到,鸢尾花数据集中的三个类别分布较为均衡,这使得它非常适合作为多分类模型的教学示例。在这种相对理想的数据条件下,模型的训练和评估通常更容易体现算法本身的能力,而不会过多受到类别不平衡问题的干扰。
8.3 模型训练与评估
# 划分训练集和测试集
X_train_iris, X_test_iris, y_train_iris, y_test_iris = train_test_split(
X_iris, y_iris, test_size=0.2, random_state=42, stratify=y_iris
)
# 对特征进行标准化
scaler_iris = StandardScaler()
X_train_iris_std = scaler_iris.fit_transform(X_train_iris)
X_test_iris_std = scaler_iris.transform(X_test_iris)
# 训练逻辑回归模型
model_iris = LogisticRegression(max_iter=1000)
model_iris.fit(X_train_iris_std, y_train_iris)
# 进行预测并输出评估结果
y_pred_iris = model_iris.predict(X_test_iris_std)
print("准确率:", accuracy_score(y_test_iris, y_pred_iris))
print(classification_report(y_test_iris, y_pred_iris, target_names=iris_label_names))
准确率: 0.9333333333333333
precision recall f1-score support
山鸢尾 1.00 1.00 1.00 10
变色鸢尾 0.90 0.90 0.90 10
维吉尼亚鸢尾 0.90 0.90 0.90 10 accuracy 0.93 30
macro avg 0.93 0.93 0.93 30
weighted avg 0.93 0.93 0.93 30
8.4 多分类 混淆矩阵热力图
# 计算混淆矩阵
cm_iris = confusion_matrix(y_test_iris, y_pred_iris)
# 绘制热力图
plt.figure(figsize=(7, 5))
ax = sns.heatmap(
cm_iris,
annot=True,
fmt="d",
cmap="Blues",
xticklabels=iris_label_names,
yticklabels=iris_label_names
)
plt.xlabel("预测类别")
plt.ylabel("真实类别")
plt.title("鸢尾花逻辑回归混淆矩阵热力图")
plt.tight_layout()
plt.show()

从多分类混淆矩阵热力图中可以看出,不同类别之间的预测结果分布情况更加清晰。如果某两个类别在特征空间中较为接近,那么模型更容易在这两类之间产生混淆。通过这样的可视化,读者不仅可以看到整体准确率,还可以进一步理解模型在具体类别层面的表现差异。
8.5 真实类别与预测结果的 PCA 单图对比
# 对整个鸢尾花数据集进行标准化
X_iris_std = StandardScaler().fit_transform(X_iris)
# 使用 PCA 将四维特征降到二维
pca = PCA(n_components=2)
X_iris_pca = pca.fit_transform(X_iris_std)
# 使用训练好的模型对全部样本进行预测
y_pred_all = model_iris.predict(X_iris_std)
# 构建可视化数据表
pca_df = pd.DataFrame({
"主成分1": X_iris_pca[:, 0],
"主成分2": X_iris_pca[:, 1],
"真实类别": y_iris,
"预测类别": y_pred_all
})
# 添加中文类别名称和预测是否正确标记
pca_df["真实类别名称"] = pca_df["真实类别"].map(iris_label_map)
pca_df["预测类别名称"] = pca_df["预测类别"].map(iris_label_map)
pca_df["预测是否正确"] = np.where(
pca_df["真实类别"] == pca_df["预测类别"],
"预测正确",
"预测错误"
)
# 自定义颜色
palette = {
"山鸢尾": "#4C72B0",
"变色鸢尾": "#DD8452",
"维吉尼亚鸢尾": "#55A868"
}
# 创建画布
fig, ax = plt.subplots(figsize=(10.5, 7.5))
# 按预测是否正确分组
correct_df = pca_df[pca_df["预测是否正确"] == "预测正确"]
wrong_df = pca_df[pca_df["预测是否正确"] == "预测错误"]
# 绘制预测正确的样本
sns.scatterplot(
data=correct_df,
x="主成分1",
y="主成分2",
hue="真实类别名称",
hue_order=iris_label_names,
palette=palette,
s=85,
edgecolor="white",
linewidth=0.9,
alpha=0.9,
ax=ax,
legend=False
)
# 绘制预测错误的样本
sns.scatterplot(
data=wrong_df,
x="主成分1",
y="主成分2",
hue="真实类别名称",
hue_order=iris_label_names,
palette=palette,
marker="X",
s=140,
edgecolor="black",
linewidth=1.1,
alpha=0.95,
ax=ax,
legend=False
)
# 设置标题与坐标轴
ax.set_title("鸢尾花数据集真实类别与逻辑回归预测结果对比图", fontsize=16, pad=14)
ax.set_xlabel("主成分1", fontsize=12)
ax.set_ylabel("主成分2", fontsize=12)
ax.grid(True, linestyle="--", linewidth=0.8, alpha=0.6)
# 构造“真实类别”图例
class_handles = [
Line2D([0], [0], marker='o', color='w', label='山鸢尾',
markerfacecolor=palette["山鸢尾"], markeredgecolor='white', markersize=10),
Line2D([0], [0], marker='o', color='w', label='变色鸢尾',
markerfacecolor=palette["变色鸢尾"], markeredgecolor='white', markersize=10),
Line2D([0], [0], marker='o', color='w', label='维吉尼亚鸢尾',
markerfacecolor=palette["维吉尼亚鸢尾"], markeredgecolor='white', markersize=10)
]
legend1 = ax.legend(
handles=class_handles,
title="真实类别",
title_fontsize=12,
fontsize=11,
loc="upper right",
frameon=True,
fancybox=True,
borderpad=0.8,
labelspacing=0.6
)
# 构造“预测结果”图例
result_handles = [
Line2D([0], [0], marker='o', color='w', label='预测正确',
markerfacecolor='gray', markeredgecolor='white', markersize=9),
Line2D([0], [0], marker='X', color='w', label='预测错误',
markerfacecolor='gray', markeredgecolor='black', markersize=10)
]
legend2 = ax.legend(
handles=result_handles,
title="预测结果",
title_fontsize=12,
fontsize=11,
loc="lower right",
frameon=True,
fancybox=True,
borderpad=0.8,
labelspacing=0.6
)
# 美化图例边框与透明度
legend1.get_frame().set_alpha(0.88)
legend1.get_frame().set_edgecolor("#CCCCCC")
legend1.get_frame().set_linewidth(0.8)
legend2.get_frame().set_alpha(0.88)
legend2.get_frame().set_edgecolor("#CCCCCC")
legend2.get_frame().set_linewidth(0.8)
# 将第一个图例重新添加到坐标轴上
ax.add_artist(legend1)
plt.tight_layout()
plt.show()

为了在同一张图中同时展示真实类别分布与模型预测效果,这里采用“颜色表示真实类别、点形状表示预测结果是否正确”的方式进行可视化,并将图例拆分为“真实类别”和“预测结果”两个部分。这样不仅能够保留 PCA 二维投影下各类别的整体分布情况,也可以更清晰地观察模型在哪些区域预测正确、哪些区域更容易发生误分类。
从图中可以看出,山鸢尾样本大多集中在左侧独立区域,并且几乎都被正确分类,说明逻辑回归对这一类别具有较好的识别能力。而变色鸢尾与维吉尼亚鸢尾在中部和右侧区域存在一定重叠,因此错误样本主要分布在两类交界附近。这说明逻辑回归在类别边界较清晰时表现稳定,而在类别分布存在交叉时更容易产生混淆。
9. 逻辑回归的优点与局限性
逻辑回归最大的优点在于模型结构清晰、实现简单、训练效率高,并且能够直接输出概率结果。对于很多实际业务问题来说,这种“简单但稳定”的模型往往更容易落地。尤其是在需要较强可解释性的任务中,逻辑回归通常比复杂的黑盒模型更容易被接受。
不过,逻辑回归的局限性同样十分明显。由于它本质上仍然是线性模型,因此在面对复杂的非线性关系时,往往难以准确刻画数据分布。如果数据的真实边界非常复杂,那么决策树、随机森林、支持向量机或神经网络等模型通常会有更强的表达能力。此外,逻辑回归对特征工程的依赖也较强,是否标准化、是否处理共线性、是否引入交互特征,都会直接影响模型最终表现。
10. 适用场景
从实际应用来看,逻辑回归非常适合作为分类任务中的基础模型。一方面,它训练速度快,能够快速建立基线结果;另一方面,它输出清晰、可解释性较强,便于分析不同特征对预测结果的影响。因此,在很多中小规模数据集上,逻辑回归依然是值得优先尝试的选择。
它常见于用户流失预测、信用风险评估、文本情感分类、广告点击率预测以及医疗辅助诊断等任务中。即使在后续需要引入更复杂模型时,逻辑回归也通常会作为一个重要的对照模型存在。
11. 总结
scikit-learn 中的 LogisticRegression 是一个经典而实用的分类算法。它基于线性组合与 Sigmoid 概率映射完成分类任务,在二分类和多分类问题中都具有广泛应用价值。该模型不仅训练速度快,而且具备较强的可解释性,同时还能通过正则化机制控制过拟合风险,因此在实际机器学习项目中经常被作为首选基线模型。
本文围绕逻辑回归的基本原理、主要参数、二分类实战、多分类示例以及可视化分析进行了系统介绍。特别是在案例部分,通过 sns.countplot、sns.scatterplot、sns.heatmap、sns.barplot、sns.lineplot 和 PCA 对比图等方式,能够更直观地观察数据分布、分类效果、特征影响以及参数变化趋势,这也更符合技术博客系列文章中“代码 + 图示 + 解释”的写作风格。
总体来看,逻辑回归虽然结构简单,但并不意味着它能力有限。相反,正是由于它简单、稳定、易解释,才使得它在大量实际问题中始终保持着重要地位。对于学习 scikit-learn 的读者来说,逻辑回归既是理解分类模型的重要起点,也是进一步学习线性模型、概率模型和正则化方法的重要基础。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐


所有评论(0)