十大基础机器学习算法详解与实践

十大基础机器学习算法详解与实践

本文档详细介绍十大经典机器学习算法(非深度学习),包含算法原理、数学公式、Python实现和可运行的训练代码。所有代码基于Python 3.11,可直接运行。

目录

  1. 引言
  2. 算法1:线性回归 (Linear Regression)
  3. 算法2:逻辑回归 (Logistic Regression)
  4. 算法3:支持向量机 (SVM)
  5. 算法4:朴素贝叶斯 (Naive Bayes)
  6. 算法5:决策树 (Decision Tree)
  7. 算法6:随机森林 (Random Forest)
  8. 算法7:K近邻 (KNN)
  9. 算法8:K均值聚类 (K-Means)
  10. 算法9:主成分分析 (PCA)
  11. 算法10:梯度提升树 (Gradient Boosting)
  12. 算法对比与选择指南
  13. 总结

引言

为什么学习这些算法?

基础机器学习算法是理解机器学习的基石,它们具有以下特点:

  1. 易于理解:算法原理清晰,数学基础扎实
  2. 实用性强:在实际项目中广泛应用
  3. 可解释性好:模型决策过程可解释
  4. 计算效率高:训练和推理速度快
  5. 数据要求低:不需要大量数据即可工作

环境准备

Python版本:Python 3.11

依赖安装

bash 复制代码
pip install -r docs/requirements_visualization.txt

核心依赖

  • numpy >= 1.24.0
  • scikit-learn >= 1.3.0
  • matplotlib >= 3.7.0
  • pandas >= 2.0.0
  • scipy >= 1.10.0

算法1:线性回归 (Linear Regression)

算法原理

线性回归是最基础的回归算法,通过拟合一条直线(或超平面)来预测连续值。它是统计学和机器学习中最基础、最常用的算法之一。

核心思想:找到一条直线(或超平面),使得所有数据点到直线的距离(误差)最小。

算法流程

复制代码
1. 数据准备 → 2. 特征选择 → 3. 模型训练 → 4. 预测 → 5. 评估
     ↓              ↓              ↓           ↓          ↓
  清洗数据      相关性分析      最小二乘法    新数据     MSE/R²
  处理缺失值    特征工程        或梯度下降    预测值     残差分析
  异常值检测    特征缩放

工作原理示意图

复制代码
一维情况(简单线性回归):
     y
     |     ●
     |   ●   ●
     | ●       ●
     |           ●
     |_____________x
     拟合直线 y = wx + b

多维情况(多元线性回归):
     y
     |     ●
     |   ●   ●
     | ●       ●
     |           ●
     |_____________x₁
     超平面 y = w₁x₁ + w₂x₂ + ... + b

数学公式详解

1. 模型公式

简单线性回归(一维)

复制代码
y = w₀ + w₁x + ε

多元线性回归(多维)

复制代码
y = w₀ + w₁x₁ + w₂x₂ + ... + wₙxₙ + ε

矩阵形式

复制代码
Y = XW + ε

其中:

  • y:目标变量(预测值),形状为 (n_samples,)
  • X:特征矩阵,形状为 (n_samples, n_features)
  • W:权重向量 [w₀, w₁, ..., wₙ]ᵀ,形状为 (n_features+1,)
  • ε:误差项,假设服从正态分布 N(0, σ²)
2. 损失函数

均方误差(MSE)

复制代码
MSE = (1/n) × Σ(yᵢ - ŷᵢ)²

均方根误差(RMSE)

复制代码
RMSE = √MSE = √[(1/n) × Σ(yᵢ - ŷᵢ)²]

平均绝对误差(MAE)

复制代码
MAE = (1/n) × Σ|yᵢ - ŷᵢ|
3. 求解方法

方法1:最小二乘法(解析解)

通过求导并令导数为零,得到解析解:

复制代码
W = (XᵀX)⁻¹XᵀY

优点 :一步到位,无需迭代
缺点:需要计算矩阵逆,当特征很多时计算量大

方法2:梯度下降(迭代优化)

梯度下降通过迭代更新参数:

复制代码
wⱼ = wⱼ - α × (∂MSE/∂wⱼ)

其中:

  • α:学习率(learning rate)
  • ∂MSE/∂wⱼ:损失函数对权重wⱼ的偏导数

梯度计算公式

复制代码
∂MSE/∂wⱼ = (2/n) × Σ xᵢⱼ(yᵢ - ŷᵢ)
∂MSE/∂b = (2/n) × Σ(yᵢ - ŷᵢ)

优点 :适用于大规模数据,可以处理特征很多的情况
缺点:需要调学习率,可能需要多次迭代

4. 评估指标

R²决定系数

复制代码
R² = 1 - (SS_res / SS_tot)

其中:

  • SS_res = Σ(yᵢ - ŷᵢ)²:残差平方和
  • SS_tot = Σ(yᵢ - ȳ)²:总平方和

R²的取值范围:[0, 1],越接近1表示模型拟合越好

调整R²(Adjusted R²)

复制代码
R²_adj = 1 - [(1-R²)(n-1)/(n-p-1)]

其中p是特征数量,用于惩罚过多的特征

数据预处理

1. 数据清洗

缺失值处理

  • 删除缺失值(如果缺失比例很小)
  • 用均值/中位数/众数填充
  • 用回归预测填充

异常值检测与处理

  • IQR方法:Q1 - 1.5×IQR < 数据 < Q3 + 1.5×IQR
  • Z-score方法:|z| > 3 视为异常值
  • 可视化方法:箱线图、散点图识别异常值

处理策略

  • 删除异常值(如果确认是错误数据)
  • 用截断值替换(Winsorization)
  • 保留但标记(如果可能是真实值)
2. 特征工程

特征缩放

虽然线性回归理论上不需要特征缩放,但实际应用中建议进行:

  • 标准化(Standardization)z = (x - μ) / σ
  • 归一化(Normalization)x_norm = (x - min) / (max - min)

特征变换

  • 多项式特征:x², x³(处理非线性关系)
  • 对数变换:log(x)(处理指数关系)
  • 交互特征:x₁ × x₂(捕捉特征交互)

特征选择

  • 相关性分析:选择与目标变量相关性高的特征
  • 方差分析:删除方差很小的特征(几乎常数)
  • 正则化:L1正则化(Lasso)可以自动进行特征选择
3. 数据划分
python 复制代码
# 训练集:用于训练模型(通常70-80%)
# 验证集:用于调参(通常10-15%)
# 测试集:用于最终评估(通常10-15%)

模型训练与优化

1. 正则化

Ridge回归(L2正则化)

复制代码
Loss = MSE + λ × Σwᵢ²

Lasso回归(L1正则化)

复制代码
Loss = MSE + λ × Σ|wᵢ|

Elastic Net(L1+L2)

复制代码
Loss = MSE + λ₁ × Σ|wᵢ| + λ₂ × Σwᵢ²

正则化可以:

  • 防止过拟合
  • 处理多重共线性
  • Lasso可以进行特征选择
2. 超参数调优

学习率(梯度下降)

  • 太小:收敛慢
  • 太大:可能不收敛或震荡
  • 建议:0.001 - 0.1,使用学习率衰减

正则化系数λ

  • 使用交叉验证选择最优值
  • 网格搜索或随机搜索
3. 模型诊断

残差分析

  • 残差应该随机分布,无模式
  • 残差应该服从正态分布
  • 残差应该同方差(方差恒定)

多重共线性检测

  • VIF(方差膨胀因子)> 10 表示存在多重共线性
  • 相关系数矩阵检查特征间相关性

线性假设检验

  • 检查残差图是否有非线性模式
  • 如果存在非线性,考虑多项式回归或非线性模型

Python实现

1. 使用scikit-learn实现
python 复制代码
import numpy as np
import matplotlib.pyplot as plt
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error, r2_score
import warnings
warnings.filterwarnings('ignore')

# 设置中文字体
plt.rcParams['font.sans-serif'] = ['SimHei', 'DejaVu Sans', 'Arial Unicode MS']
plt.rcParams['axes.unicode_minus'] = False

def linear_regression_demo():
    """
    线性回归完整示例
    """
    print("=" * 60)
    print("线性回归 (Linear Regression) 示例")
    print("=" * 60)
    
    # 1. 生成示例数据
    np.random.seed(42)
    n_samples = 100
    X = np.random.randn(n_samples, 1) * 10
    # y = 2x + 3 + 噪声
    y = 2 * X.flatten() + 3 + np.random.randn(n_samples) * 2
    
    # 2. 划分训练集和测试集
    X_train, X_test, y_train, y_test = train_test_split(
        X, y, test_size=0.2, random_state=42
    )
    
    # 3. 创建并训练模型
    model = LinearRegression()
    model.fit(X_train, y_train)
    
    # 4. 预测
    y_train_pred = model.predict(X_train)
    y_test_pred = model.predict(X_test)
    
    # 5. 评估
    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"  权重 (w): {model.coef_[0]:.4f}")
    print(f"  截距 (b): {model.intercept_:.4f}")
    print(f"\n训练集评估:")
    print(f"  MSE: {train_mse:.4f}")
    print(f"  R²: {train_r2:.4f}")
    print(f"\n测试集评估:")
    print(f"  MSE: {test_mse:.4f}")
    print(f"  R²: {test_r2:.4f}")
    
    # 6. 可视化
    plt.figure(figsize=(12, 5))
    
    # 训练集
    plt.subplot(1, 2, 1)
    plt.scatter(X_train, y_train, alpha=0.6, label='训练数据', color='blue')
    plt.plot(X_train, y_train_pred, 'r-', linewidth=2, label='拟合直线')
    plt.xlabel('特征 X', fontsize=12)
    plt.ylabel('目标 y', fontsize=12)
    plt.title(f'训练集 (R² = {train_r2:.3f})', fontsize=14, fontweight='bold')
    plt.legend()
    plt.grid(True, alpha=0.3)
    
    # 测试集
    plt.subplot(1, 2, 2)
    plt.scatter(X_test, y_test, alpha=0.6, label='测试数据', color='green')
    plt.plot(X_test, y_test_pred, 'r-', linewidth=2, label='拟合直线')
    plt.xlabel('特征 X', fontsize=12)
    plt.ylabel('目标 y', fontsize=12)
    plt.title(f'测试集 (R² = {test_r2:.3f})', fontsize=14, fontweight='bold')
    plt.legend()
    plt.grid(True, alpha=0.3)
    
    plt.tight_layout()
    plt.savefig('docs/images/linear_regression_demo.png', dpi=300, bbox_inches='tight')
    plt.show()
    
    return model, X_test, y_test, y_test_pred

# 运行示例
if __name__ == '__main__':
    model, X_test, y_test, y_pred = linear_regression_demo()
2. 从零实现线性回归
python 复制代码
class LinearRegressionFromScratch:
    """
    从零实现线性回归(使用梯度下降)
    """
    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
        self.cost_history = []
    
    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):
            # 预测
            y_pred = np.dot(X, self.weights) + self.bias
            
            # 计算损失
            cost = (1 / n_samples) * np.sum((y_pred - y) ** 2)
            self.cost_history.append(cost)
            
            # 计算梯度
            dw = (1 / n_samples) * np.dot(X.T, (y_pred - y))
            db = (1 / n_samples) * np.sum(y_pred - y)
            
            # 更新参数
            self.weights -= self.learning_rate * dw
            self.bias -= self.learning_rate * db
    
    def predict(self, X):
        """
        预测
        """
        return np.dot(X, self.weights) + self.bias

# 使用示例
def linear_regression_from_scratch_demo():
    """
    从零实现线性回归示例
    """
    print("\n" + "=" * 60)
    print("从零实现线性回归示例")
    print("=" * 60)
    
    # 生成数据
    np.random.seed(42)
    X = np.random.randn(100, 1) * 10
    y = 2 * X.flatten() + 3 + np.random.randn(100) * 2
    
    # 训练模型
    model = LinearRegressionFromScratch(learning_rate=0.01, n_iterations=1000)
    model.fit(X, y)
    
    # 预测
    y_pred = model.predict(X)
    
    # 评估
    mse = mean_squared_error(y, y_pred)
    r2 = r2_score(y, y_pred)
    
    print(f"\n模型参数:")
    print(f"  权重 (w): {model.weights[0]:.4f}")
    print(f"  截距 (b): {model.bias:.4f}")
    print(f"\n评估指标:")
    print(f"  MSE: {mse:.4f}")
    print(f"  R²: {r2:.4f}")
    
    # 可视化损失函数
    plt.figure(figsize=(10, 6))
    plt.plot(model.cost_history, linewidth=2)
    plt.xlabel('迭代次数', fontsize=12)
    plt.ylabel('损失 (MSE)', fontsize=12)
    plt.title('损失函数收敛曲线', fontsize=14, fontweight='bold')
    plt.grid(True, alpha=0.3)
    plt.savefig('docs/images/linear_regression_loss.png', dpi=300, bbox_inches='tight')
    plt.show()

# 运行
if __name__ == '__main__':
    linear_regression_from_scratch_demo()

模型后处理

1. 预测结果解释

系数解释

  • 系数wᵢ表示:当特征xᵢ增加1个单位,目标变量y平均增加wᵢ个单位(其他特征不变)
  • 截距w₀表示:当所有特征为0时的预测值

置信区间

python 复制代码
# 预测值的95%置信区间
from scipy import stats
std_err = np.sqrt(mse)
confidence_interval = stats.t.interval(0.95, len(y)-2, 
                                       loc=y_pred, 
                                       scale=std_err)
2. 模型解释性

特征重要性

  • 标准化系数:w_std = w × (std_x / std_y)
  • 标准化系数越大,特征对目标变量的影响越大

SHAP值(如果需要更详细的解释):

python 复制代码
import shap
explainer = shap.LinearExplainer(model, X_train)
shap_values = explainer.shap_values(X_test)
3. 模型部署

保存模型

python 复制代码
import joblib
joblib.dump(model, 'linear_regression_model.pkl')

模型服务化

  • REST API封装
  • 批量预测接口
  • 实时预测接口

实际应用案例

案例1:房价预测

问题描述:根据房屋面积、房间数、位置等特征预测房价

数据预处理

python 复制代码
# 1. 处理缺失值
df['bedrooms'].fillna(df['bedrooms'].median(), inplace=True)

# 2. 特征工程
df['price_per_sqft'] = df['price'] / df['sqft_living']
df['age'] = 2024 - df['yr_built']

# 3. 特征选择
features = ['sqft_living', 'bedrooms', 'bathrooms', 'age', 'zipcode']
X = df[features]
y = df['price']

# 4. 处理分类特征(zipcode)
from sklearn.preprocessing import LabelEncoder
le = LabelEncoder()
X['zipcode'] = le.fit_transform(X['zipcode'])

模型训练

python 复制代码
from sklearn.linear_model import Ridge
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import GridSearchCV

scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)

model = Ridge()
param_grid = {'alpha': [0.1, 1.0, 10.0, 100.0]}
grid_search = GridSearchCV(model, param_grid, cv=5, scoring='neg_mean_squared_error')
grid_search.fit(X_scaled, y)

best_model = grid_search.best_estimator_

结果解释

  • 房屋面积每增加100平方英尺,房价平均增加约$20,000
  • 每增加一个卧室,房价平均增加约$15,000
案例2:销售额预测

问题描述:根据广告投入、促销活动等预测销售额

特征工程

python 复制代码
# 创建交互特征
df['tv_radio_interaction'] = df['TV'] * df['Radio']
df['tv_newspaper_interaction'] = df['TV'] * df['Newspaper']

# 对数变换(处理非线性关系)
df['TV_log'] = np.log1p(df['TV'])

模型选择

  • 简单线性回归:基线模型
  • Ridge回归:处理多重共线性
  • 多项式回归:捕捉非线性关系

优缺点分析

优点

  1. 简单易懂:算法原理直观,易于理解和实现
  2. 训练速度快:最小二乘法有解析解,计算效率高
  3. 可解释性强:系数有明确的物理意义
  4. 不需要特征缩放:在某些情况下(最小二乘法)不需要
  5. 理论基础扎实:有完整的统计理论支撑
  6. 不易过拟合:当使用正则化时

缺点

  1. 线性假设:假设特征和目标变量是线性关系,无法捕捉非线性模式
  2. 对异常值敏感:MSE损失函数对异常值敏感
  3. 容易过拟合:当特征很多时,容易过拟合(需要用正则化)
  4. 多重共线性问题:特征间高度相关时,系数不稳定
  5. 需要特征工程:需要手动创建非线性特征

常见问题与解决方案

Q1: 模型预测不准确怎么办?

可能原因及解决方案

  1. 非线性关系

    • 解决方案:使用多项式特征、对数变换
    • 或使用非线性模型(决策树、随机森林)
  2. 特征不足

    • 解决方案:特征工程,创建更多有意义的特征
    • 特征选择,删除无关特征
  3. 数据质量问题

    • 解决方案:检查异常值、缺失值
    • 数据清洗和预处理
Q2: 如何判断模型是否过拟合?

判断方法

  • 训练集R²很高,但测试集R²很低
  • 训练集MSE很小,但测试集MSE很大

解决方案

  • 使用正则化(Ridge、Lasso)
  • 减少特征数量
  • 增加训练数据
  • 使用交叉验证
Q3: 如何处理多重共线性?

检测方法

python 复制代码
from statsmodels.stats.outliers_influence import variance_inflation_factor

vif_data = pd.DataFrame()
vif_data["feature"] = X.columns
vif_data["VIF"] = [variance_inflation_factor(X.values, i) 
                   for i in range(len(X.columns))]
# VIF > 10 表示存在多重共线性

解决方案

  • 删除高度相关的特征之一
  • 使用Ridge回归(L2正则化)
  • 使用主成分分析(PCA)降维
Q4: 如何处理异方差性?

检测方法

  • 绘制残差图,检查残差是否随预测值变化

解决方案

  • 使用加权最小二乘法(WLS)
  • 对目标变量进行对数变换
  • 使用稳健回归方法
Q5: 如何选择正则化参数?

方法

python 复制代码
from sklearn.linear_model import RidgeCV

# 使用交叉验证自动选择最优alpha
ridge_cv = RidgeCV(alphas=[0.1, 1.0, 10.0, 100.0], cv=5)
ridge_cv.fit(X_train, y_train)
print(f"最优alpha: {ridge_cv.alpha_}")

算法流程图

复制代码
开始
  ↓
数据加载与探索
  ↓
数据清洗(缺失值、异常值)
  ↓
特征工程(缩放、变换、选择)
  ↓
数据划分(训练集/验证集/测试集)
  ↓
模型选择(线性回归/Ridge/Lasso)
  ↓
超参数调优(交叉验证)
  ↓
模型训练
  ↓
模型评估(MSE、R²、残差分析)
  ↓
模型诊断(多重共线性、异方差性)
  ↓
模型优化(正则化、特征选择)
  ↓
最终预测
  ↓
模型解释与部署
  ↓
结束

算法2:逻辑回归 (Logistic Regression)

算法原理

逻辑回归虽然名字叫"回归",但实际上是分类算法,主要用于二分类问题(也可以扩展到多分类)。它是线性回归的扩展,通过Sigmoid函数将线性组合映射到概率空间。

核心思想:使用Sigmoid函数将线性回归的输出映射到[0,1]区间,表示样本属于正类的概率。

算法流程

复制代码
1. 数据准备 → 2. 特征工程 → 3. 模型训练 → 4. 概率预测 → 5. 分类决策
     ↓              ↓              ↓            ↓            ↓
  清洗数据      特征缩放        梯度下降      输出概率     阈值选择
  处理不平衡    特征选择        或牛顿法      [0,1]区间    默认0.5
  编码类别      处理共线性

工作原理示意图

复制代码
线性回归输出 z = w₀ + w₁x₁ + ... + wₙxₙ
         ↓
    Sigmoid函数
         ↓
   概率 P(y=1|x) = σ(z) = 1/(1+e^(-z))
         ↓
   决策规则:如果 P > 0.5,预测为类别1,否则为类别0

Sigmoid函数图像:
    P
    1 |        ╱──────
      |      ╱
      |    ╱
    0.5 |───
      |  ╱
      |╱
    0 |─────────────── z
      -∞    0    +∞

数学公式详解

1. Sigmoid函数

定义

复制代码
σ(z) = 1 / (1 + e^(-z))

性质

  • 值域:[0, 1]
  • 单调递增
  • 关于点(0, 0.5)中心对称
  • 导数:σ'(z) = σ(z)(1 - σ(z))

为什么使用Sigmoid

  1. 将任意实数映射到[0,1],符合概率定义
  2. 单调性保证特征越大,概率越大
  3. 导数形式简单,便于梯度计算
2. 模型公式

二分类逻辑回归

复制代码
P(y=1|x) = σ(w₀ + w₁x₁ + ... + wₙxₙ)
         = 1 / (1 + e^(-(w₀ + w₁x₁ + ... + wₙxₙ)))

P(y=0|x) = 1 - P(y=1|x)

对数几率(Logit)

复制代码
logit(P) = ln(P / (1-P)) = w₀ + w₁x₁ + ... + wₙxₙ

多分类逻辑回归(Softmax)

复制代码
P(y=k|x) = e^(z_k) / Σᵢ e^(z_i)

其中 z_k = w₀ᵏ + w₁ᵏx₁ + ... + wₙᵏxₙ

3. 损失函数

对数损失(Log Loss / Cross Entropy)

复制代码
Loss = -[y·log(ŷ) + (1-y)·log(1-ŷ)]

批量损失

复制代码
J(W) = -(1/n) × Σ[yᵢ·log(ŷᵢ) + (1-yᵢ)·log(1-ŷᵢ)]

为什么使用对数损失

  • 当预测错误时,损失会很大(惩罚严重错误)
  • 当预测正确时,损失接近0
  • 梯度形式简单,便于优化
4. 优化方法

梯度下降

复制代码
wⱼ = wⱼ - α × (∂J/∂wⱼ)

梯度计算

复制代码
∂J/∂wⱼ = (1/n) × Σ xᵢⱼ(ŷᵢ - yᵢ)

牛顿法(二阶优化)

  • 收敛速度更快
  • 但计算Hessian矩阵成本高

数据预处理

1. 数据清洗

缺失值处理

  • 分类特征:用众数填充
  • 数值特征:用均值/中位数填充
  • 或使用模型预测填充

异常值处理

  • 逻辑回归对异常值相对稳健(因为Sigmoid函数有界)
  • 但仍需检查和处理极端值
2. 特征工程

特征缩放

  • 必须进行特征缩放(与线性回归不同)
  • 标准化:z = (x - μ) / σ
  • 归一化:x_norm = (x - min) / (max - min)

原因:梯度下降需要特征尺度相近才能快速收敛

特征变换

  • 多项式特征:捕捉非线性关系
  • 交互特征:x₁ × x₂
  • 分箱(Binning):将连续特征离散化

类别特征编码

  • One-Hot编码:每个类别一个二进制特征
  • Label编码:仅适用于有序类别
  • Target编码:用目标变量的均值编码
3. 处理类别不平衡

问题:正负样本比例悬殊(如1:99)

解决方案

  1. 调整类别权重
python 复制代码
model = LogisticRegression(class_weight='balanced')
# 或
model = LogisticRegression(class_weight={0: 1, 1: 10})
  1. 过采样(SMOTE)
python 复制代码
from imblearn.over_sampling import SMOTE
smote = SMOTE(random_state=42)
X_resampled, y_resampled = smote.fit_resample(X_train, y_train)
  1. 欠采样
python 复制代码
from imblearn.under_sampling import RandomUnderSampler
undersample = RandomUnderSampler(random_state=42)
X_resampled, y_resampled = undersample.fit_resample(X_train, y_train)
  1. 调整决策阈值
python 复制代码
# 默认阈值0.5,可以调整
y_pred = (y_proba > 0.3).astype(int)  # 降低阈值,增加召回率

模型训练与优化

1. 正则化

L2正则化(Ridge)

python 复制代码
model = LogisticRegression(penalty='l2', C=1.0)

L1正则化(Lasso)

python 复制代码
model = LogisticRegression(penalty='l1', C=1.0, solver='liblinear')

Elastic Net

python 复制代码
model = LogisticRegression(penalty='elasticnet', l1_ratio=0.5, solver='saga')

参数C

  • C = 1/λ(正则化强度的倒数)
  • C越大,正则化越弱(容易过拟合)
  • C越小,正则化越强(容易欠拟合)
2. 超参数调优

主要超参数

  • C:正则化强度(通常0.001 - 100)
  • penalty:正则化类型('l1', 'l2', 'elasticnet')
  • solver:优化算法('lbfgs', 'liblinear', 'saga'等)
  • max_iter:最大迭代次数

调优方法

python 复制代码
from sklearn.model_selection import GridSearchCV

param_grid = {
    'C': [0.001, 0.01, 0.1, 1.0, 10.0, 100.0],
    'penalty': ['l1', 'l2'],
    'solver': ['liblinear', 'lbfgs']
}

grid_search = GridSearchCV(LogisticRegression(), param_grid, cv=5, scoring='roc_auc')
grid_search.fit(X_train, y_train)
3. 多分类问题

方法1:One-vs-Rest (OvR)

  • 训练K个二分类器(K为类别数)
  • 每个分类器区分一个类别和其他所有类别

方法2:One-vs-One (OvO)

  • 训练K(K-1)/2个二分类器
  • 每对类别训练一个分类器

方法3:Softmax(多分类逻辑回归)

python 复制代码
model = LogisticRegression(multi_class='multinomial', solver='lbfgs')

Python实现

python 复制代码
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score, confusion_matrix, classification_report, roc_curve, auc
from sklearn.datasets import make_classification

def logistic_regression_demo():
    """
    逻辑回归完整示例
    """
    print("=" * 60)
    print("逻辑回归 (Logistic Regression) 示例")
    print("=" * 60)
    
    # 1. 生成二分类数据
    X, y = make_classification(
        n_samples=1000,
        n_features=2,
        n_redundant=0,
        n_informative=2,
        n_clusters_per_class=1,
        random_state=42
    )
    
    # 2. 划分数据集
    X_train, X_test, y_train, y_test = train_test_split(
        X, y, test_size=0.2, random_state=42
    )
    
    # 3. 训练模型
    model = LogisticRegression(max_iter=1000, random_state=42)
    model.fit(X_train, y_train)
    
    # 4. 预测
    y_train_pred = model.predict(X_train)
    y_test_pred = model.predict(X_test)
    y_test_proba = model.predict_proba(X_test)[:, 1]
    
    # 5. 评估
    train_acc = accuracy_score(y_train, y_train_pred)
    test_acc = accuracy_score(y_test, y_test_pred)
    
    print(f"\n模型参数:")
    print(f"  权重: {model.coef_}")
    print(f"  截距: {model.intercept_}")
    print(f"\n训练集准确率: {train_acc:.4f}")
    print(f"测试集准确率: {test_acc:.4f}")
    print(f"\n分类报告:")
    print(classification_report(y_test, y_test_pred))
    
    # 6. 可视化
    fig, axes = plt.subplots(1, 3, figsize=(18, 5))
    
    # 决策边界
    ax1 = axes[0]
    h = 0.02
    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, h),
                         np.arange(y_min, y_max, h))
    Z = model.predict(np.c_[xx.ravel(), yy.ravel()])
    Z = Z.reshape(xx.shape)
    ax1.contourf(xx, yy, Z, alpha=0.3, cmap=plt.cm.RdYlBu)
    scatter = ax1.scatter(X[:, 0], X[:, 1], c=y, cmap=plt.cm.RdYlBu, edgecolors='black')
    ax1.set_xlabel('特征 1', fontsize=12)
    ax1.set_ylabel('特征 2', fontsize=12)
    ax1.set_title('决策边界', fontsize=14, fontweight='bold')
    plt.colorbar(scatter, ax=ax1)
    
    # 混淆矩阵
    ax2 = axes[1]
    cm = confusion_matrix(y_test, y_test_pred)
    sns.heatmap(cm, annot=True, fmt='d', cmap='Blues', ax=ax2)
    ax2.set_xlabel('预测标签', fontsize=12)
    ax2.set_ylabel('真实标签', fontsize=12)
    ax2.set_title('混淆矩阵', fontsize=14, fontweight='bold')
    
    # ROC曲线
    ax3 = axes[2]
    fpr, tpr, _ = roc_curve(y_test, y_test_proba)
    roc_auc = auc(fpr, tpr)
    ax3.plot(fpr, tpr, linewidth=2, label=f'ROC曲线 (AUC = {roc_auc:.3f})')
    ax3.plot([0, 1], [0, 1], 'k--', label='随机分类器')
    ax3.set_xlabel('假正率 (FPR)', fontsize=12)
    ax3.set_ylabel('真正率 (TPR)', fontsize=12)
    ax3.set_title('ROC曲线', fontsize=14, fontweight='bold')
    ax3.legend()
    ax3.grid(True, alpha=0.3)
    
    plt.tight_layout()
    plt.savefig('docs/images/logistic_regression_demo.png', dpi=300, bbox_inches='tight')
    plt.show()
    
    return model

# 运行示例
if __name__ == '__main__':
    model = logistic_regression_demo()

模型后处理

1. 概率校准

问题:逻辑回归输出的概率可能不够准确

校准方法

python 复制代码
from sklearn.calibration import CalibratedClassifierCV

# Platt Scaling
calibrated_model = CalibratedClassifierCV(model, method='sigmoid', cv=3)
calibrated_model.fit(X_train, y_train)
y_proba_calibrated = calibrated_model.predict_proba(X_test)[:, 1]
2. 阈值优化

默认阈值:0.5(可能不是最优)

优化方法

python 复制代码
from sklearn.metrics import roc_curve

fpr, tpr, thresholds = roc_curve(y_test, y_proba)
# 找到最优阈值(最大化F1分数或Youden指数)
optimal_idx = np.argmax(tpr - fpr)
optimal_threshold = thresholds[optimal_idx]

y_pred_optimal = (y_proba > optimal_threshold).astype(int)
3. 模型解释

系数解释

  • 系数wᵢ表示:特征xᵢ增加1个单位,对数几率增加wᵢ
  • 优势比(Odds Ratio):OR = e^wᵢ
    • OR > 1:特征增加会提高正类概率
    • OR < 1:特征增加会降低正类概率

特征重要性

python 复制代码
# 标准化系数
feature_importance = np.abs(model.coef_[0]) * np.std(X_train, axis=0)

实际应用案例

案例1:垃圾邮件分类

问题描述:根据邮件内容判断是否为垃圾邮件

数据预处理

python 复制代码
from sklearn.feature_extraction.text import TfidfVectorizer

# 文本特征提取
vectorizer = TfidfVectorizer(max_features=5000, ngram_range=(1, 2))
X = vectorizer.fit_transform(emails)

# 处理不平衡(假设垃圾邮件占10%)
from imblearn.over_sampling import SMOTE
smote = SMOTE(random_state=42)
X_resampled, y_resampled = smote.fit_resample(X, y)

模型训练

python 复制代码
from sklearn.linear_model import LogisticRegression

model = LogisticRegression(
    C=1.0,
    penalty='l2',
    class_weight='balanced',
    max_iter=1000
)
model.fit(X_resampled, y_resampled)

结果评估

  • 准确率:95%
  • 精确率:92%(垃圾邮件中真正是垃圾邮件的比例)
  • 召回率:88%(所有垃圾邮件中被正确识别的比例)
  • F1分数:90%
案例2:疾病诊断

问题描述:根据患者症状预测是否患病

特征工程

python 复制代码
# 处理类别特征
from sklearn.preprocessing import OneHotEncoder

encoder = OneHotEncoder(drop='first', sparse=False)
X_categorical = encoder.fit_transform(df[['性别', '血型']])

# 数值特征标准化
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
X_numerical = scaler.fit_transform(df[['年龄', '血压', '血糖']])

# 合并特征
X = np.hstack([X_numerical, X_categorical])

模型解释

  • 年龄每增加1岁,患病概率的对数几率增加0.05
  • 血压每增加1个单位,患病概率的对数几率增加0.15
  • 优势比:e^0.15 ≈ 1.16,表示血压每增加1个单位,患病概率增加16%

优缺点分析

优点

  1. 输出概率:不仅给出分类结果,还给出概率值
  2. 可解释性强:系数有明确的统计意义
  3. 训练速度快:优化算法成熟,收敛快
  4. 不需要特征缩放:虽然建议缩放,但不是必须的
  5. 不易过拟合:使用正则化可以有效防止过拟合
  6. 支持多分类:可以扩展到多分类问题

缺点

  1. 线性决策边界:只能学习线性决策边界(除非使用核技巧)
  2. 需要特征工程:需要手动创建非线性特征
  3. 对异常值敏感:虽然比线性回归好,但仍可能受影响
  4. 假设特征独立:虽然不像朴素贝叶斯那样严格,但仍可能受影响
  5. 需要大量样本:在小样本上可能表现不佳

常见问题与解决方案

Q1: 模型预测概率总是接近0.5怎么办?

可能原因

  • 特征不够区分性强
  • 数据不平衡但未处理
  • 正则化过强

解决方案

  • 特征工程,创建更有区分性的特征
  • 处理类别不平衡
  • 调整正则化参数C
Q2: 如何选择最优阈值?

方法

python 复制代码
from sklearn.metrics import precision_recall_curve, f1_score

precision, recall, thresholds = precision_recall_curve(y_test, y_proba)
f1_scores = 2 * (precision * recall) / (precision + recall)
optimal_idx = np.argmax(f1_scores)
optimal_threshold = thresholds[optimal_idx]

考虑因素

  • 如果假阳性成本高:提高阈值(更保守)
  • 如果假阴性成本高:降低阈值(更激进)
Q3: 如何处理多分类问题?

方法1:One-vs-Rest

python 复制代码
model = LogisticRegression(multi_class='ovr')

方法2:Multinomial(Softmax)

python 复制代码
model = LogisticRegression(multi_class='multinomial', solver='lbfgs')

选择建议

  • 类别数少(<10):使用Multinomial
  • 类别数多(>10):使用OvR
Q4: 模型过拟合怎么办?

解决方案

  • 增加正则化强度(减小C值)
  • 减少特征数量
  • 增加训练数据
  • 使用交叉验证选择最优参数
Q5: 如何处理特征间的交互?

方法

python 复制代码
from sklearn.preprocessing import PolynomialFeatures

poly = PolynomialFeatures(degree=2, interaction_only=True)
X_poly = poly.fit_transform(X)

注意:会增加特征数量,可能导致过拟合

算法流程图

复制代码
开始
  ↓
数据加载与探索
  ↓
数据清洗(缺失值、异常值)
  ↓
特征工程(文本向量化/数值标准化/类别编码)
  ↓
处理类别不平衡(SMOTE/欠采样/权重调整)
  ↓
数据划分(训练集/验证集/测试集)
  ↓
模型选择(二分类/多分类)
  ↓
超参数调优(C、penalty、solver)
  ↓
模型训练(梯度下降/牛顿法)
  ↓
模型评估(准确率/精确率/召回率/F1/ROC-AUC)
  ↓
阈值优化(根据业务需求)
  ↓
概率校准(如果需要)
  ↓
模型解释(系数、优势比)
  ↓
模型部署
  ↓
结束

算法3:支持向量机 (SVM)

算法原理

支持向量机(Support Vector Machine, SVM)是一种强大的分类算法,通过寻找最优分离超平面来分类数据。SVM的核心思想是最大化两类数据之间的间隔(margin),从而获得更好的泛化能力。

核心思想:找到能够最大化两类数据间隔的超平面,使得分类边界距离最近的样本点(支持向量)最远。

算法流程

复制代码
1. 数据准备 → 2. 特征缩放 → 3. 选择核函数 → 4. 训练SVM → 5. 预测
     ↓              ↓              ↓              ↓          ↓
  清洗数据      标准化/归一化    线性/多项式/RBF  求解优化问题  决策函数
  处理缺失值    (必须!)        高斯/ Sigmoid    二次规划      sign(w·x+b)
  异常值检测

工作原理示意图

复制代码
硬间隔SVM(线性可分):
     ●
   ●   ●
 ●       ●
           ●
─────────── 超平面 w·x + b = 0
           ●
 ●       ●
   ●   ●
     ●

软间隔SVM(线性不可分):
     ●
   ●   ●  ξ
 ●    ξ  ●     允许一些样本在间隔内
           ●
─────────── 超平面(允许错误)
           ●
 ●       ●
   ●   ●
     ●

支持向量:距离超平面最近的样本点
间隔:两个平行超平面之间的距离

数学公式详解

1. 硬间隔SVM(线性可分)

优化目标

复制代码
minimize: (1/2)||w||²
subject to: yᵢ(w·xᵢ + b) ≥ 1,  ∀i

几何意义

  • 最大化间隔 = 最小化 ||w||
  • 约束条件确保所有样本正确分类且距离超平面至少为1

对偶问题(更易求解):

复制代码
maximize: Σαᵢ - (1/2)ΣΣαᵢαⱼyᵢyⱼ(xᵢ·xⱼ)
subject to: Σαᵢyᵢ = 0, αᵢ ≥ 0
2. 软间隔SVM(线性不可分)

优化目标

复制代码
minimize: (1/2)||w||² + CΣξᵢ
subject to: yᵢ(w·xᵢ + b) ≥ 1 - ξᵢ, ξᵢ ≥ 0

参数说明

  • C:惩罚参数,控制对误分类的惩罚程度
    • C大:严格分类,可能过拟合
    • C小:允许更多错误,泛化能力更强
  • ξᵢ:松弛变量,允许样本在间隔内或错误分类
3. 核技巧(非线性SVM)

问题:数据线性不可分时,需要非线性决策边界

解决方案:通过核函数将数据映射到高维空间,在高维空间中线性可分

常用核函数

  1. 线性核K(xᵢ, xⱼ) = xᵢ·xⱼ

    • 适用于线性可分数据
  2. 多项式核K(xᵢ, xⱼ) = (γxᵢ·xⱼ + r)^d

    • 参数:d(次数)、γ(缩放)、r(常数项)
  3. RBF(高斯)核K(xᵢ, xⱼ) = exp(-γ||xᵢ - xⱼ||²)

    • 参数:γ(gamma),控制决策边界的复杂度
    • γ大:决策边界复杂,可能过拟合
    • γ小:决策边界平滑,可能欠拟合
  4. Sigmoid核K(xᵢ, xⱼ) = tanh(γxᵢ·xⱼ + r)

决策函数

复制代码
f(x) = sign(ΣαᵢyᵢK(xᵢ, x) + b)
4. 支持向量

定义 :满足 αᵢ > 0 的样本点

特点

  • 支持向量决定了决策边界
  • 只有支持向量对模型有影响
  • 删除非支持向量不影响模型

数据预处理

1. 特征缩放(必须!)

为什么必须缩放

  • SVM使用距离度量,对特征尺度敏感
  • 不同尺度的特征会导致某些特征主导模型

方法

python 复制代码
from sklearn.preprocessing import StandardScaler

scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)

标准化 vs 归一化

  • 标准化z = (x - μ) / σ(推荐,保持分布形状)
  • 归一化x_norm = (x - min) / (max - min)(映射到[0,1])
2. 处理类别不平衡

方法

python 复制代码
from sklearn.svm import SVC

# 方法1:调整类别权重
model = SVC(class_weight='balanced')

# 方法2:自定义权重
model = SVC(class_weight={0: 1, 1: 10})
3. 特征选择

原因:SVM在高维空间中计算成本高

方法

  • 相关性分析
  • 主成分分析(PCA)
  • 递归特征消除(RFE)

模型训练与优化

1. 核函数选择

选择指南

  • 线性核:特征数 >> 样本数,或数据线性可分
  • RBF核:数据非线性,样本数适中(默认选择)
  • 多项式核:数据有明显的多项式关系
  • Sigmoid核:很少使用

经验法则

  • 先尝试RBF核
  • 如果效果不好,再尝试其他核
2. 超参数调优

主要超参数

  • C:惩罚参数(通常0.001 - 1000)
  • gamma:RBF核参数(通常0.0001 - 10)
  • kernel:核函数类型
  • degree:多项式核的次数(通常2-5)

调优方法

python 复制代码
from sklearn.model_selection import GridSearchCV

param_grid = {
    'C': [0.1, 1, 10, 100],
    'gamma': [0.001, 0.01, 0.1, 1],
    'kernel': ['rbf', 'poly', 'sigmoid']
}

grid_search = GridSearchCV(SVC(), param_grid, cv=5, scoring='accuracy')
grid_search.fit(X_train, y_train)
3. 处理大规模数据

问题:SVM训练时间复杂度为O(n²)或O(n³),不适合大规模数据

解决方案

  • 使用LinearSVC(线性SVM,更快)
  • 采样数据
  • 使用增量学习
  • 使用近似方法(如Nystroem方法)

Python实现

python 复制代码
from sklearn.svm import SVC
from sklearn.preprocessing import StandardScaler

def svm_demo():
    """
    支持向量机完整示例
    """
    print("=" * 60)
    print("支持向量机 (SVM) 示例")
    print("=" * 60)
    
    # 1. 生成数据
    X, y = make_classification(
        n_samples=200,
        n_features=2,
        n_redundant=0,
        n_informative=2,
        n_clusters_per_class=1,
        random_state=42
    )
    
    # 2. 数据标准化(SVM对尺度敏感)
    scaler = StandardScaler()
    X_scaled = scaler.fit_transform(X)
    
    X_train, X_test, y_train, y_test = train_test_split(
        X_scaled, y, test_size=0.2, random_state=42
    )
    
    # 3. 训练不同核函数的SVM
    kernels = ['linear', 'poly', 'rbf', 'sigmoid']
    models = {}
    
    for kernel in kernels:
        model = SVC(kernel=kernel, random_state=42, probability=True)
        model.fit(X_train, y_train)
        models[kernel] = model
        test_acc = accuracy_score(y_test, model.predict(X_test))
        print(f"{kernel} 核函数 - 测试准确率: {test_acc:.4f}")
    
    # 4. 可视化不同核函数的效果
    fig, axes = plt.subplots(2, 2, figsize=(16, 12))
    axes = axes.flatten()
    
    h = 0.02
    x_min, x_max = X_scaled[:, 0].min() - 1, X_scaled[:, 0].max() + 1
    y_min, y_max = X_scaled[:, 1].min() - 1, X_scaled[:, 1].max() + 1
    xx, yy = np.meshgrid(np.arange(x_min, x_max, h),
                         np.arange(y_min, y_max, h))
    
    for idx, (kernel, model) in enumerate(models.items()):
        ax = axes[idx]
        Z = model.predict(np.c_[xx.ravel(), yy.ravel()])
        Z = Z.reshape(xx.shape)
        ax.contourf(xx, yy, Z, alpha=0.3, cmap=plt.cm.RdYlBu)
        scatter = ax.scatter(X_scaled[:, 0], X_scaled[:, 1], c=y, 
                           cmap=plt.cm.RdYlBu, edgecolors='black')
        ax.set_title(f'{kernel} 核函数', fontsize=14, fontweight='bold')
        ax.set_xlabel('特征 1', fontsize=12)
        ax.set_ylabel('特征 2', fontsize=12)
    
    plt.tight_layout()
    plt.savefig('docs/images/svm_demo.png', dpi=300, bbox_inches='tight')
    plt.show()
    
    return models

# 运行示例
if __name__ == '__main__':
    models = svm_demo()

模型后处理

1. 支持向量分析

查看支持向量

python 复制代码
# 支持向量的数量
n_support = model.n_support_
print(f"支持向量数量: {n_support}")

# 支持向量的索引
support_vectors = model.support_
print(f"支持向量索引: {support_vectors}")

# 支持向量的系数
support_coef = model.dual_coef_

支持向量比例

  • 比例高:模型可能过拟合
  • 比例低:模型泛化能力好
2. 决策边界可视化

2D可视化

python 复制代码
def plot_decision_boundary(model, X, y):
    h = 0.02
    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, h),
                         np.arange(y_min, y_max, h))
    
    Z = model.predict(np.c_[xx.ravel(), yy.ravel()])
    Z = Z.reshape(xx.shape)
    
    plt.contourf(xx, yy, Z, alpha=0.3, cmap=plt.cm.RdYlBu)
    plt.scatter(X[:, 0], X[:, 1], c=y, cmap=plt.cm.RdYlBu, edgecolors='black')
    
    # 标记支持向量
    support_vectors = model.support_vectors_
    plt.scatter(support_vectors[:, 0], support_vectors[:, 1], 
               s=200, facecolors='none', edgecolors='red', linewidths=2)
3. 概率预测校准

SVM概率输出

python 复制代码
model = SVC(probability=True)  # 需要设置probability=True
model.fit(X_train, y_train)
y_proba = model.predict_proba(X_test)

注意:SVM的概率输出使用Platt Scaling,可能不够准确

实际应用案例

案例1:文本分类

问题描述:新闻文章分类(政治、体育、科技等)

数据预处理

python 复制代码
from sklearn.feature_extraction.text import TfidfVectorizer

# TF-IDF特征提取
vectorizer = TfidfVectorizer(max_features=10000, ngram_range=(1, 2))
X = vectorizer.fit_transform(texts)

# 特征已经标准化(TF-IDF本身就是标准化的)

模型训练

python 复制代码
from sklearn.svm import LinearSVC  # 线性SVM,更快

model = LinearSVC(C=1.0, class_weight='balanced')
model.fit(X_train, y_train)

结果

  • 准确率:92%
  • 训练速度快(线性SVM)
  • 适合高维稀疏数据
案例2:图像分类

问题描述:手写数字识别(MNIST)

数据预处理

python 复制代码
from sklearn.preprocessing import StandardScaler

# 图像数据展平
X = images.reshape(len(images), -1)  # (n_samples, 784)

# 标准化像素值
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)

模型训练

python 复制代码
from sklearn.svm import SVC

# 使用RBF核处理非线性
model = SVC(kernel='rbf', C=10, gamma=0.001)
model.fit(X_train_scaled, y_train)

优化

  • 使用PCA降维(减少特征数)
  • 使用网格搜索调参
  • 考虑使用线性SVM + 特征工程

优缺点分析

优点

  1. 泛化能力强:最大化间隔,泛化性能好
  2. 支持非线性:通过核技巧处理非线性问题
  3. 内存效率高:只需要存储支持向量
  4. 对异常值相对稳健:软间隔SVM可以处理异常值
  5. 适合高维数据:在高维空间中表现好

缺点

  1. 训练时间长:时间复杂度O(n²)或O(n³)
  2. 不适合大规模数据:样本数>10万时训练很慢
  3. 对参数敏感:C和gamma需要仔细调优
  4. 可解释性差:难以解释决策过程
  5. 需要特征缩放:必须进行特征标准化
  6. 概率输出不准确:概率预测使用近似方法

常见问题与解决方案

Q1: SVM训练太慢怎么办?

解决方案

  1. 使用LinearSVC(线性SVM):
python 复制代码
from sklearn.svm import LinearSVC
model = LinearSVC()  # 比SVC快很多
  1. 减少样本数
python 复制代码
from sklearn.model_selection import train_test_split
X_small, _, y_small, _ = train_test_split(X, y, train_size=10000, random_state=42)
  1. 特征降维
python 复制代码
from sklearn.decomposition import PCA
pca = PCA(n_components=100)
X_reduced = pca.fit_transform(X)
Q2: 如何选择C和gamma?

方法

python 复制代码
from sklearn.model_selection import GridSearchCV

param_grid = {
    'C': [0.1, 1, 10, 100, 1000],
    'gamma': [0.0001, 0.001, 0.01, 0.1, 1]
}

grid_search = GridSearchCV(SVC(kernel='rbf'), param_grid, cv=5)
grid_search.fit(X_train, y_train)

经验值

  • C:通常0.1 - 100
  • gamma:通常0.001 - 1
Q3: 如何选择核函数?

选择指南

  • 线性核:特征数 >> 样本数,或数据线性可分
  • RBF核:默认选择,适合大多数情况
  • 多项式核:数据有明显的多项式关系

测试方法

python 复制代码
kernels = ['linear', 'rbf', 'poly']
for kernel in kernels:
    model = SVC(kernel=kernel)
    scores = cross_val_score(model, X_train, y_train, cv=5)
    print(f"{kernel}: {scores.mean():.4f}")
Q4: 支持向量太多怎么办?

可能原因

  • C太大(过拟合)
  • gamma太大(决策边界太复杂)

解决方案

  • 减小C值
  • 减小gamma值
  • 增加训练数据
  • 特征选择,减少噪声特征
Q5: 如何处理多分类问题?

方法

  • One-vs-Rest:默认方法,训练K个二分类器
  • One-vs-One:训练K(K-1)/2个二分类器
python 复制代码
# One-vs-Rest(默认)
model = SVC(decision_function_shape='ovr')

# One-vs-One
model = SVC(decision_function_shape='ovo')

算法流程图

复制代码
开始
  ↓
数据加载与探索
  ↓
数据清洗(缺失值、异常值)
  ↓
特征缩放(标准化/归一化,必须!)
  ↓
特征选择(如果特征太多)
  ↓
数据划分(训练集/验证集/测试集)
  ↓
选择核函数(线性/RBF/多项式)
  ↓
超参数调优(C、gamma、degree)
  ↓
模型训练(求解二次规划问题)
  ↓
模型评估(准确率/精确率/召回率)
  ↓
支持向量分析
  ↓
决策边界可视化
  ↓
模型部署
  ↓
结束

算法4:朴素贝叶斯 (Naive Bayes)

算法原理

朴素贝叶斯基于贝叶斯定理,假设特征之间相互独立。

核心思想:根据先验概率和条件概率计算后验概率。

数学公式

贝叶斯定理

复制代码
P(y|x) = P(x|y) · P(y) / P(x)

朴素假设

复制代码
P(x₁, x₂, ..., xₙ|y) = P(x₁|y) · P(x₂|y) · ... · P(xₙ|y)

Python实现

python 复制代码
from sklearn.naive_bayes import GaussianNB, MultinomialNB, BernoulliNB
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.datasets import fetch_20newsgroups

def naive_bayes_demo():
    """
    朴素贝叶斯完整示例
    """
    print("=" * 60)
    print("朴素贝叶斯 (Naive Bayes) 示例")
    print("=" * 60)
    
    # 1. 生成数据
    X, y = make_classification(
        n_samples=1000,
        n_features=10,
        n_classes=3,
        n_informative=5,
        random_state=42
    )
    
    X_train, X_test, y_train, y_test = train_test_split(
        X, y, test_size=0.2, random_state=42
    )
    
    # 2. 训练高斯朴素贝叶斯
    model = GaussianNB()
    model.fit(X_train, y_train)
    
    # 3. 预测
    y_pred = model.predict(X_test)
    y_proba = model.predict_proba(X_test)
    
    # 4. 评估
    acc = accuracy_score(y_test, y_pred)
    print(f"\n测试集准确率: {acc:.4f}")
    print(f"\n分类报告:")
    print(classification_report(y_test, y_pred))
    
    # 5. 可视化
    fig, axes = plt.subplots(1, 2, figsize=(16, 6))
    
    # 混淆矩阵
    ax1 = axes[0]
    cm = confusion_matrix(y_test, y_pred)
    sns.heatmap(cm, annot=True, fmt='d', cmap='Blues', ax=ax1)
    ax1.set_xlabel('预测标签', fontsize=12)
    ax1.set_ylabel('真实标签', fontsize=12)
    ax1.set_title('混淆矩阵', fontsize=14, fontweight='bold')
    
    # 概率分布
    ax2 = axes[1]
    for i in range(len(np.unique(y_test))):
        ax2.hist(y_proba[y_test == i, i], bins=20, alpha=0.6, 
                label=f'类别 {i}')
    ax2.set_xlabel('预测概率', fontsize=12)
    ax2.set_ylabel('频数', fontsize=12)
    ax2.set_title('各类别预测概率分布', fontsize=14, fontweight='bold')
    ax2.legend()
    ax2.grid(True, alpha=0.3)
    
    plt.tight_layout()
    plt.savefig('docs/images/naive_bayes_demo.png', dpi=300, bbox_inches='tight')
    plt.show()
    
    return model

# 运行示例
if __name__ == '__main__':
    model = naive_bayes_demo()

应用场景

  • 文本分类(垃圾邮件检测)
  • 情感分析
  • 推荐系统
  • 医疗诊断

算法5:决策树 (Decision Tree)

算法原理

决策树是一种树形结构的分类和回归算法,通过一系列if-else规则对数据进行分类或回归。决策树具有很好的可解释性,是理解数据模式的重要工具。

核心思想:递归地将数据分割成更纯的子集,直到满足停止条件。

算法流程

复制代码
1. 选择最优特征 → 2. 分割数据 → 3. 递归构建子树 → 4. 剪枝优化
     ↓                ↓                ↓                  ↓
  信息增益/基尼    按阈值分割      左子树/右子树       防止过拟合
  不纯度最小化     连续/离散特征    重复步骤1-2        后剪枝/预剪枝

工作原理示意图

复制代码
决策树结构:
                    [根节点]
                   /        \
            [特征1 < 阈值]  [特征1 ≥ 阈值]
            /                    \
      [特征2 < 阈值]        [特征2 ≥ 阈值]
      /          \          /          \
   [类别A]   [类别B]   [类别C]   [类别D]

每个节点代表一个决策规则
每个叶子节点代表一个类别(或回归值)

数学公式详解

1. 分割准则

信息熵(Entropy)

复制代码
H(S) = -Σ pᵢ log₂(pᵢ)
  • 衡量数据集的混乱程度
  • 熵越大,数据越混乱
  • 熵为0表示数据完全纯净(只有一个类别)

基尼不纯度(Gini Impurity)

复制代码
Gini(S) = 1 - Σ pᵢ²
  • 另一种衡量混乱程度的方法
  • 计算速度比熵快
  • 结果通常与熵相似

信息增益(Information Gain)

复制代码
IG(S, A) = H(S) - Σ (|Sᵥ|/|S|) · H(Sᵥ)
  • 选择信息增益最大的特征进行分割
  • 信息增益越大,分割效果越好

信息增益比(Gain Ratio)

复制代码
GainRatio(S, A) = IG(S, A) / H_A(S)
  • 解决信息增益偏向多值特征的问题
  • H_A(S)是特征A的固有值
2. 分割方法

连续特征

  • 选择最优分割点(阈值)
  • 遍历所有可能的分割点,选择信息增益最大的

离散特征

  • 二分类:直接分割
  • 多分类:可以多路分割或二值化
3. 停止条件

预剪枝(Pre-pruning)

  • max_depth:最大深度
  • min_samples_split:节点最小样本数
  • min_samples_leaf:叶子节点最小样本数
  • min_impurity_decrease:最小不纯度减少量

后剪枝(Post-pruning)

  • 先构建完整树,再删除不重要的分支
  • 使用验证集评估剪枝效果

数据预处理

1. 数据清洗

缺失值处理

  • 决策树可以处理缺失值(sklearn不支持)
  • 通常需要填充:用众数/中位数/均值
  • 或创建"缺失"类别

异常值处理

  • 决策树对异常值相对稳健
  • 但仍需检查和处理极端值
2. 特征工程

特征缩放

  • 不需要特征缩放(决策树的优势)
  • 因为决策树基于阈值分割,不受特征尺度影响

类别特征编码

  • Label编码:适用于有序类别
  • One-Hot编码:适用于无序类别

特征变换

  • 分箱(Binning):将连续特征离散化
  • 可以创建更有意义的特征
3. 处理类别不平衡

方法

python 复制代码
model = DecisionTreeClassifier(class_weight='balanced')
# 或
model = DecisionTreeClassifier(class_weight={0: 1, 1: 10})

模型训练与优化

1. 超参数调优

关键超参数

  • max_depth:最大深度(防止过拟合)
  • min_samples_split:节点最小样本数(默认2)
  • min_samples_leaf:叶子节点最小样本数(默认1)
  • max_features:每次分割考虑的特征数
  • criterion:分割准则('gini'或'entropy')
  • min_impurity_decrease:最小不纯度减少量

调优方法

python 复制代码
from sklearn.model_selection import GridSearchCV

param_grid = {
    'max_depth': [3, 5, 7, 10, None],
    'min_samples_split': [2, 5, 10],
    'min_samples_leaf': [1, 2, 4],
    'criterion': ['gini', 'entropy']
}

grid_search = GridSearchCV(DecisionTreeClassifier(), param_grid, cv=5)
grid_search.fit(X_train, y_train)
2. 防止过拟合

方法

  1. 限制树深度max_depth
  2. 增加最小样本数min_samples_split, min_samples_leaf
  3. 限制特征数max_features
  4. 后剪枝 :使用ccp_alpha参数

后剪枝示例

python 复制代码
from sklearn.tree import DecisionTreeClassifier

# 计算ccp_alpha路径
model = DecisionTreeClassifier(random_state=42)
path = model.cost_complexity_pruning_path(X_train, y_train)
ccp_alphas = path.ccp_alphas

# 使用交叉验证选择最优alpha
from sklearn.model_selection import cross_val_score
scores = []
for ccp_alpha in ccp_alphas:
    model = DecisionTreeClassifier(ccp_alpha=ccp_alpha, random_state=42)
    score = cross_val_score(model, X_train, y_train, cv=5).mean()
    scores.append(score)

best_alpha = ccp_alphas[np.argmax(scores)]
3. 特征重要性

计算

python 复制代码
feature_importance = model.feature_importances_

解释

  • 值越大,特征越重要
  • 所有特征重要性之和为1
  • 可以用于特征选择

Python实现

python 复制代码
from sklearn.tree import DecisionTreeClassifier, plot_tree, export_text
from sklearn.datasets import load_iris

def decision_tree_demo():
    """
    决策树完整示例
    """
    print("=" * 60)
    print("决策树 (Decision Tree) 示例")
    print("=" * 60)
    
    # 1. 加载Iris数据集
    iris = load_iris()
    X, y = iris.data, iris.target
    
    X_train, X_test, y_train, y_test = train_test_split(
        X, y, test_size=0.2, random_state=42
    )
    
    # 2. 训练决策树
    model = DecisionTreeClassifier(max_depth=3, random_state=42)
    model.fit(X_train, y_train)
    
    # 3. 预测
    y_pred = model.predict(X_test)
    acc = accuracy_score(y_test, y_pred)
    
    print(f"\n测试集准确率: {acc:.4f}")
    print(f"\n决策树结构:")
    print(export_text(model, feature_names=iris.feature_names))
    
    # 4. 可视化决策树
    plt.figure(figsize=(20, 10))
    plot_tree(model, feature_names=iris.feature_names, 
             class_names=iris.target_names, filled=True, fontsize=10)
    plt.title('决策树可视化', fontsize=16, fontweight='bold')
    plt.savefig('docs/images/decision_tree_demo.png', dpi=300, bbox_inches='tight')
    plt.show()
    
    # 5. 特征重要性
    feature_importance = model.feature_importances_
    plt.figure(figsize=(10, 6))
    plt.barh(iris.feature_names, feature_importance)
    plt.xlabel('重要性', fontsize=12)
    plt.title('特征重要性', fontsize=14, fontweight='bold')
    plt.grid(True, alpha=0.3, axis='x')
    plt.savefig('docs/images/decision_tree_feature_importance.png', dpi=300, bbox_inches='tight')
    plt.show()
    
    return model

# 运行示例
if __name__ == '__main__':
    model = decision_tree_demo()

模型后处理

1. 决策树可视化

文本表示

python 复制代码
from sklearn.tree import export_text

tree_rules = export_text(model, feature_names=feature_names)
print(tree_rules)

图形可视化

python 复制代码
from sklearn.tree import plot_tree
import matplotlib.pyplot as plt

plt.figure(figsize=(20, 10))
plot_tree(model, feature_names=feature_names, 
         class_names=class_names, filled=True, fontsize=10)
plt.show()

Graphviz可视化(更美观):

python 复制代码
from sklearn.tree import export_graphviz
import graphviz

dot_data = export_graphviz(model, out_file=None, 
                          feature_names=feature_names,
                          class_names=class_names,
                          filled=True, rounded=True)
graph = graphviz.Source(dot_data)
graph.render("decision_tree")
2. 规则提取

提取决策路径

python 复制代码
def get_decision_path(model, X_sample):
    """获取样本的决策路径"""
    path = model.decision_path(X_sample)
    node_indicator = path.toarray()
    
    leaf_id = model.apply(X_sample)
    
    # 获取路径上的节点
    node_index = np.where(node_indicator[0] == 1)[0]
    
    return node_index
3. 特征重要性分析

可视化特征重要性

python 复制代码
feature_importance = model.feature_importances_
indices = np.argsort(feature_importance)[::-1]

plt.figure(figsize=(10, 6))
plt.barh(range(len(feature_importance)), feature_importance[indices])
plt.yticks(range(len(feature_importance)), 
           [feature_names[i] for i in indices])
plt.xlabel('重要性', fontsize=12)
plt.title('特征重要性', fontsize=14, fontweight='bold')
plt.show()

实际应用案例

案例1:医疗诊断

问题描述:根据患者症状判断疾病类型

数据预处理

python 复制代码
# 处理类别特征
from sklearn.preprocessing import LabelEncoder

le = LabelEncoder()
df['症状'] = le.fit_transform(df['症状'])

# 处理数值特征(不需要缩放)
X = df[['年龄', '体温', '血压', '症状']]
y = df['疾病类型']

模型训练

python 复制代码
model = DecisionTreeClassifier(
    max_depth=5,
    min_samples_split=10,
    min_samples_leaf=5,
    criterion='gini',
    random_state=42
)
model.fit(X_train, y_train)

模型解释

  • 可视化决策树,医生可以理解诊断规则
  • 特征重要性显示哪些症状最关键
  • 可以提取if-else规则用于医疗系统
案例2:信用评估

问题描述:根据客户信息评估信用等级

特征工程

python 复制代码
# 创建特征
df['收入负债比'] = df['月收入'] / (df['月负债'] + 1)
df['信用历史长度'] = 2024 - df['首次信用记录年份']

# 分箱处理
df['年龄组'] = pd.cut(df['年龄'], bins=[0, 30, 40, 50, 100], 
                    labels=['青年', '中年', '中老年', '老年'])

模型训练

python 复制代码
model = DecisionTreeClassifier(
    max_depth=6,
    min_samples_split=20,
    min_samples_leaf=10,
    class_weight='balanced',
    random_state=42
)

结果解释

  • 决策规则清晰,符合业务逻辑
  • 可以用于解释拒绝贷款的原因
  • 特征重要性指导特征工程

优缺点分析

优点

  1. 可解释性强:决策过程清晰,易于理解
  2. 不需要特征缩放:不受特征尺度影响
  3. 可以处理混合数据类型:数值和类别特征
  4. 可以处理非线性关系:通过树结构捕捉复杂模式
  5. 特征重要性:自动提供特征重要性
  6. 对异常值稳健:基于阈值分割,对异常值不敏感

缺点

  1. 容易过拟合:需要仔细调参和剪枝
  2. 不稳定:数据微小变化可能导致树结构大变化
  3. 偏向多值特征:信息增益偏向取值多的特征
  4. 难以处理连续输出:回归任务效果不如分类
  5. 忽略特征间相关性:每次只考虑一个特征
  6. 可能产生偏向:如果数据不平衡

常见问题与解决方案

Q1: 决策树过拟合怎么办?

解决方案

  1. 限制树深度max_depth=5(根据数据调整)
  2. 增加最小样本数min_samples_split=20, min_samples_leaf=10
  3. 后剪枝 :使用ccp_alpha参数
  4. 使用集成方法:随机森林、梯度提升
Q2: 如何选择最优的max_depth?

方法

python 复制代码
depths = range(1, 21)
train_scores = []
test_scores = []

for depth in depths:
    model = DecisionTreeClassifier(max_depth=depth, random_state=42)
    model.fit(X_train, y_train)
    train_scores.append(model.score(X_train, y_train))
    test_scores.append(model.score(X_test, y_test))

# 选择测试集得分最高的深度
optimal_depth = depths[np.argmax(test_scores)]
Q3: 如何解释决策树?

方法

  1. 可视化树结构 :使用plot_treeexport_graphviz
  2. 提取规则 :使用export_text
  3. 分析特征重要性 :查看feature_importances_
  4. 追踪样本路径 :使用decision_path
Q4: 决策树不稳定怎么办?

问题:数据微小变化导致树结构大变化

解决方案

  • 使用随机森林(多个树的平均)
  • 增加min_samples_splitmin_samples_leaf
  • 使用集成方法
Q5: 如何处理类别不平衡?

方法

python 复制代码
# 方法1:调整类别权重
model = DecisionTreeClassifier(class_weight='balanced')

# 方法2:自定义权重
model = DecisionTreeClassifier(class_weight={0: 1, 1: 5})

# 方法3:使用SMOTE过采样
from imblearn.over_sampling import SMOTE
smote = SMOTE(random_state=42)
X_resampled, y_resampled = smote.fit_resample(X_train, y_train)

算法流程图

复制代码
开始
  ↓
数据加载与探索
  ↓
数据清洗(缺失值、异常值)
  ↓
特征工程(编码类别特征、创建新特征)
  ↓
数据划分(训练集/验证集/测试集)
  ↓
选择分割准则(Gini/Entropy)
  ↓
构建决策树(递归分割)
  ↓
   ├─ 选择最优特征和阈值
  ↓
   ├─ 分割数据
  ↓
   ├─ 递归构建子树
  ↓
   └─ 直到满足停止条件
  ↓
剪枝优化(预剪枝/后剪枝)
  ↓
模型评估(准确率/精确率/召回率)
  ↓
可视化决策树
  ↓
提取决策规则
  ↓
特征重要性分析
  ↓
模型部署
  ↓
结束

算法6:随机森林 (Random Forest)

算法原理

随机森林是多个决策树的集成,通过投票或平均来做出最终预测。

核心思想:多个弱学习器组合成强学习器。

Python实现

python 复制代码
from sklearn.ensemble import RandomForestClassifier, RandomForestRegressor

def random_forest_demo():
    """
    随机森林完整示例
    """
    print("=" * 60)
    print("随机森林 (Random Forest) 示例")
    print("=" * 60)
    
    # 1. 生成数据
    X, y = make_classification(
        n_samples=1000,
        n_features=20,
        n_informative=10,
        n_classes=3,
        random_state=42
    )
    
    X_train, X_test, y_train, y_test = train_test_split(
        X, y, test_size=0.2, random_state=42
    )
    
    # 2. 训练不同树数量的随机森林
    n_trees = [10, 50, 100, 200]
    accuracies = []
    
    for n_tree in n_trees:
        model = RandomForestClassifier(n_estimators=n_tree, random_state=42)
        model.fit(X_train, y_train)
        acc = accuracy_score(y_test, model.predict(X_test))
        accuracies.append(acc)
        print(f"树数量: {n_tree:3d} - 准确率: {acc:.4f}")
    
    # 3. 可视化树数量对性能的影响
    plt.figure(figsize=(10, 6))
    plt.plot(n_trees, accuracies, 'o-', linewidth=2, markersize=8)
    plt.xlabel('树数量', fontsize=12)
    plt.ylabel('准确率', fontsize=12)
    plt.title('随机森林性能 vs 树数量', fontsize=14, fontweight='bold')
    plt.grid(True, alpha=0.3)
    plt.savefig('docs/images/random_forest_demo.png', dpi=300, bbox_inches='tight')
    plt.show()
    
    # 4. 特征重要性
    best_model = RandomForestClassifier(n_estimators=100, random_state=42)
    best_model.fit(X_train, y_train)
    
    feature_importance = best_model.feature_importances_
    top_features = np.argsort(feature_importance)[-10:][::-1]
    
    plt.figure(figsize=(10, 6))
    plt.barh(range(len(top_features)), feature_importance[top_features])
    plt.yticks(range(len(top_features)), [f'特征 {i}' for i in top_features])
    plt.xlabel('重要性', fontsize=12)
    plt.title('Top 10 特征重要性', fontsize=14, fontweight='bold')
    plt.grid(True, alpha=0.3, axis='x')
    plt.savefig('docs/images/random_forest_feature_importance.png', dpi=300, bbox_inches='tight')
    plt.show()
    
    return best_model

# 运行示例
if __name__ == '__main__':
    model = random_forest_demo()

应用场景

  • 特征选择
  • 异常检测
  • 任何需要高准确率的分类/回归问题

算法7:K近邻 (KNN)

算法原理

K近邻通过查找最近的K个样本,根据它们的标签进行预测。

核心思想:相似的样本应该有相似的标签。

Python实现

python 复制代码
from sklearn.neighbors import KNeighborsClassifier
from sklearn.preprocessing import StandardScaler

def knn_demo():
    """
    K近邻完整示例
    """
    print("=" * 60)
    print("K近邻 (KNN) 示例")
    print("=" * 60)
    
    # 1. 生成数据
    X, y = make_classification(
        n_samples=300,
        n_features=2,
        n_redundant=0,
        n_informative=2,
        n_clusters_per_class=1,
        random_state=42
    )
    
    scaler = StandardScaler()
    X_scaled = scaler.fit_transform(X)
    
    X_train, X_test, y_train, y_test = train_test_split(
        X_scaled, y, test_size=0.2, random_state=42
    )
    
    # 2. 测试不同的K值
    k_values = range(1, 21)
    train_accuracies = []
    test_accuracies = []
    
    for k in k_values:
        model = KNeighborsClassifier(n_neighbors=k)
        model.fit(X_train, y_train)
        train_acc = accuracy_score(y_train, model.predict(X_train))
        test_acc = accuracy_score(y_test, model.predict(X_test))
        train_accuracies.append(train_acc)
        test_accuracies.append(test_acc)
    
    # 3. 可视化K值对性能的影响
    plt.figure(figsize=(12, 6))
    plt.plot(k_values, train_accuracies, 'o-', label='训练集', linewidth=2)
    plt.plot(k_values, test_accuracies, 's-', label='测试集', linewidth=2)
    plt.xlabel('K值', fontsize=12)
    plt.ylabel('准确率', fontsize=12)
    plt.title('K值对KNN性能的影响', fontsize=14, fontweight='bold')
    plt.legend()
    plt.grid(True, alpha=0.3)
    plt.xticks(k_values[::2])
    plt.savefig('docs/images/knn_demo.png', dpi=300, bbox_inches='tight')
    plt.show()
    
    # 4. 可视化决策边界(最佳K值)
    best_k = k_values[np.argmax(test_accuracies)]
    print(f"\n最佳K值: {best_k}")
    
    model = KNeighborsClassifier(n_neighbors=best_k)
    model.fit(X_train, y_train)
    
    h = 0.02
    x_min, x_max = X_scaled[:, 0].min() - 1, X_scaled[:, 0].max() + 1
    y_min, y_max = X_scaled[:, 1].min() - 1, X_scaled[:, 1].max() + 1
    xx, yy = np.meshgrid(np.arange(x_min, x_max, h),
                         np.arange(y_min, y_max, h))
    Z = model.predict(np.c_[xx.ravel(), yy.ravel()])
    Z = Z.reshape(xx.shape)
    
    plt.figure(figsize=(10, 8))
    plt.contourf(xx, yy, Z, alpha=0.3, cmap=plt.cm.RdYlBu)
    scatter = plt.scatter(X_scaled[:, 0], X_scaled[:, 1], c=y, 
                         cmap=plt.cm.RdYlBu, edgecolors='black', s=50)
    plt.xlabel('特征 1', fontsize=12)
    plt.ylabel('特征 2', fontsize=12)
    plt.title(f'KNN决策边界 (K={best_k})', fontsize=14, fontweight='bold')
    plt.colorbar(scatter)
    plt.savefig('docs/images/knn_decision_boundary.png', dpi=300, bbox_inches='tight')
    plt.show()
    
    return model

# 运行示例
if __name__ == '__main__':
    model = knn_demo()

应用场景

  • 推荐系统
  • 图像识别
  • 模式识别
  • 任何需要局部相似性的问题

算法8:K均值聚类 (K-Means)

算法原理

K均值聚类是一种无监督学习算法,将数据分成K个簇,使得簇内距离最小,簇间距离最大。它是应用最广泛的聚类算法之一。

核心思想:迭代优化簇中心位置,使得每个数据点到其最近簇中心的距离平方和最小。

算法流程

复制代码
1. 初始化K个簇中心 → 2. 分配数据点到最近簇 → 3. 更新簇中心 → 4. 重复2-3直到收敛
     ↓                      ↓                        ↓
  随机选择K个点         计算距离,分配          计算新中心(均值)
  或K-means++初始化     到最近簇                更新中心位置

工作原理示意图

复制代码
初始状态:
  ●  ●     ●
    ●    ●   ●
  ●    ●   ●
    ●  ●     ●
  [随机选择K个中心]

迭代过程:
  ●  ●     ●
    ●    ●   ●
  ●    ●   ●
    ●  ●     ●
  [分配点到最近中心]
  [更新中心位置]
  [重复直到收敛]

最终结果:
  ●●●
  ●●●
  ●●●
  [K个簇,每个簇内数据相似]

数学公式详解

1. 目标函数

簇内平方和(Within-Cluster Sum of Squares, WCSS)

复制代码
J = Σᵢ₌₁ⁿ minⱼ ||xᵢ - μⱼ||²

其中:

  • xᵢ:第i个数据点
  • μⱼ:第j个簇中心
  • n:数据点数量
  • K:簇数量

目标:最小化J,即最小化簇内距离

2. 算法步骤

步骤1:初始化簇中心

  • 随机选择K个数据点作为初始中心
  • 或使用K-means++(更智能的初始化)

步骤2:分配数据点

复制代码
cᵢ = argminⱼ ||xᵢ - μⱼ||²

将每个数据点分配到最近的簇中心

步骤3:更新簇中心

复制代码
μⱼ = (1/|Cⱼ|) × Σxᵢ∈Cⱼ xᵢ

计算每个簇中所有数据点的均值作为新中心

步骤4:重复步骤2-3

直到簇中心不再变化或达到最大迭代次数

3. K-means++初始化

目的:选择更好的初始中心,避免局部最优

方法

  1. 随机选择第一个中心
  2. 选择下一个中心时,优先选择距离已有中心较远的点
  3. 重复直到选择K个中心

数据预处理

1. 特征缩放(必须!)

为什么必须缩放

  • K-means基于欧氏距离,对特征尺度敏感
  • 不同尺度的特征会导致某些特征主导聚类结果

方法

python 复制代码
from sklearn.preprocessing import StandardScaler

scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
2. 处理缺失值

方法

  • 删除缺失值
  • 用均值/中位数填充
  • 用模型预测填充
3. 处理异常值

问题:异常值会影响簇中心位置

方法

  • 使用Z-score方法检测异常值
  • 删除或截断异常值
  • 使用鲁棒聚类方法(如K-medoids)
4. 特征选择

目的:选择相关特征,提高聚类质量

方法

  • 相关性分析
  • 主成分分析(PCA)
  • 领域知识

模型训练与优化

1. 选择K值

方法1:肘部法则(Elbow Method)

python 复制代码
inertias = []
K_range = range(1, 11)

for k in K_range:
    kmeans = KMeans(n_clusters=k, random_state=42)
    kmeans.fit(X)
    inertias.append(kmeans.inertia_)

# 绘制肘部曲线,选择"肘部"对应的K值
plt.plot(K_range, inertias, 'o-')
plt.xlabel('K值')
plt.ylabel('Inertia')
plt.title('肘部法则')
plt.show()

方法2:轮廓系数(Silhouette Score)

python 复制代码
from sklearn.metrics import silhouette_score

silhouette_scores = []
K_range = range(2, 11)

for k in K_range:
    kmeans = KMeans(n_clusters=k, random_state=42)
    labels = kmeans.fit_predict(X)
    score = silhouette_score(X, labels)
    silhouette_scores.append(score)

# 选择轮廓系数最大的K值
optimal_k = K_range[np.argmax(silhouette_scores)]

方法3:Gap统计量

  • 比较实际数据与随机数据的聚类质量
  • 选择Gap最大的K值
2. 初始化方法

随机初始化

python 复制代码
kmeans = KMeans(n_clusters=k, init='random', n_init=10)

K-means++(推荐)

python 复制代码
kmeans = KMeans(n_clusters=k, init='k-means++', n_init=10)

n_init参数

  • 运行多次,选择最好的结果
  • 默认10次,可以增加以提高稳定性
3. 处理局部最优

方法

  • 增加n_init参数(多次运行)
  • 使用K-means++初始化
  • 使用不同的随机种子

模型后处理

1. 评估聚类质量

轮廓系数

python 复制代码
from sklearn.metrics import silhouette_score, silhouette_samples

# 整体轮廓系数
score = silhouette_score(X, labels)

# 每个样本的轮廓系数
samples_silhouette = silhouette_samples(X, labels)

Davies-Bouldin指数

python 复制代码
from sklearn.metrics import davies_bouldin_score

db_score = davies_bouldin_score(X, labels)
# 值越小越好

Calinski-Harabasz指数

python 复制代码
from sklearn.metrics import calinski_harabasz_score

ch_score = calinski_harabasz_score(X, labels)
# 值越大越好
2. 簇分析

簇大小

python 复制代码
unique, counts = np.unique(labels, return_counts=True)
for cluster_id, count in zip(unique, counts):
    print(f"簇 {cluster_id}: {count} 个样本")

簇中心特征

python 复制代码
centers = kmeans.cluster_centers_
for i, center in enumerate(centers):
    print(f"簇 {i} 中心: {center}")

簇内距离

python 复制代码
for i in range(k):
    cluster_points = X[labels == i]
    distances = np.linalg.norm(cluster_points - centers[i], axis=1)
    print(f"簇 {i} 平均距离: {np.mean(distances):.4f}")
3. 可视化

2D可视化

python 复制代码
plt.scatter(X[:, 0], X[:, 1], c=labels, cmap='viridis', alpha=0.6)
plt.scatter(centers[:, 0], centers[:, 1], c='red', marker='x', s=200, linewidths=3)
plt.title('K-Means聚类结果')
plt.show()

轮廓图

python 复制代码
from sklearn.metrics import silhouette_samples
import matplotlib.cm as cm

fig, ax = plt.subplots(figsize=(10, 6))
y_lower = 10

for i in range(k):
    ith_cluster_silhouette_values = samples_silhouette[labels == i]
    ith_cluster_silhouette_values.sort()
    
    size_cluster_i = ith_cluster_silhouette_values.shape[0]
    y_upper = y_lower + size_cluster_i
    
    color = cm.nipy_spectral(float(i) / k)
    ax.fill_betweenx(np.arange(y_lower, y_upper),
                     0, ith_cluster_silhouette_values,
                     facecolor=color, edgecolor=color, alpha=0.7)
    
    y_lower = y_upper + 10

ax.set_title('轮廓图')
ax.set_xlabel('轮廓系数')
ax.set_ylabel('簇标签')
plt.show()

Python实现

python 复制代码
from sklearn.cluster import KMeans
from sklearn.metrics import silhouette_score, silhouette_samples

def kmeans_demo():
    """
    K均值聚类完整示例
    """
    print("=" * 60)
    print("K均值聚类 (K-Means) 示例")
    print("=" * 60)
    
    # 1. 生成数据
    X, y_true = make_blobs(
        n_samples=300,
        centers=4,
        n_features=2,
        random_state=42
    )
    
    # 2. 测试不同的K值
    k_range = range(2, 11)
    inertias = []
    silhouette_scores = []
    
    for k in k_range:
        kmeans = KMeans(n_clusters=k, random_state=42, n_init=10)
        labels = kmeans.fit_predict(X)
        inertias.append(kmeans.inertia_)
        silhouette_scores.append(silhouette_score(X, labels))
    
    # 3. 可视化肘部法则和轮廓系数
    fig, axes = plt.subplots(1, 2, figsize=(16, 6))
    
    # 肘部法则
    ax1 = axes[0]
    ax1.plot(k_range, inertias, 'o-', linewidth=2, markersize=8)
    ax1.set_xlabel('K值', fontsize=12)
    ax1.set_ylabel('Inertia (簇内平方和)', fontsize=12)
    ax1.set_title('肘部法则 (Elbow Method)', fontsize=14, fontweight='bold')
    ax1.grid(True, alpha=0.3)
    ax1.set_xticks(k_range)
    
    # 轮廓系数
    ax2 = axes[1]
    ax2.plot(k_range, silhouette_scores, 'o-', linewidth=2, markersize=8, color='green')
    ax2.set_xlabel('K值', fontsize=12)
    ax2.set_ylabel('轮廓系数', fontsize=12)
    ax2.set_title('轮廓系数 vs K值', fontsize=14, fontweight='bold')
    ax2.grid(True, alpha=0.3)
    ax2.set_xticks(k_range)
    
    plt.tight_layout()
    plt.savefig('docs/images/kmeans_evaluation.png', dpi=300, bbox_inches='tight')
    plt.show()
    
    # 4. 可视化聚类结果(最佳K值)
    best_k = k_range[np.argmax(silhouette_scores)]
    print(f"\n最佳K值: {best_k}")
    
    kmeans = KMeans(n_clusters=best_k, random_state=42, n_init=10)
    labels = kmeans.fit_predict(X)
    centers = kmeans.cluster_centers_
    
    plt.figure(figsize=(12, 5))
    
    # 真实标签
    plt.subplot(1, 2, 1)
    scatter1 = plt.scatter(X[:, 0], X[:, 1], c=y_true, cmap='viridis', s=50, alpha=0.6)
    plt.scatter(centers[:, 0], centers[:, 1], c='red', marker='x', s=200, linewidths=3, label='聚类中心')
    plt.xlabel('特征 1', fontsize=12)
    plt.ylabel('特征 2', fontsize=12)
    plt.title('真实标签', fontsize=14, fontweight='bold')
    plt.legend()
    plt.colorbar(scatter1)
    
    # 预测标签
    plt.subplot(1, 2, 2)
    scatter2 = plt.scatter(X[:, 0], X[:, 1], c=labels, cmap='viridis', s=50, alpha=0.6)
    plt.scatter(centers[:, 0], centers[:, 1], c='red', marker='x', s=200, linewidths=3, label='聚类中心')
    plt.xlabel('特征 1', fontsize=12)
    plt.ylabel('特征 2', fontsize=12)
    plt.title(f'K-Means聚类结果 (K={best_k})', fontsize=14, fontweight='bold')
    plt.legend()
    plt.colorbar(scatter2)
    
    plt.tight_layout()
    plt.savefig('docs/images/kmeans_demo.png', dpi=300, bbox_inches='tight')
    plt.show()
    
    return kmeans

# 运行示例
if __name__ == '__main__':
    model = kmeans_demo()

实际应用案例

案例1:客户细分

问题描述:根据客户行为数据将客户分成不同群体

数据预处理

python 复制代码
# 特征工程
df['消费频率'] = df['订单数'] / df['注册天数']
df['平均订单金额'] = df['总消费'] / df['订单数']
df['最近购买天数'] = (pd.Timestamp.now() - df['最后购买日期']).dt.days

# 特征选择
features = ['消费频率', '平均订单金额', '最近购买天数', '浏览时长']
X = df[features]

# 标准化
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)

选择K值

python 复制代码
# 使用肘部法则和轮廓系数
k_range = range(2, 11)
inertias = []
silhouette_scores = []

for k in k_range:
    kmeans = KMeans(n_clusters=k, random_state=42, n_init=10)
    labels = kmeans.fit_predict(X_scaled)
    inertias.append(kmeans.inertia_)
    silhouette_scores.append(silhouette_score(X_scaled, labels))

# 选择最优K(假设K=5)
optimal_k = 5

结果分析

  • 簇1:高价值客户(高消费、高频)
  • 簇2:潜在流失客户(长时间未购买)
  • 簇3:新客户(低消费、低频)
  • 簇4:稳定客户(中等消费、中等频率)
  • 簇5:低价值客户(低消费、低频)
案例2:图像分割

问题描述:将图像分成K个颜色区域

数据预处理

python 复制代码
# 将图像转换为像素点
image = plt.imread('image.jpg')
pixels = image.reshape(-1, 3)  # (height*width, RGB)

# 标准化(K-means需要)
scaler = StandardScaler()
pixels_scaled = scaler.fit_transform(pixels)

聚类

python 复制代码
# 选择K=8(8种主要颜色)
kmeans = KMeans(n_clusters=8, random_state=42)
labels = kmeans.fit_predict(pixels_scaled)

# 用簇中心替换像素值
segmented_pixels = kmeans.cluster_centers_[labels]
segmented_image = segmented_pixels.reshape(image.shape)

优缺点分析

优点

  1. 简单高效:算法简单,易于实现和理解
  2. 计算速度快:时间复杂度O(n×K×I×d),其中I是迭代次数
  3. 可扩展性好:可以处理大规模数据
  4. 结果可解释:每个簇有明确的中心
  5. 适用于球形簇:适合数据呈球形分布的情况

缺点

  1. 需要指定K值:K值选择困难
  2. 对初始值敏感:可能陷入局部最优
  3. 假设球形簇:不适合非球形簇(如月牙形)
  4. 对异常值敏感:异常值会影响簇中心
  5. 需要特征缩放:对特征尺度敏感
  6. 不适合类别特征:只适用于数值特征

常见问题与解决方案

Q1: 如何选择最优K值?

方法

  1. 肘部法则:寻找inertia下降的"肘部"
  2. 轮廓系数:选择轮廓系数最大的K
  3. 领域知识:根据业务需求确定K
  4. Gap统计量:比较实际数据与随机数据

代码示例

python 复制代码
# 综合方法
def find_optimal_k(X, max_k=10):
    inertias = []
    silhouette_scores = []
    K_range = range(2, max_k + 1)
    
    for k in K_range:
        kmeans = KMeans(n_clusters=k, random_state=42, n_init=10)
        labels = kmeans.fit_predict(X)
        inertias.append(kmeans.inertia_)
        silhouette_scores.append(silhouette_score(X, labels))
    
    # 肘部法则
    # 计算二阶导数,找到变化最大的点
    # 或直接观察图形
    
    # 轮廓系数
    optimal_k_silhouette = K_range[np.argmax(silhouette_scores)]
    
    return optimal_k_silhouette
Q2: 如何避免局部最优?

解决方案

  1. 多次运行 :增加n_init参数
python 复制代码
kmeans = KMeans(n_clusters=k, n_init=50, random_state=42)
  1. K-means++初始化
python 复制代码
kmeans = KMeans(n_clusters=k, init='k-means++', n_init=10)
  1. 不同随机种子
python 复制代码
best_score = -1
best_labels = None

for seed in range(10):
    kmeans = KMeans(n_clusters=k, random_state=seed, n_init=1)
    labels = kmeans.fit_predict(X)
    score = silhouette_score(X, labels)
    if score > best_score:
        best_score = score
        best_labels = labels
Q3: 如何处理非球形簇?

解决方案

  1. 使用其他聚类算法

    • DBSCAN(基于密度)
    • 谱聚类(Spectral Clustering)
    • 高斯混合模型(GMM)
  2. 特征变换

    • 使用核方法将数据映射到高维空间
    • 使用PCA降维后再聚类
Q4: 如何处理类别特征?

方法

  1. One-Hot编码:将类别特征转换为数值
  2. 使用K-modes:专门处理类别数据的算法
  3. 混合距离:结合数值和类别距离
Q5: 如何评估聚类质量?

方法

python 复制代码
# 1. 轮廓系数(-1到1,越大越好)
silhouette_score(X, labels)

# 2. Davies-Bouldin指数(越小越好)
davies_bouldin_score(X, labels)

# 3. Calinski-Harabasz指数(越大越好)
calinski_harabasz_score(X, labels)

# 4. 如果有真实标签,使用调整兰德指数
from sklearn.metrics import adjusted_rand_score
adjusted_rand_score(y_true, labels)

算法流程图

复制代码
开始
  ↓
数据加载与探索
  ↓
数据清洗(缺失值、异常值)
  ↓
特征工程(特征选择、创建新特征)
  ↓
特征缩放(标准化/归一化,必须!)
  ↓
选择K值(肘部法则/轮廓系数/Gap统计量)
  ↓
初始化簇中心(随机/K-means++)
  ↓
分配数据点到最近簇中心
  ↓
更新簇中心(计算均值)
  ↓
   ├─ 中心是否变化?
  ↓ 否
  是  ↓
   ↓  继续迭代
  ↓
达到最大迭代次数?
  ↓
评估聚类质量(轮廓系数/DB指数)
  ↓
可视化聚类结果
  ↓
分析每个簇的特征
  ↓
应用聚类结果
  ↓
结束

算法9:主成分分析 (PCA)

算法原理

PCA通过线性变换将高维数据投影到低维空间,保留最重要的信息。

核心思想:找到数据方差最大的方向(主成分)。

数学公式

协方差矩阵

复制代码
C = (1/n) X^T X

特征值分解

复制代码
C = V Λ V^T

Python实现

python 复制代码
from sklearn.decomposition import PCA
from sklearn.datasets import load_iris

def pca_demo():
    """
    主成分分析完整示例
    """
    print("=" * 60)
    print("主成分分析 (PCA) 示例")
    print("=" * 60)
    
    # 1. 加载Iris数据集
    iris = load_iris()
    X, y = iris.data, iris.target
    
    # 2. 标准化
    scaler = StandardScaler()
    X_scaled = scaler.fit_transform(X)
    
    # 3. PCA降维
    pca = PCA()
    X_pca = pca.fit_transform(X_scaled)
    
    # 4. 可视化解释方差比例
    explained_variance_ratio = pca.explained_variance_ratio_
    cumulative_variance = np.cumsum(explained_variance_ratio)
    
    fig, axes = plt.subplots(2, 2, figsize=(16, 12))
    
    # 解释方差比例
    ax1 = axes[0, 0]
    ax1.bar(range(1, len(explained_variance_ratio) + 1), 
            explained_variance_ratio, alpha=0.7)
    ax1.set_xlabel('主成分', fontsize=12)
    ax1.set_ylabel('解释方差比例', fontsize=12)
    ax1.set_title('各主成分解释方差比例', fontsize=14, fontweight='bold')
    ax1.grid(True, alpha=0.3, axis='y')
    
    # 累积解释方差
    ax2 = axes[0, 1]
    ax2.plot(range(1, len(cumulative_variance) + 1), cumulative_variance, 
            'o-', linewidth=2, markersize=8)
    ax2.axhline(y=0.95, color='r', linestyle='--', label='95%阈值')
    ax2.set_xlabel('主成分数量', fontsize=12)
    ax2.set_ylabel('累积解释方差比例', fontsize=12)
    ax2.set_title('累积解释方差', fontsize=14, fontweight='bold')
    ax2.legend()
    ax2.grid(True, alpha=0.3)
    
    # 2D投影
    ax3 = axes[1, 0]
    scatter = ax3.scatter(X_pca[:, 0], X_pca[:, 1], c=y, cmap='viridis', s=50, alpha=0.6)
    ax3.set_xlabel(f'第一主成分 (解释方差: {explained_variance_ratio[0]:.2%})', fontsize=12)
    ax3.set_ylabel(f'第二主成分 (解释方差: {explained_variance_ratio[1]:.2%})', fontsize=12)
    ax3.set_title('PCA 2D投影', fontsize=14, fontweight='bold')
    plt.colorbar(scatter, ax=ax3)
    
    # 3D投影(如果可能)
    if X_pca.shape[1] >= 3:
        ax4 = axes[1, 1]
        scatter = ax4.scatter(X_pca[:, 0], X_pca[:, 1], X_pca[:, 2], 
                            c=y, cmap='viridis', s=50, alpha=0.6)
        ax4.set_xlabel('PC1', fontsize=12)
        ax4.set_ylabel('PC2', fontsize=12)
        ax4.set_zlabel('PC3', fontsize=12)
        ax4.set_title('PCA 3D投影', fontsize=14, fontweight='bold')
    else:
        ax4.axis('off')
    
    plt.tight_layout()
    plt.savefig('docs/images/pca_demo.png', dpi=300, bbox_inches='tight')
    plt.show()
    
    print(f"\n各主成分解释方差比例:")
    for i, ratio in enumerate(explained_variance_ratio):
        print(f"  PC{i+1}: {ratio:.4f} ({ratio*100:.2f}%)")
    print(f"\n前2个主成分累积解释方差: {cumulative_variance[1]:.4f} ({cumulative_variance[1]*100:.2f}%)")
    
    return pca

# 运行示例
if __name__ == '__main__':
    pca = pca_demo()

应用场景

  • 数据可视化
  • 特征降维
  • 噪声过滤
  • 数据压缩

算法10:梯度提升树 (Gradient Boosting)

算法原理

梯度提升通过串行训练多个弱学习器,每个学习器纠正前一个的错误。

核心思想:逐步减少残差。

Python实现

python 复制代码
from sklearn.ensemble import GradientBoostingClassifier, GradientBoostingRegressor

def gradient_boosting_demo():
    """
    梯度提升树完整示例
    """
    print("=" * 60)
    print("梯度提升树 (Gradient Boosting) 示例")
    print("=" * 60)
    
    # 1. 生成数据
    X, y = make_classification(
        n_samples=1000,
        n_features=20,
        n_informative=10,
        n_classes=2,
        random_state=42
    )
    
    X_train, X_test, y_train, y_test = train_test_split(
        X, y, test_size=0.2, random_state=42
    )
    
    # 2. 训练梯度提升树
    model = GradientBoostingClassifier(
        n_estimators=100,
        learning_rate=0.1,
        max_depth=3,
        random_state=42
    )
    model.fit(X_train, y_train)
    
    # 3. 预测
    y_pred = model.predict(X_test)
    y_proba = model.predict_proba(X_test)[:, 1]
    acc = accuracy_score(y_test, y_pred)
    
    print(f"\n测试集准确率: {acc:.4f}")
    
    # 4. 可视化训练过程
    train_scores = np.zeros((model.n_estimators,), dtype=np.float64)
    test_scores = np.zeros((model.n_estimators,), dtype=np.float64)
    
    for i, y_pred_train in enumerate(model.staged_predict(X_train)):
        train_scores[i] = accuracy_score(y_train, y_pred_train)
    
    for i, y_pred_test in enumerate(model.staged_predict(X_test)):
        test_scores[i] = accuracy_score(y_test, y_pred_test)
    
    plt.figure(figsize=(12, 5))
    
    # 训练过程
    plt.subplot(1, 2, 1)
    plt.plot(np.arange(model.n_estimators), train_scores, 
            label='训练集', linewidth=2)
    plt.plot(np.arange(model.n_estimators), test_scores, 
            label='测试集', linewidth=2)
    plt.xlabel('迭代次数', fontsize=12)
    plt.ylabel('准确率', fontsize=12)
    plt.title('梯度提升训练过程', fontsize=14, fontweight='bold')
    plt.legend()
    plt.grid(True, alpha=0.3)
    
    # 特征重要性
    plt.subplot(1, 2, 2)
    feature_importance = model.feature_importances_
    top_features = np.argsort(feature_importance)[-10:][::-1]
    plt.barh(range(len(top_features)), feature_importance[top_features])
    plt.yticks(range(len(top_features)), [f'特征 {i}' for i in top_features])
    plt.xlabel('重要性', fontsize=12)
    plt.title('Top 10 特征重要性', fontsize=14, fontweight='bold')
    plt.grid(True, alpha=0.3, axis='x')
    
    plt.tight_layout()
    plt.savefig('docs/images/gradient_boosting_demo.png', dpi=300, bbox_inches='tight')
    plt.show()
    
    return model

# 运行示例
if __name__ == '__main__':
    model = gradient_boosting_demo()

应用场景

  • 竞赛(Kaggle等)
  • 高精度预测
  • 特征重要性分析
  • 任何需要最高准确率的场景

算法对比与选择指南

算法对比表

算法 类型 优点 缺点 适用场景
线性回归 回归 简单、快速、可解释 假设线性关系 连续值预测
逻辑回归 分类 简单、快速、概率输出 假设线性关系 二分类问题
SVM 分类 高准确率、支持非线性 对参数敏感 小样本、非线性
朴素贝叶斯 分类 快速、对小样本有效 特征独立假设 文本分类
决策树 分类/回归 可解释、无需特征缩放 容易过拟合 需要可解释性
随机森林 分类/回归 高准确率、特征重要性 黑盒模型 高准确率需求
KNN 分类/回归 简单、无需训练 计算慢、对K敏感 局部模式识别
K-Means 聚类 简单、快速 需要指定K 无监督聚类
PCA 降维 降维、可视化 线性变换 数据降维
梯度提升 分类/回归 最高准确率 训练慢、易过拟合 竞赛、高精度

选择指南

根据问题类型选择

  • 回归问题:线性回归 → 随机森林 → 梯度提升
  • 二分类问题:逻辑回归 → SVM → 随机森林
  • 多分类问题:决策树 → 随机森林 → 梯度提升
  • 聚类问题:K-Means
  • 降维问题:PCA

根据数据规模选择

  • 小样本(<1000):SVM、朴素贝叶斯
  • 中等样本(1000-10000):大部分算法都适用
  • 大样本(>10000):随机森林、梯度提升

根据可解释性需求选择

  • 高可解释性:线性回归、逻辑回归、决策树
  • 中等可解释性:随机森林(特征重要性)
  • 低可解释性:SVM、梯度提升

总结

核心要点

  1. 十大基础算法覆盖了机器学习的主要任务类型
  2. 每个算法都有其适用场景和优缺点
  3. 实践为主:通过代码实现加深理解
  4. 可视化:通过图表直观理解算法行为

学习建议

  1. 理解原理:掌握每个算法的数学原理
  2. 动手实践:运行代码,观察结果
  3. 参数调优:尝试不同的超参数
  4. 对比分析:在相同数据集上对比不同算法
  5. 实际应用:在真实项目中应用这些算法

下一步学习

  • 深度学习:神经网络、CNN、RNN等
  • 强化学习:Q-learning、Policy Gradient等
  • 高级技术:AutoML、模型解释、模型部署

相关资源

完整代码 :所有代码都可以在 docs/ml_algorithms_fundamentals.py 中找到并直接运行。

复制代码
"""
十大基础机器学习算法完整实现
Python 3.11 兼容版本
所有代码可直接运行
"""
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.linear_model import LinearRegression, LogisticRegression
from sklearn.svm import SVC
from sklearn.naive_bayes import GaussianNB
from sklearn.tree import DecisionTreeClassifier, plot_tree, export_text
from sklearn.ensemble import RandomForestClassifier, GradientBoostingClassifier
from sklearn.neighbors import KNeighborsClassifier
from sklearn.cluster import KMeans
from sklearn.decomposition import PCA
from sklearn.model_selection import train_test_split
from sklearn.metrics import (accuracy_score, mean_squared_error, r2_score,
                           confusion_matrix, classification_report, roc_curve, auc,
                           silhouette_score)
from sklearn.preprocessing import StandardScaler
from sklearn.datasets import make_classification, make_blobs, load_iris
import warnings
warnings.filterwarnings('ignore')

# 设置中文字体
plt.rcParams['font.sans-serif'] = ['SimHei', 'DejaVu Sans', 'Arial Unicode MS']
plt.rcParams['axes.unicode_minus'] = False
sns.set_style("whitegrid")

# 创建输出目录
import os
os.makedirs('docs/images', exist_ok=True)


# ==================== 算法1:线性回归 ====================

def linear_regression_demo():
    """线性回归完整示例"""
    print("=" * 60)
    print("算法1:线性回归 (Linear Regression)")
    print("=" * 60)
    
    # 生成数据
    np.random.seed(42)
    n_samples = 100
    X = np.random.randn(n_samples, 1) * 10
    y = 2 * X.flatten() + 3 + np.random.randn(n_samples) * 2
    
    # 划分数据集
    X_train, X_test, y_train, y_test = train_test_split(
        X, y, test_size=0.2, random_state=42
    )
    
    # 训练模型
    model = LinearRegression()
    model.fit(X_train, y_train)
    
    # 预测
    y_train_pred = model.predict(X_train)
    y_test_pred = model.predict(X_test)
    
    # 评估
    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"  权重 (w): {model.coef_[0]:.4f}")
    print(f"  截距 (b): {model.intercept_:.4f}")
    print(f"\n训练集 - MSE: {train_mse:.4f}, R²: {train_r2:.4f}")
    print(f"测试集 - MSE: {test_mse:.4f}, R²: {test_r2:.4f}")
    
    # 可视化
    plt.figure(figsize=(12, 5))
    plt.subplot(1, 2, 1)
    plt.scatter(X_train, y_train, alpha=0.6, label='训练数据', color='blue')
    plt.plot(X_train, y_train_pred, 'r-', linewidth=2, label='拟合直线')
    plt.xlabel('特征 X', fontsize=12)
    plt.ylabel('目标 y', fontsize=12)
    plt.title(f'训练集 (R² = {train_r2:.3f})', fontsize=14, fontweight='bold')
    plt.legend()
    plt.grid(True, alpha=0.3)
    
    plt.subplot(1, 2, 2)
    plt.scatter(X_test, y_test, alpha=0.6, label='测试数据', color='green')
    plt.plot(X_test, y_test_pred, 'r-', linewidth=2, label='拟合直线')
    plt.xlabel('特征 X', fontsize=12)
    plt.ylabel('目标 y', fontsize=12)
    plt.title(f'测试集 (R² = {test_r2:.3f})', fontsize=14, fontweight='bold')
    plt.legend()
    plt.grid(True, alpha=0.3)
    
    plt.tight_layout()
    plt.savefig('docs/images/linear_regression_demo.png', dpi=300, bbox_inches='tight')
    plt.close()
    print("✓ 图表已保存: docs/images/linear_regression_demo.png")


# ==================== 算法2:逻辑回归 ====================

def logistic_regression_demo():
    """逻辑回归完整示例"""
    print("\n" + "=" * 60)
    print("算法2:逻辑回归 (Logistic Regression)")
    print("=" * 60)
    
    # 生成二分类数据
    X, y = make_classification(
        n_samples=1000, n_features=2, n_redundant=0,
        n_informative=2, n_clusters_per_class=1, random_state=42
    )
    
    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_test_pred = model.predict(X_test)
    y_test_proba = model.predict_proba(X_test)[:, 1]
    
    # 评估
    test_acc = accuracy_score(y_test, y_test_pred)
    print(f"\n测试集准确率: {test_acc:.4f}")
    
    # 可视化
    fig, axes = plt.subplots(1, 3, figsize=(18, 5))
    
    # 决策边界
    h = 0.02
    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, h),
                         np.arange(y_min, y_max, h))
    Z = model.predict(np.c_[xx.ravel(), yy.ravel()])
    Z = Z.reshape(xx.shape)
    
    axes[0].contourf(xx, yy, Z, alpha=0.3, cmap=plt.cm.RdYlBu)
    scatter = axes[0].scatter(X[:, 0], X[:, 1], c=y, cmap=plt.cm.RdYlBu, edgecolors='black')
    axes[0].set_xlabel('特征 1', fontsize=12)
    axes[0].set_ylabel('特征 2', fontsize=12)
    axes[0].set_title('决策边界', fontsize=14, fontweight='bold')
    plt.colorbar(scatter, ax=axes[0])
    
    # 混淆矩阵
    cm = confusion_matrix(y_test, y_test_pred)
    sns.heatmap(cm, annot=True, fmt='d', cmap='Blues', ax=axes[1])
    axes[1].set_xlabel('预测标签', fontsize=12)
    axes[1].set_ylabel('真实标签', fontsize=12)
    axes[1].set_title('混淆矩阵', fontsize=14, fontweight='bold')
    
    # ROC曲线
    fpr, tpr, _ = roc_curve(y_test, y_test_proba)
    roc_auc = auc(fpr, tpr)
    axes[2].plot(fpr, tpr, linewidth=2, label=f'ROC曲线 (AUC = {roc_auc:.3f})')
    axes[2].plot([0, 1], [0, 1], 'k--', label='随机分类器')
    axes[2].set_xlabel('假正率 (FPR)', fontsize=12)
    axes[2].set_ylabel('真正率 (TPR)', fontsize=12)
    axes[2].set_title('ROC曲线', fontsize=14, fontweight='bold')
    axes[2].legend()
    axes[2].grid(True, alpha=0.3)
    
    plt.tight_layout()
    plt.savefig('docs/images/logistic_regression_demo.png', dpi=300, bbox_inches='tight')
    plt.close()
    print("✓ 图表已保存: docs/images/logistic_regression_demo.png")


# ==================== 算法3:支持向量机 ====================

def svm_demo():
    """支持向量机完整示例"""
    print("\n" + "=" * 60)
    print("算法3:支持向量机 (SVM)")
    print("=" * 60)
    
    # 生成数据
    X, y = make_classification(
        n_samples=200, n_features=2, n_redundant=0,
        n_informative=2, n_clusters_per_class=1, random_state=42
    )
    
    # 标准化
    scaler = StandardScaler()
    X_scaled = scaler.fit_transform(X)
    
    X_train, X_test, y_train, y_test = train_test_split(
        X_scaled, y, test_size=0.2, random_state=42
    )
    
    # 训练不同核函数
    kernels = ['linear', 'poly', 'rbf', 'sigmoid']
    models = {}
    
    for kernel in kernels:
        model = SVC(kernel=kernel, random_state=42, probability=True)
        model.fit(X_train, y_train)
        models[kernel] = model
        test_acc = accuracy_score(y_test, model.predict(X_test))
        print(f"{kernel:8s} 核函数 - 测试准确率: {test_acc:.4f}")
    
    # 可视化
    fig, axes = plt.subplots(2, 2, figsize=(16, 12))
    axes = axes.flatten()
    
    h = 0.02
    x_min, x_max = X_scaled[:, 0].min() - 1, X_scaled[:, 0].max() + 1
    y_min, y_max = X_scaled[:, 1].min() - 1, X_scaled[:, 1].max() + 1
    xx, yy = np.meshgrid(np.arange(x_min, x_max, h),
                         np.arange(y_min, y_max, h))
    
    for idx, (kernel, model) in enumerate(models.items()):
        ax = axes[idx]
        Z = model.predict(np.c_[xx.ravel(), yy.ravel()])
        Z = Z.reshape(xx.shape)
        ax.contourf(xx, yy, Z, alpha=0.3, cmap=plt.cm.RdYlBu)
        scatter = ax.scatter(X_scaled[:, 0], X_scaled[:, 1], c=y, 
                           cmap=plt.cm.RdYlBu, edgecolors='black')
        ax.set_title(f'{kernel} 核函数', fontsize=14, fontweight='bold')
        ax.set_xlabel('特征 1', fontsize=12)
        ax.set_ylabel('特征 2', fontsize=12)
    
    plt.tight_layout()
    plt.savefig('docs/images/svm_demo.png', dpi=300, bbox_inches='tight')
    plt.close()
    print("✓ 图表已保存: docs/images/svm_demo.png")


# ==================== 算法4:朴素贝叶斯 ====================

def naive_bayes_demo():
    """朴素贝叶斯完整示例"""
    print("\n" + "=" * 60)
    print("算法4:朴素贝叶斯 (Naive Bayes)")
    print("=" * 60)
    
    # 生成数据
    X, y = make_classification(
        n_samples=1000, n_features=10, n_classes=3,
        n_informative=5, random_state=42
    )
    
    X_train, X_test, y_train, y_test = train_test_split(
        X, y, test_size=0.2, random_state=42
    )
    
    # 训练模型
    model = GaussianNB()
    model.fit(X_train, y_train)
    
    # 预测
    y_pred = model.predict(X_test)
    y_proba = model.predict_proba(X_test)
    
    # 评估
    acc = accuracy_score(y_test, y_pred)
    print(f"\n测试集准确率: {acc:.4f}")
    
    # 可视化
    fig, axes = plt.subplots(1, 2, figsize=(16, 6))
    
    # 混淆矩阵
    cm = confusion_matrix(y_test, y_pred)
    sns.heatmap(cm, annot=True, fmt='d', cmap='Blues', ax=axes[0])
    axes[0].set_xlabel('预测标签', fontsize=12)
    axes[0].set_ylabel('真实标签', fontsize=12)
    axes[0].set_title('混淆矩阵', fontsize=14, fontweight='bold')
    
    # 概率分布
    for i in range(len(np.unique(y_test))):
        axes[1].hist(y_proba[y_test == i, i], bins=20, alpha=0.6, 
                    label=f'类别 {i}')
    axes[1].set_xlabel('预测概率', fontsize=12)
    axes[1].set_ylabel('频数', fontsize=12)
    axes[1].set_title('各类别预测概率分布', fontsize=14, fontweight='bold')
    axes[1].legend()
    axes[1].grid(True, alpha=0.3)
    
    plt.tight_layout()
    plt.savefig('docs/images/naive_bayes_demo.png', dpi=300, bbox_inches='tight')
    plt.close()
    print("✓ 图表已保存: docs/images/naive_bayes_demo.png")


# ==================== 算法5:决策树 ====================

def decision_tree_demo():
    """决策树完整示例"""
    print("\n" + "=" * 60)
    print("算法5:决策树 (Decision Tree)")
    print("=" * 60)
    
    # 加载Iris数据集
    iris = load_iris()
    X, y = iris.data, iris.target
    
    X_train, X_test, y_train, y_test = train_test_split(
        X, y, test_size=0.2, random_state=42
    )
    
    # 训练决策树
    model = DecisionTreeClassifier(max_depth=3, random_state=42)
    model.fit(X_train, y_train)
    
    # 预测
    y_pred = model.predict(X_test)
    acc = accuracy_score(y_test, y_pred)
    
    print(f"\n测试集准确率: {acc:.4f}")
    print(f"\n决策树结构:")
    print(export_text(model, feature_names=iris.feature_names))
    
    # 可视化决策树
    plt.figure(figsize=(20, 10))
    plot_tree(model, feature_names=iris.feature_names, 
             class_names=iris.target_names, filled=True, fontsize=10)
    plt.title('决策树可视化', fontsize=16, fontweight='bold')
    plt.savefig('docs/images/decision_tree_demo.png', dpi=300, bbox_inches='tight')
    plt.close()
    
    # 特征重要性
    feature_importance = model.feature_importances_
    plt.figure(figsize=(10, 6))
    plt.barh(iris.feature_names, feature_importance)
    plt.xlabel('重要性', fontsize=12)
    plt.title('特征重要性', fontsize=14, fontweight='bold')
    plt.grid(True, alpha=0.3, axis='x')
    plt.savefig('docs/images/decision_tree_feature_importance.png', dpi=300, bbox_inches='tight')
    plt.close()
    print("✓ 图表已保存: docs/images/decision_tree_demo.png")


# ==================== 算法6:随机森林 ====================

def random_forest_demo():
    """随机森林完整示例"""
    print("\n" + "=" * 60)
    print("算法6:随机森林 (Random Forest)")
    print("=" * 60)
    
    # 生成数据
    X, y = make_classification(
        n_samples=1000, n_features=20, n_informative=10,
        n_classes=3, random_state=42
    )
    
    X_train, X_test, y_train, y_test = train_test_split(
        X, y, test_size=0.2, random_state=42
    )
    
    # 测试不同树数量
    n_trees = [10, 50, 100, 200]
    accuracies = []
    
    for n_tree in n_trees:
        model = RandomForestClassifier(n_estimators=n_tree, random_state=42)
        model.fit(X_train, y_train)
        acc = accuracy_score(y_test, model.predict(X_test))
        accuracies.append(acc)
        print(f"树数量: {n_tree:3d} - 准确率: {acc:.4f}")
    
    # 可视化
    plt.figure(figsize=(10, 6))
    plt.plot(n_trees, accuracies, 'o-', linewidth=2, markersize=8)
    plt.xlabel('树数量', fontsize=12)
    plt.ylabel('准确率', fontsize=12)
    plt.title('随机森林性能 vs 树数量', fontsize=14, fontweight='bold')
    plt.grid(True, alpha=0.3)
    plt.savefig('docs/images/random_forest_demo.png', dpi=300, bbox_inches='tight')
    plt.close()
    print("✓ 图表已保存: docs/images/random_forest_demo.png")


# ==================== 算法7:K近邻 ====================

def knn_demo():
    """K近邻完整示例"""
    print("\n" + "=" * 60)
    print("算法7:K近邻 (KNN)")
    print("=" * 60)
    
    # 生成数据
    X, y = make_classification(
        n_samples=300, n_features=2, n_redundant=0,
        n_informative=2, n_clusters_per_class=1, random_state=42
    )
    
    scaler = StandardScaler()
    X_scaled = scaler.fit_transform(X)
    
    X_train, X_test, y_train, y_test = train_test_split(
        X_scaled, y, test_size=0.2, random_state=42
    )
    
    # 测试不同的K值
    k_values = range(1, 21)
    train_accuracies = []
    test_accuracies = []
    
    for k in k_values:
        model = KNeighborsClassifier(n_neighbors=k)
        model.fit(X_train, y_train)
        train_acc = accuracy_score(y_train, model.predict(X_train))
        test_acc = accuracy_score(y_test, model.predict(X_test))
        train_accuracies.append(train_acc)
        test_accuracies.append(test_acc)
    
    # 可视化K值影响
    plt.figure(figsize=(12, 6))
    plt.plot(k_values, train_accuracies, 'o-', label='训练集', linewidth=2)
    plt.plot(k_values, test_accuracies, 's-', label='测试集', linewidth=2)
    plt.xlabel('K值', fontsize=12)
    plt.ylabel('准确率', fontsize=12)
    plt.title('K值对KNN性能的影响', fontsize=14, fontweight='bold')
    plt.legend()
    plt.grid(True, alpha=0.3)
    plt.xticks(k_values[::2])
    plt.savefig('docs/images/knn_demo.png', dpi=300, bbox_inches='tight')
    plt.close()
    print("✓ 图表已保存: docs/images/knn_demo.png")


# ==================== 算法8:K均值聚类 ====================

def kmeans_demo():
    """K均值聚类完整示例"""
    print("\n" + "=" * 60)
    print("算法8:K均值聚类 (K-Means)")
    print("=" * 60)
    
    # 生成数据
    X, y_true = make_blobs(
        n_samples=300, centers=4, n_features=2, random_state=42
    )
    
    # 测试不同的K值
    k_range = range(2, 11)
    inertias = []
    silhouette_scores = []
    
    for k in k_range:
        kmeans = KMeans(n_clusters=k, random_state=42, n_init=10)
        labels = kmeans.fit_predict(X)
        inertias.append(kmeans.inertia_)
        silhouette_scores.append(silhouette_score(X, labels))
    
    # 可视化
    fig, axes = plt.subplots(1, 2, figsize=(16, 6))
    
    axes[0].plot(k_range, inertias, 'o-', linewidth=2, markersize=8)
    axes[0].set_xlabel('K值', fontsize=12)
    axes[0].set_ylabel('Inertia (簇内平方和)', fontsize=12)
    axes[0].set_title('肘部法则 (Elbow Method)', fontsize=14, fontweight='bold')
    axes[0].grid(True, alpha=0.3)
    axes[0].set_xticks(k_range)
    
    axes[1].plot(k_range, silhouette_scores, 'o-', linewidth=2, markersize=8, color='green')
    axes[1].set_xlabel('K值', fontsize=12)
    axes[1].set_ylabel('轮廓系数', fontsize=12)
    axes[1].set_title('轮廓系数 vs K值', fontsize=14, fontweight='bold')
    axes[1].grid(True, alpha=0.3)
    axes[1].set_xticks(k_range)
    
    plt.tight_layout()
    plt.savefig('docs/images/kmeans_evaluation.png', dpi=300, bbox_inches='tight')
    plt.close()
    
    best_k = k_range[np.argmax(silhouette_scores)]
    print(f"\n最佳K值: {best_k}")
    print("✓ 图表已保存: docs/images/kmeans_evaluation.png")


# ==================== 算法9:主成分分析 ====================

def pca_demo():
    """主成分分析完整示例"""
    print("\n" + "=" * 60)
    print("算法9:主成分分析 (PCA)")
    print("=" * 60)
    
    # 加载Iris数据集
    iris = load_iris()
    X, y = iris.data, iris.target
    
    # 标准化
    scaler = StandardScaler()
    X_scaled = scaler.fit_transform(X)
    
    # PCA降维
    pca = PCA()
    X_pca = pca.fit_transform(X_scaled)
    
    # 可视化
    explained_variance_ratio = pca.explained_variance_ratio_
    cumulative_variance = np.cumsum(explained_variance_ratio)
    
    fig, axes = plt.subplots(2, 2, figsize=(16, 12))
    
    axes[0, 0].bar(range(1, len(explained_variance_ratio) + 1), 
                  explained_variance_ratio, alpha=0.7)
    axes[0, 0].set_xlabel('主成分', fontsize=12)
    axes[0, 0].set_ylabel('解释方差比例', fontsize=12)
    axes[0, 0].set_title('各主成分解释方差比例', fontsize=14, fontweight='bold')
    axes[0, 0].grid(True, alpha=0.3, axis='y')
    
    axes[0, 1].plot(range(1, len(cumulative_variance) + 1), cumulative_variance, 
                   'o-', linewidth=2, markersize=8)
    axes[0, 1].axhline(y=0.95, color='r', linestyle='--', label='95%阈值')
    axes[0, 1].set_xlabel('主成分数量', fontsize=12)
    axes[0, 1].set_ylabel('累积解释方差比例', fontsize=12)
    axes[0, 1].set_title('累积解释方差', fontsize=14, fontweight='bold')
    axes[0, 1].legend()
    axes[0, 1].grid(True, alpha=0.3)
    
    scatter = axes[1, 0].scatter(X_pca[:, 0], X_pca[:, 1], c=y, cmap='viridis', s=50, alpha=0.6)
    axes[1, 0].set_xlabel(f'第一主成分 (解释方差: {explained_variance_ratio[0]:.2%})', fontsize=12)
    axes[1, 0].set_ylabel(f'第二主成分 (解释方差: {explained_variance_ratio[1]:.2%})', fontsize=12)
    axes[1, 0].set_title('PCA 2D投影', fontsize=14, fontweight='bold')
    plt.colorbar(scatter, ax=axes[1, 0])
    
    axes[1, 1].axis('off')
    
    plt.tight_layout()
    plt.savefig('docs/images/pca_demo.png', dpi=300, bbox_inches='tight')
    plt.close()
    
    print(f"\n各主成分解释方差比例:")
    for i, ratio in enumerate(explained_variance_ratio):
        print(f"  PC{i+1}: {ratio:.4f} ({ratio*100:.2f}%)")
    print(f"\n前2个主成分累积解释方差: {cumulative_variance[1]:.4f} ({cumulative_variance[1]*100:.2f}%)")
    print("✓ 图表已保存: docs/images/pca_demo.png")


# ==================== 算法10:梯度提升树 ====================

def gradient_boosting_demo():
    """梯度提升树完整示例"""
    print("\n" + "=" * 60)
    print("算法10:梯度提升树 (Gradient Boosting)")
    print("=" * 60)
    
    # 生成数据
    X, y = make_classification(
        n_samples=1000, n_features=20, n_informative=10,
        n_classes=2, random_state=42
    )
    
    X_train, X_test, y_train, y_test = train_test_split(
        X, y, test_size=0.2, random_state=42
    )
    
    # 训练梯度提升树
    model = GradientBoostingClassifier(
        n_estimators=100, learning_rate=0.1,
        max_depth=3, random_state=42
    )
    model.fit(X_train, y_train)
    
    # 预测
    y_pred = model.predict(X_test)
    acc = accuracy_score(y_test, y_pred)
    
    print(f"\n测试集准确率: {acc:.4f}")
    
    # 可视化训练过程
    train_scores = np.zeros((model.n_estimators,), dtype=np.float64)
    test_scores = np.zeros((model.n_estimators,), dtype=np.float64)
    
    for i, y_pred_train in enumerate(model.staged_predict(X_train)):
        train_scores[i] = accuracy_score(y_train, y_pred_train)
    
    for i, y_pred_test in enumerate(model.staged_predict(X_test)):
        test_scores[i] = accuracy_score(y_test, y_pred_test)
    
    plt.figure(figsize=(12, 5))
    
    plt.subplot(1, 2, 1)
    plt.plot(np.arange(model.n_estimators), train_scores, 
            label='训练集', linewidth=2)
    plt.plot(np.arange(model.n_estimators), test_scores, 
            label='测试集', linewidth=2)
    plt.xlabel('迭代次数', fontsize=12)
    plt.ylabel('准确率', fontsize=12)
    plt.title('梯度提升训练过程', fontsize=14, fontweight='bold')
    plt.legend()
    plt.grid(True, alpha=0.3)
    
    plt.subplot(1, 2, 2)
    feature_importance = model.feature_importances_
    top_features = np.argsort(feature_importance)[-10:][::-1]
    plt.barh(range(len(top_features)), feature_importance[top_features])
    plt.yticks(range(len(top_features)), [f'特征 {i}' for i in top_features])
    plt.xlabel('重要性', fontsize=12)
    plt.title('Top 10 特征重要性', fontsize=14, fontweight='bold')
    plt.grid(True, alpha=0.3, axis='x')
    
    plt.tight_layout()
    plt.savefig('docs/images/gradient_boosting_demo.png', dpi=300, bbox_inches='tight')
    plt.close()
    print("✓ 图表已保存: docs/images/gradient_boosting_demo.png")


# ==================== 主函数 ====================

def main():
    """运行所有算法示例"""
    print("\n" + "=" * 60)
    print("十大基础机器学习算法完整演示")
    print("Python 3.11 兼容版本")
    print("=" * 60)
    
    # 运行所有算法
    linear_regression_demo()
    logistic_regression_demo()
    svm_demo()
    naive_bayes_demo()
    decision_tree_demo()
    random_forest_demo()
    knn_demo()
    kmeans_demo()
    pca_demo()
    gradient_boosting_demo()
    
    print("\n" + "=" * 60)
    print("✓ 所有算法演示完成!")
    print("=" * 60)
    print("\n所有图表已保存到 docs/images/ 目录")
    print("详细文档请参考: docs/ml_algorithms_fundamentals.md")


if __name__ == '__main__':
    main()
相关推荐
冰西瓜6003 小时前
通俗易懂讲解马尔可夫模型
人工智能·机器学习
霖大侠3 小时前
Squeeze-and-Excitation Networks
人工智能·算法·机器学习·transformer
tangjunjun-owen3 小时前
DINOv3 demo
python·深度学习·机器学习
你们补药再卷啦4 小时前
识别手写数字(keras)
深度学习·机器学习·keras
python机器学习ML4 小时前
论文复现-以动物图像分类为例进行多模型性能对比分析
人工智能·python·神经网络·机器学习·计算机视觉·scikit-learn·sklearn
m0_704887894 小时前
Day44
人工智能·深度学习·机器学习
cici158744 小时前
模式识别,非监督聚类分析分类方法
人工智能·机器学习·分类
木头左4 小时前
集成学习方法在LSTM交易预测中的应用多元入参的作用
机器学习·lstm·集成学习
byzh_rc5 小时前
[模式识别-从入门到入土] 拓展-KKT条件
人工智能·机器学习·支持向量机