Python线性回归与逻辑回归实战教程:二分类与多分类全解析 线性回归和逻辑回归是机器学习入门的核心算法,前者是回归任务的基础(预测连续值,如房价、销量),后者是分类任务的经典方法(预测离散类别,如疾病诊断、图像分类)。逻辑回归不仅能解决二分类问题(如判断是否患病),还能通过扩展实现多分类(如手写数字识别)。
一、准备工作:安装必备库
实现线性回归和逻辑回归需用到Python的机器学习核心库,其中scikit-learn提供了算法实现与数据集,pandas用于数据处理,numpy负责数值计算,matplotlib用于可视化。执行以下命令安装依赖:
pip install scikit-learn pandas numpy matplotlib
库功能说明:
scikit-learn:内置线性回归、逻辑回归模型,以及经典数据集和评估工具;pandas:快速处理结构化数据,查看数据特征与分布;numpy:支持数组与矩阵运算,是机器学习数值计算的基础;matplotlib:绘制数据可视化图表,直观展示特征关系与模型结果。
二、线性回归:预测连续值的基础算法
2.1 算法原理
线性回归的核心是拟合特征与目标值的线性关系,假设特征与目标值满足: 其中,为截距,为特征权重,模型通过最小二乘法最小化预测值与真实值的平方误差,求解最优权重。
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-learn的LinearRegression实现普通最小二乘线性回归:
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之间,代表样本属于正类的概率: 其中,当时预测为正类,否则为负类。模型通过对数似然损失优化权重。
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-learn的LogisticRegression默认使用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 线性回归常见问题
- 多重共线性:若特征间高度相关,可通过主成分分析(PCA)降维或剔除冗余特征;
- 非线性关系:可对特征进行非线性变换(如对数、平方),或使用多项式回归;
- 异常值:通过箱线图或Z-score剔除异常值,避免模型被极端值影响。
5.2 逻辑回归常见问题
- 特征标准化:逻辑回归基于梯度下降,特征尺度差异会导致收敛缓慢,必须标准化;
- 正则化选择:L1正则化(
penalty='l1')可实现特征选择,适合高维数据;L2正则化(penalty='l2')适合避免过拟合; - 迭代次数:若出现“收敛警告”,可增大
max_iter参数(如1000); - 类别不平衡:除了
class_weight,还可通过过采样(SMOTE)或欠采样平衡数据。
5.3 通用实战技巧
- 交叉验证:使用
GridSearchCV或RandomizedSearchCV优化超参数,避免单一测试集的结果偏差; - 特征工程:通过相关性分析、方差分析筛选重要特征,提升模型效率;
- 模型解释性:线性回归和逻辑回归的权重具有明确的物理意义,可通过权重分析特征的重要性。