Python线性回归与逻辑回归,二分类与多分类全解析

32 阅读7分钟

Python线性回归与逻辑回归实战教程:二分类与多分类全解析 线性回归和逻辑回归是机器学习入门的核心算法,前者是回归任务的基础(预测连续值,如房价、销量),后者是分类任务的经典方法(预测离散类别,如疾病诊断、图像分类)。逻辑回归不仅能解决二分类问题(如判断是否患病),还能通过扩展实现多分类(如手写数字识别)。

一、准备工作:安装必备库

实现线性回归和逻辑回归需用到Python的机器学习核心库,其中scikit-learn提供了算法实现与数据集,pandas用于数据处理,numpy负责数值计算,matplotlib用于可视化。执行以下命令安装依赖:

pip install scikit-learn pandas numpy matplotlib

库功能说明:

  • scikit-learn:内置线性回归、逻辑回归模型,以及经典数据集和评估工具;
  • pandas:快速处理结构化数据,查看数据特征与分布;
  • numpy:支持数组与矩阵运算,是机器学习数值计算的基础;
  • matplotlib:绘制数据可视化图表,直观展示特征关系与模型结果。

二、线性回归:预测连续值的基础算法

2.1 算法原理

线性回归的核心是拟合特征与目标值的线性关系,假设特征与目标值满足: y=w0+w1x1+w2x2+...+wnxny = w_0 + w_1x_1 + w_2x_2 + ... + w_nx_n 其中,w0w_0为截距,w1wnw_1-w_n为特征权重,模型通过最小二乘法最小化预测值与真实值的平方误差,求解最优权重。

2.2 实战:加州房价预测

scikit-learn加州房价数据集为例,实现房价(连续值)的预测,步骤包括数据加载、探索、预处理、模型训练与评估。

步骤1:加载与探索数据集

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import fetch_california_housing

# 加载数据集
housing = fetch_california_housing()
# 转换为DataFrame方便探索
housing_df = pd.DataFrame(housing.data, columns=housing.feature_names)
housing_df['MedHouseVal'] = housing.target  # 添加房价标签

# 查看数据基本信息
print("数据集前5行:")
print(housing_df.head())

print("\n数据统计描述:")
print(housing_df.describe())

# 查看特征与房价的相关性
corr = housing_df.corr()['MedHouseVal'].sort_values(ascending=False)
print("\n特征与房价的相关性:")
print(corr)

# 可视化:平均收入与房价的关系
plt.figure(figsize=(8, 6))
plt.scatter(housing_df['MedInc'], housing_df['MedHouseVal'], alpha=0.5)
plt.xlabel('平均收入(万元)')
plt.ylabel('房屋中位数价格(万美元)')
plt.title('加州平均收入与房价的关系')
plt.show()

探索结论:平均收入(MedInc)与房价正相关性最强,是影响房价的核心特征。

步骤2:数据预处理

线性回归对特征尺度不敏感,但标准化能加速模型收敛;同时需划分训练集和测试集,避免数据泄露。

from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler

# 分离特征与标签
X = housing.data  # 特征矩阵
y = housing.target  # 房价标签

# 划分训练集(80%)和测试集(20%)
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, random_state=42
)

# 特征标准化
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)  # 仅在训练集拟合
X_test_scaled = scaler.transform(X_test)

print(f"训练集特征形状:{X_train_scaled.shape}")
print(f"测试集特征形状:{X_test_scaled.shape}")

步骤3:构建模型并训练

使用scikit-learnLinearRegression实现普通最小二乘线性回归:

from sklearn.linear_model import LinearRegression

# 初始化模型
lr = LinearRegression()

# 训练模型
lr.fit(X_train_scaled, y_train)

# 输出模型参数
print("模型截距:", lr.intercept_)
print("\n特征权重:")
for feature, coef in zip(housing.feature_names, lr.coef_):
    print(f"{feature}: {coef:.2f}")

参数解读:权重为正表示特征与房价正相关(如平均收入),权重为负表示负相关(如经度,代表加州东西部地域差异)。

步骤4:模型评估

回归任务的核心评估指标包括平均绝对误差(MAE)根均方误差(RMSE)决定系数(R²)

from sklearn.metrics import mean_absolute_error, mean_squared_error, r2_score

# 测试集预测
y_pred = lr.predict(X_test_scaled)

# 计算评估指标
mae = mean_absolute_error(y_test, y_pred)
rmse = np.sqrt(mean_squared_error(y_test, y_pred))
r2 = r2_score(y_test, y_pred)

print(f"平均绝对误差(MAE):{mae:.2f} 万美元")
print(f"根均方误差(RMSE):{rmse:.2f} 万美元")
print(f"决定系数(R²):{r2:.2f}")

# 可视化:真实值vs预测值
plt.figure(figsize=(8, 6))
plt.scatter(y_test, y_pred, alpha=0.5)
plt.plot([y_test.min(), y_test.max()], [y_test.min(), y_test.max()], 'r--')
plt.xlabel('真实房价(万美元)')
plt.ylabel('预测房价(万美元)')
plt.title('线性回归:真实房价与预测房价对比')
plt.show()

结果解读:普通线性回归在该数据集上的R²约为0.58,说明模型能解释58%的房价变异,剩余误差源于特征的非线性关系。

步骤5:模型优化(正则化)

普通线性回归易过拟合,可通过**岭回归(Ridge)**加入L2正则化约束权重:

from sklearn.linear_model import Ridge
from sklearn.model_selection import GridSearchCV

# 网格搜索优化正则化强度
param_grid = {'alpha': [0.1, 1, 10, 100]}
grid = GridSearchCV(Ridge(), param_grid, cv=5, scoring='r2')
grid.fit(X_train_scaled, y_train)

print(f"最优正则化强度:{grid.best_params_['alpha']}")
print(f"交叉验证最优R²:{grid.best_score_:.2f}")

# 最优模型评估
best_ridge = grid.best_estimator_
y_pred_ridge = best_ridge.predict(X_test_scaled)
print(f"岭回归测试集R²:{r2_score(y_test, y_pred_ridge):.2f}")

优化效果:岭回归通过正则化能小幅提升模型泛化能力,R²通常略高于普通线性回归。

三、逻辑回归:二分类任务实战

3.1 算法原理

逻辑回归虽名为“回归”,实则是分类算法,核心是通过Sigmoid函数将线性回归的输出(连续值)映射到0-1之间,代表样本属于正类的概率: σ(z)=11+ez\sigma(z) = \frac{1}{1+e^{-z}} 其中z=w0+w1x1+...+wnxnz = w_0 + w_1x_1 + ... + w_nx_n,当σ(z)>0.5\sigma(z) > 0.5时预测为正类,否则为负类。模型通过对数似然损失优化权重。

3.2 实战:乳腺癌良恶性二分类

scikit-learn乳腺癌数据集为例,实现肿瘤良恶性的二分类预测(正类:恶性,负类:良性)。

步骤1:加载与探索数据集

from sklearn.datasets import load_breast_cancer

# 加载数据集
cancer = load_breast_cancer()
cancer_df = pd.DataFrame(cancer.data, columns=cancer.feature_names)
cancer_df['target'] = cancer.target  # 0:恶性,1:良性

# 查看数据信息
print("数据集前5行:")
print(cancer_df.head())

print("\n样本类别分布:")
print(cancer_df['target'].value_counts())  # 查看类别是否平衡

# 可视化:第一个特征在两类中的分布
plt.figure(figsize=(8, 6))
for target, color in zip([0, 1], ['red', 'green']):
    data = cancer_df[cancer_df['target'] == target]
    plt.hist(data['mean radius'], bins=20, color=color, alpha=0.5, label=cancer.target_names[target])
plt.xlabel('平均半径')
plt.ylabel('样本数')
plt.title('乳腺癌样本平均半径分布')
plt.legend()
plt.show()

探索结论:恶性肿瘤的平均半径显著大于良性,该特征具有强区分度。

步骤2:数据预处理

逻辑回归基于梯度下降优化,特征标准化能大幅提升模型收敛速度,同时需划分训练集和测试集:

# 分离特征与标签
X = cancer.data
y = cancer.target

# 划分数据集
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.3, random_state=42, stratify=y  # stratify保持类别比例
)

# 标准化
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)

步骤3:构建二分类逻辑回归模型

from sklearn.linear_model import LogisticRegression

# 初始化模型(默认L2正则化,C为正则化强度的倒数)
lr_clf = LogisticRegression(C=1.0, random_state=42, max_iter=1000)

# 训练模型
lr_clf.fit(X_train_scaled, y_train)

# 输出特征权重(绝对值越大,特征对分类的影响越强)
print("特征权重(前5个):")
for feature, coef in zip(cancer.feature_names[:5], lr_clf.coef_[0][:5]):
    print(f"{feature}: {coef:.2f}")

步骤4:模型评估

二分类任务的评估指标包括准确率混淆矩阵精确率/召回率ROC-AUC

from sklearn.metrics import accuracy_score, confusion_matrix, classification_report, roc_auc_score, roc_curve

# 测试集预测
y_pred = lr_clf.predict(X_test_scaled)
y_pred_proba = lr_clf.predict_proba(X_test_scaled)[:, 1]  # 正类概率

# 准确率与混淆矩阵
print(f"模型准确率:{accuracy_score(y_test, y_pred):.2f}")
print("\n混淆矩阵:")
print(confusion_matrix(y_test, y_pred))

# 分类报告(精确率、召回率、F1值)
print("\n分类报告:")
print(classification_report(y_test, y_pred, target_names=cancer.target_names))

# ROC-AUC曲线
auc = roc_auc_score(y_test, y_pred_proba)
fpr, tpr, _ = roc_curve(y_test, y_pred_proba)

plt.figure(figsize=(8, 6))
plt.plot(fpr, tpr, label=f'AUC = {auc:.2f}')
plt.plot([0, 1], [0, 1], 'r--')
plt.xlabel('假正例率(FPR)')
plt.ylabel('真正例率(TPR)')
plt.title('逻辑回归二分类:ROC曲线')
plt.legend()
plt.show()

结果解读:该数据集特征区分度高,逻辑回归的准确率可达97%以上,AUC接近1,模型性能优异。

步骤5:处理类别不平衡(可选)

若数据中两类样本数量差异大,可通过class_weight参数设置权重:

# 初始化带类别权重的模型
lr_balanced = LogisticRegression(class_weight='balanced', random_state=42, max_iter=1000)
lr_balanced.fit(X_train_scaled, y_train)

# 评估
y_pred_balanced = lr_balanced.predict(X_test_scaled)
print(f"平衡权重后准确率:{accuracy_score(y_test, y_pred_balanced):.2f}")

四、逻辑回归:多分类任务实战

4.1 算法原理

逻辑回归默认解决二分类问题,实现多分类需采用**一对多(OVR)多对多(OVO)**策略:

  • OVR:为每个类别训练一个二分类模型,预测时选择概率最大的类别;
  • OVO:为每两个类别训练一个二分类模型,预测时通过投票确定类别。 scikit-learnLogisticRegression默认使用OVR,可通过multi_class参数指定。

4.2 实战:鸢尾花品种多分类

以鸢尾花数据集为例,实现3个品种的多分类预测。

步骤1:数据加载与预处理

from sklearn.datasets import load_iris

# 加载数据集
iris = load_iris()
X = iris.data
y = iris.target

# 划分数据集并标准化
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.3, random_state=42, stratify=y
)
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)

步骤2:构建多分类逻辑回归模型

# 初始化多分类模型(指定multi_class='ovr'或'multinomial')
lr_multi = LogisticRegression(multi_class='ovr', random_state=42, max_iter=1000)

# 训练模型
lr_multi.fit(X_train_scaled, y_train)

参数说明multi_class='multinomial'时使用软最大化(Softmax)回归,更适合多分类场景。

步骤3:模型评估

# 测试集预测
y_pred = lr_multi.predict(X_test_scaled)
y_pred_proba = lr_multi.predict_proba(X_test_scaled)

# 准确率与分类报告
print(f"多分类准确率:{accuracy_score(y_test, y_pred):.2f}")
print("\n分类报告:")
print(classification_report(y_test, y_pred, target_names=iris.target_names))

# 混淆矩阵
print("\n混淆矩阵:")
print(confusion_matrix(y_test, y_pred))

结果解读:鸢尾花数据集特征区分度高,多分类逻辑回归的准确率可达98%以上,错误主要出现在相似度较高的品种边界样本。

步骤4:新样本预测

# 模拟新样本(花萼长度、花萼宽度、花瓣长度、花瓣宽度)
new_sample = np.array([[5.1, 3.5, 1.4, 0.2]])
new_sample_scaled = scaler.transform(new_sample)

# 预测类别与概率
pred_class = lr_multi.predict(new_sample_scaled)
pred_proba = lr_multi.predict_proba(new_sample_scaled)

print(f"预测品种:{iris.target_names[pred_class[0]]}")
print(f"各品种概率:{pred_proba[0].round(3)}")

五、实战技巧与常见问题

5.1 线性回归常见问题

  1. 多重共线性:若特征间高度相关,可通过主成分分析(PCA)降维或剔除冗余特征;
  2. 非线性关系:可对特征进行非线性变换(如对数、平方),或使用多项式回归;
  3. 异常值:通过箱线图或Z-score剔除异常值,避免模型被极端值影响。

5.2 逻辑回归常见问题

  1. 特征标准化:逻辑回归基于梯度下降,特征尺度差异会导致收敛缓慢,必须标准化;
  2. 正则化选择:L1正则化(penalty='l1')可实现特征选择,适合高维数据;L2正则化(penalty='l2')适合避免过拟合;
  3. 迭代次数:若出现“收敛警告”,可增大max_iter参数(如1000);
  4. 类别不平衡:除了class_weight,还可通过过采样(SMOTE)或欠采样平衡数据。

5.3 通用实战技巧

  1. 交叉验证:使用GridSearchCVRandomizedSearchCV优化超参数,避免单一测试集的结果偏差;
  2. 特征工程:通过相关性分析、方差分析筛选重要特征,提升模型效率;
  3. 模型解释性:线性回归和逻辑回归的权重具有明确的物理意义,可通过权重分析特征的重要性。