用Python+Scikit-learn实战复现机器学习核心算法

期末考试临近,翻开厚重的教材,满眼都是抽象公式和理论推导?别担心,这篇文章将带你用Python代码重新理解那些看似晦涩的机器学习概念。我们不会停留在理论层面,而是通过Scikit-learn库将教材中的关键算法转化为可运行的代码,让你在动手实践中真正掌握这些知识。

1. 决策树实战:从信息增益到剪枝策略

决策树是机器学习中最直观的算法之一,但很多同学在计算信息增益和选择划分属性时容易混淆。让我们用代码来理清这个过程。

首先,我们导入必要的库并准备一个简单的数据集:

from sklearn.datasets import load_iris
from sklearn.tree import DecisionTreeClassifier, export_text
import numpy as np

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

1.1 信息增益计算

Scikit-learn默认使用基尼指数,但我们可以通过设置参数来使用信息增益:

# 使用信息增益作为划分标准
clf = DecisionTreeClassifier(criterion='entropy', max_depth=3)
clf.fit(X, y)

# 查看决策树结构
tree_rules = export_text(clf, feature_names=iris.feature_names)
print(tree_rules)

运行这段代码,你会看到决策树的具体划分过程。通过可视化,可以更直观地理解信息增益如何影响划分:

from sklearn.tree import plot_tree
import matplotlib.pyplot as plt

plt.figure(figsize=(12,8))
plot_tree(clf, feature_names=iris.feature_names, 
          class_names=iris.target_names, filled=True)
plt.show()

1.2 剪枝策略对比

预剪枝和后剪枝是防止过拟合的两种重要方法。让我们比较它们的实际效果:

# 预剪枝示例
pre_pruned = DecisionTreeClassifier(max_depth=3, min_samples_leaf=5)
pre_pruned.fit(X, y)

# 后剪枝示例(通过ccp_alpha参数)
post_pruned = DecisionTreeClassifier(ccp_alpha=0.02)
post_pruned.fit(X, y)

通过调整 max_depth ccp_alpha 参数,观察模型复杂度和准确率的变化,你会对剪枝有更直观的认识。

2. 支持向量机:从线性可分到核技巧

支持向量机(SVM)是另一个常考的重点,特别是核函数的概念。让我们用代码来演示不同核函数的效果。

2.1 线性SVM基础

首先实现一个简单的线性SVM:

from sklearn.svm import SVC
from sklearn.datasets import make_classification

# 生成线性可分数据
X, y = make_classification(n_features=2, n_redundant=0, n_informative=2,
                           random_state=1, n_clusters_per_class=1)

# 训练线性SVM
linear_svm = SVC(kernel='linear', C=1.0)
linear_svm.fit(X, y)

可视化决策边界:

def plot_decision_boundary(clf, X, y):
    # 设置绘图范围
    x_min, x_max = X[:, 0].min() - 1, X[:, 0].max() + 1
    y_min, y_max = X[:, 1].min() - 1, X[:, 1].max() + 1
    
    # 生成网格点
    xx, yy = np.meshgrid(np.arange(x_min, x_max, 0.02),
                         np.arange(y_min, y_max, 0.02))
    
    # 预测每个网格点的类别
    Z = clf.predict(np.c_[xx.ravel(), yy.ravel()])
    Z = Z.reshape(xx.shape)
    
    # 绘制决策边界
    plt.contourf(xx, yy, Z, alpha=0.4)
    plt.scatter(X[:, 0], X[:, 1], c=y, s=20, edgecolor='k')
    plt.show()

plot_decision_boundary(linear_svm, X, y)

2.2 核函数实战

对于非线性可分数据,核函数就派上用场了:

from sklearn.datasets import make_circles

# 生成环形数据
X, y = make_circles(n_samples=100, factor=0.3, noise=0.1)

# 使用不同核函数的SVM
kernels = ['linear', 'poly', 'rbf', 'sigmoid']

plt.figure(figsize=(15, 10))
for i, kernel in enumerate(kernels):
    plt.subplot(2, 2, i+1)
    clf = SVC(kernel=kernel, gamma=2)
    clf.fit(X, y)
    plot_decision_boundary(clf, X, y)
    plt.title(f'Kernel: {kernel}')

通过这个对比,你可以直观地看到不同核函数如何处理非线性数据。

3. 模型评估:从P-R曲线到ROC分析

模型评估是考试的重点,也是实际项目中至关重要的环节。让我们用代码生成各种评估指标。

3.1 P-R曲线绘制

from sklearn.metrics import precision_recall_curve
from sklearn.model_selection import train_test_split

# 分割数据集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3)

# 训练模型并获取预测概率
model = DecisionTreeClassifier()
model.fit(X_train, y_train)
probs = model.predict_proba(X_test)[:, 1]

# 计算P-R曲线
precision, recall, thresholds = precision_recall_curve(y_test, probs)

# 绘制曲线
plt.plot(recall, precision)
plt.xlabel('Recall')
plt.ylabel('Precision')
plt.title('P-R Curve')
plt.show()

3.2 ROC曲线与AUC值

from sklearn.metrics import roc_curve, auc

# 计算ROC曲线
fpr, tpr, thresholds = roc_curve(y_test, probs)
roc_auc = auc(fpr, tpr)

# 绘制曲线
plt.plot(fpr, tpr, label=f'ROC curve (area = {roc_auc:.2f})')
plt.plot([0, 1], [0, 1], 'k--')  # 对角线
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.title('ROC Curve')
plt.legend()
plt.show()

通过调整模型参数,观察这些曲线的变化,你会对模型性能评估有更深入的理解。

4. 神经网络基础:从感知机到BP算法

神经网络是当前机器学习的热点,也是考试的重点内容。让我们从最简单的感知机开始。

4.1 感知机实现

from sklearn.linear_model import Perceptron

# 生成线性可分数据
X, y = make_classification(n_features=2, n_redundant=0, n_informative=2,
                           random_state=42, n_clusters_per_class=1)

# 训练感知机
perceptron = Perceptron()
perceptron.fit(X, y)

# 可视化决策边界
plot_decision_boundary(perceptron, X, y)

4.2 多层感知机与BP算法

Scikit-learn提供了MLPClassifier来实现多层感知机:

from sklearn.neural_network import MLPClassifier

# 生成异或数据(感知机无法处理)
X = np.array([[0, 0], [0, 1], [1, 0], [1, 1]])
y = np.array([0, 1, 1, 0])

# 训练MLP
mlp = MLPClassifier(hidden_layer_sizes=(4,), activation='tanh',
                    solver='sgd', learning_rate_init=0.1, max_iter=1000)
mlp.fit(X, y)

# 查看预测结果
print("Predictions:", mlp.predict(X))

通过调整隐藏层大小和激活函数,观察模型对异或问题的处理能力。

5. 集成学习:从随机森林到Boosting

集成学习通过组合多个模型来提高性能,是考试中常考的综合题内容。

5.1 随机森林实现

from sklearn.ensemble import RandomForestClassifier

# 训练随机森林
rf = RandomForestClassifier(n_estimators=100, max_depth=3)
rf.fit(X_train, y_train)

# 查看特征重要性
importances = rf.feature_importances_
indices = np.argsort(importances)[::-1]

# 绘制特征重要性
plt.figure()
plt.title("Feature importances")
plt.bar(range(X.shape[1]), importances[indices])
plt.xticks(range(X.shape[1]), iris.feature_names, rotation=90)
plt.show()

5.2 AdaBoost示例

from sklearn.ensemble import AdaBoostClassifier

# 使用决策树桩作为弱分类器
ada = AdaBoostClassifier(n_estimators=100, base_estimator=DecisionTreeClassifier(max_depth=1))
ada.fit(X_train, y_train)

# 查看各阶段的准确率
train_errors = []
test_errors = []

for y_pred in ada.staged_predict(X_train):
    train_errors.append(np.mean(y_pred != y_train))

for y_pred in ada.staged_predict(X_test):
    test_errors.append(np.mean(y_pred != y_test))

plt.plot(train_errors, label='Train error')
plt.plot(test_errors, label='Test error')
plt.legend()
plt.title('AdaBoost error over iterations')
plt.show()

通过这些代码示例,你可以直观地看到集成学习如何通过组合多个弱分类器来提高性能。

更多推荐