欢迎光临
我们一直在努力

机器学习基础(Python)

一、机器学习概述。

1.1 什么是机器学习。

        机器学习是一个研究领域,可以让计算机不需要明确的编程就具备学习能力,其主旨是以数据驱动的方式,在数据上通过算法来总结规律,并将得出的规律运用在新数据上或者预测出新的数据。

1.2 机器学习类型。

        机器学习一般可以分为有监督学习、无监督学习、强化学习。

1. 2.1 监督学习(Supervised Learning)

  • 定义: 监督学习是指使用带标签的数据进行训练,模型通过学习输入数据与标签之间的关系,来做出预测或分类。
  • 应用: 分类(如垃圾邮件识别)、回归(如房价预测)。
  • 例子: 线性回归、决策树、支持向量机(SVM)、K近邻。

1.2.3 无监督学习(Unsupervised Learning)

  • 定义: 无监督学习使用没有标签的数据,模型试图在数据中发现潜在的结构或模式。
  • 应用: 聚类(如客户分群)、降维(如数据可视化)。
  • 例子: K-means 聚类、主成分分析(PCA)。

1.2.3 强化学习(Reinforcement Learning)

  • 定义: 强化学习通过与环境互动,智能体在试错中学习最佳策略,以最大化长期回报。每次行动后,系统会收到奖励或惩罚,来指导行为的改进。
  • 应用: 游戏AI(如AlphaGo)、自动驾驶、机器人控制。
  • 例子: Q-learning、深度Q网络(DQN)。

1.2 机器学习应用领域

  • 推荐系统: 例如,抖音推荐你可能感兴趣的视频,淘宝推荐你可能会购买的商品,网易云音乐推荐你喜欢的音乐。

  • 自然语言处理(NLP): 机器学习在语音识别、机器翻译、情感分析、聊天机器人等方面的应用。例如,Google 翻译、Siri 和智能客服等。

  • 计算机视觉: 机器学习在图像识别、物体检测、面部识别、自动驾驶等领域有广泛应用。例如,自动驾驶汽车通过摄像头和传感器识别周围的障碍物,识别行人和其他车辆。

  • 金融分析: 机器学习在股市预测、信用评分、欺诈检测等金融领域具有重要应用。例如,银行利用机器学习检测信用卡交易中的欺诈行为。

  • 医疗健康: 机器学习帮助医生诊断疾病、发现药物副作用、预测病情发展等。例如,IBM 的 Watson 系统帮助医生分析患者的病历数据,提供诊断和治疗建议。

  • 游戏和娱乐: 机器学习不仅用于游戏中的智能对手,还应用于游戏设计、动态难度调整等方面。例如,AlphaGo 使用深度学习技术战胜了围棋世界冠军。

1.3 机器学习概念与术语

1.3.1 基本概念

  • 训练集、测试集和验证集:帮助训练、评估和调优模型。
  • 特征与标签:特征是输入,标签是模型预测的目标。
  • 模型与算法:模型是通过算法训练得到的,算法帮助模型学习数据中的模式。
  • 监督学习、无监督学习和强化学习:三种常见的学习方式,分别用于不同的任务。
  • 过拟合与欠拟合:两种常见的问题,影响模型的泛化能力。
  • 训练误差与测试误差:反映模型是否能适应数据,并进行有效预测。
  • 评估指标:衡量模型好坏的标准,根据任务选择合适的指标。

1.3.2 训练集、测试集和验证集

  • 训练集(Training Set): 训练集是用于训练机器学习模型的数据集,它包含输入特征和对应的标签(在监督学习中)。模型通过学习训练集中的数据来调整参数,逐步提高预测的准确性。

  • 测试集(Test Set): 测试集用于评估训练好的模型的性能。测试集中的数据不参与模型的训练,模型使用它来进行预测,并与真实标签进行比较,帮助我们了解模型在未见过的数据上的表现。

  • 验证集(Validation Set): 验证集用于在训练过程中调整模型的超参数(如学习率、正则化参数等)。它通常被用于模型调优,帮助选择最佳的模型参数,避免过拟合。验证集的作用是对模型进行监控和调试

1.3.3 特征(Features)和标签(Labels)

  • 特征(Features): 特征是输入数据的不同属性,模型使用这些特征来做出预测或分类。例如,在房价预测中,特征可能包括房子的面积、地理位置、卧室数量等。

  • 标签(Labels): 标签是机器学习任务中的目标变量,模型要预测的结果。对于监督学习任务,标签通常是已知的。例如,在房价预测中,标签就是房子的实际价格。

  • 特征是模型输入的数据。标签是模型需要预测的输出。

1.3.4 过拟合与欠拟合

  • 过拟合(Overfitting): 过拟合是指模型在训练数据上表现非常好,但在测试数据上表现很差。这通常发生在模型复杂度过高、参数过多,导致模型"记住"了训练数据中的噪声或偶然性,而不具备泛化能力。过拟合的模型无法有效应对新数据。

  • 欠拟合(Underfitting): 欠拟合是指模型在训练数据上和测试数据上都表现不佳,通常是因为模型过于简单,无法捕捉数据中的复杂模式。欠拟合的模型无法从数据中学习到有用的规律。

解决方法:

  • 过拟合:可以通过简化模型、增加训练数据或使用正则化等方法来缓解。
  • 欠拟合:可以通过增加模型复杂度或使用更复杂的算法来改进。

1.3.5 评估指标

        根据任务的不同,机器学习模型的评估指标也不同。以下是常用的一些评估指标:

  • 准确率(Accuracy): 分类任务中,正确分类的样本占总样本的比例。

  • 精确率(Precision)和召回率(Recall): 主要用于处理不平衡数据集,精确率衡量的是被模型预测为正类的样本中,有多少是真正的正类;召回率衡量的是所有实际正类中,有多少被模型正确识别为正类。

  • F1 分数: 精确率与召回率的调和平均数,用于综合考虑模型的表现。

  • 均方误差(MSE): 回归任务中,预测值与真实值之间差异的平方的平均值。

评估指标帮助我们衡量模型的表现,选择最合适的指标可以根据任务的需求来进行

1.4 机器学习工作流程

        机器学习一般遵循以下步骤:

1. 数据收集

  • 收集数据:这是机器学习项目的第一步,涉及收集相关数据。数据可以来自数据库、文件、网络或实时数据流。

  • 数据类型:可以是结构化数据(如表格数据)或非结构化数据(如文本、图像、视频)。

2. 数据预处理

  • 清洗数据:处理缺失值、异常值、错误和重复数据。

  • 特征工程:选择有助于模型学习的最相关特征,可能包括创建新特征或转换现有特征。

  • 数据标准化/归一化:调整数据的尺度,使其在同一范围内,有助于某些算法的性能。

3. 选择模型

  • 确定问题类型:根据问题的性质(分类、回归、聚类等)选择合适的机器学习模型。

  • 选择算法:基于问题类型和数据特性,选择一个或多个算法进行实验。

4. 训练模型

  • 划分数据集:将数据分为训练集、验证集和测试集。

  • 训练:使用训练集上的数据来训练模型,调整模型参数以最小化损失函数。

  • 验证:使用验证集来调整模型参数,防止过拟合。

5. 评估模型

  • 性能指标:使用测试集来评估模型的性能,常用的指标包括准确率、召回率、F1分数等。

  • 交叉验证:一种评估模型泛化能力的技术,通过将数据分成多个子集进行训练和验证。

6. 模型优化

  • 调整超参数:超参数是学习过程之前设置的参数,如学习率、树的深度等,可以通过网格搜索、随机搜索或贝叶斯优化等方法来调整。

  • 特征选择:可能需要重新评估和选择特征,以提高模型性能。

7. 部署模型

  • 集成到应用:将训练好的模型集成到实际应用中,如网站、移动应用或软件中。

  • 监控和维护:持续监控模型的性能,并根据新数据更新模型。

8. 反馈循环

  • 持续学习:机器学习模型可以设计为随着时间的推移自动从新数据中学习,以适应变化。

1.5 机器学习入门案列及代码。

        Scikit-learn(简称 Sklearn)是一个开源的机器学习库,建立在 NumPy、SciPy 和 matplotlib 这些科学计算库之上,提供了简单高效的数据挖掘和数据分析工具。

Scikit-learn 包含了许多常见的机器学习算法,包括:

  • 线性回归、岭回归、Lasso回归
  • 支持向量机(SVM)
  • 决策树、随机森林、梯度提升树
  • 聚类算法(如K-Means、层次聚类、DBSCAN)
  • 降维技术(如PCA、t-SNE)
  • 神经网络

        简单的分类任务——使用鸢尾花数据集(Iris Dataset)来演示机器学习的流程,鸢尾花数据集是一个经典的数据集,包含 150 个样本,描述了三种不同类型的鸢尾花的花瓣和萼片的长度和宽度。注意下载好所需库。

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.neighbors import KNeighborsClassifier
from sklearn.metrics import accuracy_score

# 加载鸢尾花数据集
iris = load_iris()

# 将数据转化为 pandas DataFrame
X = pd.DataFrame(iris.data, columns=iris.feature_names) # 特征数据
y = pd.Series(iris.target) # 标签数据

# 划分训练集和测试集(80% 训练集,20% 测试集)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# 标准化特征
scaler = StandardScaler()
X_train = scaler.fit_transform(X_train)
X_test = scaler.transform(X_test)

# 创建 KNN 分类器
knn = KNeighborsClassifier(n_neighbors=3)

# 训练模型
knn.fit(X_train, y_train)

# 预测测试集
y_pred = knn.predict(X_test)

# 计算准确率
accuracy = accuracy_score(y_test, y_pred)

# 可视化 – 这里只是一个简单示例,具体可根据实际情况选择绘图方式
plt.scatter(X_test[:, 0], X_test[:, 1], c=y_pred, cmap='viridis', marker='o')
plt.title("KNN Classification Results")
plt.xlabel("Feature 1")
plt.ylabel("Feature 2")
plt.show()

二、回归算法

2.1 线性回归 (Linear Regression)

        线性回归(Linear Regression)是机器学习中最基础且广泛应用的算法之一,它 是一种用于预测连续值的最基本的机器学习算法,它假设目标变量 y 和特征变量 x 之间存在线性关系,并试图找到一条最佳拟合直线来描述这种关系。即:

                                                      y = w * x + b y是预测值,x是特征变量(输入的数据),w是权重 (斜率),b是偏置 (截距)。目标是找到最佳的 w 和 b,使得预测值y与真实值之间的误差(有多种函数选择,一般采用均方误差(MSE)作为损失函数)最小。通过不断地训练模型,会不断地调整 w 和 b,直到训练完成。 

2.1.1 线性回归参数解法(梯度下降法)

        目标是最小化 损失函数 J(w,b)。对于线性回归问题,通常使用均方误差(MSE)作为损失函数:

J(w,b)=\\frac{1}{2m}\\sum_{i=1}^{m}\\left ( y_{i}-y\\hat{}_{i}\\right )^{2}

其中:

  • m是样本数量。

  • y_{_{i}} 是实际值。

  • y\\hat{}_{_{_{_{i}}}}​ 是预测值,由线性回归模型 计算得到。

        梯度是损失函数对参数的偏导数,表示损失函数在参数空间中的变化方向。对于线性回归,梯度计算如下:

​ [ \\frac{\\partial J}{\\partial w} = -\\frac{1}{m} \\sum_{i=1}^m x_i (y_i - \\hat{y}_i) ]

[ \\frac{\\partial J}{\\partial b} = -\\frac{1}{m} \\sum_{i=1}^m (y_i - \\hat{y}_i)]

2.1.2 参数更新规则

        梯度下降法通过以下规则更新参数 w 和  b:

[ w := w - \\alpha \\cdot \\frac{\\partial J}{\\partial w} ]

[ b := b - \\alpha \\cdot \\frac{\\partial J}{\\partial b} ]

其中:

  • α 是学习率(learning rate)(超参数),可自己设置,控制每次更新的步长。

梯度下降法的步骤

  • 初始化参数:初始化 w 和  b 的值(通常设为 0 或随机值)。

  • 计算损失函数:计算当前参数下的损失函数值 J(w,b)。

  • 计算梯度:计算损失函数对 w 和 b 的偏导数。

  • 更新参数:根据梯度更新 w 和 b。

  • 重复迭代:重复步骤 2 到 4,直到损失函数收敛或达到最大迭代次数。

  • 2.1.3 梯度下降法代码实现

            比较以下两种方法,了解Scikit-learn中已实现的模型中的细节。

            1.使用 Scikit-learn 进行线性回归代码:

    import numpy as np
    import matplotlib.pyplot as plt
    from sklearn.linear_model import LinearRegression

    # 生成一些随机数据
    np.random.seed(0)
    x = 2 * np.random.rand(100, 1)
    y = 4 + 3 * x + np.random.randn(100, 1)

    # 创建线性回归模型
    model = LinearRegression()

    # 拟合模型
    model.fit(x, y)

    # 输出模型的参数
    print(f"斜率 (w): {model.coef_[0][0]}")
    print(f"截距 (b): {model.intercept_[0]}")

    # 预测
    y_pred = model.predict(x)

    # 可视化拟合结果
    plt.scatter(x, y)
    plt.plot(x, y_pred, color='red')
    plt.xlabel('x')
    plt.ylabel('y')
    plt.title('Linear Regression Fit')
    plt.show()

           2. 手动实现梯度下降法代码:

    import numpy as np
    import matplotlib.pyplot as plt
    from sklearn.linear_model import LinearRegression

    # 生成一些随机数据
    np.random.seed(0)
    x = 2 * np.random.rand(100, 1)
    y = 4 + 3 * x + np.random.randn(100, 1)

    # 初始化参数
    w = 0
    b = 0
    learning_rate = 0.1
    n_iterations = 1000

    # 梯度下降
    for i in range(n_iterations):
    y_pred = w * x + b
    dw = -(2/len(x)) * np.sum(x * (y – y_pred))
    db = -(2/len(x)) * np.sum(y – y_pred)
    w = w – learning_rate * dw
    b = b – learning_rate * db

    # 输出最终参数
    print(f"手动实现的斜率 (w): {w}")
    print(f"手动实现的截距 (b): {b}")

    # 可视化手动实现的拟合结果
    y_pred_manual = w * x + b
    plt.scatter(x, y)
    plt.plot(x, y_pred_manual, color='green')
    plt.xlabel('x')
    plt.ylabel('y')
    plt.title('Manual Gradient Descent Fit')
    plt.show()

    2.2 逻辑回归(Logistic Regression)

            逻辑回归是一种广泛应用于分类问题的统计学习方法,尽管名字中带有"回归",但它实际上是一种用于二分类或多分类问题的算法。它使用逻辑函数(也称为 Sigmoid 函数)将线性回归的输出映射到 0 和 1 之间,从而预测某个事件发生的概率。逻辑回归广泛应用于各种分类问题,例如:

    • 垃圾邮件检测(是垃圾邮件/不是垃圾邮件)
    • 疾病预测(患病/不患病)
    • 客户流失预测(流失/不流失)

    2.2.1 逻辑回归模型

            Sigmoid函数图像如下图:

            逻辑回归的损失函数是对数损失函数(Log Loss),其形式如下:

    2.2.2 逻辑回归模型代码实现

            逻辑回归通常也使用梯度下降法来优化损失函数,求解参数 w 和 b,并且不断更新。如下代码中使用 Scikit-learn 自带的 Iris 数据集。Iris 数据集包含 150 个样本,每个样本有 4 个特征,目标是将样本分为 3 类。为了简化问题,只使用前两个特征,并将问题转化为二分类问题。

    from sklearn.datasets import load_iris
    from sklearn.model_selection import train_test_split
    from sklearn.linear_model import LogisticRegression
    from sklearn.metrics import accuracy_score, confusion_matrix, classification_report

    # 加载数据集
    iris = load_iris()
    X = iris.data[:, :2] # 只使用前两个特征
    y = (iris.target != 0) * 1 # 将目标转化为二分类问题

    # 划分训练集和测试集
    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)

    # 创建逻辑回归模型
    model = LogisticRegression()
    # 训练模型
    model.fit(X_train, y_train)

    # 预测测试集
    y_pred = model.predict(X_test)

    # 计算准确率
    accuracy = accuracy_score(y_test, y_pred)
    print(f"模型准确率: {accuracy:.2f}")

    # 混淆矩阵
    conf_matrix = confusion_matrix(y_test, y_pred)
    print("混淆矩阵:")
    print(conf_matrix)

    # 分类报告
    class_report = classification_report(y_test, y_pred)
    print("分类报告:")
    print(class_report)

    2.2.3 可视化决策边界

            决策边界(Decision Boundary)是机器学习中用于分类问题的核心概念,指在特征空间中划分不同类别的超平面或分界线。以下是其关键要点:

    1. ‌基本定义‌

            决策边界是监督学习中分类模型对样本进行分类的数学分界,它将特征空间划分为不同类别区域。例如,在二维空间中,决策边界可能是一条直线(线性分类器)或曲线(非线性分类器)‌。

    2. ‌作用与可视化‌         分类依据‌:通过决策边界可直接判断新样本的类别归属,例如逻辑回归中若θᵀx≥0则预测为类别1,否则为类别0‌。         性能评估‌:绘制决策边界可直观观察模型分类效果,如线性边界可能无法处理复杂数据分布,导致分类错误‌。 3. ‌类型与示例‌         线性边界‌:如逻辑回归的直线边界(θᵀx=0)‌。         非线性边界‌:如多项式特征或核方法生成的曲线(如x₁² + x₂²=1)‌。 4. ‌应用场景‌

            决策边界广泛用于解释模型行为,例如在KNN、SVM等算法中,边界形状直接影响分类精度‌。在自动驾驶等不确定性决策场景中,边界划分需结合概率模型处理动态环境‌。

    2.3 岭回归(Ridge Regression)

            岭回归(Ridge Regression)是解决线性回归中多重共线性问题的正则化方法,由Andrey Tikhonov提出。其核心思想是:通过在损失函数中引入L2正则化项,约束模型的复杂度,避免过拟合。通过惩罚回归系数的大小,岭回归能更好地处理多重共线性问题。

            岭回归的优化目标为:[ \\min_{\\beta} \\left( \\sum_{i=1}^n (y_i - \\mathbf{X}i \\beta)^2 + \\lambda \\sum{}_{j= 1}^p \\beta_j^2 \\right) ],其中:

    • 第一项为 残差平方和(最小二乘损失);

    • 第二项为 L2正则化项,(\\lambda)为正则化参数,控制惩罚强度。

            参数估计为: [ \\hat{\\beta} = (\\mathbf{X}^T\\mathbf{X} + \\lambda I)^{-1} \\mathbf{X}^T y ],其中(I)为单位矩阵。当(\\lambda \\to 0)时,退化为普通最小二乘法;(\\lambda \\to +\\infty)时,系数趋近于零。

    核心特性与优势:

  • L2正则化:通过惩罚大系数,避免过拟合,提升泛化能力。

  • 参数收缩:所有回归系数均被压缩,但不会完全为零(与Lasso回归不同)。

  • 病态矩阵处理:通过添加(\\lambda I)使矩阵可逆,解决最小二乘法在共线性下的数值不稳定问题。

  • from sklearn.linear_model import Ridge

    model = Ridge(alpha=1.0) # alpha 是正则化参数
    model.fit(X_train, y_train)

    # 预测
    y_pred = model.predict(X_test)

    2.4 Lasso 回归(Lasso Regression)

            Lasso 回归也是线性回归的一种形式,它使用 L1 正则化 来对回归系数进行惩罚。与岭回归不同,Lasso 会将一些回归系数压缩到零,从而实现特征选择。

    \\min_{\\beta} \\left( \\sum_{i=1}^n (y_i - X_i \\beta)^2 + \\lambda \\sum_{j=1}^p |\\beta_j| \\right)

    第一部分‌(残差平方和):衡量模型预测值与真实值的误差。 第二部分‌(L1惩罚项):对系数绝对值求和,促使不重要的特征系数归零。

    • β:待求解的回归系数向量。
    • λ:正则化强度参数,控制稀疏性(λ越大,系数越稀疏)。
    • n:样本数量,p:特征数量。

    核心特性与优势:‌

    • ‌稀疏性‌:L1惩罚项 能自动进行特征选择,适合高维数据。
    • ‌不可导性‌:绝对值函数在零点不可导,需用坐标下降法等优化算法求解。

    from sklearn.linear_model import Lasso

    model = Lasso(alpha=0.1) # alpha 是正则化参数
    model.fit(X_train, y_train)

    # 预测
    y_pred = model.predict(X_test)

    三、支持向量机(Support Vector Machine)

            SVM是一种监督学习算法,主要用于分类和回归问题。SVM 的核心思想是找到一个最优的超平面,将不同类别的数据分开。这个超平面不仅要能够正确分类数据,还要使得两个类别之间的间隔(margin)最大化。

            支持向量机(SVM)是一种二分类模型,通过最大间隔策略找到最优超平面。在处理线性可分数据时,SVM寻找最大间隔的超平面。对于线性不可分数据,SVM利用核函数映射到高维空间实现线性可分。

            此外,SVM通过引入软间隔和正则化参数C,处理非完美分类情况。SVM在文本分类、图像识别、金融和医学等领域有广泛应用,但对大规模数据集和缺失数据处理较慢,且模型解释性较差。

    3.1 SVM基本概念

    超平面:

    • 在二维空间中,超平面是一个直线。
    • 在三维空间中,超平面是一个平面。
    • 在更高维空间中,超平面是一个分割空间的超平面。

    支持向量:

    • 支持向量 是离超平面最近的样本点。这些支持向量对于定义超平面至关重要。
    • 支持向量机 通过最大化 支持向量到超平面的距离(即最大化间隔)来选择最佳的超平面。

    最大间隔:

    • SVM的目标是最大化分类间隔,使得分类边界尽可能远离两类数据点。这可以有效地减少模型的泛化误差。

    核技巧(Kernel Trick):

    • 对于非线性可分的数据,SVM使用核函数将数据映射到更高维的空间,在这个空间中,数据可能是线性可分的。
    • 常用的核函数有:线性核、多项式核、径向基函数(RBF)核等。

    SVM 分类流程:

  • 选择一个超平面:找到一个能够最大化分类边界的超平面。
  • 训练支持向量:通过支持向量机算法,选择离超平面最近的样本点作为支持向量。
  • 通过最大化间隔来找到最优超平面:选择一个最优超平面,使得间隔最大化。
  • 使用核函数处理非线性问题:通过核函数将数据映射到高维空间来解决非线性可分问题
  • 3.2 SVM的分类(原理未理解)

    3.2.1 线性可分支持向量机

            当训练数据线性可分时,通过硬间隔(不允许任何数据分类越过分界线且都在正确的一边)最大化 学习一个线性分类器,即:线性可分支持向量机,此时SVM得到的最优超平面是 平面或直线。

    3.2.2 线性支持向量机

            当训练数据近似可分时,引入松弛变量,会变成软间隔最大化训练一个分类器,即:线性支持向量机。

    3.2.3 非线性支持向量机

            日常中大部分时候的数据不是 线性可分的,这个时候满足条件的超平面根本不存在。如果希望能够解决这个问题,那么需要进行一个非线性变换,将非线性问题变换为线性问题。通过核函数将数据映射到高维空间中,来解决在原始空间中线性不可分的问题。如下图所示:x是一个数据集特征,由图可知特征不可线性再分,但如果由一维升为二维,生成的数据集特征完全线性可分。

    下图类似:二维 ——> 三维。

    3.3 核函数(Kernel Function)

            核函数是机器学习中处理非线性问题的核心工具,通过隐式映射将数据从原始空间转换到高维特征空间,从而在高维空间中实现 线性可分或线性建模‌。其数学本质是计算两个样本在高维空间中的内积,而无需显式计算映射函数(低维计算,高维分类),从而大大减少了高维数据的计算量。

     一般核函数的种类:

    一、线性核函数(Linear Kernel)                                                 公式‌:𝐾(𝑥,𝑦)=𝑥⋅𝑦 特点‌:直接计算原始空间的内积,不进行非线性变换,计算效率高但无法处理非线性问题‌。 适用场景‌:线性可分数据(如文本分类、高维稀疏数据)‌。不需要设置任何参数,直接可使用。

    from sklearn.svm import SVC
    clf = svm.SVC(kernel='linear') # 使用线性核函数

    二、多项式核函数(Polynomial Kernel)                                                 公式‌:𝐾(𝑥,𝑦)=(𝛾(𝑥⋅𝑦)+c)^d。

            𝛾:对内积(x⋅y)进行放缩,> 0,一般等于 1/类别数。

            c:代表常数,>=0。

            d:整数,一般 = 2,d越大,计算量越大,越复杂。

    特点‌:通过升维将数据映射到高维空间,灵活性高但参数敏感(需调整阶数𝑑、缩放系数𝛾等)‌。 适用场景‌:中等规模数据集,数据存在多项式关系时‌。

    from sklearn.svm import SVC
    # 多项式核SVM模型
    poly_svm = SVC(kernel='poly', degree=3, coef0=1.0)

    """
    kernel='poly':指定使用多项式核函数,这种核函数可以处理 非线性可分数据

    degree=3:设置多项式核的阶数为3,这意味着模型会考虑特征间的三次多项式关系

    coef0=1.0:核函数中的独立项系数,影响多项式核的计算方式

    特点说明:多项式核通过将原始特征空间映射到 更高维空间来实现非线性分类
    degree:控制模型复杂度,值越大模型越复杂可能过拟合
    coef0:影响核函数形状,调整它可以改变决策边界的形态
    适合处理特征间存在多项式关系的分类问题
    """
    参数调优函数:
    def train_poly_svm(X_train, y_train):
    # 创建多项式核SVM模型
    model = SVC(kernel='poly', random_state=42)

    # 定义参数网格
    param_grid = {
    'C': [0.1, 1, 10],
    'degree': [2, 3, 4],
    'coef0': [0.0, 1.0, 2.0]
    }

    # 网格搜索交叉验证
    grid_search = GridSearchCV(model, param_grid, cv=5, n_jobs=-1)
    grid_search.fit(X_train, y_train)

    return grid_search.best_estimator_, grid_search.best_params_

    三、高斯核/径向基函数核(RBF Kernel)                                                 公式‌:𝐾(𝑥,𝑦)=exp⁡(−𝛾∥𝑥−𝑦∥^2)

     特点‌:强大的非线性映射能力,需设置参数𝛾控制函数宽度,适用于复杂数据分布‌。  适用场景‌:分类和回归任务,尤其适合小样本或高维数据‌。

    from sklearn.svm import SVC
    # 初始化RBF核SVM
    model = SVC(kernel='rbf', C=1.0, gamma='scale')
    """
    # gamma可选'scale'或'auto'
    #使用kernel='rbf'指定核函数类型,gamma='scale'表示1/(n_features * X.var())作为默认值
    #支持概率估计可添加probability=True参数,
    #‌惩罚系数C:控制分类错误的容忍度,较大值可能导致过拟合,较小值可能欠拟
    #核系数gamma‌:决定单个样本影响范围,较大值使决策边界更复杂
    """

    四、Sigmoid核函数                                                 公式‌:𝐾(𝑥,𝑦)=tanh⁡(𝛾𝑥⋅𝑦+𝑟) 特点‌:类似神经网络激活函数,实际应用较少,参数调优复杂‌。 适用场景‌:需模拟神经网络非线性特性的任务‌。 五、其他核函数 拉普拉斯核‌:基于绝对距离的核函数,适用于图像处理‌。 复合核函数‌:结合多种核函数特性,提升模型灵活性‌。 六、核函数选择建议

    优先尝试RBF核‌:因其普适性强,适合大多数非线性问题‌。

    线性核验证‌:若数据线性可分,优先使用线性核以提升效率‌。

    参数调优‌:通过交叉验证选择最优参数(如RBF的𝛾、多项式核的𝑑)‌。

    3.4 SVM入门代码实例

            使用scikit-learn自带的鸢尾花(Iris)数据集来预测莺尾花分类。

    import numpy as np
    import matplotlib.pyplot as plt
    from sklearn import svm, datasets
    from sklearn.model_selection import train_test_split
    from sklearn.metrics import accuracy_score

    # 加载鸢尾花数据集
    iris = datasets.load_iris()
    X = iris.data[:, :2] # 只使用前两个特征
    y = iris.target

    # 将数据集划分为训练集和测试集
    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)

    # 创建SVM分类器,直接使用线性核函数
    clf = svm.SVC(kernel='linear') # 使用线性核函数
    # 初始化RBF核SVM
    #clf = svm.SVC(kernel='rbf', C=1.0, gamma='scale')
    # 多项式核SVM模型
    #clf = svm.SVC(kernel='poly', degree=3, coef0=1.0)

    # 训练模型
    clf.fit(X_train, y_train)

    # 在测试集上进行预测
    y_pred = clf.predict(X_test)

    # 计算准确率
    accuracy = accuracy_score(y_test, y_pred)
    print(f"模型准确率: {accuracy:.2f}")

    # 绘制决策边界
    def plot_decision_boundary(X, y, model):
    h = .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.8)
    plt.scatter(X[:, 0], X[:, 1], c=y, edgecolors='k', marker='o')
    plt.xlabel('Sepal length')
    plt.ylabel('Sepal width')
    plt.title('SVM Decision Boundary')
    plt.show()

    plot_decision_boundary(X_train, y_train, clf)

    四、K-近邻(K-Nearest Neighbors, KNN)

            K 近邻算法(K-Nearest Neighbors,简称 KNN)是一种简单且常用的分类和回归算法。属于监督学习的一种,核心思想是通过计算 待分类样本 与训练集中各个样本的距离,找到距离最近的 K 个样本,然后根据这 K 个样本的类别或值来预测待分类样本的类别或值。

    4.1 KNN的基本概念

    4.1.1 KNN 的基本原理

    KNN 算法的基本原理可以概括为以下几个步骤:

  • 计算距离:计算待分类样本与训练集中每个样本的距离。常用的距离度量方法有欧氏距离、曼哈顿距离等。
  • 选择 K 个最近邻:根据计算出的距离,选择距离最近的 K 个样本。
  • 投票或平均:对于分类问题,K 个最近邻中出现次数最多的类别即为待分类样本的类别;对于回归问题,K 个最近邻的值的平均值即为待分类样本的值。
  • 4.1.2 KNN 的特点

    • 简单易理解:KNN 算法的原理非常简单,容易理解和实现。
    • 无需训练:KNN 是一种"懒惰学习"算法,不需要显式的训练过程,所有的计算都在预测时进行。
    • 对数据分布无假设:KNN 不对数据的分布做任何假设,适用于各种类型的数据。
    • 计算复杂度高:由于 KNN 需要在预测时计算所有样本的距离,当数据集较大时,计算复杂度会很高。

    4.1.3 KNN 算法的优缺点

    优点

    • 简单易用:KNN 算法的原理简单,易于理解和实现。
    • 无需训练:KNN 不需要显式的训练过程,所有的计算都在预测时进行。
    • 适用于多分类问题:KNN 可以轻松处理多分类问题。

    缺点

    • 计算复杂度高:KNN 需要在预测时计算所有样本的距离,当数据集较大时,计算复杂度会很高。
    • 对噪声敏感:KNN 对噪声数据较为敏感,噪声数据可能会影响预测结果。
    • 需要选择合适的 K 值:K 值的选择对模型的性能有很大影响,选择合适的 K 值是一个挑战。

    4.2 KNN的基本要素

    4.2.1 K值的确定(含代码)

            K 值的选择对模型的性能有重要影响。通常通过交叉验证或可视化方法选择最佳的 K 值。

  • ‌K值过小(如K=1)‌

    • 模型复杂度高,决策边界敏感,易受噪声和异常值影响,导致过拟合‌

    • 训练误差低但泛化误差大,分类结果可能不稳定‌

  • ‌K值过大(如K接近样本总数)‌

    • 模型过于简单,决策边界平滑,可能忽略局部特征,导致欠拟合‌

    • 极端情况下(K=N),模型直接预测训练集中多数类,失去分类意义‌

  • ‌K值适中‌

    • 平衡近似误差与估计误差,实现最优分类效果‌

    • 需通过实验确定,通常选择较小的奇数(如3、5、7)‌

  •         如下代码是采用鸢尾花数据集来确定K值的选择,可以由运行结果图看出k=11时,损失值最低,因此选择k=11是一个不错的选择。

    from sklearn.datasets import load_iris
    from sklearn.model_selection import cross_val_score
    import matplotlib.pyplot as plt
    from sklearn.neighbors import KNeighborsClassifier
    import numpy as np

    #加载鸢尾花数据集
    iris = load_iris()
    x = iris.data
    y = iris.target
    k_range = range(1, 31) # 设置循环次数
    k_error = []
    #循环,取k从1~30,查看误差效果
    for k in k_range:
    knn = KNeighborsClassifier(n_neighbors=k)
    #cv参数决定数据集划分比例,这里是按照5:1划分训练集和测试集
    scores = cross_val_score(knn, x, y, cv=6, scoring='accuracy')
    k_error.append(1 – scores.mean())

    #画图,x轴为k值,y值为误差值
    plt.figure(dpi=600)
    plt.plot(k_range, k_error)
    plt.xlabel('Value of K in KNN')
    plt.ylabel('Error')
    plt.show()

            运行结果:

    4.2.2 距离度量的选择

    1. 欧氏距离(Euclidean Distance)         原理‌:计算特征空间中两点间的直线距离,公式为 

    D = \\sqrt{\\sum_{i=1}^{n} (x_i - y_i)^2}

            特点‌:最常用,适用于连续数值型数据 且 各维度尺度相近的情况‌。         注意‌:需先对数据进行标准化或归一化,避免量纲差异影响结果‌。 2. 曼哈顿距离(Manhattan Distance)         原理‌:计算两点在各维度上的绝对差之和,公式为

    D = \\sum_{i=1}^{n} |x_i - y_i| 

            特点‌:对异常值更鲁棒,适用于高维稀疏数据(如文本分类)‌。 3. 余弦相似度(Cosine Similarity)         原理‌:通过向量夹角的余弦值衡量相似性,公式为 

    D = \\frac{\\sum x_i y_i}{\\sqrt{\\sum x_i^2} \\cdot \\sqrt{\\sum y_i^2}}

            特点‌:适用于高维稀疏数据(如文本、推荐系统),忽略向量长度差异‌。

    4.闵可夫斯基距离(Minkowski Distance)

             原理:对于两个 nn 维向量 x=(x1,x2,…,xn) 和 y=(y1,y2,…,yn),闵可夫斯基距离定义为:

    d(x,y) = \\left( \\sum_{i=1}^{n} |x_i - y_i|^p \\right)^{1/p}

            ‌p=1‌:曼哈顿距离(Manhattan Distance),即各维度绝对差之和。

            p=2‌:欧氏距离(Euclidean Distance),即平方差和的平方根。

            p→∞‌:切比雪夫距离(Chebyshev Distance),即各维度绝对差的最大值。

    d(x, y) = \\max_{i} \\left| x_i - y_i \\right| \\label{eq:chebyshev}

            使用KNN时选择不同距离算法的代码:

    from sklearn.neighbors import KNeighborsRegressor
    """
    metric='euclidean':欧氏距离,无参时默认
    metric='minkowski':闵可夫斯基距离
    metric='manhattan':曼哈顿距离
    示例如下:
    knn_reg = KNeighborsRegressor(
    n_neighbors=2,
    metric='minkowski',
    p=3 # 可调整p值(1:曼哈顿距离,2:欧氏距离,其他值:广义闵可夫斯基距离)
    )

    """
    # 使用曼哈顿距离
    knn_reg = KNeighborsRegressor(n_neighbors=5, metric='manhattan')

    4.2.3 分类决策原则

            KNN通过统计K个最近邻样本中占比最高的类别作为预测结果。

    4.2.4 使用网格搜索确定最佳值

    from sklearn.datasets import load_iris
    from sklearn.model_selection import train_test_split, GridSearchCV
    from sklearn.neighbors import KNeighborsClassifier
    from sklearn.preprocessing import StandardScaler
    '''
    # 加载数据并划分
    data = load_iris()
    X, y = data.data, data.target
    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)

    # 数据标准化
    scaler = StandardScaler()
    X_train = scaler.fit_transform(X_train)
    X_test = scaler.transform(X_test)
    '''
    # 定义参数网格
    param_grid = [
    {'n_neighbors': range(1, 15), 'metric': ['euclidean', 'manhattan']},
    {'n_neighbors': range(1, 15), 'metric': ['minkowski'], 'p': [1, 2, 3]}
    ]
    # 执行网格搜索
    knn = KNeighborsClassifier()
    grid_search = GridSearchCV(knn, param_grid, cv=5, scoring='accuracy', n_jobs=-1)
    grid_search.fit(X_train, y_train)

    # 输出结果
    print("最佳参数组合:", grid_search.best_params_)
    print("交叉验证最佳得分:", grid_search.best_score_)
    print("测试集得分:", grid_search.score(X_test, y_test))

    4.3 代码示例。

            使用 sklearn 中的 load_iris 函数加载经典的鸢尾花数据集。这个数据集包含 150 个样本,每个样本有 4 个特征,目标是将样本分为 3 类。

    import numpy as np
    import matplotlib.pyplot as plt
    from sklearn import datasets
    from sklearn.neighbors import KNeighborsClassifier
    from sklearn.metrics import accuracy_score
    from sklearn.model_selection import train_test_split, GridSearchCV
    # 加载Iris数据集
    iris = datasets.load_iris()
    X = iris.data[:, :2] # 只取前两个特征,便于可视化
    y = iris.target

    # 将数据集拆分为训练集和测试集
    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)

    param_grid = [
    {'n_neighbors': range(1, 15), 'metric': ['euclidean', 'manhattan']},
    {'n_neighbors': range(1, 15), 'metric': ['minkowski'], 'p': [1, 2, 3]}
    ]
    # 执行网格搜索,得出最佳参数
    knn = KNeighborsClassifier()
    grid_search = GridSearchCV(knn, param_grid, cv=5, scoring='accuracy', n_jobs=-1)
    grid_search.fit(X_train, y_train)
    # 输出结果
    print("最佳参数组合:", grid_search.best_params_)
    print("交叉验证最佳得分:", grid_search.best_score_)
    print("测试集得分:", grid_search.score(X_test, y_test))
    # 从网格搜索结果中提取最佳参数
    best_params = grid_search.best_params_
    # 创建KNN模型,设置最佳参数
    knn = KNeighborsClassifier(n_neighbors = best_params['n_neighbors'],
    metric = best_params['metric'],
    p = best_params['p'] if 'p' in best_params else None)

    # 训练模型
    knn.fit(X_train, y_train)

    # 在测试集上进行预测
    y_pred = knn.predict(X_test)

    # 计算准确率
    accuracy = accuracy_score(y_test, y_pred)
    print(f"KNN模型的准确率: {accuracy:.4f}")

    # 绘制决策边界和数据点
    h = .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))

    # 使用KNN模型预测网格中的每个点的类别
    Z = knn.predict(np.c_[xx.ravel(), yy.ravel()])
    Z = Z.reshape(xx.shape)

    # 绘制决策边界
    plt.contourf(xx, yy, Z, alpha=0.8)

    # 绘制训练数据点
    plt.scatter(X[:, 0], X[:, 1], c=y, edgecolors='k', marker='o', s=50)
    plt.title("KNN Demo")
    plt.xlabel("Feature 1")
    plt.ylabel("Feature 2")
    plt.show()

    五、决策树(Decision Tree)

            决策树(Decision Tree)是一种常用的机器学习算法,广泛应用于分类和回归问题。决策树通过树状结构来表示决策过程,每个内部节点代表一个特征或属性的测试,每个分支代表测试的结果,每个叶节点代表一个类别或值。

    5.1 决策树的基本概念

    • 节点(Node):树中的每个点称为节点。根节点是树的起点,内部节点是决策点,叶节点是最终的决策结果。
    • 分支(Branch):从一个节点到另一个节点的路径称为分支。
    • 分裂(Split):根据某个特征将数据集分成多个子集的过程。
    • 纯度(Purity):衡量一个子集中样本的类别是否一致。纯度越高,说明子集中的样本越相似。

            决策树的工作原理:

    决策树通过递归地将数据集分割成更小的子集来构建树结构。具体步骤如下:

  • 选择最佳特征:根据某种标准(如信息增益、基尼指数等)选择最佳特征进行分割。
  • 分割数据集:根据选定的特征将数据集分成多个子集。
  • 递归构建子树:对每个子集重复上述过程,直到满足停止条件(如所有样本属于同一类别、达到最大深度等)。
  • 生成叶节点:当满足停止条件时,生成叶节点并赋予类别或值。
  •         决策树的优缺点:

    优点

    • 易于理解和解释:决策树的结构直观,易于理解和解释。
    • 处理多种数据类型:可以处理数值型和类别型数据。
    • 不需要数据标准化:决策树不需要对数据进行标准化或归一化处理。

    缺点

    • 容易过拟合:决策树容易过拟合,特别是在数据集较小或树深度较大时。
    • 对噪声敏感:决策树对噪声数据较为敏感,可能导致模型性能下降。
    • 不稳定:数据的小变化可能导致生成完全不同的树。

    5.2 决策树的构建标准

    5.2.1 决策树构建标准方法

            决策树的构建标准是机器学习中用于选择最佳特征进行数据分割的核心依据,主要包括以下三类方法:

    1. 信息增益(Information Gain)

            用于分类问题,衡量特征对数据集纯度的提升程度。计算公式为:                         信息增益 = 原始数据集的熵 – 特征分割后的条件熵         其中熵(Entropy)反映数据的不确定性,计算公式为:H(Y) = -Σ p(y) log₂ p(y),其中p(y)为类别y的概率‌。熵值越大,数据越混乱。

            条件熵(Conditional Entropy)‌:在特征X条件下类别Y的不确定性,计算公式为: H(Y|X) = Σ p(x) H(Y|X=x),其中p(x)为 特征X取值的概率‌ 。表示特征划分后的子集熵的加权和‌。例如,在用户流失预测中,通过计算性别和活跃度对信息熵的减少量,选择增益更大的特征作为分割点‌。

            信息增益‌:定义为熵与条件熵的差值,即:IG(X) = H(Y) – H(Y|X)‌。值越大,说明特征X对分类的贡献越大。

            计算步骤:‌

  • ‌计算原始数据集的熵‌(如用户是否购买产品的熵)‌。
  • ‌按特征划分数据‌,计算每个子集的熵及条件熵‌。
  • ‌加权求和‌条件熵,并与原始熵相减得到信息增益‌。
  • ‌选择信息增益最大的特征‌作为当前节点的分割依据‌。
  •         优缺点及改进:

    • ‌优点‌:直观反映特征对分类的贡献‌。
    • ‌缺点‌:倾向选择取值多的特征(如ID编号)‌。
    • ‌改进‌:使用‌信息增益率‌(信息增益/特征自身熵)修正偏差‌
    2.信息增益率(Gain Ratio)

            是C4.5决策树算法中用于特征选择的核心指标,通过修正ID3算法的信息增益缺陷,解决其对多值特征的偏好问题。

            计算公式为:\\text{GainRatio}(S,A) = \\frac{\\text{Gain}(S,A)}{\\text{IV}(A)} 其中:

    • ‌信息增益‌(Gain):Gain(S,A)=H(S)−H(S∣A),H(S)为数据集熵,H(S∣A)为条件熵‌。
    • ‌内在信息‌(IV):\\text{IV}(A) = -\\sum_{v=1}^{n} \\frac{|S_v|}{|S|} \\log_2 \\frac{|S_v|}{|S|},衡量特征A的取值分布均匀性‌。
    3. 基尼指数(Gini Index)

           基尼指数 是决策树算法中用于衡量数据集纯度的核心指标,尤其在CART(分类与回归树)算法中作为默认的分裂准则,同样适用于分类问题。

            基尼指数 表示从数据集中随机抽取两个样本时,其类别标记不一致的概率。其取值范围为0到0.5,其中0表示完全纯净(所有样本属于同一类),0.5表示最不纯净(各类样本比例均等)。计算公式为:                         基尼指数 = 1 – Σ(pi²)(pi为类别i的样本占比)         基尼指数越小,表示数据越纯净。与信息增益相比,基尼指数计算更高效,但对多分类问题可能不如信息增益敏感‌。

            计算步骤

  • ‌计算节点基尼值‌:对当前节点数据集,统计各类别比例后代入公式。
  • ‌选择最优分裂特征‌:对每个特征的所有可能分裂点,计算分裂后的加权基尼指数(子节点基尼值按样本数加权平均),选择使加权基尼指数最小的特征和分裂点‌34。
  • ‌递归构建树‌:重复上述过程直至满足终止条件(如最大深度或样本数阈值)。
  • 4. 均方误差(MSE)

            均方误差(Mean Squared Error, MSE)是决策树回归任务中常用的划分标准,用于衡量预测值与真实值之间的差异。其数学表达式为:

    MSE = [ \\frac{1}{N} \\sum_{i=1}^{N} (y_i - \\hat{y}_i)^2 ]         

            其中,yi为真实值,y^i为预测值‌。MSE通过平方误差放大较大误差的影响,对异常值敏感,适用于需要惩罚大误差的场景‌。 用于回归问题,通过计算预测值与真实值的平方差来评估分割效果。MSE越小,表示回归树的预测效果越好‌。例如,预测房价时,选择使子集MSE最小的特征进行分割‌。

       

    其他补充标准:

    信息增益率‌:对信息增益的修正,避免偏向取值多的特征‌。

    剪枝策略‌:如预剪枝(限制树深度)和后剪枝(如CCP剪枝),用于防止过拟合‌。

    实际应用中需根据问题类型(分类/回归)和数据特性选择标准,并通过交叉验证优化模型参数‌。

    5.2.2 决策树的基本代码及调参

            1. 决策树函数使用

    from sklearn.datasets import load_iris
    from sklearn.model_selection import train_test_split
    from sklearn.tree import DecisionTreeClassifier

    iris = load_iris()
    X_train, X_test, y_train, y_test = train_test_split(iris.data, iris.target, test_size=0.2)
    clf = DecisionTreeClassifier(max_depth=3, criterion='gini')
    clf.fit(X_train, y_train)
    print("准确率:", clf.score(X_test, y_test)) # 输出测试集准确率

    """
    关键参数详解‌
    1.分裂标准(criterion)
    ‌gini‌(默认):基尼不纯度,计算节点的不纯度。
    ‌entropy‌:信息增益,基于信息熵划分节点。
    2.树结构控制
    ‌max_depth‌:限制树的最大深度,防止过拟合(如设为3)。
    ‌min_samples_split‌:节点继续分裂所需的最小样本数(默认2)。
    ‌min_samples_leaf‌:叶子节点的最小样本数,避免噪声影响(默认1)。
    3.其他参数
    ‌max_features‌:每节点考虑的最大特征数(如sqrt表示平方根)。
    ‌class_weight‌:处理类别不平衡问题(如balanced)。
    ‌4.splitter='best'‌:指定在每个节点选择最优划分特征的方式
    'best'表示全局搜索最优划分(计算所有可能划分点)
    替代选项是'random'(随机选择局部最优划分,可加速训练)
    """

            2. 决策树网格搜索调参

    from sklearn.datasets import load_iris
    from sklearn.model_selection import train_test_split, GridSearchCV
    from sklearn.tree import DecisionTreeClassifier

    # 数据加载与分割
    iris = load_iris()
    X_train, X_test, y_train, y_test = train_test_split(iris.data, iris.target, test_size=0.2, random_state=42)

    # 参数网格设置
    param_grid = {
    'criterion': ['gini', 'entropy'],
    'max_depth': [3, 5, 7, None],
    'min_samples_split': [2, 5, 10],
    'min_samples_leaf': [1, 2, 4],
    'max_features': ['sqrt', 'log2', None]
    }

    # 网格搜索优化
    clf = GridSearchCV(
    DecisionTreeClassifier(random_state=42),
    param_grid=param_grid,
    cv=5,
    scoring='accuracy'
    )
    clf.fit(X_train, y_train)

    # 输出最佳参数和准确率
    print("最佳参数:", clf.best_params_)
    print("训练集准确率:", clf.best_score_)
    print("测试集准确率:", clf.score(X_test, y_test))

    5.3 决策树的特征选择算法

            在scikit-learn的sklearn.tree模块中,决策树分类器DecisionTreeClassifier通过criterion参数支持ID3和CART算法的核心划分标准,而C4.5算法未被直接实现但可通过调整参数间接模拟。

    5.3.1 ID3算法

            是一种经典的决策树学习算法,由Ross Quinlan于1986年提出,其核心思想是通过信息熵和信息增益来选择最优特征进行数据划分‌。

    算法特点:

    • ‌优点‌:
      • 可解释性强,生成的决策树直观易理解‌。
      • 适用于离散型特征,计算效率较高‌。
    • ‌缺点‌:
      • 对连续值特征需离散化处理‌。
      • 容易过拟合,需通过剪枝优化‌。

    算法流程:

  • ‌输入‌:训练数据集D、特征集A、阈值ϵ。
  • ‌终止条件‌:
    • 所有实例属于同一类别Ck,返回单节点树‌。
    • 特征集为空A=∅,返回多数类标记的单节点树‌。
    • 最大信息增益<ϵ,返回多数类标记的单节点树‌。
  • ‌分裂过程‌:对每个特征值Ai​划分子集Di,递归构建子树‌
  • 算法代码:

    def ID3(data, features, target):
    if all_samples_same_class(data):
    return leaf_node(data.target)
    if no_features_left(features):
    return majority_vote(data.target)
    best_feature = max(features, key=lambda f: information_gain(data, f))
    tree = {best_feature: {}}
    for value in best_feature.values:
    subtree = ID3(data[data[best_feature] == value],
    features – {best_feature}, target)
    tree[best_feature][value] = subtree
    return tree

    5.3.2 C4.5算法

            C4.5是ID3算法的改进版本,由Ross Quinlan提出,主要解决ID3算法中 信息增益偏向多值属性 的问题‌。其核心改进在于引入‌信息增益率‌作为分裂标准,并通过处理连续属性和缺失值增强了实用性‌。

    算法优缺点

    • ‌优点‌:
      • 解决ID3的多值偏好问题‌
      • 支持连续属性和缺失值‌
    • ‌缺点‌:
      • 计算复杂度较高(需多次排序和二分)‌
      • 对噪声数据敏感

    5.3.3 CART(Classification and Regression Tree)

            是一种基于二叉树的决策树算法,由Breiman等人于1984年提出‌。其核心特点是通过‌二分递归分割‌技术构建二叉树结构,适用于分类和回归任务‌。

    ‌分裂标准‌

    • ‌分类任务‌:使用‌基尼系数(Gini Index)作为划分依据。
    • ‌回归任务‌:采用‌均方误差‌(MSE)最小化准则‌。

    优缺点分析

    • ‌优点‌:
      • 支持连续值和离散值特征‌。
      • 计算效率高(基尼指数避免log运算)‌。
    • ‌缺点‌:
      • 对噪声敏感,需严格剪枝‌。
      • 回归任务效果通常弱于分类任务‌

    三种算法总结:

    六、聚类算法

    6.1 聚类的基本概念

            聚类算法是一种无监督学习方法,用于将一组数据点 分成 若干个簇,使得同一个簇中的数据点彼此相似,而不同簇中的数据点则差异较大。聚类在数据挖掘、图像处理、市场分析、推荐系统等领域有广泛应用。

            聚类算法的划分:

  • ‌基于划分的方法‌

    • ‌K-means‌:通过迭代计算将数据划分为K个簇,以簇内平方和最小化为目标‌。
    • ‌K-medoids‌:用实际数据点(medoids)替代均值作为簇中心,对噪声更鲁棒‌。
  • ‌基于密度的方法‌

    • ‌DBSCAN‌:通过密度可达性识别任意形状簇,自动处理噪声点‌。
    • ‌OPTICS‌:改进版DBSCAN,适用于多密度数据集‌。
  • ‌基于层次的方法‌

    • ‌BIRCH‌:利用树结构高效处理大规模数据,支持增量聚类‌。
    • ‌凝聚/分裂层次聚类‌:通过自底向上或自顶向下构建层次结构‌。
  • ‌其他方法‌

    • ‌谱聚类‌:基于图论和相似性矩阵,适合复杂形状数据‌。
    • ‌高斯混合模型‌:基于概率分布建模,支持软聚类‌

  • 6.2 K-means‌算法

            K-means是一种基于距离的划分式聚类算法,其核心目标是通过 迭代优化 将数据划分为K个簇,使得每个数据点到所属簇中心的距离平方和最小化‌。算法通过以下两个关键步骤实现:

  • ‌分配步骤‌:将每个数据点分配到最近的簇中心
  • ‌更新步骤‌:重新计算每个簇的中心为簇内点的均值
  • 6.2.1 K-means算法原理

  • ‌初始化‌:随机选择K个初始质心(或使用K-means++优化初始化)‌
  • ‌迭代优化‌:
    • 计算所有点到质心的距离
    • 将点分配到最近质心的簇
    • 重新计算簇质心
  • ‌终止条件‌:质心变化小于阈值或达到最大迭代次数
  • ‌优势‌:

    • 计算效率高,适合大规模数据‌
    • 实现简单,易于理解‌
    • 收敛速度快‌

    ‌局限‌:

    • 需预先指定K值‌
    • 对初始质心敏感,可能陷入局部最优‌
    • 对噪声和异常值敏感‌
    • 仅适用于凸形簇‌

    6.2.2 K-means++的优化及代码

            K-means++通过概率分布策略选择初始质心:

    • 首质心随机选取
    • 后续质心按 距离平方概率分布 选取(距离现有质心越远的点被选中的概率越高) 该机制有效降低算法陷入局部最优的风险,提升聚类稳定性‌

             二者的比较:

            利用k-means算法可视化load_iris数据集:

    import matplotlib.pyplot as plt
    from sklearn.cluster import KMeans
    from sklearn.datasets import load_iris
    from sklearn.decomposition import PCA

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

    # K-means聚类与K-means++聚类
    kmeans = KMeans(n_clusters=3, random_state=42)
    #kmeans = KMeans(n_clusters=3, random_state=42, init='k-means++')
    clusters = kmeans.fit_predict(X)

    # PCA降维可视化
    pca = PCA(n_components=2)
    X_pca = pca.fit_transform(X)

    # 创建可视化图形
    plt.figure(figsize=(12, 5))

    # 真实分类可视化
    plt.subplot(1, 2, 1)
    plt.scatter(X_pca[:, 0], X_pca[:, 1], c=y, cmap='viridis', edgecolor='k')
    plt.title('Actual Classification')
    plt.xlabel('PCA Component 1')
    plt.ylabel('PCA Component 2')

    # K-means聚类结果可视化
    plt.subplot(1, 2, 2)
    plt.scatter(X_pca[:, 0], X_pca[:, 1], c=clusters, cmap='viridis', edgecolor='k')
    plt.scatter(kmeans.cluster_centers_[:, 0], kmeans.cluster_centers_[:, 1],
    s=300, c='red', marker='X', label='Centroids')
    plt.title('K-means Clustering')
    plt.xlabel('PCA Component 1')
    plt.ylabel('PCA Component 2')
    plt.legend()

    plt.tight_layout()
    plt.show()

    6.2.3 选择最佳簇数量(K值)及代码

            选择K-means算法中最佳的簇数量(K值)是聚类分析中的关键步骤,以下是几种常用的方法及其原理:

    肘部法则(Elbow Method)

            通过计算不同K值对应的聚类平方误差和(SSE),绘制K-SSE曲线。当SSE下降速度出现明显拐点(形如手肘)时,对应的K值即为最佳簇数。该方法基于簇内紧密性随K增加而改善的规律,但需注意拐点可能不明显的情况。代码函数:

    import matplotlib.pyplot as plt
    from sklearn.datasets import load_iris
    from sklearn.cluster import KMeans
    from sklearn.metrics import silhouette_score
    from sklearn.preprocessing import StandardScaler
    from sklearn.decomposition import PCA

    def elbow_method(X, max_k=8):
    sse = []
    for k in range(2, max_k + 1):
    kmeans = KMeans(n_clusters=k, init='k-means++', n_init=20, random_state=42)
    kmeans.fit(X)
    sse.append(kmeans.inertia_)

    plt.figure(figsize=(10, 4))
    plt.subplot(1, 2, 1)
    plt.plot(range(2, max_k + 1), sse, 'bo-')
    plt.xlabel('Number of clusters')
    plt.ylabel('SSE')
    plt.title('Elbow Method')

    轮廓系数(Silhouette Coefficient)

            计算每个样本的轮廓系数(取值范围[-1,1]),反映样本与同簇和其他簇的相似性。整体轮廓系数越接近1,聚类效果越好。通过比较不同K值的平均轮廓系数,选择最大值对应的K。代码函数如下:

    import matplotlib.pyplot as plt
    from sklearn.datasets import load_iris
    from sklearn.cluster import KMeans
    from sklearn.metrics import silhouette_score
    from sklearn.preprocessing import StandardScaler
    from sklearn.decomposition import PCA

    def silhouette_analysis(X, max_k=8):
    silhouette_scores = []
    for k in range(2, max_k + 1):
    kmeans = KMeans(n_clusters=k, init='k-means++', n_init=20, random_state=42)
    labels = kmeans.fit_predict(X)
    silhouette_scores.append(silhouette_score(X, labels))

    plt.subplot(1, 2, 2)
    plt.plot(range(2, max_k + 1), silhouette_scores, 'ro-')
    plt.xlabel('Number of clusters')
    plt.ylabel('Silhouette Score')
    plt.title('Silhouette Analysis')
    plt.tight_layout()
    plt.show()

    间隔统计量(Gap Statistic)

            比较实际数据与参考分布(如均匀分布)的聚类效果差异。Gap值最大时对应的K值最优,适用于数据分布复杂或肘部法则失效的场景。

    CH指数(Calinski-Harabasz Index)

            通过簇间离散度与簇内离散度的比值评估聚类质量,值越大表示簇间分离度越高。通常选择CH指数峰值对应的K值。

    6.2.4 K-means聚类优化完整代码

            使用鸢尾花数据集,利用K-means++进行聚类,同时使用肘部法则、轮廓系数来选择最佳K值。

    import matplotlib.pyplot as plt
    from sklearn.datasets import load_iris
    from sklearn.cluster import KMeans
    from sklearn.metrics import silhouette_score
    from sklearn.preprocessing import StandardScaler
    from sklearn.decomposition import PCA

    def load_and_preprocess():
    iris = load_iris()
    X = StandardScaler().fit_transform(iris.data)
    return X, iris.target

    def elbow_method(X, max_k=8):
    sse = []
    for k in range(2, max_k + 1):
    kmeans = KMeans(n_clusters=k, init='k-means++', n_init=20, random_state=42)
    kmeans.fit(X)
    sse.append(kmeans.inertia_)

    plt.figure(figsize=(10, 4))
    plt.subplot(1, 2, 1)
    plt.plot(range(2, max_k + 1), sse, 'bo-')
    plt.xlabel('Number of clusters')
    plt.ylabel('SSE')
    plt.title('Elbow Method')

    def silhouette_analysis(X, max_k=8):
    silhouette_scores = []
    for k in range(2, max_k + 1):
    kmeans = KMeans(n_clusters=k, init='k-means++', n_init=20, random_state=42)
    labels = kmeans.fit_predict(X)
    silhouette_scores.append(silhouette_score(X, labels))

    plt.subplot(1, 2, 2)
    plt.plot(range(2, max_k + 1), silhouette_scores, 'ro-')
    plt.xlabel('Number of clusters')
    plt.ylabel('Silhouette Score')
    plt.title('Silhouette Analysis')
    plt.tight_layout()
    plt.show()

    def visualize_clusters(X, y, optimal_k=3):
    pca = PCA(n_components=2)
    X_pca = pca.fit_transform(X)

    kmeans = KMeans(n_clusters=optimal_k, init='k-means++', n_init=20, random_state=42)
    clusters = kmeans.fit_predict(X)

    plt.figure(figsize=(12, 5))
    plt.subplot(1, 2, 1)
    plt.scatter(X_pca[:, 0], X_pca[:, 1], c=y, cmap='viridis')
    plt.title('Actual Classes')

    plt.subplot(1, 2, 2)
    plt.scatter(X_pca[:, 0], X_pca[:, 1], c=clusters, cmap='viridis')
    plt.scatter(kmeans.cluster_centers_[:, 0], kmeans.cluster_centers_[:, 1],
    s=200, c='red', marker='X')
    plt.title(f'K-means Clustering (K={optimal_k})')
    plt.tight_layout()
    plt.show()

    if __name__ == "__main__":
    X, y = load_and_preprocess()
    elbow_method(X)
    silhouette_analysis(X)
    visualize_clusters(X, y)

    6.3‌ DBSCAN算法

            DBSCAN(Density-Based Spatial Clustering of Applications with Noise)算法是一种基于密度的无监督聚类算法,其核心思想是通过数据点的局部密度来识别任意形状的簇,并将低密度区域视为噪声‌ ,它将簇定义为密度相连的点的最大集合,能够把具有足够高密度的区域划分为簇,并可在带噪声的数据集空间中发现任意形状的类别簇。

            和K-Means,BIRCH这些一般只适用于凸样本集的聚类相比,DBSCAN既可以适用于凸样本集,也可以适用于非凸样本集。

    6.3.1 DBSCAN算法原理

    核心概念:

  • ‌核心点‌:若某点的ε邻域内包含至少minPts个点(包括自身),则为核心点‌。
  • ‌密度可达‌:若点A是核心点,且点B在其ε邻域内,则B从A直接密度可达;通过传递性可定义更广泛的密度可达关系‌。
  • ‌密度相连‌:若两点A和B均从某核心点O密度可达,则A与B密度相连‌。
  • ‌噪声点‌:既非核心点,也不属于任何核心点邻域的点‌。
  • 算法流程:

  • ‌参数设置‌:需指定邻域半径ε和最小邻域点数minPts‌。
  • ‌聚类过程‌:
    • 遍历未访问点,若为核心点则扩展聚类,合并密度可达的点‌。
    • 非核心点若未被任何簇包含,则标记为噪声‌。
  • ‌输出结果‌:生成簇和噪声点集合‌。
  • 参数选择建议

    • ‌ε‌:可通过 k 距离图(k=minPts-1)选择距离突变点作为阈值‌。
    • ‌minPts‌:通常取数据维度+1,或通过实验调整‌。

    优缺点分析

    • ‌优势‌:
      • 无需预设簇数,可发现任意形状簇‌。
      • 对噪声鲁棒,能有效识别离群点‌。
    • ‌局限‌:
      • 对高维数据或密度差异大的数据集效果较差‌。
      • 参数选择敏感,需结合领域知识调整‌

    6.3.2 sklearn的DBSCAN聚类器

    from sklearn.cluster import DBSCAN
    dbscan = DBSCAN(eps=optimal_eps, min_samples=5)

    """
    eps (float):邻域半径,默认0.5
    min_samples (int):核心点所需的最小邻域点数,默认5
    metric (str/callable):距离度量方式,默认'euclidean'
    metric_params (dict):距离度量额外参数,默认None
    algorithm (str):邻域搜索算法('auto','ball_tree','kd_tree','brute'),默认'auto'
    ‌leaf_size (int):树类算法的叶子节点大小,默认30
    p (float):Minkowski距离的幂参数,默认2(即欧式距离)
    ‌n_jobs (int):并行计算线程数,默认None(单线程)
    实际使用时通常只需调整eps和min_samples,其他参数保持默认即可应对大多数场景。

    ‌eps选择‌:可通过k距离图(k=min_samples-1)观察拐点
    ‌min_samples‌:高维数据需增大该值,小数据集可减小,min_samples ≥ 数据维度 + 1(二维数据建议4-5)
    """
    #eps参数优化,‌k-距离图法
    from sklearn.neighbors import NearestNeighbors
    import matplotlib.pyplot as plt

    neighbors = NearestNeighbors(n_neighbors=4)
    distances, _ = neighbors.fit(X).kneighbors()
    plt.plot(np.sort(distances[:, -1]))
    plt.xlabel('Points')
    plt.ylabel('4th NN Distance')

    6.3.3 对DBSCAN聚类器的优化参数代码

            如下代码使用k-距离图法优化iris数据集DBSCAN参数:

  • 数据预处理:标准化iris数据集消除量纲影响
  • k-距离图生成:计算每个点到第4个最近邻的距离并可视化
  • 拐点检测:通过梯度变化自动识别最优eps值
  • 参数验证:使用推荐参数执行DBSCAN并输出聚类结果
  • import numpy as np
    import matplotlib.pyplot as plt
    from sklearn.datasets import load_iris
    from sklearn.neighbors import NearestNeighbors
    from sklearn.preprocessing import StandardScaler
    from sklearn.cluster import DBSCAN
    # 加载并预处理数据
    iris = load_iris()
    X = StandardScaler().fit_transform(iris.data)
    # k-距离图分析
    def plot_k_distance(X, k=4):
    neighbors = NearestNeighbors(n_neighbors=k)
    neighbors_fit = neighbors.fit(X)
    distances, _ = neighbors_fit.kneighbors(X)
    distances = np.sort(distances[:, -1])
    plt.figure(figsize=(10, 6))
    plt.plot(distances)
    plt.xlabel('Points sorted by distance')
    plt.ylabel(f'{k}-NN distance')
    plt.grid(True)
    plt.title('k-Distance Graph for eps Selection')
    plt.legend()
    plt.show()
    return distances
    # 自动寻找拐点
    def find_elbow(distances, sensitivity=0.1):
    gradients = np.gradient(distances)
    elbow_idx = np.argmax(gradients > sensitivity)
    return distances[elbow_idx]

    # 执行优化流程
    distances = plot_k_distance(X)
    optimal_eps = find_elbow(distances)
    print(f'Recommended eps value: {optimal_eps:.3f}')
    # 验证优化结果
    dbscan = DBSCAN(eps=optimal_eps, min_samples=5)
    labels = dbscan.fit_predict(X)
    n_clusters = len(set(labels)) – (1 if -1 in labels else 0)
    print(f'Number of clusters found: {n_clusters}')

    6.4 高斯混合模型(Gaussian Mixture Model, GMM)

            GMM是一种基于概率模型的聚类方法,通过多个高斯分布的线性组合来建模复杂数据分布‌。与K-means等硬聚类方法不同,GMM采用软聚类方式,允许数据点以概率形式属于多个簇‌。

    6.4.1 GMM算法原理

            高斯混合模型(Gaussian Mixture Model, GMM)通过多高斯分布的线性组合实现对复杂数据分布的建模。其GMM的概率密度函数为:

    p(x|\\theta) = \\sum_{k=1}^{K} \\pi_k \\mathcal{N}(x|\\mu_k, \\Sigma_k) \\label{eq:gmm}

    其中:

    • x 是待建模的多维数据点。
    • K 是混合成分的数量,即潜在高斯簇的个数。
    • \\pi _{k} 是第 k 个高斯分布的混合权重,满足 \\sum_{K-1}^{K}\\pi _{k}= 1和 \\pi _{k}> 0
    • \\mathbb{N}\\left ( X|\\mu _{k},\\sum _{k} \\right )表示第 k 个高斯分布,其均值向量为 \\mu _{k}​,协方差矩阵为 \\sum _{k}​。

    GMM通过EM算法实现参数估计,其核心步骤可分为以下三个阶段:

    1. 模型初始化

    • 随机选择K个高斯分量的初始参数(均值μ、协方差Σ、混合权重π)
    • 或采用K-means预聚类结果作为初始参数‌
    • 初始化时需确保协方差矩阵正定,混合权重满足归一化条件

    2. EM算法迭代过程

    ‌E步(期望计算)‌:         计算每个数据点x_{_{_{_{i}}}}属于第k个分量的后验概率y_{i=k}

    ‌M步(参数更新)‌:

    • 更新混合权重
    • 更新均值
    • 更新协方差

    3. 收敛判断

    • 当对数似然函数变化量小于阈值(如1e-4)时停止迭代
    • 或达到预设最大迭代次数时终止‌
    • 最终输出各分量的参数估计结果

    GMM优缺点

    优点:

  • ‌灵活性高‌:不需要预先指定聚类的数量,可以处理任意形状的聚类。
  • ‌概率化分类‌:提供数据点属于每个簇的概率,而不仅仅是硬分类。
  • ‌模型表达能力‌:能够捕捉数据分布的方差差异和协方差结构,比K-means等简单模型更具表达能力。
  • 缺点:

  • ‌计算复杂度高‌:特别是处理大规模数据集时,计算成本较高。
  • ‌对初始参数敏感‌:不同的初始参数可能导致不同的聚类结果。
  • ‌对异常值敏感‌:数据集中存在噪声或异常值时,模型性能可能受到影响。
  • ‌需要预设簇数‌:虽然比K-means灵活,但仍需预先估计或指定高斯分量的数量。
  • 6.4.2 sklearn的GaussianMixture聚类器

    from sklearn.mixture import GaussianMixture
    gmm = GaussianMixture(
    n_components=3,
    covariance_type='full',
    init_params='kmeans',
    n_init=20,
    reg_covar=1e-6,
    max_iter=500,
    random_state=42,
    verbose=1,
    tol=1e-4
    )
    """
    1.n_components = 3
    ‌ 功能‌:指定混合模型中高斯分布的数量
    可通过BIC/AIC准则自动选择最优值
    2. covariance_type='full'
    ‌可选值‌:
    'full':完全协方差矩阵(各分量有独立的全协方差)
    'tied':所有分量共享相同协方差矩阵
    'diag':对角协方差矩阵(特征间独立)
    'spherical':球形协方差(各维度方差相同)
    3.random_state=42
    ‌作用‌:控制随机数生成器的种子
    ‌重要性‌:
    确保EM算法初始化可复现,避免每次运行结果随机波动,42是机器学习中常用的默认种子值
    4.init_params='kmeans':采用K-means初始化,相比随机初始化更稳定
    5.n_init=20:增加初始化次数,降低陷入局部最优的概率
    6.reg_covar=1e-6:添加微小正则项确保数值稳定性
    7.max_iter=500:增大迭代次数保证复杂情况下的收敛
    8.tol:控制收敛阈值(默认1e-3)
    9.verbose = 1:输出训练过程信息
    """
    # BIC准则自动选择最优K值
    def find_optimal_k(X, max_k=8):
    bics = []
    for k in range(1, max_k+1):
    gmm = GaussianMixture(n_components=k, covariance_type='full', n_init=10)
    gmm.fit(X)
    bics.append(gmm.bic(X))
    return np.argmin(bics) + 1 # 返回BIC最小的K值

    6.4.3 对GaussianMixture聚类器参数优化代码

            使用高斯混合模型(GMM)对鸢尾花(Iris)数据集进行聚类的完整实。

    import numpy as np
    import matplotlib.pyplot as plt
    from sklearn import datasets
    from sklearn.mixture import GaussianMixture
    from sklearn.metrics import silhouette_score
    from sklearn.decomposition import PCA

    # 自动选择最优K值
    def find_optimal_k(X, max_k=8):
    bics = []
    for k in range(1, max_k+1):
    gmm = GaussianMixture(n_components=k, covariance_type='full', n_init=10)
    gmm.fit(X)
    bics.append(gmm.bic(X))
    return np.argmin(bics) + 1 # 返回BIC最小的K值

    # 加载数据
    iris = datasets.load_iris()
    X = iris.data
    y_true = iris.target

    optimal_k = find_optimal_k(X)
    print(f"Optimal number of components: {optimal_k}")

    # 优化后的GMM模型
    optimized_gmm = GaussianMixture(
    n_components=optimal_k,
    covariance_type='full',
    init_params='kmeans',
    n_init=20,
    reg_covar=1e-6,
    max_iter=500,
    random_state=42
    )
    optimized_gmm.fit(X)
    y_pred = optimized_gmm.predict(X)
    probs = optimized_gmm.predict_proba(X)

    # 评估指标
    print(f"BIC: {optimized_gmm.bic(X):.2f}")
    print(f"Silhouette Score: {silhouette_score(X, y_pred):.2f}")
    print(f"Average Confidence: {np.mean(np.max(probs, axis=1)):.2%}")

    # 可视化降维结果
    pca = PCA(n_components=2)
    X_pca = pca.fit_transform(X)

    plt.figure(figsize=(12,6))
    plt.scatter(X_pca[:,0], X_pca[:,1], c=y_pred, cmap='viridis', s=50, alpha=0.6)
    plt.title('Optimized GMM Clustering (PCA Projection)')
    plt.xlabel('Principal Component 1')
    plt.ylabel('Principal Component 2')
    plt.colorbar(label='Cluster')
    plt.grid(True)
    plt.show()

    七、集成学习(Ensemble Learning)

    7.1 集成学习基本概念        

            集成学习(Ensemble Learning)是一种通过结合多个模型的预测结果来提高整体性能的技术。核心思想是"三个臭皮匠,顶个诸葛亮",即通过多个弱学习器的组合,可以构建一个强学习器。主要目标是通过组合多个模型来提高预测的准确性和鲁棒性。

    常见的集成学习方法包括:

  • Bagging:通过自助采样法(Bootstrap Sampling)生成多个训练集,然后分别训练多个模型,最后通过投票或平均的方式得到最终结果。
  • Boosting:通过迭代的方式训练多个模型,每个模型都试图纠正前一个模型的错误,最终通过加权投票的方式得到结果。
  • Stacking:通过训练多个不同的模型,然后将这些模型的输出作为新的特征,再训练一个元模型(Meta-Model)来进行最终的预测。
  • 7.2 Bagging(Bootstrap Aggregating)

            Bagging 的目标是通过减少模型的方差来提高性能,适用于高方差、易过拟合的模型。它通过以下步骤实现:

    • 数据集重采样:对训练数据集进行多次有放回的随机采样(bootstrap),每次采样得到一个子数据集。
    • 训练多个模型:在每个子数据集上训练一个基学习器(通常是相同类型的模型)。
    • 结果合并:将多个基学习器的结果进行合并,通常是通过投票(分类问题)或平均(回归问题)。

            步骤如图所示:

    典型算法:

    • 随机森林(Random Forest):随机森林是 Bagging 的经典实现,它通过构建多个决策树,每棵树在训练时随机选择特征,从而减少过拟合的风险。

    优势:

    • 可以有效减少方差,提高模型稳定性。
    • 适用于高方差的模型,如决策树。

    缺点:

    • 训练过程时间较长,因为需要训练多个模型。
    • 结果难以解释,因为没有单一的模型。

    7.2.1 随机森林

            随机森林是一种基于Bagging策略的集成学习方法,通过构建多棵决策树并集成其预测结果(分类问题投票/回归问题平均)来提升模型性能‌。其名称来源于两个关键特性:

    • ‌随机性‌:每棵树通过Bootstrap采样(有放回抽样)和随机特征选择构建
    • ‌森林‌:由大量决策树组成的模型集合‌

    算法原理

  • ‌双重随机化机制‌

    • 样本随机:每棵树使用原始数据集的63.2%样本(Bootstrap采样)‌
    • 特征随机:每次分裂仅考虑√p(p为总特征数)个随机特征‌
  • ‌决策树构建‌ 每棵树独立训练,分裂时使用基尼指数或信息增益等指标选择最优特征‌。

  • ‌预测集成‌

    • 分类:多数投票(Majority Voting)
    • 回归:简单平均(Simple Averaging)‌
  • 7.2.2 sklearn的RandomForestClassifier

    from sklearn.ensemble import RandomForestClassifier
    # 创建随机森林分类器
    rf_classifier = RandomForestClassifier(
    n_estimators=100,
    random_state=42,
    max_depth=3
    )
    """
    核心框架参数:
    1.n_estimators‌
    森林中决策树的数量,默认值为100。增加树的数量通常会提高模型性能,但计算成本也会增加。当超过一定数量后,模型性能趋于稳定。
    2.random_state‌
    控制随机数生成器的种子,用于保证结果可复现性。设定固定值(如42)可使每次运行结果一致。
    3.max_depth‌
    单棵决策树的最大深度。设为None时节点会持续分裂直到所有叶子纯净或包含少于min_samples_split个样本。限制深度可防止过拟合,建议范围10-100。
    树分裂控制参数
    4.criterion‌
    节点分裂质量的衡量标准,可选"gini"(基尼系数)或"entropy"(信息增益),默认"gini"。
    5.min_samples_split‌
    节点继续分裂所需的最小样本数,可为整数或比例。样本量少时建议保持默认值2,大数据集需调高。
    6.min_samples_leaf‌
    叶节点所需的最小样本数,可设为整数或比例。增大该值能平滑模型,尤其对回归任务有效。
    7.特征选择参数
    max_features‌
    寻找最佳分裂时考虑的特征数量,可选"auto"(sqrt(n_features))、"log2"、整数或浮点数。控制特征随机性,是防止过拟合的关键参数。
    其他重要参数
    8.bootstrap‌
    是否使用有放回抽样构建树,默认True。若为False则使用全部样本。
    9.oob_score‌
    是否使用袋外样本评估模型泛化能力,默认False。设为True可获取额外性能评估。
    10.n_jobs‌
    并行运行的CPU核数,-1表示使用所有可用核心。
    完整参数列表还包括:
    min_weight_fraction_leaf‌(叶节点最小权重和)
    max_leaf_nodes‌(最大叶节点数)
    min_impurity_decrease‌(分裂最小纯度增益)
    class_weight‌(类别权重)等。
    调参时建议优先关注n_estimators、max_features和max_depth的组合优化,再调整其他参数。对于具体任务(如乳腺癌分类),可通过网格搜索(GridSearchCV)系统化调参。
    """

    7.2.3 对RandomForestClassifier代码的参数优化

    代码实现特点:

  • 采用GridSearchCV实现自动化参数调优,覆盖n_estimators、max_depth等关键参数
  • 输出最优参数组合及测试集准确率,包含完整的分类评估报告
  • 可视化特征重要性排序和混淆矩阵,增强结果可解释性
  • 包含标准化的项目依赖配置,确保环境可复现
  • from sklearn.datasets import load_iris
    from sklearn.ensemble import RandomForestClassifier
    from sklearn.model_selection import train_test_split, GridSearchCV
    from sklearn.metrics import classification_report, confusion_matrix
    import matplotlib.pyplot as plt
    import seaborn as sns
    import pandas as pd
    import numpy as np

    # 数据加载与预处理
    iris = load_iris()
    X = pd.DataFrame(iris.data, columns=iris.feature_names)
    y = iris.target
    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)

    # 参数网格设置
    param_grid = {
    'n_estimators': [50, 100, 200],
    'max_depth': [3, 5, None],
    'min_samples_split': [2, 5, 10],
    'max_features': ['sqrt', 'log2']
    }

    # 网格搜索优化
    rf = RandomForestClassifier(random_state=42)
    grid_search = GridSearchCV(estimator=rf, param_grid=param_grid, cv=5, n_jobs=-1)
    grid_search.fit(X_train, y_train)
    # 最优模型评估
    best_rf = grid_search.best_estimator_ # 直接获取优化后的模型
    y_pred = best_rf.predict(X_test) # 直接用于预测
    print(f"最优参数: {grid_search.best_params_}")
    print(f"测试集准确率: {best_rf.score(X_test, y_test):.4f}")
    print("\\n分类报告:")
    print(classification_report(y_test, y_pred))

    # 特征重要性可视化
    features = X.columns
    importances = best_rf.feature_importances_
    indices = np.argsort(importances)[::-1]

    plt.figure(figsize=(10,6))
    plt.title("特征重要性排序", fontsize=14)
    sns.barplot(x=importances[indices],
    y=features[indices],
    hue=features[indices], # 将y变量赋值给hue
    palette="viridis",
    legend=False) # 禁用图例
    plt.xlabel("重要性得分")
    plt.rcParams['font.sans-serif'] = ['SimHei'] # 指定中文字体
    plt.rcParams['axes.unicode_minus'] = False # 解决负号显示
    plt.show()
    # 混淆矩阵可视化
    cm = confusion_matrix(y_test, y_pred)
    plt.figure(figsize=(8,6))
    sns.heatmap(cm, annot=True, fmt='d', cmap='Blues',
    xticklabels=iris.target_names,
    yticklabels=iris.target_names)
    plt.title('混淆矩阵', fontsize=14)
    plt.ylabel('真实标签')
    plt.xlabel('预测标签')
    plt.rcParams['font.sans-serif'] = ['SimHei'] # 指定中文字体
    plt.rcParams['axes.unicode_minus'] = False # 解决负号显示
    plt.show()

    7.3 Boosting

            Boosting 的目标是通过减少模型的偏差来提高性能,适用于弱学习器。Boosting 的核心思想通过迭代训练多个弱分类器,让后续模型专注于前序模型分类错误的样本,通过加权投票或残差拟合提升整体性能‌,并逐步调整样本权重和模型权重,最终组合成强分类器‌。

    Boosting 通过以下步骤实现:

    • 序列化训练:模型是一个接一个地训练的,每一轮训练都会根据前一轮的错误进行调整。
    • 加权投票:最终的预测是所有弱学习器预测的加权和,其中错误分类的样本会被赋予更高的权重。
    • 合并模型:每个模型的权重是根据其在训练过程中的表现来确定的。

    如图所示:

    典型算法:

    • AdaBoost(Adaptive Boosting):AdaBoost 通过改变样本的权重,使得每个后续分类器更加关注前一轮错误分类的样本。
    • 梯度提升树(Gradient Boosting Trees, GBT):GBT 通过迭代优化目标函数,逐步减少偏差。
    • XGBoost(Extreme Gradient Boosting):XGBoost 是一种高效的梯度提升算法,广泛应用于数据科学竞赛中,具有较强的性能和优化。
    • LightGBM(Light Gradient Boosting Machine):LightGBM 是一种基于梯度提升树的框架,相较于 XGBoost,具有更快的训练速度和更低的内存使用。

    优势:

    • 适用于偏差较大的模型,能有效提高预测准确性。
    • 强大的性能,在许多实际应用中表现优异。

    缺点:

    • 对噪声数据比较敏感,容易导致过拟合。
    • 训练过程较慢,特别是在数据量较大的情况下。

    7.3.1 AdaBoost(Adaptive Boosting)

            AdaBoost(Adaptive Boosting)是一种通过迭代组合 弱分类器构建强分类器的集成学习算法,其核心机制包括:

  • ‌样本权重动态调整‌:每轮迭代后,错误分类样本的权重会指数级增加(正确分类样本权重降低),迫使后续模型更关注 难样本‌。
  • ‌弱分类器加权组合‌:最终模型通过加权投票(分类)或加权平均(回归)组合所有弱分类器,权重由分类器错误率决定。
  • 算法步骤详解

  • ‌初始化‌ 所有样本初始权重相同(wi(1)=1/N),其中N为样本总数‌。

  • ‌迭代训练‌

    • 训练弱分类器ht,计算其加权错误率ϵt
    • 根据错误率计算分类器权重αt
    • 更新样本权重
  • ‌组合输出‌

  • 特点:

    • 自适应调整样本权重,重点关注错误样本‌
    • 提供分类器AdaBoostClassifier和回归器AdaBoostRegressor
    • 关键参数:n_estimators(弱学习器数量)、learning_rate(学习率)‌

    优势‌:

    • 对高偏差模型提升显著
    • 可处理类别不平衡数据(通过权重调整)‌

    局限‌:

    • 对异常值敏感(错误分类样本权重持续放大)
    • 需谨慎选择弱分类器(如决策树桩效果较好)‌

    7.3.2 sklearn中的AdaBoost

            在sklearn中的AdaBoost有基础 分类与回归 两中接口:

  • ‌分类器‌:AdaBoostClassifier,默认使用决策树作为基学习器,支持SAMME和SAMME.R两种算法。
  • ‌回归器‌:AdaBoostRegressor,支持线性、平方和指数三种损失函数。
  • from sklearn.ensemble import AdaBoostClassifier, AdaBoostRegressor
    clf = AdaBoostClassifier(n_estimators=50) # 分类
    reg = AdaBoostRegressor(loss='square') # 回归

    """
    核心参数:
    estimator弱学习器类型,默认为决策树(分类用DecisionTreeClassifier(max_depth=1))通用
    n_estimators弱学习器最大数量,影响模型复杂度与训练时间 通用
    learning_rate学习率(0-1),控制权重更新幅度,需与n_estimators权衡(通常取0.1-1)通用
    algorithm分类专用:SAMME(离散型)或SAMME.R(实值型,需支持概率预测)仅分类
    loss回归专用:误差计算方式(linear/square/exponential) 仅回归
    random_state随机种子,保证结果可复现 通用
    """

    7.3.3 AdaBoostClassifier和AdaBoostRegressor的参数优化

            以下是基于鸢尾花数据集的AdaBoostClassifier和AdaBoostRegressor参数调优实现代码,结合网格搜索和交叉验证技术进行超参数优化。

    from sklearn.datasets import load_iris
    from sklearn.ensemble import AdaBoostClassifier, AdaBoostRegressor
    from sklearn.tree import DecisionTreeClassifier, DecisionTreeRegressor
    from sklearn.model_selection import GridSearchCV, train_test_split
    from sklearn.metrics import accuracy_score, mean_squared_error

    # 加载鸢尾花数据集
    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)

    # AdaBoostClassifier调参
    abc = AdaBoostClassifier(estimator=DecisionTreeClassifier(max_depth=1))
    param_grid_abc = {
    'n_estimators': [50, 100, 200],
    'learning_rate': [0.01, 0.1, 1.0],
    'base_estimator__max_depth': [1, 2, 3],
    'algorithm': ['SAMME', 'SAMME.R']
    }
    grid_abc = GridSearchCV(abc, param_grid_abc, cv=5, scoring='accuracy')
    grid_abc.fit(X_train, y_train)

    # 回归任务参数调优(使用花瓣宽度作为目标变量)
    y_reg = iris.data[:, 3] # 花瓣宽度作为回归目标
    X_train_reg, X_test_reg, y_train_reg, y_test_reg = train_test_split(
    X, y_reg, test_size=0.2, random_state=42)

    # AdaBoostRegressor调参
    abr = AdaBoostRegressor(estimator=DecisionTreeRegressor(max_depth=3))
    param_grid_abr = {
    'n_estimators': [50, 100, 200],
    'learning_rate': [0.01, 0.1, 1.0],
    'loss': ['linear', 'square', 'exponential'],
    'base_estimator__max_depth': [1, 2, 3]
    }
    grid_abr = GridSearchCV(abr, param_grid_abr, cv=5, scoring='neg_mean_squared_error')
    grid_abr.fit(X_train_reg, y_train_reg)

    # 输出最佳参数和评估结果
    print("AdaBoostClassifier最佳参数:", grid_abc.best_params_)
    print("分类准确率:", accuracy_score(y_test, grid_abc.predict(X_test)))
    print("\\nAdaBoostRegressor最佳参数:", grid_abr.best_params_)
    print("回归MSE:", mean_squared_error(y_test_reg, grid_abr.predict(X_test_reg)))

    7.4 Stacking(Stacked Generalization)

            Stacking 是一种通过训练不同种类的模型并组合它们的预测 来提高整体预测准确度的方法。其核心思想是:

    • 第一层(基学习器):训练多个不同类型的基学习器(例如,决策树、SVM、KNN 等)来对数据进行预测。
    • 第二层(元学习器):将第一层学习器的预测结果作为输入,训练一个元学习器(通常是逻辑回归、线性回归等),来做最终的预测。

    如图所示:

    优势:

    • 可以使用不同类型的基学习器,捕捉数据中不同的模式。
    • 理论上可以结合多种模型的优势,达到更强的预测能力。

    缺点:

    • 训练过程复杂,需要对多个模型进行训练,且模型之间的结合方式也需要精心设计。
    • 比其他集成方法如 Bagging 和 Boosting 更复杂,且容易过拟合。

            Stacking集成学习在鸢尾花分类任务上的应用:

    from sklearn.ensemble import StackingClassifier
    from sklearn.linear_model import LogisticRegression
    from sklearn.tree import DecisionTreeClassifier
    from sklearn.svm import SVC
    from sklearn.datasets import load_iris
    from sklearn.model_selection import train_test_split, cross_val_score, GridSearchCV
    from sklearn.metrics import accuracy_score, classification_report, confusion_matrix
    import numpy as np

    # 1. 数据准备阶段 ==============================================
    # 加载标准鸢尾花数据集(3类,4个特征)
    iris = load_iris()
    X, y = iris.data, iris.target # X: (150,4), y: (150,)

    # 划分训练集和测试集(70%训练,30%测试)
    # random_state保证可复现性,stratify保持类别比例
    X_train, X_test, y_train, y_test = train_test_split(
    X, y,
    test_size=0.3,
    random_state=42,
    stratify=y # 新增:保持类别分布
    )

    # 2. 构建Stacking模型 ========================================
    """
    基学习器选择策略:
    1. 决策树:捕捉非线性关系(限制深度防止过拟合)
    2. SVM(RBF核):处理高维特征空间
    3. 逻辑回归:线性模型作为补充
    """
    estimators = [
    ('dt', DecisionTreeClassifier(
    max_depth=3, # 限制树深度
    min_samples_split=5, # 新增:防止过拟合
    random_state=42
    )),
    ('svc', SVC(
    kernel='rbf',
    probability=True, # 必须设为True才能用于Stacking
    random_state=42
    )),
    ('lr', LogisticRegression(
    max_iter=1000, # 增加迭代次数保证收敛
    random_state=42
    ))
    ]

    # 元学习器使用带正则化的逻辑回归
    final_estimator = LogisticRegression(
    C=1.0,
    penalty='l2',
    random_state=42
    )

    # 创建Stacking分类器
    stacking = StackingClassifier(
    estimators=estimators,
    final_estimator=final_estimator,
    cv=5, # 使用5折交叉验证生成元特征
    stack_method='auto', # 自动选择predict_proba或decision_function
    n_jobs=-1 # 新增:启用并行计算
    )

    # 3. 超参数优化 ==============================================
    """
    参数搜索空间说明:
    – svc__C: SVM正则化参数(权衡间隔大小和分类错误)
    – svc__gamma: RBF核宽度参数(控制决策边界复杂度)
    – final_estimator__C: 逻辑回归的正则化强度
    """
    param_grid = {
    'final_estimator__C': [0.1, 1, 10],
    'svc__C': [0.1, 1, 10],
    'svc__gamma': ['scale', 'auto', 0.1, 1], # 扩展搜索范围
    'dt__max_depth': [2, 3, 4] # 新增:优化决策树深度
    }

    # 使用网格搜索(5折交叉验证)
    grid_search = GridSearchCV(
    estimator=stacking,
    param_grid=param_grid,
    refit=True, # 用最佳参数重新训练
    cv=5,
    scoring='accuracy',
    n_jobs=-1, # 并行计算
    verbose=1 # 新增:显示搜索进度
    )

    print("开始网格搜索…")
    grid_search.fit(X_train, y_train)
    print("网格搜索完成")

    # 4. 模型评估 ================================================
    # 获取最佳模型
    best_model = grid_search.best_estimator_
    print("\\n=== 最佳参数 ===")
    print(grid_search.best_params_)

    # 测试集评估
    y_pred = best_model.predict(X_test)
    print("\\n=== 测试集性能 ===")
    print("准确率:", accuracy_score(y_test, y_pred))
    print("\\n分类报告(包含精确率/召回率/F1):")
    print(classification_report(y_test, y_pred, target_names=iris.target_names))
    print("\\n混淆矩阵:")
    print(confusion_matrix(y_test, y_pred))

    # 交叉验证评估(更可靠的性能估计)
    print("\\n=== 交叉验证结果 ===")
    cv_scores = cross_val_score(
    best_model,
    X_train,
    y_train,
    cv=5,
    scoring='accuracy',
    n_jobs=-1
    )
    print(f"5折交叉验证结果: {cv_scores}")
    print(f"平均准确率: {np.mean(cv_scores):.4f} ± {np.std(cv_scores):.4f}")

    # 5. 改进建议
    """
    1. 特征工程:可以考虑添加多项式特征或标准化
    2. 模型多样性:可尝试加入KNN或朴素贝叶斯作为基学习器
    3. 高级技巧:使用特征选择或PCA降维
    4. 部署优化:使用joblib保存训练好的模型
    """

    八、结尾

            这是个人学习机器学习时做的笔记,学习过程中观看的是语雀上的一篇关于机器学习的笔记,文章中的代码时通过AI给出并经过自己修改,基本能一键运行。

    赞(0)
    未经允许不得转载:171主机测评 » 机器学习基础(Python)
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址