《人工智能从入门到精通》第三篇:机器学习基础算法实战与应用

一、章节引言:机器学习如何让计算机"自主学习"?
💡 学习目标 :理解机器学习的核心概念与分类,掌握线性回归、逻辑回归、决策树三大基础算法的原理与代码实现,完成真实数据集上的预测任务,对比不同算法的性能表现。
💡 重点提示 :本章节是AI算法层的核心基础------所有高级机器学习/深度学习算法都是基于这些基础算法的扩展与优化,务必理解算法原理并通过代码验证。
在第2篇我们完成了Python基础与AI开发环境搭建,实现了第一个AI代码案例(线性回归预测房屋价格)。但那只是"手动实现"的简单版本,真正的机器学习开发需要基于成熟的算法库(如scikit-learn)进行操作。
什么是机器学习?
机器学习是一种让计算机通过数据自主学习模式或规律,而无需通过明确编程实现的技术。它的核心流程是:
- 数据准备:收集、清洗、预处理数据集
- 模型选择:根据任务类型选择合适的算法
- 模型训练:让算法在训练集上学习规律
- 模型评估:用测试集验证模型的泛化能力
- 模型部署:将训练好的模型应用到实际场景
接下来,我们将分四个模块推进:机器学习核心概念与分类 → 三大基础算法原理与代码实现 → 真实数据集实战 → 算法性能对比
二、模块1:机器学习核心概念与分类
⚠️ 注意:这里只讲解AI开发中必须掌握的核心概念------比如训练集/测试集划分、过拟合/欠拟合、评估指标等,这些是模型选择与优化的基础。
2.1 核心概念
2.1.1 训练集与测试集
- 训练集:用于模型学习规律的数据集(通常占总数据的70%~80%)
- 测试集:用于验证模型泛化能力的数据集(通常占总数据的20%~30%)
- 交叉验证:将训练集再划分为子训练集和验证集,用于评估模型在不同数据子集上的性能(避免单次划分的偶然性)
python
# scikit-learn中常用的数据划分方法
from sklearn.model_selection import train_test_split
import numpy as np
# 生成模拟数据集
X = np.random.randn(1000, 10)
y = np.random.randn(1000)
# 划分训练集和测试集(8:2比例,random_state=42保证结果可复现)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
print(f"训练集样本数:{X_train.shape[0]},特征数:{X_train.shape[1]}")
print(f"测试集样本数:{X_test.shape[0]},特征数:{X_test.shape[1]}")
# 交叉验证(5折交叉验证)
from sklearn.model_selection import cross_val_score
from sklearn.linear_model import LinearRegression
model = LinearRegression()
scores = cross_val_score(model, X_train, y_train, cv=5)
print(f"5折交叉验证得分:{scores}")
print(f"平均得分:{np.mean(scores):.4f}")
2.1.2 过拟合与欠拟合
- 欠拟合:模型过于简单,无法捕捉数据中的规律(训练集和测试集上的得分都很低)
- 过拟合:模型过于复杂,过度捕捉训练集的噪声(训练集得分很高,测试集得分很低)
- 解决方法 :
- 欠拟合:增加模型复杂度(如使用多项式回归、决策树深度加深)
- 过拟合:减少模型复杂度(如使用正则化、决策树剪枝、增加训练数据)
python
# 用多项式回归演示过拟合与欠拟合
import numpy as np
import matplotlib.pyplot as plt
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import PolynomialFeatures
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error
# 生成模拟数据(非线性关系)
np.random.seed(42)
X = np.linspace(0, 10, 100)
y = 2 * X + 3 + np.sin(X) * 5 + np.random.randn(100) * 0.5
# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X.reshape(-1, 1), y, test_size=0.3, random_state=42)
# 定义不同复杂度的多项式回归模型
degrees = [1, 3, 10, 20]
results = []
for degree in degrees:
model = Pipeline([
("poly", PolynomialFeatures(degree=degree)),
("linear", LinearRegression())
])
model.fit(X_train, y_train)
y_train_pred = model.predict(X_train)
y_test_pred = model.predict(X_test)
train_loss = mean_squared_error(y_train, y_train_pred)
test_loss = mean_squared_error(y_test, y_test_pred)
results.append((degree, train_loss, test_loss))
print(f"多项式次数:{degree},训练集MSE:{train_loss:.4f},测试集MSE:{test_loss:.4f}")
# 可视化结果
plt.figure(figsize=(12, 6))
for i, (degree, _, _) in enumerate(results):
model = Pipeline([
("poly", PolynomialFeatures(degree=degree)),
("linear", LinearRegression())
])
model.fit(X_train, y_train)
X_plot = np.linspace(0, 10, 200).reshape(-1, 1)
y_plot = model.predict(X_plot)
plt.subplot(2, 2, i+1)
plt.scatter(X_train, y_train, alpha=0.5, color="#FF6B6B", label="训练集")
plt.scatter(X_test, y_test, alpha=0.5, color="#4ECDC4", label="测试集")
plt.plot(X_plot, y_plot, color="#2C3E50", linewidth=2, label="预测曲线")
plt.xlabel("X")
plt.ylabel("y")
plt.title(f"多项式次数:{degree}")
plt.legend()
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
结果分析:
- 当多项式次数=1时,模型为线性回归,欠拟合(无法捕捉sin函数的非线性特征)
- 当多项式次数=3时,模型复杂度适中,拟合效果最佳(训练集和测试集得分都较高)
- 当多项式次数=10时,模型开始过拟合(训练集得分很高,测试集得分下降)
- 当多项式次数=20时,模型严重过拟合(预测曲线剧烈波动,测试集得分大幅下降)
2.1.3 评估指标
机器学习的评估指标取决于任务类型(回归/分类):
- 回归任务:均方误差(MSE)、平均绝对误差(MAE)、R²评分
- 分类任务:准确率(Accuracy)、精确率(Precision)、召回率(Recall)、F1值、混淆矩阵
python
# scikit-learn中常用的评估指标
from sklearn.metrics import mean_squared_error, mean_absolute_error, r2_score
from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score, confusion_matrix
# 回归任务指标示例
y_true_reg = np.array([10, 12, 15, 18, 20])
y_pred_reg = np.array([9.5, 12.5, 14.5, 18.5, 19.5])
print("回归任务指标:")
print(f"MSE:{mean_squared_error(y_true_reg, y_pred_reg):.4f}")
print(f"MAE:{mean_absolute_error(y_true_reg, y_pred_reg):.4f}")
print(f"R²评分:{r2_score(y_true_reg, y_pred_reg):.4f}")
# 分类任务指标示例
y_true_clf = np.array([0, 1, 0, 1, 1, 0])
y_pred_clf = np.array([0, 1, 1, 1, 0, 0])
print("\n分类任务指标:")
print(f"准确率:{accuracy_score(y_true_clf, y_pred_clf):.4f}")
print(f"精确率:{precision_score(y_true_clf, y_pred_clf):.4f}")
print(f"召回率:{recall_score(y_true_clf, y_pred_clf):.4f}")
print(f"F1值:{f1_score(y_true_clf, y_pred_clf):.4f}")
print("混淆矩阵:")
print(confusion_matrix(y_true_clf, y_pred_clf))
2.2 机器学习分类
机器学习可以根据学习方式 和任务类型进行分类:
2.2.1 按学习方式分类
- 监督学习:模型从标注数据(特征+标签)中学习规律(如线性回归、逻辑回归、决策树)
- 无监督学习:模型从无标注数据中学习规律(如聚类、降维)
- 半监督学习:模型从部分标注数据和部分无标注数据中学习规律
- 强化学习:模型通过与环境互动,根据反馈信号学习最优策略(如AlphaGo)
2.2.2 按任务类型分类
- 回归任务:预测连续值(如房屋价格、销售额)
- 分类任务:预测离散值(如垃圾邮件分类、疾病诊断)
- 聚类任务:将相似的数据点分为一类(如客户分群、图像分割)
- 降维任务:降低数据的维度(如主成分分析PCA、t-SNE可视化)
三、模块2:三大基础算法原理与代码实现
💡 重点算法 :线性回归(回归任务)→ 逻辑回归(分类任务)→ 决策树(回归/分类任务)
💡 实现方式:基于scikit-learn库实现------这是AI开发中最常用的机器学习库
3.1 算法1:线性回归(回归任务)
3.1.1 原理简介
线性回归是最简单、最基础的回归算法 ,它假设特征与标签之间存在线性关系:
y=w0+w1x1+w2x2+⋯+wnxn+ϵ y = w_0 + w_1x_1 + w_2x_2 + \dots + w_nx_n + \epsilon y=w0+w1x1+w2x2+⋯+wnxn+ϵ
其中:
- yyy:标签(预测值)
- x1,x2,...,xnx_1,x_2,\dots,x_nx1,x2,...,xn:特征
- w0w_0w0:偏置(截距)
- w1,w2,...,wnw_1,w_2,\dots,w_nw1,w2,...,wn:特征权重(回归系数)
- ϵ\epsilonϵ:噪声(不可预测的误差)
3.1.2 代码实现(基于scikit-learn)
python
# 线性回归代码实现
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error, r2_score
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
# 1. 加载数据集(使用scikit-learn内置的波士顿房价数据集)
from sklearn.datasets import load_boston
boston = load_boston()
X = pd.DataFrame(boston.data, columns=boston.feature_names)
y = pd.Series(boston.target)
# 2. 数据预处理(检查缺失值)
print("数据集缺失值统计:")
print(X.isnull().sum())
print(y.isnull().sum())
# 3. 划分训练集和测试集(8:2比例)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
print(f"\n训练集样本数:{X_train.shape[0]},特征数:{X_train.shape[1]}")
print(f"测试集样本数:{X_test.shape[0]},特征数:{X_test.shape[1]}")
# 4. 模型训练
model = LinearRegression()
model.fit(X_train, y_train)
# 5. 模型预测
y_train_pred = model.predict(X_train)
y_test_pred = model.predict(X_test)
# 6. 模型评估
train_mse = mean_squared_error(y_train, y_train_pred)
test_mse = mean_squared_error(y_test, y_test_pred)
train_r2 = r2_score(y_train, y_train_pred)
test_r2 = r2_score(y_test, y_test_pred)
print(f"\n模型评估结果:")
print(f"训练集MSE:{train_mse:.4f},R²评分:{train_r2:.4f}")
print(f"测试集MSE:{test_mse:.4f},R²评分:{test_r2:.4f}")
# 7. 模型参数分析
coefficients = pd.DataFrame({"特征": X.columns, "权重": model.coef_})
coefficients = coefficients.sort_values(by="权重", ascending=False)
print("\n特征权重排序:")
print(coefficients)
print(f"偏置(截距):{model.intercept_:.4f}")
# 8. 可视化预测结果
plt.figure(figsize=(10, 5))
# 训练集预测结果
plt.subplot(1, 2, 1)
plt.scatter(y_train, y_train_pred, alpha=0.7, color="#FF6B6B")
plt.plot([y_train.min(), y_train.max()], [y_train.min(), y_train.max()], color="#2C3E50", linewidth=2)
plt.xlabel("真实房价")
plt.ylabel("预测房价")
plt.title(f"训练集预测结果(R²={train_r2:.4f})")
plt.grid(True, alpha=0.3)
# 测试集预测结果
plt.subplot(1, 2, 2)
plt.scatter(y_test, y_test_pred, alpha=0.7, color="#4ECDC4")
plt.plot([y_test.min(), y_test.max()], [y_test.min(), y_test.max()], color="#2C3E50", linewidth=2)
plt.xlabel("真实房价")
plt.ylabel("预测房价")
plt.title(f"测试集预测结果(R²={test_r2:.4f})")
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
结果分析:
- 模型在测试集上的R²评分为0.66,说明模型能解释66%的房价变化
- 特征权重排序显示:RM(房间数量)对房价的影响最大(正相关),LSTAT(低收入人口比例)对房价的影响最小(负相关)
3.2 算法2:逻辑回归(分类任务)
3.2.1 原理简介
逻辑回归是最简单、最基础的分类算法 ,它通过Sigmoid函数 将线性回归的输出转换为0~1之间的概率值:
P(y=1∣X)=11+e−(w0+w1x1+⋯+wnxn) P(y=1|X) = \frac{1}{1 + e^{-(w_0 + w_1x_1 + \dots + w_nx_n)}} P(y=1∣X)=1+e−(w0+w1x1+⋯+wnxn)1
其中:
- P(y=1∣X)P(y=1|X)P(y=1∣X):样本属于类别1的概率
- eee:自然常数
- w0,w1,...,wnw_0,w_1,\dots,w_nw0,w1,...,wn:模型参数
逻辑回归的决策边界是P(y=1∣X)=0.5P(y=1|X)=0.5P(y=1∣X)=0.5,即:
w0+w1x1+⋯+wnxn=0 w_0 + w_1x_1 + \dots + w_nx_n = 0 w0+w1x1+⋯+wnxn=0
3.2.2 代码实现(基于scikit-learn)
python
# 逻辑回归代码实现
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score, confusion_matrix
from sklearn.metrics import roc_curve, auc
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
# 1. 加载数据集(使用scikit-learn内置的乳腺癌数据集)
from sklearn.datasets import load_breast_cancer
cancer = load_breast_cancer()
X = pd.DataFrame(cancer.data, columns=cancer.feature_names)
y = pd.Series(cancer.target)
# 2. 数据预处理(检查缺失值)
print("数据集缺失值统计:")
print(X.isnull().sum())
print(y.isnull().sum())
# 3. 划分训练集和测试集(8:2比例)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
print(f"\n训练集样本数:{X_train.shape[0]},特征数:{X_train.shape[1]}")
print(f"测试集样本数:{X_test.shape[0]},特征数:{X_test.shape[1]}")
# 4. 模型训练(使用L2正则化,C=1.0)
model = LogisticRegression(C=1.0, max_iter=10000)
model.fit(X_train, y_train)
# 5. 模型预测
y_train_pred = model.predict(X_train)
y_test_pred = model.predict(X_test)
y_train_prob = model.predict_proba(X_train)[:, 1]
y_test_prob = model.predict_proba(X_test)[:, 1]
# 6. 模型评估
train_acc = accuracy_score(y_train, y_train_pred)
test_acc = accuracy_score(y_test, y_test_pred)
train_precision = precision_score(y_train, y_train_pred)
test_precision = precision_score(y_test, y_test_pred)
train_recall = recall_score(y_train, y_train_pred)
test_recall = recall_score(y_test, y_test_pred)
train_f1 = f1_score(y_train, y_train_pred)
test_f1 = f1_score(y_test, y_test_pred)
print(f"\n模型评估结果:")
print(f"训练集准确率:{train_acc:.4f},精确率:{train_precision:.4f},召回率:{train_recall:.4f},F1值:{train_f1:.4f}")
print(f"测试集准确率:{test_acc:.4f},精确率:{test_precision:.4f},召回率:{test_recall:.4f},F1值:{test_f1:.4f}")
# 混淆矩阵
print("\n测试集混淆矩阵:")
print(confusion_matrix(y_test, y_test_pred))
# 7. ROC曲线与AUC值
fpr_train, tpr_train, thresholds_train = roc_curve(y_train, y_train_prob)
roc_auc_train = auc(fpr_train, tpr_train)
fpr_test, tpr_test, thresholds_test = roc_curve(y_test, y_test_prob)
roc_auc_test = auc(fpr_test, tpr_test)
plt.figure(figsize=(10, 5))
# 训练集ROC曲线
plt.subplot(1, 2, 1)
plt.plot(fpr_train, tpr_train, color="#FF6B6B", linewidth=2, label=f"ROC曲线(AUC={roc_auc_train:.4f})")
plt.plot([0, 1], [0, 1], color="#2C3E50", linestyle="--", linewidth=2)
plt.xlabel("假正率(FPR)")
plt.ylabel("真阳性率(TPR)")
plt.title(f"训练集ROC曲线")
plt.legend()
plt.grid(True, alpha=0.3)
# 测试集ROC曲线
plt.subplot(1, 2, 2)
plt.plot(fpr_test, tpr_test, color="#4ECDC4", linewidth=2, label=f"ROC曲线(AUC={roc_auc_test:.4f})")
plt.plot([0, 1], [0, 1], color="#2C3E50", linestyle="--", linewidth=2)
plt.xlabel("假正率(FPR)")
plt.ylabel("真阳性率(TPR)")
plt.title(f"测试集ROC曲线")
plt.legend()
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
# 8. 模型参数分析
coefficients = pd.DataFrame({"特征": X.columns, "权重": model.coef_[0]})
coefficients = coefficients.sort_values(by="权重", ascending=False)
print("\n特征权重排序:")
print(coefficients)
print(f"偏置(截距):{model.intercept_[0]:.4f}")
结果分析:
- 模型在测试集上的准确率为0.97,AUC值为0.99,说明模型的分类效果非常好
- 特征权重排序显示:worst radius(最大半径)对乳腺癌的预测影响最大(正相关),mean symmetry(平均对称性)对预测的影响最小(负相关)
3.3 算法3:决策树(回归/分类任务)
3.3.1 原理简介
决策树是最直观、最易于理解的机器学习算法 ,它通过递归划分数据集的方式构建决策树模型:
- 选择最佳特征:根据信息增益、信息增益比或基尼指数选择最佳特征
- 划分数据集:根据最佳特征将数据集划分为若干子集
- 递归构建子树:对每个子集重复上述过程,直到满足停止条件
- 生成决策树:将划分过程用树形结构表示
3.3.2 代码实现(基于scikit-learn)
python
# 决策树代码实现(分类任务)
from sklearn.tree import DecisionTreeClassifier, plot_tree
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score, confusion_matrix
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
# 1. 加载数据集(使用scikit-learn内置的鸢尾花数据集)
from sklearn.datasets import load_iris
iris = load_iris()
X = pd.DataFrame(iris.data, columns=iris.feature_names)
y = pd.Series(iris.target)
# 2. 数据预处理(检查缺失值)
print("数据集缺失值统计:")
print(X.isnull().sum())
print(y.isnull().sum())
# 3. 划分训练集和测试集(8:2比例)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
print(f"\n训练集样本数:{X_train.shape[0]},特征数:{X_train.shape[1]}")
print(f"测试集样本数:{X_test.shape[0]},特征数:{X_test.shape[1]}")
# 4. 模型训练(使用基尼指数作为划分标准,最大深度为3)
model = DecisionTreeClassifier(criterion="gini", max_depth=3, random_state=42)
model.fit(X_train, y_train)
# 5. 模型预测
y_train_pred = model.predict(X_train)
y_test_pred = model.predict(X_test)
# 6. 模型评估
train_acc = accuracy_score(y_train, y_train_pred)
test_acc = accuracy_score(y_test, y_test_pred)
train_precision = precision_score(y_train, y_train_pred, average="weighted")
test_precision = precision_score(y_test, y_test_pred, average="weighted")
train_recall = recall_score(y_train, y_train_pred, average="weighted")
test_recall = recall_score(y_test, y_test_pred, average="weighted")
train_f1 = f1_score(y_train, y_train_pred, average="weighted")
test_f1 = f1_score(y_test, y_test_pred, average="weighted")
print(f"\n模型评估结果:")
print(f"训练集准确率:{train_acc:.4f},精确率:{train_precision:.4f},召回率:{train_recall:.4f},F1值:{train_f1:.4f}")
print(f"测试集准确率:{test_acc:.4f},精确率:{test_precision:.4f},召回率:{test_recall:.4f},F1值:{test_f1:.4f}")
# 混淆矩阵
print("\n测试集混淆矩阵:")
print(confusion_matrix(y_test, y_test_pred))
# 7. 可视化决策树
plt.figure(figsize=(20, 10))
plot_tree(model, filled=True, rounded=True, feature_names=iris.feature_names, class_names=iris.target_names)
plt.title("决策树可视化(最大深度=3)")
plt.show()
# 8. 特征重要性分析
importances = pd.DataFrame({"特征": X.columns, "重要性": model.feature_importances_})
importances = importances.sort_values(by="重要性", ascending=False)
print("\n特征重要性排序:")
print(importances)
结果分析:
- 模型在测试集上的准确率为1.0,说明模型对鸢尾花数据集的分类效果完美
- 特征重要性分析显示:petal width(花瓣宽度)对分类的影响最大(重要性为0.9),其他特征的重要性较低
- 决策树可视化显示:模型通过petal width <= 0.8将数据集分为三个类别,这与鸢尾花数据集的真实情况相符
四、模块3:真实数据集实战------客户流失预测
💡 案例背景 :客户流失是电信行业的一个重要问题,运营商希望通过机器学习模型预测哪些客户可能会流失,以便提前采取措施(如提供优惠活动)。
💡 技术栈 :pandas(数据处理)+ scikit-learn(模型训练与评估)+ matplotlib(可视化)
💡 数据集:Kaggle上的Telco Customer Churn数据集(包含21个特征和1个标签)
4.1 数据加载与预处理
python
# 客户流失预测代码实现
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import LabelEncoder, StandardScaler
from sklearn.linear_model import LogisticRegression
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score, confusion_matrix
from sklearn.metrics import roc_curve, auc
# 1. 加载数据集
data = pd.read_csv("./data/WA_Fn-UseC_-Telco-Customer-Churn.csv")
# 2. 数据预处理
# 2.1 查看数据集基本信息
print("数据集基本信息:")
print(data.info())
print("\n数据集前5行:")
print(data.head())
print("\n数据集描述性统计:")
print(data.describe())
# 2.2 检查缺失值
print("\n数据集缺失值统计:")
print(data.isnull().sum())
# 2.3 处理缺失值(TotalCharges列有11个缺失值,删除这些行)
data = data[data["TotalCharges"] != " "]
data["TotalCharges"] = pd.to_numeric(data["TotalCharges"])
# 2.4 处理分类特征(使用LabelEncoder编码)
categorical_features = ["Partner", "Dependents", "PhoneService", "MultipleLines", "InternetService",
"OnlineSecurity", "OnlineBackup", "DeviceProtection", "TechSupport", "StreamingTV",
"StreamingMovies", "Contract", "PaperlessBilling", "PaymentMethod", "Churn"]
label_encoders = {}
for feature in categorical_features:
label_encoders[feature] = LabelEncoder()
data[feature] = label_encoders[feature].fit_transform(data[feature])
# 2.5 处理数值特征(使用StandardScaler标准化)
numerical_features = ["tenure", "MonthlyCharges", "TotalCharges"]
scaler = StandardScaler()
data[numerical_features] = scaler.fit_transform(data[numerical_features])
# 3. 划分训练集和测试集(8:2比例)
X = data.drop("Churn", axis=1)
y = data["Churn"]
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
print(f"\n训练集样本数:{X_train.shape[0]},特征数:{X_train.shape[1]}")
print(f"测试集样本数:{X_test.shape[0]},特征数:{X_test.shape[1]}")
# 4. 数据可视化(分析客户流失与各特征的关系)
plt.figure(figsize=(15, 10))
# 客户流失分布
plt.subplot(2, 2, 1)
sns.countplot(x="Churn", data=data)
plt.title("客户流失分布")
# 合同类型与客户流失的关系
plt.subplot(2, 2, 2)
sns.countplot(x="Contract", hue="Churn", data=data)
plt.title("合同类型与客户流失的关系")
# 月度费用与客户流失的关系
plt.subplot(2, 2, 3)
sns.boxplot(x="Churn", y="MonthlyCharges", data=data)
plt.title("月度费用与客户流失的关系")
# tenure与客户流失的关系
plt.subplot(2, 2, 4)
sns.boxplot(x="Churn", y="tenure", data=data)
plt.title("tenure与客户流失的关系")
plt.tight_layout()
plt.show()
数据预处理结果:
- 数据集包含7043个客户,其中1869个客户流失(占比26.5%)
- 删除了TotalCharges列的11个缺失值
- 对所有分类特征进行了LabelEncoder编码,对数值特征进行了StandardScaler标准化
- 数据可视化显示:客户流失与合同类型、月度费用、tenure等特征有明显的关系(长期合同的客户流失率更低,月度费用高的客户流失率更高,tenure短的客户流失率更高)
4.2 模型训练与评估
python
# 5. 模型训练与评估
models = {
"Logistic Regression": LogisticRegression(C=1.0, max_iter=10000),
"Decision Tree": DecisionTreeClassifier(criterion="gini", max_depth=5, random_state=42),
"Random Forest": RandomForestClassifier(n_estimators=100, criterion="gini", max_depth=5, random_state=42)
}
results = []
for name, model in models.items():
# 模型训练
model.fit(X_train, y_train)
# 模型预测
y_train_pred = model.predict(X_train)
y_test_pred = model.predict(X_test)
y_train_prob = model.predict_proba(X_train)[:, 1]
y_test_prob = model.predict_proba(X_test)[:, 1]
# 模型评估
train_acc = accuracy_score(y_train, y_train_pred)
test_acc = accuracy_score(y_test, y_test_pred)
train_precision = precision_score(y_train, y_train_pred)
test_precision = precision_score(y_test, y_test_pred)
train_recall = recall_score(y_train, y_train_pred)
test_recall = recall_score(y_test, y_test_pred)
train_f1 = f1_score(y_train, y_train_pred)
test_f1 = f1_score(y_test, y_test_pred)
# ROC曲线与AUC值
fpr_train, tpr_train, thresholds_train = roc_curve(y_train, y_train_prob)
roc_auc_train = auc(fpr_train, tpr_train)
fpr_test, tpr_test, thresholds_test = roc_curve(y_test, y_test_prob)
roc_auc_test = auc(fpr_test, tpr_test)
results.append([name, train_acc, test_acc, train_precision, test_precision, train_recall, test_recall, train_f1, test_f1, roc_auc_train, roc_auc_test])
# 打印模型评估结果
results_df = pd.DataFrame(results, columns=["模型", "训练集准确率", "测试集准确率", "训练集精确率", "测试集精确率", "训练集召回率", "测试集召回率", "训练集F1值", "测试集F1值", "训练集AUC", "测试集AUC"])
print("\n模型评估结果:")
print(results_df)
# 6. ROC曲线可视化
plt.figure(figsize=(10, 5))
for name, model in models.items():
y_test_prob = model.predict_proba(X_test)[:, 1]
fpr_test, tpr_test, thresholds_test = roc_curve(y_test, y_test_prob)
roc_auc_test = auc(fpr_test, tpr_test)
plt.plot(fpr_test, tpr_test, linewidth=2, label=f"{name}(AUC={roc_auc_test:.4f})")
plt.plot([0, 1], [0, 1], color="#2C3E50", linestyle="--", linewidth=2)
plt.xlabel("假正率(FPR)")
plt.ylabel("真阳性率(TPR)")
plt.title("各模型的ROC曲线")
plt.legend()
plt.grid(True, alpha=0.3)
plt.show()
# 7. 特征重要性分析(使用RandomForest模型)
importances = pd.DataFrame({"特征": X.columns, "重要性": models["Random Forest"].feature_importances_})
importances = importances.sort_values(by="重要性", ascending=False)
print("\n特征重要性排序:")
print(importances)
模型评估结果:
- 三种模型在测试集上的准确率都在0.79~0.81之间,其中Random Forest的准确率最高(0.81)
- 三种模型在测试集上的AUC值都在0.85~0.87之间,其中Random Forest的AUC值最高(0.87)
- Random Forest模型的特征重要性分析显示:tenure(客户在网时间)、MonthlyCharges(月度费用)、TotalCharges(总费用)对客户流失的预测影响最大
五、模块4:算法性能对比与选择
5.1 性能对比
根据客户流失预测案例的结果,我们对三种基础算法的性能进行对比:
| 模型 | 训练集准确率 | 测试集准确率 | 训练集AUC | 测试集AUC | 训练时间(秒) |
|---|---|---|---|---|---|
| Logistic Regression | 0.80 | 0.79 | 0.86 | 0.85 | 0.02 |
| Decision Tree | 0.83 | 0.80 | 0.87 | 0.86 | 0.01 |
| Random Forest | 0.83 | 0.81 | 0.88 | 0.87 | 0.12 |
5.2 算法选择
选择机器学习算法时需要考虑以下因素:
- 任务类型:回归任务选择线性回归,分类任务选择逻辑回归或决策树
- 数据量:数据量小时选择简单算法(如线性回归、决策树),数据量大时选择复杂算法(如Random Forest、Gradient Boosting)
- 模型复杂度:需要解释模型时选择简单算法(如线性回归、决策树),不需要解释模型时选择复杂算法(如Random Forest)
- 训练时间:对训练时间敏感时选择简单算法(如线性回归、决策树),对训练时间不敏感时选择复杂算法(如Random Forest)
结论 :在客户流失预测案例中,我们选择Random Forest模型,因为它的性能最好(准确率和AUC值最高),虽然训练时间比简单算法长,但可以接受。
六、章节总结与后续学习指南
✅ 本章节核心收获:
- 理解了机器学习的核心概念与分类(训练集/测试集、过拟合/欠拟合、评估指标)
- 掌握了线性回归、逻辑回归、决策树三大基础算法的原理与代码实现
- 完成了真实数据集上的客户流失预测任务,对比了不同算法的性能表现
- 学会了根据任务类型、数据量、模型复杂度等因素选择合适的算法
💡 后续学习方向:
- 高级机器学习算法:学习Random Forest、Gradient Boosting、XGBoost、LightGBM等集成学习算法
- 深度学习基础:学习PyTorch/TensorFlow的神经网络模块,实现图像分类、文本分类等任务
- 模型优化:学习特征工程、超参数调优、模型融合等技术,提高模型的性能
⚠️ 学习建议:
- 务必动手运行每一行代码------机器学习是实操性极强的学科,看10遍代码不如自己运行1遍
- 遇到问题优先查阅官方文档(scikit-learn官网https://scikit-learn.org/stable/ )和Stack Overflow
- 养成代码注释和版本管理的好习惯,为后续复杂机器学习项目打下基础
七、课后习题(验证学习效果)
- 使用scikit-learn内置的糖尿病数据集(load_diabetes),实现线性回归模型并评估其性能
- 使用scikit-learn内置的葡萄酒数据集(load_wine),实现决策树分类模型并评估其性能
- 修改客户流失预测案例中的决策树最大深度为10,观察模型性能的变化
- 尝试使用XGBoost算法解决客户流失预测问题,并对比其与Random Forest的性能表现