第4章:经典算法
本章将详细介绍机器学习中最重要的经典算法,包括监督学习、集成学习和无监督学习的核心方法。每种算法都包含原理简述、适用场景、优缺点分析和Python代码示例。
4.1 监督学习算法
4.1.1 线性回归 (Linear Regression)
| 维度 |
说明 |
| 原理简述 |
假设目标变量与特征之间存在线性关系,通过最小化预测值与真实值之间的均方误差(MSE)来拟合最佳直线:y = w₁x₁ + w₂x₂ + ... + wₙxₙ + b |
| 适用场景 |
房价预测、销售预测、趋势分析、连续数值预测任务 |
| 优点 |
简单易懂、计算高效、可解释性强、不容易过拟合 |
| 缺点 |
只能拟合线性关系、对异常值敏感、假设特征间相互独立 |
# 线性回归示例
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
# 生成示例数据:学习时间与考试成绩的关系
np.random.seed(42)
study_hours = np.random.uniform(1, 10, 100).reshape(-1, 1)
scores = 50 + 5 * study_hours.ravel() + np.random.normal(0, 5, 100)
# 划分数据集
X_train, X_test, y_train, y_test = train_test_split(
study_hours, scores, test_size=0.2, random_state=42
)
# 创建并训练模型
model = LinearRegression()
model.fit(X_train, y_train)
# 预测与评估
y_pred = model.predict(X_test)
print(f"R² Score: {r2_score(y_test, y_pred):.4f}")
print(f"RMSE: {np.sqrt(mean_squared_error(y_test, y_pred)):.4f}")
print(f"回归系数: {model.coef_[0]:.2f}")
print(f"截距: {model.intercept_:.2f}")
4.1.2 逻辑回归 (Logistic Regression)
| 维度 |
说明 |
| 原理简述 |
使用Sigmoid函数将线性回归的输出映射到[0,1]区间,表示概率:P(y=1|x) = 1 / (1 + e^-(wx+b))。通过最大似然估计求解参数。 |
| 适用场景 |
二分类问题(是/否)、广告点击率预测、疾病诊断、信用评分 |
| 优点 |
输出概率值、训练速度快、可解释性强(特征权重)、不易过拟合 |
| 缺点 |
只能处理线性可分问题、对特征工程依赖较大、多分类需特殊处理 |
# 逻辑回归示例
from sklearn.linear_model import LogisticRegression
from sklearn.datasets import load_breast_cancer
from sklearn.metrics import accuracy_score, classification_report
# 加载乳腺癌数据集
data = load_breast_cancer()
X, y = data.data, data.target
# 划分数据集
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42
)
# 创建模型(增加迭代次数防止不收敛警告)
model = LogisticRegression(max_iter=1000, random_state=42)
model.fit(X_train, y_train)
# 预测与评估
y_pred = model.predict(X_test)
print(f"准确率: {accuracy_score(y_test, y_pred):.4f}")
print("\n分类报告:")
print(classification_report(y_test, y_pred, target_names=['恶性', '良性']))
4.1.3 决策树 (Decision Tree)
| 维度 |
说明 |
| 原理简述 |
通过递归地选择最优特征进行数据分割,构建树形结构。分类树使用信息增益/基尼指数,回归树使用均方误差来选择分裂点。 |
| 适用场景 |
需要强可解释性的场景、特征有明确业务含义、混合类型数据 |
| 优点 |
直观可解释、无需特征缩放、可处理非线性关系、能处理缺失值 |
| 缺点 |
容易过拟合、对数据变化敏感、可能产生偏向性(偏向取值多的特征) |
# 决策树示例(带可视化)
from sklearn.tree import DecisionTreeClassifier, export_text, plot_tree
import matplotlib.pyplot as plt
# 使用鸢尾花数据集简化版(仅2个特征便于可视化)
from sklearn.datasets import load_iris
iris = load_iris()
X, y = iris.data[:, :2], iris.target # 只取前2个特征
# 创建决策树模型(限制深度防止过拟合)
model = DecisionTreeClassifier(max_depth=3, random_state=42)
model.fit(X, y)
# 文本形式展示树结构
print("决策树规则:")
print(export_text(model, feature_names=['花瓣长度', '花瓣宽度']))
# 可视化(需要matplotlib)
plt.figure(figsize=(20, 10))
plot_tree(model, feature_names=['花瓣长度', '花瓣宽度'],
class_names=iris.target_names, filled=True, rounded=True)
plt.title('决策树可视化')
plt.savefig('decision_tree.png', dpi=150, bbox_inches='tight')
plt.show()
决策树可视化解读:每个节点显示分裂条件、基尼系数/熵、样本数和类别分布。颜色越深表示该类纯度越高。叶子节点给出最终预测结果。
4.1.4 支持向量机 (SVM)
| 维度 |
说明 |
| 原理简述 |
寻找最优超平面使不同类别的间隔最大化。通过核函数(Kernel)将数据映射到高维空间处理非线性问题。支持向量是距离超平面最近的样本点。 |
| 适用场景 |
高维数据分类、图像识别、文本分类、小样本学习 |
| 优点 |
泛化能力强、适合高维数据、通过核函数处理非线性、最终模型只依赖支持向量 |
| 缺点 |
大规模数据训练慢、对参数敏感、核函数选择困难、黑盒模型难解释 |
# SVM示例
from sklearn.svm import SVC
from sklearn.preprocessing import StandardScaler
# 数据标准化(SVM对特征尺度敏感)
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)
# 创建SVM模型(RBF核)
model = SVC(kernel='rbf', C=1.0, gamma='scale', random_state=42)
model.fit(X_train_scaled, y_train)
# 预测
y_pred = model.predict(X_test_scaled)
print(f"准确率: {accuracy_score(y_test, y_pred):.4f}")
# 使用线性核对比
model_linear = SVC(kernel='linear', random_state=42)
model_linear.fit(X_train_scaled, y_train)
print(f"线性核准确率: {accuracy_score(y_test, model_linear.predict(X_test_scaled)):.4f}")
4.1.5 K近邻 (KNN)
| 维度 |
说明 |
| 原理简述 |
懒惰学习算法,没有显式的训练过程。预测时找到测试样本的K个最近邻居,分类问题采用投票法,回归问题采用平均值。 |
| 适用场景 |
小数据集、低维数据、推荐系统、异常检测 |
| 优点 |
简单直观、无需训练、对数据分布无假设、适合多分类 |
| 缺点 |
预测慢(需遍历所有样本)、维度灾难、对异常值敏感、需要大量内存 |
# KNN示例
from sklearn.neighbors import KNeighborsClassifier
# 创建KNN模型(K=5,使用欧氏距离)
model = KNeighborsClassifier(n_neighbors=5, metric='euclidean')
model.fit(X_train, y_train)
# 预测
y_pred = model.predict(X_test)
print(f"K=5 准确率: {accuracy_score(y_test, y_pred):.4f}")
# 寻找最优K值
from sklearn.model_selection import cross_val_score
k_range = range(1, 31)
cv_scores = []
for k in k_range:
knn = KNeighborsClassifier(n_neighbors=k)
scores = cross_val_score(knn, X_train, y_train, cv=5, scoring='accuracy')
cv_scores.append(scores.mean())
optimal_k = k_range[np.argmax(cv_scores)]
print(f"最优K值: {optimal_k}, 交叉验证准确率: {max(cv_scores):.4f}")
4.1.6 朴素贝叶斯 (Naive Bayes)
| 维度 |
说明 |
| 原理简述 |
基于贝叶斯定理,假设特征之间相互独立("朴素"的来源)。计算后验概率 P(y|x) 选择最大概率的类别。核心公式:P(y|x) ∝ P(y) × Π P(xᵢ|y) |
| 适用场景 |
文本分类(垃圾邮件、情感分析)、文档分类、实时预测系统 |
| 优点 |
训练速度极快、对缺失值不敏感、适合高维数据、对小样本效果好 |
| 缺点 |
特征独立性假设往往不成立、概率估计可能不准确、对输入数据分布敏感 |
# 朴素贝叶斯 - 文本分类示例
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.naive_bayes import MultinomialNB
from sklearn.pipeline import Pipeline
# 示例数据
reviews = [
"这部电影太精彩了,强烈推荐",
"完全浪费时间,剧情老套",
"演员演技出色,值得一看",
"特效很差,故事无聊",
"这是我今年看过最好的电影",
"太失望了,根本不值得票价"
]
labels = [1, 0, 1, 0, 1, 0] # 1=正面, 0=负面
# 构建管道
pipeline = Pipeline([
('tfidf', TfidfVectorizer()),
('nb', MultinomialNB())
])
pipeline.fit(reviews, labels)
# 预测新评论
new_reviews = ["故事很棒,演员表现出色", "完全看不懂,太无聊了"]
predictions = pipeline.predict(new_reviews)
for review, pred in zip(new_reviews, predictions):
sentiment = "正面" if pred == 1 else "负面"
print(f"评论: {review} -> {sentiment}")
4.2 集成学习
集成学习(Ensemble Learning)的核心思想是"三个臭皮匠,顶个诸葛亮"——通过组合多个基学习器的预测结果,获得比单一模型更好的性能。
4.2.1 集成学习算法对比
| 算法 |
核心原理 |
基学习器 |
集成方式 |
特点 |
适用场景 |
| 随机森林 |
Bagging思想,多棵决策树并行训练,随机选择特征和样本 |
决策树 |
投票/平均 |
并行训练、抗过拟合、特征重要性 |
通用场景、特征选择 |
| AdaBoost |
Boosting思想,串行训练,重点学习前序模型分错的样本 |
弱学习器 |
加权投票 |
关注难样本、容易过拟合 |
二分类、基线模型 |
| XGBoost |
梯度提升+正则化,使用二阶泰勒展开优化目标函数 |
决策树 |
加法模型 |
速度快、精度高、支持并行、功能丰富 |
竞赛首选、表格数据 |
| LightGBM |
基于直方图的决策树算法,叶子优先分裂策略 |
决策树 |
加法模型 |
训练极快、内存高效、大数据首选 |
大规模数据、实时预测 |
4.2.2 随机森林 (Random Forest)
# 随机森林示例
from sklearn.ensemble import RandomForestClassifier
# 创建随机森林模型
model = RandomForestClassifier(
n_estimators=100, # 树的数量
max_depth=10, # 最大深度
min_samples_split=5, # 节点分裂最小样本数
random_state=42,
n_jobs=-1 # 使用所有CPU核心
)
model.fit(X_train, y_train)
# 预测与评估
y_pred = model.predict(X_test)
print(f"准确率: {accuracy_score(y_test, y_pred):.4f}")
# 特征重要性
importances = model.feature_importances_
for i, imp in enumerate(importances):
print(f"特征 {i}: 重要性 {imp:.4f}")
4.2.3 XGBoost
# XGBoost示例(需安装: pip install xgboost)
import xgboost as xgb
from sklearn.datasets import load_breast_cancer
# 加载数据
data = load_breast_cancer()
X, y = data.data, data.target
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42
)
# 转换为DMatrix(XGBoost专用数据结构)
dtrain = xgb.DMatrix(X_train, label=y_train)
dtest = xgb.DMatrix(X_test, label=y_test)
# 设置参数
params = {
'objective': 'binary:logistic',
'max_depth': 6,
'learning_rate': 0.1,
'n_estimators': 100,
'subsample': 0.8,
'colsample_bytree': 0.8,
'eval_metric': 'auc'
}
# 训练模型
model = xgb.XGBClassifier(**params, random_state=42)
model.fit(X_train, y_train)
# 预测与评估
y_pred = model.predict(X_test)
print(f"准确率: {accuracy_score(y_test, y_pred):.4f}")
# 特征重要性可视化
xgb.plot_importance(model, max_num_features=10)
plt.show()
4.2.4 LightGBM
# LightGBM示例(需安装: pip install lightgbm)
import lightgbm as lgb
# 创建数据集
train_data = lgb.Dataset(X_train, label=y_train)
valid_data = lgb.Dataset(X_test, label=y_test, reference=train_data)
# 设置参数
params = {
'objective': 'binary',
'metric': 'auc',
'boosting_type': 'gbdt',
'num_leaves': 31,
'learning_rate': 0.05,
'feature_fraction': 0.9,
'bagging_fraction': 0.8,
'bagging_freq': 5,
'verbose': -1
}
# 训练模型
model = lgb.train(
params,
train_data,
num_boost_round=100,
valid_sets=[valid_data],
callbacks=[lgb.early_stopping(stopping_rounds=10), lgb.log_evaluation(0)]
)
# 预测
y_pred = (model.predict(X_test) > 0.5).astype(int)
print(f"准确率: {accuracy_score(y_test, y_pred):.4f}")
集成学习选择建议:
- 快速原型:随机森林,参数少、效果稳定
- 竞赛/高精度:XGBoost或LightGBM
- 大规模数据:LightGBM速度最快
- 特征分析:随机森林的特征重要性功能
4.3 无监督学习算法
4.3.1 聚类算法对比
| 算法 |
核心原理 |
优点 |
缺点 |
| K-Means |
迭代优化,将样本分配到最近的质心,然后更新质心位置,直到收敛 |
简单高效、可扩展性好、时间复杂度O(n) |
需预设K值、对初始值敏感、假设球形簇 |
| 层次聚类 |
自底向上(凝聚)或自顶向下(分裂),逐步合并/分裂簇 |
无需预设K值、输出树状图、可解释性强 |
计算复杂度高O(n²)、对噪声敏感 |
| DBSCAN |
基于密度,将高密度区域划分为簇,可识别噪声点 |
自动识别簇数量、发现任意形状簇、抗噪声 |
对参数敏感、密度不均时效果差 |
4.3.2 K-Means
# K-Means聚类示例
from sklearn.cluster import KMeans
from sklearn.datasets import make_blobs
import matplotlib.pyplot as plt
# 生成模拟数据
X, _ = make_blobs(n_samples=300, centers=4, cluster_std=0.6, random_state=42)
# 肘部法则确定K值
inertias = []
K_range = range(1, 10)
for k in K_range:
kmeans = KMeans(n_clusters=k, random_state=42, n_init=10)
kmeans.fit(X)
inertias.append(kmeans.inertia_)
# 绘制肘部图
plt.figure(figsize=(8, 4))
plt.plot(K_range, inertias, 'bo-')
plt.xlabel('K值')
plt.ylabel('惯性(簇内平方和)')
plt.title('肘部法则')
plt.show()
# 使用最优K值聚类
optimal_k = 4
kmeans = KMeans(n_clusters=optimal_k, random_state=42, n_init=10)
labels = kmeans.fit_predict(X)
# 可视化结果
plt.figure(figsize=(8, 6))
plt.scatter(X[:, 0], X[:, 1], c=labels, cmap='viridis', alpha=0.6)
plt.scatter(kmeans.cluster_centers_[:, 0], kmeans.cluster_centers_[:, 1],
marker='X', s=200, c='red', label='质心')
plt.legend()
plt.title(f'K-Means聚类结果 (K={optimal_k})')
plt.show()
4.3.3 层次聚类
# 层次聚类示例
from sklearn.cluster import AgglomerativeClustering
from scipy.cluster.hierarchy import dendrogram, linkage
# 凝聚聚类
model = AgglomerativeClustering(n_clusters=3, linkage='ward')
labels = model.fit_predict(X)
# 绘制树状图(需scipy)
linked = linkage(X[:50], 'ward') # 取子集便于展示
plt.figure(figsize=(10, 5))
dendrogram(linked, orientation='top', distance_sort='descending')
plt.title('层次聚类树状图')
plt.show()
4.3.4 DBSCAN
# DBSCAN示例
from sklearn.cluster import DBSCAN
from sklearn.datasets import make_moons
# 生成月牙形数据(K-Means难以处理)
X, _ = make_moons(n_samples=300, noise=0.05, random_state=42)
# K-Means效果
kmeans = KMeans(n_clusters=2, random_state=42, n_init=10)
kmeans_labels = kmeans.fit_predict(X)
# DBSCAN效果
dbscan = DBSCAN(eps=0.3, min_samples=5)
dbscan_labels = dbscan.fit_predict(X)
# 可视化对比
fig, axes = plt.subplots(1, 2, figsize=(12, 5))
axes[0].scatter(X[:, 0], X[:, 1], c=kmeans_labels, cmap='viridis')
axes[0].set_title('K-Means(效果不佳)')
axes[1].scatter(X[:, 0], X[:, 1], c=dbscan_labels, cmap='viridis')
axes[1].set_title('DBSCAN(正确识别)')
plt.tight_layout()
plt.show()
print(f"DBSCAN发现簇数: {len(set(dbscan_labels)) - (1 if -1 in dbscan_labels else 0)}")
print(f"噪声点数量: {list(dbscan_labels).count(-1)}")
4.3.5 降维方法对比
| 方法 |
核心原理 |
优点 |
缺点 |
| PCA |
线性变换,寻找方差最大的正交方向(主成分),保留最大信息量 |
计算高效、无参数、去相关、降噪 |
仅捕捉线性关系、对异常值敏感 |
| t-SNE |
非线性降维,保持局部邻域结构,高维相似点映射到低维也相似 |
可视化效果极佳、保留局部结构 |
计算慢、结果随机、不保持全局结构 |
4.3.6 PCA
# PCA示例
from sklearn.decomposition import PCA
from sklearn.datasets import load_iris
# 加载数据
iris = load_iris()
X, y = iris.data, iris.target
# 应用PCA
pca = PCA(n_components=2) # 降至2维
X_pca = pca.fit_transform(X)
# 可视化
plt.figure(figsize=(8, 6))
for i, target_name in enumerate(iris.target_names):
plt.scatter(X_pca[y == i, 0], X_pca[y == i, 1], label=target_name, alpha=0.7)
plt.xlabel(f'第一主成分 ({pca.explained_variance_ratio_[0]:.2%})')
plt.ylabel(f'第二主成分 ({pca.explained_variance_ratio_[1]:.2%})')
plt.legend()
plt.title('PCA降维可视化')
plt.show()
print(f"总方差解释率: {sum(pca.explained_variance_ratio_):.2%}")
print(f"主成分数量(全部): {PCA().fit(X).n_components_}")
4.3.7 t-SNE
# t-SNE示例
from sklearn.manifold import TSNE
from sklearn.datasets import load_digits
# 加载手写数字数据集(64维)
digits = load_digits()
X, y = digits.data[:500], digits.target[:500] # 取子集加速
# 应用t-SNE
tsne = TSNE(n_components=2, random_state=42, perplexity=30)
X_tsne = tsne.fit_transform(X)
# 可视化
plt.figure(figsize=(10, 8))
scatter = plt.scatter(X_tsne[:, 0], X_tsne[:, 1], c=y, cmap='tab10', alpha=0.6)
plt.colorbar(scatter, label='数字')
plt.title('t-SNE: 手写数字可视化 (0-9)')
plt.show()
降维方法选择建议:
- 特征压缩/预处理:使用PCA,可逆变换且保留全局结构
- 数据可视化:使用t-SNE或UMAP,视觉效果更好
- 大数据集:先用PCA降维,再用t-SNE可视化
算法速查表:
| 任务类型 | 推荐算法 |
| 回归问题 | 线性回归、随机森林回归、XGBoost |
| 二分类 | 逻辑回归、SVM、XGBoost |
| 多分类 | 随机森林、Softmax回归、XGBoost |
| 文本分类 | 朴素贝叶斯、逻辑回归 |
| 聚类分析 | K-Means、DBSCAN、层次聚类 |
| 降维可视化 | PCA、t-SNE |
| 竞赛/高精度 | XGBoost、LightGBM |
本章详细介绍了机器学习的经典算法,从基础的线性回归到强大的集成学习方法,再到无监督学习的聚类和降维技术。掌握这些算法后,你将能够应对大多数机器学习任务。下一章我们将进入深度学习的世界。