传统机器学习模型保姆级指南:线性回归到XGBoost全掌握

1 阅读1分钟

欢迎来到第二周的学习!在第一周我们了解了AI的基础知识和早期案例,今天我们将深入学习传统机器学习模型,从最基础的线性回归到强大的XGBoost,带你全面掌握这些经典但仍然非常实用的算法。

传统机器学习概览

传统机器学习是现代AI技术的重要基石,虽然深度学习在许多领域取得了突破性进展,但传统机器学习算法在许多场景下仍然表现出色,尤其是在数据量有限或特征工程充分的情况下。

graph TD
    A[机器学习] --> B[监督学习]
    A --> C[无监督学习]
    A --> D[强化学习]
    B --> E[回归]
    B --> F[分类]
    C --> G[聚类]
    C --> H[降维]

监督学习基础

监督学习是机器学习中最常见的类型,它使用带有标签的数据进行训练。

回归 vs 分类

  • 回归任务:预测连续值(如房价、温度)
  • 分类任务:预测离散类别(如垃圾邮件识别、图像分类)
import numpy as np
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error, r2_score

# 生成示例数据
np.random.seed(42)
X = np.linspace(0, 10, 100).reshape(-1, 1)
y = 2 * X.ravel() + 1 + np.random.normal(0, 2, 100)  # y = 2x + 1 + 噪声

# 可视化数据
plt.figure(figsize=(10, 6))
plt.scatter(X, y, alpha=0.6)
plt.xlabel('特征 X')
plt.ylabel('目标值 y')
plt.title('回归问题示例数据')
plt.grid(True, alpha=0.3)
plt.show()

print(f"数据形状: X={X.shape}, y={y.shape}")
print("这是一个典型的回归问题,目标是预测连续值")

分类任务示例

from sklearn.datasets import make_classification
from sklearn.linear_model import LogisticRegression
import seaborn as sns

# 生成分类数据
X_class, y_class = make_classification(
    n_samples=200,
    n_features=2,
    n_redundant=0,
    n_informative=2,
    n_clusters_per_class=1,
    random_state=42
)

# 可视化分类数据
plt.figure(figsize=(10, 6))
plt.scatter(X_class[:, 0], X_class[:, 1], c=y_class, cmap='viridis', alpha=0.7)
plt.xlabel('特征 1')
plt.ylabel('特征 2')
plt.title('分类问题示例数据')
plt.colorbar(label='类别')
plt.grid(True, alpha=0.3)
plt.show()

print(f"分类数据形状: X={X_class.shape}, y={y_class.shape}")
print(f"类别数量: {len(np.unique(y_class))}")
print("这是一个二分类问题,目标是将数据分为两个类别")

线性模型详解

线性模型是机器学习中最基础也是最重要的模型之一,包括线性回归和逻辑回归。

线性回归

线性回归用于解决回归问题,假设目标值与特征之间存在线性关系。

# 线性回归实现
class SimpleLinearRegression:
    """简单线性回归实现"""
    
    def __init__(self):
        self.slope = None
        self.intercept = None
    
    def fit(self, X, y):
        """训练模型"""
        X = X.ravel()  # 确保X是一维的
        x_mean = np.mean(X)
        y_mean = np.mean(y)
        
        # 计算斜率和截距
        numerator = np.sum((X - x_mean) * (y - y_mean))
        denominator = np.sum((X - x_mean) ** 2)
        
        self.slope = numerator / denominator
        self.intercept = y_mean - self.slope * x_mean
    
    def predict(self, X):
        """预测"""
        return self.slope * X.ravel() + self.intercept

# 使用自定义线性回归
custom_lr = SimpleLinearRegression()
custom_lr.fit(X, y)
y_pred_custom = custom_lr.predict(X)

# 使用sklearn线性回归
sklearn_lr = LinearRegression()
sklearn_lr.fit(X, y)
y_pred_sklearn = sklearn_lr.predict(X)

# 比较结果
print("自定义线性回归:")
print(f"斜率: {custom_lr.slope:.4f}")
print(f"截距: {custom_lr.intercept:.4f}")

print("\nSklearn线性回归:")
print(f"斜率: {sklearn_lr.coef_[0]:.4f}")
print(f"截距: {sklearn_lr.intercept_:.4f}")

# 计算评估指标
mse_custom = mean_squared_error(y, y_pred_custom)
r2_custom = r2_score(y, y_pred_custom)

mse_sklearn = mean_squared_error(y, y_pred_sklearn)
r2_sklearn = r2_score(y, y_pred_sklearn)

print(f"\n自定义模型 - MSE: {mse_custom:.4f}, R²: {r2_custom:.4f}")
print(f"Sklearn模型 - MSE: {mse_sklearn:.4f}, R²: {r2_sklearn:.4f}")

# 可视化结果
plt.figure(figsize=(12, 5))

plt.subplot(1, 2, 1)
plt.scatter(X, y, alpha=0.6, label='原始数据')
plt.plot(X, y_pred_custom, 'r-', linewidth=2, label=f'拟合直线 (y={custom_lr.slope:.2f}x+{custom_lr.intercept:.2f})')
plt.xlabel('X')
plt.ylabel('y')
plt.title('自定义线性回归')
plt.legend()
plt.grid(True, alpha=0.3)

plt.subplot(1, 2, 2)
plt.scatter(X, y, alpha=0.6, label='原始数据')
plt.plot(X, y_pred_sklearn, 'g-', linewidth=2, label=f'拟合直线 (y={sklearn_lr.coef_[0]:.2f}x+{sklearn_lr.intercept_:.2f})')
plt.xlabel('X')
plt.ylabel('y')
plt.title('Sklearn线性回归')
plt.legend()
plt.grid(True, alpha=0.3)

plt.tight_layout()
plt.show()

逻辑回归

逻辑回归用于解决分类问题,通过sigmoid函数将线性回归的输出映射到0-1之间。

# 逻辑回归实现
class SimpleLogisticRegression:
    """简单逻辑回归实现"""
    
    def __init__(self, learning_rate=0.01, n_iterations=1000):
        self.learning_rate = learning_rate
        self.n_iterations = n_iterations
        self.weights = None
        self.bias = None
    
    def sigmoid(self, z):
        """Sigmoid函数"""
        # 防止溢出
        z = np.clip(z, -500, 500)
        return 1 / (1 + np.exp(-z))
    
    def fit(self, X, y):
        """训练模型"""
        n_samples, n_features = X.shape
        
        # 初始化参数
        self.weights = np.zeros(n_features)
        self.bias = 0
        
        # 梯度下降
        for i in range(self.n_iterations):
            # 前向传播
            linear_pred = np.dot(X, self.weights) + self.bias
            predictions = self.sigmoid(linear_pred)
            
            # 计算损失
            loss = (-1/n_samples) * np.sum(y*np.log(predictions) + (1-y)*np.log(1-predictions))
            
            # 计算梯度
            dw = (1/n_samples) * np.dot(X.T, (predictions - y))
            db = (1/n_samples) * np.sum(predictions - y)
            
            # 更新参数
            self.weights -= self.learning_rate * dw
            self.bias -= self.learning_rate * db
    
    def predict(self, X):
        """预测概率"""
        linear_pred = np.dot(X, self.weights) + self.bias
        return self.sigmoid(linear_pred)
    
    def predict_class(self, X, threshold=0.5):
        """预测类别"""
        probabilities = self.predict(X)
        return (probabilities >= threshold).astype(int)

# 使用逻辑回归进行分类
X_train, X_test, y_train, y_test = train_test_split(
    X_class, y_class, test_size=0.3, random_state=42
)

# 自定义逻辑回归
custom_log_reg = SimpleLogisticRegression(learning_rate=0.1, n_iterations=1000)
custom_log_reg.fit(X_train, y_train)
y_pred_proba = custom_log_reg.predict(X_test)
y_pred_class = custom_log_reg.predict_class(X_test)

# Sklearn逻辑回归
sklearn_log_reg = LogisticRegression()
sklearn_log_reg.fit(X_train, y_train)
sklearn_pred_proba = sklearn_log_reg.predict_proba(X_test)[:, 1]
sklearn_pred_class = sklearn_log_reg.predict(X_test)

# 计算准确率
from sklearn.metrics import accuracy_score

custom_accuracy = accuracy_score(y_test, y_pred_class)
sklearn_accuracy = accuracy_score(y_test, sklearn_pred_class)

print("逻辑回归分类结果:")
print(f"自定义模型准确率: {custom_accuracy:.4f}")
print(f"Sklearn模型准确率: {sklearn_accuracy:.4f}")

# 可视化分类结果
plt.figure(figsize=(15, 5))

# 原始数据
plt.subplot(1, 3, 1)
plt.scatter(X_class[:, 0], X_class[:, 1], c=y_class, cmap='viridis', alpha=0.7)
plt.xlabel('特征 1')
plt.ylabel('特征 2')
plt.title('原始分类数据')
plt.colorbar(label='真实类别')

# 自定义逻辑回归结果
plt.subplot(1, 3, 2)
plt.scatter(X_test[:, 0], X_test[:, 1], c=y_pred_class, cmap='viridis', alpha=0.7)
plt.xlabel('特征 1')
plt.ylabel('特征 2')
plt.title(f'自定义逻辑回归\n准确率: {custom_accuracy:.4f}')
plt.colorbar(label='预测类别')

# Sklearn逻辑回归结果
plt.subplot(1, 3, 3)
plt.scatter(X_test[:, 0], X_test[:, 1], c=sklearn_pred_class, cmap='viridis', alpha=0.7)
plt.xlabel('特征 1')
plt.ylabel('特征 2')
plt.title(f'Sklearn逻辑回归\n准确率: {sklearn_accuracy:.4f}')
plt.colorbar(label='预测类别')

plt.tight_layout()
plt.show()

决策树与集成学习

决策树是一种基于树结构的分类和回归模型,易于理解和解释。集成学习通过组合多个模型来提高性能。

决策树

from sklearn.tree import DecisionTreeClassifier, plot_tree
from sklearn.datasets import load_iris

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

# 创建决策树
dt_classifier = DecisionTreeClassifier(max_depth=3, random_state=42)
dt_classifier.fit(X_iris, y_iris)

# 预测
y_pred_iris = dt_classifier.predict(X_iris)

# 计算准确率
accuracy_iris = accuracy_score(y_iris, y_pred_iris)
print(f"决策树在鸢尾花数据集上的准确率: {accuracy_iris:.4f}")

# 可视化决策树
plt.figure(figsize=(15, 10))
plot_tree(dt_classifier, 
          feature_names=iris.feature_names,
          class_names=iris.target_names,
          filled=True,
          rounded=True,
          fontsize=10)
plt.title('鸢尾花分类决策树')
plt.show()

# 特征重要性
feature_importance = dt_classifier.feature_importances_
plt.figure(figsize=(10, 6))
plt.bar(range(len(feature_importance)), feature_importance)
plt.xlabel('特征')
plt.ylabel('重要性')
plt.title('决策树特征重要性')
plt.xticks(range(len(feature_importance)), iris.feature_names, rotation=45)
plt.tight_layout()
plt.show()

for i, importance in enumerate(feature_importance):
    print(f"{iris.feature_names[i]}: {importance:.4f}")

随机森林

随机森林是一种集成学习方法,通过组合多个决策树来提高性能。

from sklearn.ensemble import RandomForestClassifier

# 创建随机森林
rf_classifier = RandomForestClassifier(n_estimators=100, random_state=42)
rf_classifier.fit(X_iris, y_iris)

# 预测
y_pred_rf = rf_classifier.predict(X_iris)

# 计算准确率
accuracy_rf = accuracy_score(y_iris, y_pred_rf)
print(f"随机森林在鸢尾花数据集上的准确率: {accuracy_rf:.4f}")

# 特征重要性
rf_feature_importance = rf_classifier.feature_importances_
plt.figure(figsize=(10, 6))
plt.bar(range(len(rf_feature_importance)), rf_feature_importance)
plt.xlabel('特征')
plt.ylabel('重要性')
plt.title('随机森林特征重要性')
plt.xticks(range(len(rf_feature_importance)), iris.feature_names, rotation=45)
plt.tight_layout()
plt.show()

for i, importance in enumerate(rf_feature_importance):
    print(f"{iris.feature_names[i]}: {importance:.4f}")

XGBoost

XGBoost是一种强大的梯度提升算法,在许多机器学习竞赛中表现出色。

# 注意:需要先安装xgboost: pip install xgboost
try:
    import xgboost as xgb
    
    # 创建XGBoost分类器
    xgb_classifier = xgb.XGBClassifier(
        n_estimators=100,
        max_depth=3,
        learning_rate=0.1,
        random_state=42
    )
    xgb_classifier.fit(X_iris, y_iris)
    
    # 预测
    y_pred_xgb = xgb_classifier.predict(X_iris)
    
    # 计算准确率
    accuracy_xgb = accuracy_score(y_iris, y_pred_xgb)
    print(f"XGBoost在鸢尾花数据集上的准确率: {accuracy_xgb:.4f}")
    
    # 特征重要性
    xgb_feature_importance = xgb_classifier.feature_importances_
    plt.figure(figsize=(10, 6))
    plt.bar(range(len(xgb_feature_importance)), xgb_feature_importance)
    plt.xlabel('特征')
    plt.ylabel('重要性')
    plt.title('XGBoost特征重要性')
    plt.xticks(range(len(xgb_feature_importance)), iris.feature_names, rotation=45)
    plt.tight_layout()
    plt.show()
    
    for i, importance in enumerate(xgb_feature_importance):
        print(f"{iris.feature_names[i]}: {importance:.4f}")
        
except ImportError:
    print("未安装xgboost,请使用 'pip install xgboost' 安装")
    print("XGBoost是一种强大的梯度提升算法,在Kaggle等数据科学竞赛中广泛使用")

模型评估指标

选择合适的评估指标对于模型性能评估至关重要。

from sklearn.metrics import classification_report, confusion_matrix
import seaborn as sns

# 使用分类报告详细评估模型
print("分类报告:")
print(classification_report(y_test, y_pred_class, target_names=['类别 0', '类别 1']))

# 混淆矩阵
cm = confusion_matrix(y_test, y_pred_class)
plt.figure(figsize=(8, 6))
sns.heatmap(cm, annot=True, fmt='d', cmap='Blues', 
            xticklabels=['预测 0', '预测 1'],
            yticklabels=['实际 0', '实际 1'])
plt.title('混淆矩阵')
plt.ylabel('实际类别')
plt.xlabel('预测类别')
plt.show()

# 回归评估指标
print("回归模型评估指标:")
print(f"MSE (均方误差): {mean_squared_error(y, y_pred_sklearn):.4f}")
print(f"RMSE (均方根误差): {np.sqrt(mean_squared_error(y, y_pred_sklearn)):.4f}")
print(f"R² (决定系数): {r2_score(y, y_pred_sklearn):.4f}")
print(f"MAE (平均绝对误差): {np.mean(np.abs(y - y_pred_sklearn)):.4f}")

本周学习总结

今天我们全面学习了传统机器学习模型:

  1. 监督学习基础

    • 理解了回归和分类任务的区别
    • 学会了数据可视化和基本概念
  2. 线性模型

    • 实现了线性回归和逻辑回归
    • 理解了模型的工作原理和数学基础
  3. 决策树与集成学习

    • 学习了决策树的结构和工作原理
    • 掌握了随机森林等集成学习方法
    • 了解了XGBoost的强大功能
  4. 模型评估

    • 学习了准确率、混淆矩阵等评估指标
    • 掌握了回归和分类任务的评估方法
graph TD
    A[传统机器学习] --> B[监督学习]
    A --> C[模型评估]
    B --> D[线性模型]
    B --> E[树模型]
    B --> F[集成学习]
    D --> G[线性回归]
    D --> H[逻辑回归]
    E --> I[决策树]
    F --> J[随机森林]
    F --> K[XGBoost]

课后练习

  1. 运行本节所有代码示例,理解每种算法的特点
  2. 尝试调整模型参数(如决策树深度、随机森林树的数量等),观察性能变化
  3. 在不同的数据集上测试这些算法,比较它们的表现
  4. 实现一个简单的模型比较函数,自动评估多个模型在相同数据上的性能

下节预告

下一节我们将学习无监督学习算法,包括K-Means聚类和PCA降维技术,这些方法在数据分析和特征工程中非常重要,敬请期待!


有任何疑问请在讨论区留言,我们会定期回复大家的问题。