最强总结!十大分类算法 !!

文摘   2024-10-22 11:46   北京  

哈喽,我是小白~

将之前的分类算法做了一个完善,今儿再来和大家分享一下~

分类算法在机器学习实验中非常重要,它们通过从数据中学习分类规则来将输入数据归入不同类别。合适的分类算法能提高模型的预测准确性和泛化能力,从而在测试数据上表现良好。选择合适的算法对任务成功至关重要,因为不同算法在特定数据分布和任务上可能表现不同。

整理的内容涉及到:

  • 逻辑回归
  • 决策树
  • 随机森林
  • 支持向量机
  • K近邻
  • 朴素贝叶斯
  • 梯度提升
  • XGBoost
  • 神经网络
  • LightGBM

如果需要本文PDF版本的同学,文末获取~

另外,文末有总结性的干货~

一起来看下今天的内容!

1. 逻辑回归(Logistic Regression)

逻辑回归是一种广泛使用的分类算法,常用于二分类问题。它是基于线性回归的,但通过使用逻辑函数(sigmoid函数),将回归的输出映射到概率空间,从而解决分类问题。

原理

逻辑回归的基本思想是:假设输出 是一个离散变量 ,通过模型计算得到某个输入属于类别1的概率,并通过一个阈值(通常是0.5)判断类别。

假设特征向量为 ,逻辑回归的预测函数是:

其中  是参数向量, 是逻辑函数,也叫做 sigmoid 函数。

核心公式

逻辑函数(sigmoid函数):

其中 

对数似然函数(Log-Likelihood)为:

或取对数形式:

推导

  1. 利用梯度下降优化参数 ,最大化对数似然函数。
  2. 梯度计算:

通过梯度下降不断更新权重:

其中  是学习率。

Python案例

import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import make_classification
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.metrics import confusion_matrix, roc_curve, auc

# 生成虚拟数据集
X, y = make_classification(n_samples=1000, n_features=2, n_classes=2, n_informative=2, n_redundant=0, random_state=42)

# 数据集分割为训练集和测试集
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)
y_prob = model.predict_proba(X_test)[:, 1]

# 1. 绘制散点图和决策边界
plt.figure(figsize=(1410))

# 子图1:散点图
plt.subplot(221)
plt.scatter(X_test[y_test == 0][:, 0], X_test[y_test == 0][:, 1], color='blue', label='Class 0', edgecolor='k')
plt.scatter(X_test[y_test == 1][:, 0], X_test[y_test == 1][:, 1], color='red', label='Class 1', edgecolor='k')
plt.title('Scatter Plot of Test Data', fontsize=14)
plt.xlabel('Feature 1')
plt.ylabel('Feature 2')
plt.legend()

# 决策边界
ax = plt.gca()
xlim = ax.get_xlim()
ylim = ax.get_ylim()

xx, yy = np.meshgrid(np.linspace(xlim[0], xlim[1], 200), np.linspace(ylim[0], ylim[1], 200))
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.contour(xx, yy, Z, levels=[0.5], linewidths=2, colors='black')

# 子图2:混淆矩阵
plt.subplot(222)
cm = confusion_matrix(y_test, y_pred)
plt.imshow(cm, interpolation='nearest', cmap=plt.cm.Blues)
plt.title('Confusion Matrix', fontsize=14)
plt.colorbar()
plt.xticks([01], ['Class 0''Class 1'], rotation=45)
plt.yticks([01], ['Class 0''Class 1'])
plt.ylabel('True label')
plt.xlabel('Predicted label')

# 在混淆矩阵上标注数字
thresh = cm.max() / 2
for i, j in np.ndindex(cm.shape):
    plt.text(j, i, format(cm[i, j], 'd'), ha="center", va="center", color="white" if cm[i, j] > thresh else "black")

# 子图3:ROC曲线
plt.subplot(223)
fpr, tpr, _ = roc_curve(y_test, y_prob)
roc_auc = auc(fpr, tpr)
plt.plot(fpr, tpr, color='darkorange', lw=2, label='ROC curve (area = %0.2f)' % roc_auc)
plt.plot([01], [01], color='navy', lw=2, linestyle='--')
plt.xlim([0.01.0])
plt.ylim([0.01.05])
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.title('Receiver Operating Characteristic')
plt.legend(loc="lower right")

plt.tight_layout()
plt.show()

  1. 散点图:通过散点图,我们可以直观地看到测试数据集中特征1和特征2的分布,并且可以观察到不同类别(0和1)的分离情况。红色代表类别1,蓝色代表类别0。这个图帮助我们理解两个特征对分类的影响。

  2. 决策边界:在散点图上叠加了逻辑回归模型的决策边界(黑色线)。这条边界展示了模型是如何根据输入特征将样本划分为两个类别。颜色的填充区域展示了模型对不同区域的分类概率。

  3. 混淆矩阵:混淆矩阵展示了分类器在测试集上的性能,包括正确预测的样本数量(对角线上的值)和错误预测的数量。它能够帮助我们深入了解模型是如何区分不同类别的。

  4. ROC曲线:ROC曲线展示了模型在不同分类阈值下的性能表现,曲线下的面积(AUC)用于评估模型的整体性能。曲线越接近左上角,模型的表现越好。

2. 决策树(Decision Tree)

决策树是一种基于树形结构的模型。它通过递归地将数据集划分成不同的子集,逐步建立一个树状结构。每个内部节点表示一个特征上的判断,叶节点表示决策结果(类别或回归值)。

原理

决策树的构建过程是一个递归的划分过程。在每一步,算法会选择一个特征及其对应的分裂点,使得数据集被最有效地划分。

最常见的分裂标准是信息增益(Information Gain)基尼指数(Gini Index)

核心公式

  1. 信息增益(Information Gain):

其中, 是数据集  的熵, 是按特征  划分后得到的子集。

熵的计算公式为:

  1. 基尼指数(Gini Index):

推导

  1. 选择分裂点:遍历每个特征,计算每个特征的每个可能分裂点的分裂标准(信息增益或基尼指数)。
  2. 递归划分:在每个节点上选择最优的分裂点,将数据集划分成子集,继续递归,直到满足停止条件(例如树达到最大深度,或每个叶子节点只有一个类别)。

Python案例

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier, plot_tree
from sklearn.inspection import DecisionBoundaryDisplay
from sklearn.metrics import accuracy_score

# 生成虚拟数据集
X, y = make_classification(n_samples=1000, n_features=4, n_informative=3, n_redundant=0, n_classes=3, random_state=42)
feature_names = ['Feature1''Feature2''Feature3''Feature4']
class_names = ['Class 0''Class 1''Class 2']

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

# 创建决策树模型并训练(使用四个特征)
clf = DecisionTreeClassifier(random_state=42)
clf.fit(X_train, y_train)

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

# 创建仅使用前两个特征的训练集和测试集
X_train_2d = X_train[:, :2]
X_test_2d = X_test[:, :2]

# 训练一个新的决策树模型,仅使用前两个特征
clf_2d = DecisionTreeClassifier(random_state=42)
clf_2d.fit(X_train_2d, y_train)

# 绘图
fig, axs = plt.subplots(22, figsize=(1412), tight_layout=True)

# 1. 绘制特征对特征的散点图
axs[00].scatter(X[:, 0], X[:, 1], c=y, cmap='rainbow', edgecolor='k', s=50)
axs[00].set_title('Feature1 vs Feature2')
axs[00].set_xlabel('Feature1')
axs[00].set_ylabel('Feature2')

# 2. 绘制特征重要性柱状图
importances = clf.feature_importances_
indices = np.argsort(importances)[::-1]
axs[01].bar(range(X.shape[1]), importances[indices], color='teal')
axs[01].set_title('Feature Importances')
axs[01].set_xticks(range(X.shape[1]))
axs[01].set_xticklabels([feature_names[i] for i in indices])
axs[01].set_ylabel('Importance')

# 3. 绘制决策树的分类边界(二维平面上,选取前两个特征)
DecisionBoundaryDisplay.from_estimator(clf_2d, X[:, :2], cmap='rainbow', ax=axs[10], response_method='predict', alpha=0.5)
axs[10].scatter(X[:, 0], X[:, 1], c=y, edgecolor='k', cmap='rainbow', s=50)
axs[10].set_title('Decision Boundary (Feature1 vs Feature2)')
axs[10].set_xlabel('Feature1')
axs[10].set_ylabel('Feature2')

# 4. 绘制决策树结构图
plot_tree(clf, feature_names=feature_names, class_names=class_names, filled=True, ax=axs[11], rounded=True, fontsize=8)
axs[11].set_title('Decision Tree Structure')

# 显示图形
plt.show()

  1. 特征对特征的散点图:用于观察不同类别数据在特征空间中的分布。这里我们展示了 Feature1 和 Feature2 的关系,颜色代表不同类别,帮助我们分析数据是否有明显的分界点。

  2. 特征重要性柱状图:决策树算法会根据特征的重要性进行分裂,这个柱状图展示了各个特征的重要性评分。特征重要性越高,说明该特征对决策树的分类决策影响越大。

  3. 决策树的分类边界:决策树的主要任务是创建决策边界,将数据点进行分类。我们绘制了前两个特征在二维平面上的分类决策边界,通过颜色区分不同类别的区域,直观展示了模型的分类能力。

  4. 决策树的结构可视化:通过决策树结构图,我们可以直观了解模型是如何根据特征值逐步进行分类决策的。这有助于分析模型的复杂度和分裂过程。

3. 随机森林(Random Forest)

随机森林是基于决策树的一种集成学习方法,通过生成多个决策树并结合它们的预测结果来提高分类或回归的准确性。

原理

随机森林通过引入Bagging(Bootstrap Aggregating)技术,对数据进行有放回的随机抽样,训练多棵决策树。每棵树在训练时只使用了部分数据和部分特征,最后将所有树的预测结果进行投票(分类)或平均(回归)。

核心公式

随机森林的集成预测为:

  1. 分类问题
  1. 回归问题

其中  是第  棵树的预测结果。

推导

  1. Bagging:从原始训练数据集中随机抽取不同的子集,每个子集包含的数据是通过有放回抽样得到的。
  2. 随机特征选择:在每个节点分裂时,随机选择部分特征作为候选特征,而不是使用全部特征。
  3. 多树集成:训练多个决策树,最终对结果进行投票或求平均。

Python案例

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.datasets import make_classification
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import train_test_split
from sklearn.metrics import confusion_matrix, ConfusionMatrixDisplay
import seaborn as sns

# 1. 生成虚拟数据集
X, y = make_classification(n_samples=1000
                           n_features=10
                           n_informative=5
                           n_redundant=2
                           n_classes=3
                           random_state=42)

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

# 3. 创建随机森林分类器并训练
clf = RandomForestClassifier(n_estimators=100, random_state=42)
clf.fit(X_train, y_train)

# 4. 预测
y_pred = clf.predict(X_test)

# 5. 绘制图形:混淆矩阵 + 特征重要性
fig, ax = plt.subplots(12, figsize=(146))

# 5.1 绘制混淆矩阵
cm = confusion_matrix(y_test, y_pred)
disp = ConfusionMatrixDisplay(confusion_matrix=cm)
disp.plot(ax=ax[0], cmap='Blues')
ax[0].set_title('Confusion Matrix', fontsize=16)

# 5.2 绘制特征重要性
importances = clf.feature_importances_
indices = np.argsort(importances)[::-1]
sns.barplot(x=importances[indices], y=np.array(range(X.shape[1]))[indices], palette="coolwarm", ax=ax[1])
ax[1].set_title('Feature Importance', fontsize=16)
ax[1].set_xlabel('Importance Score', fontsize=12)
ax[1].set_ylabel('Feature Index', fontsize=12)

# 6. 设置整体图像风格和显示
plt.tight_layout()
plt.show()

  1. 混淆矩阵(Confusion Matrix):用于查看模型的分类性能。矩阵中的对角线元素表示正确分类的个数,非对角线元素表示错误分类的个数。它能直观地展示模型在哪些类别上表现好,在哪些类别上可能有偏差。

  2. 特征重要性(Feature Importance):这是随机森林提供的一个有用功能,它能帮助我们理解模型最依赖于哪些特征来进行分类决策。通过绘制特征重要性的条形图,可以清楚地看到哪些特征在分类任务中最为关键。

4. 支持向量机(SVM)

支持向量机是一种监督学习模型,主要用于分类任务。它通过构建超平面来最大化数据集中不同类别之间的间隔,从而实现分类。

原理

SVM 的目标是找到一个超平面,使得它能将不同类别的数据点尽可能分开,并最大化超平面与最近的支持向量之间的距离。

核心公式

假设数据是线性可分的,SVM 的优化问题是:

约束条件为:

其中, 是超平面的法向量, 是偏置项, 表示数据点的类别。

推导

  1. 使用拉格朗日乘子法引入拉格朗日乘子 ,构造拉格朗日函数:
  1. 对  和  求偏导并令其为零,得到支持向量的约束条件。
  2. 通过对偶问题,将优化问题转化为拉格朗日乘子的优化问题。

Python案例

import numpy as np
import matplotlib.pyplot as plt
from sklearn import datasets
from sklearn.model_selection import train_test_split
from sklearn.svm import SVC
from matplotlib.colors import ListedColormap

# 生成虚拟数据集,三个类别
X, y = datasets.make_classification(n_samples=1000, n_features=2, n_informative=2
                                    n_redundant=0, n_classes=3, n_clusters_per_class=1, random_state=40)

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

# 创建支持向量机模型(多类别为"ovo"策略)
svm = SVC(kernel='linear', decision_function_shape='ovo')
svm.fit(X_train, y_train)

# 定义绘制决策边界的函数
def plot_decision_regions(X, y, classifier, resolution=0.02):
    # 设置颜色和标记
    markers = ('s''x''o')
    colors = ('red''blue''green')
    cmap = ListedColormap(colors[:len(np.unique(y))])

    # 绘制决策边界
    x1_min, x1_max = X[:, 0].min() - 1, X[:, 0].max() + 1
    x2_min, x2_max = X[:, 1].min() - 1, X[:, 1].max() + 1
    xx1, xx2 = np.meshgrid(np.arange(x1_min, x1_max, resolution),
                           np.arange(x2_min, x2_max, resolution))
    Z = classifier.predict(np.array([xx1.ravel(), xx2.ravel()]).T)
    Z = Z.reshape(xx1.shape)
    
    plt.contourf(xx1, xx2, Z, alpha=0.4, cmap=cmap)
    plt.xlim(xx1.min(), xx1.max())
    plt.ylim(xx2.min(), xx2.max())

    # 绘制训练数据点
    for idx, cl in enumerate(np.unique(y)):
        plt.scatter(x=X[y == cl, 0], y=X[y == cl, 1],
                    alpha=0.8, c=colors[idx],
                    marker=markers[idx], label=f'Class {cl}',
                    edgecolor='black')

# 创建画布
plt.figure(figsize=(128))

# 第一个子图:数据点分布
plt.subplot(121)
plt.title('Data Point Distribution with Class Labels')
plt.scatter(X[:, 0], X[:, 1], c=y, cmap='viridis', edgecolors='k')
plt.xlabel('Feature 1')
plt.ylabel('Feature 2')
plt.colorbar(label='Class')
plt.grid(True)

# 第二个子图:SVM分类决策边界和数据点
plt.subplot(122)
plt.title('SVM Decision Boundaries and Support Vectors')
plot_decision_regions(X_train, y_train, classifier=svm)
plt.scatter(svm.support_vectors_[:, 0], svm.support_vectors_[:, 1], s=100, facecolors='none', edgecolors='k', label='Support Vectors')
plt.legend()
plt.xlabel('Feature 1')
plt.ylabel('Feature 2')
plt.grid(True)

# 显示图像
plt.tight_layout()
plt.show()
  • 生成数据集datasets.make_classification()生成一个具有三个类别的二维特征虚拟数据集。
  • 支持向量机模型:使用 SVC() 创建一个线性核的支持向量机,支持多类别分类。
  • 决策边界绘制:使用 contourf() 函数绘制SVM的决策边界,并用不同颜色填充分类区域。
  • 支持向量的标记:在分类决策边界图上通过不同的标记显示支持向量的位置。

5. K近邻(K-Nearest Neighbors, KNN)

K近邻是一种简单的非参数分类算法。它通过比较新样本与训练集中最相似的  个样本,进行投票或平均来预测新样本的类别或值。

原理

KNN 主要依赖于距离度量,如欧氏距离、曼哈顿距离等。给定一个新样本,KNN算法会找到训练集中距离该样本最近的  个邻居,并根据这些邻居的类别进行投票(分类)或取平均(回归)。

核心公式

  • 欧氏距离:

分类的预测公式:

回归的预测公式:

推导

  1. 计算测试样本与所有训练样本之间的距离。
  2. 找到距离最近的  个邻居。
  3. 对于分类问题,统计这些邻居中出现次数最多的类别作为预测结果。对于回归问题,取这些邻居的平均值作为预测结果。

Python案例

import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
from sklearn.neighbors import KNeighborsClassifier
from sklearn.metrics import confusion_matrix, accuracy_score
import seaborn as sns

# 生成虚拟分类数据集
X, y = make_classification(n_samples=1000, n_features=2, n_informative=2, n_redundant=0
                           n_clusters_per_class=1, n_classes=3, random_state=42)

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

# KNN模型训练
k_values = range(120)
accuracies = []

for k in k_values:
    knn = KNeighborsClassifier(n_neighbors=k)
    knn.fit(X_train, y_train)
    y_pred = knn.predict(X_test)
    accuracies.append(accuracy_score(y_test, y_pred))

# 最优K值
best_k = k_values[np.argmax(accuracies)]
knn_best = KNeighborsClassifier(n_neighbors=best_k)
knn_best.fit(X_train, y_train)
y_pred_best = knn_best.predict(X_test)

# 绘制图形
fig, axs = plt.subplots(22, figsize=(1412))
fig.suptitle('K-Nearest Neighbors Analysis', fontsize=16)

# 图1:数据分布与分类边界
ax = axs[00]
cmap = plt.cm.get_cmap('Set1'3)
scatter = ax.scatter(X_test[:, 0], X_test[:, 1], c=y_test, cmap=cmap, edgecolor='k')
ax.set_title(f'Test Data Distribution with True Labels')
ax.set_xlabel('Feature 1')
ax.set_ylabel('Feature 2')
legend1 = ax.legend(*scatter.legend_elements(), title="Classes")
ax.add_artist(legend1)

# 创建网格用于显示决策边界
x_min, x_max = X[:, 0].min() - 0.5, X[:, 0].max() + 0.5
y_min, y_max = X[:, 1].min() - 0.5, X[:, 1].max() + 0.5
xx, yy = np.meshgrid(np.arange(x_min, x_max, 0.05),
                     np.arange(y_min, y_max, 0.05))

# 预测网格数据
Z = knn_best.predict(np.c_[xx.ravel(), yy.ravel()])
Z = Z.reshape(xx.shape)

# 绘制决策边界
ax.contourf(xx, yy, Z, alpha=0.4, cmap=cmap)

# 图2:K值与准确率的关系
ax = axs[01]
ax.plot(k_values, accuracies, marker='o', color='orange')
ax.set_title('Accuracy vs K value')
ax.set_xlabel('K')
ax.set_ylabel('Accuracy')

# 标出最佳K值
ax.axvline(x=best_k, color='red', linestyle='--')
ax.text(best_k, max(accuracies), f'Best K = {best_k}', color='red', fontsize=12)

# 图3:混淆矩阵
ax = axs[10]
cm = confusion_matrix(y_test, y_pred_best)
sns.heatmap(cm, annot=True, fmt='d', cmap='Blues', ax=ax)
ax.set_title(f'Confusion Matrix (Best K = {best_k})')
ax.set_xlabel('Predicted Label')
ax.set_ylabel('True Label')

# 图4:训练集与测试集数据分布对比
ax = axs[11]
ax.scatter(X_train[:, 0], X_train[:, 1], c=y_train, marker='o', label='Train', alpha=0.6, cmap=cmap)
ax.scatter(X_test[:, 0], X_test[:, 1], c=y_test, marker='x', label='Test', alpha=0.6, cmap=cmap, edgecolor='k')
ax.set_title('Train vs Test Data Distribution')
ax.set_xlabel('Feature 1')
ax.set_ylabel('Feature 2')
ax.legend()

plt.tight_layout(rect=[0010.96])
plt.show()

  1. 数据分布与分类边界图:展示了测试数据的真实分类和分类边界,这有助于直观理解KNN是如何根据相邻点分类的。
  2. K值与准确率的关系图:KNN中的K值是模型的超参数,这个图帮助我们选择一个合适的K值以平衡过拟合和欠拟合。
  3. 混淆矩阵图:展示了分类模型的性能,显示正确分类和错误分类的数量,帮助我们评估模型效果。
  4. 训练集与测试集分布图:显示训练集和测试集的分布差异,可以帮助我们检查数据集是否均匀。

6. 朴素贝叶斯(Naive Bayes)

朴素贝叶斯是一种基于贝叶斯定理的分类算法,假设特征之间是条件独立的,简化了联合概率的计算。

原理

朴素贝叶斯的目标是通过贝叶斯定理计算后验概率 ,即给定特征 ,求该样本属于类别  的概率。假设特征之间是条件独立的:

核心公式

贝叶斯定理:

在特征独立的假设下:

推导

  1. 根据贝叶斯定理,计算每个类别的后验概率 
  2. 假设特征独立,简化联合概率为各个特征条件概率的乘积。
  3. 选择最大后验概率对应的类别作为预测结果。

Python案例

import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
from sklearn.naive_bayes import GaussianNB
from sklearn.metrics import confusion_matrix, ConfusionMatrixDisplay, roc_curve, auc
from sklearn.preprocessing import label_binarize
from sklearn.multiclass import OneVsRestClassifier
from sklearn.metrics import roc_auc_score

# 生成一个多类分类的虚拟数据集
X, y = make_classification(n_samples=1000, n_features=2, n_informative=2
                           n_redundant=0, n_classes=3, random_state=42)

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

# 使用朴素贝叶斯进行分类
model = GaussianNB()
model.fit(X_train, y_train)
y_pred = model.predict(X_test)

# 绘制数据分布图(散点图)
plt.figure(figsize=(1612))
plt.subplot(221)
for i, color in zip(range(3), ['red''blue''green']):
    idx = np.where(y == i)
    plt.scatter(X[idx, 0], X[idx, 1], label=f'Class {i}', c=color, edgecolor='k')
plt.title("Data Distribution by Class")
plt.xlabel('Feature 1')
plt.ylabel('Feature 2')
plt.legend()

# 绘制混淆矩阵
plt.subplot(222)
cm = confusion_matrix(y_test, y_pred)
disp = ConfusionMatrixDisplay(confusion_matrix=cm)
disp.plot(ax=plt.gca())
plt.title('Confusion Matrix')

# 绘制ROC曲线
y_test_bin = label_binarize(y_test, classes=[012])
y_score = model.predict_proba(X_test)
n_classes = y_test_bin.shape[1]

# 计算每个类别的ROC曲线和AUC
fpr = dict()
tpr = dict()
roc_auc = dict()
for i in range(n_classes):
    fpr[i], tpr[i], _ = roc_curve(y_test_bin[:, i], y_score[:, i])
    roc_auc[i] = auc(fpr[i], tpr[i])

# 绘制ROC曲线图
plt.subplot(223)
colors = ['red''blue''green']
for i, color in zip(range(n_classes), colors):
    plt.plot(fpr[i], tpr[i], color=color, lw=2, label=f'Class {i} (AUC = {roc_auc[i]:.2f})')
plt.plot([01], [01], 'k--', lw=2)
plt.xlim([0.01.0])
plt.ylim([0.01.05])
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.title('ROC Curves')
plt.legend(loc="lower right")

# 综合绘图
plt.tight_layout()
plt.show()

  1. 数据分布图(左上角):该图展示了不同类别在特征空间中的分布情况。通过颜色(红色、蓝色、绿色)分别表示3个不同的类别,能够直观了解数据的分布情况。

  2. 混淆矩阵图(右上角):显示测试集中每个类别的预测结果与实际情况的对比。例如,若混淆矩阵中的对角线值很高,说明模型预测准确率较高,反之误差较大。

  3. ROC曲线图(左下角):为每个类别绘制了ROC曲线,展示了在不同阈值下模型的分类表现。AUC(曲线下的面积)值越接近1,说明分类性能越好。

7. 梯度提升(Gradient Boosting)

梯度提升是一种集成学习算法,通过构建一系列弱学习器(通常是决策树),逐步减少预测误差,从而提高模型的准确性。

原理

梯度提升的核心思想是:通过逐步拟合残差,将多个弱学习器(例如小决策树)加起来,形成一个强学习器。每次添加的新学习器都试图修正之前学习器的误差。

核心公式

假设我们有一个预测模型 ,通过迭代的方式逐步优化,每一轮的更新为:

其中, 是第  轮拟合的弱学习器, 是学习率。

误差的梯度为:

其中  是损失函数,通常是平方损失或对数损失。

推导

  1. 初始模型  是训练集的平均值。
  2. 每一轮计算梯度 ,拟合残差。
  3. 通过拟合残差建立弱学习器 ,更新模型 

Python案例

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.datasets import make_classification
from sklearn.ensemble import GradientBoostingClassifier
from sklearn.model_selection import train_test_split, learning_curve
from sklearn.metrics import confusion_matrix, roc_curve, auc, ConfusionMatrixDisplay

# 生成虚拟数据集
X, y = make_classification(n_samples=1000, n_features=10, n_informative=6, n_redundant=2, n_classes=2, random_state=42)

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

# 建立梯度提升分类模型
gb_clf = GradientBoostingClassifier(n_estimators=100, learning_rate=0.1, max_depth=3, random_state=42)
gb_clf.fit(X_train, y_train)

# 1. 特征重要性分析图
feature_importances = gb_clf.feature_importances_
features = np.arange(X.shape[1])

# 2. 混淆矩阵
y_pred = gb_clf.predict(X_test)
cm = confusion_matrix(y_test, y_pred)

# 3. ROC曲线与AUC值
y_pred_prob = gb_clf.predict_proba(X_test)[:, 1]
fpr, tpr, _ = roc_curve(y_test, y_pred_prob)
roc_auc = auc(fpr, tpr)

# 4. 学习曲线
train_sizes, train_scores, test_scores = learning_curve(gb_clf, X, y, cv=5, n_jobs=-1, train_sizes=np.linspace(0.11.010))

# 计算训练集和测试集的平均得分
train_scores_mean = np.mean(train_scores, axis=1)
test_scores_mean = np.mean(test_scores, axis=1)

# 绘制图形
plt.figure(figsize=(1812))

# 特征重要性
plt.subplot(221)
plt.bar(features, feature_importances, color='orange')
plt.title('Feature Importances', fontsize=15)
plt.xlabel('Feature Index')
plt.ylabel('Importance Score')
plt.xticks(features)

# 混淆矩阵
plt.subplot(222)
disp = ConfusionMatrixDisplay(confusion_matrix=cm)
disp.plot(ax=plt.gca(), cmap='plasma')
plt.title('Confusion Matrix', fontsize=15)

# ROC曲线
plt.subplot(223)
plt.plot(fpr, tpr, color='darkgreen', lw=2, label=f'ROC curve (AUC = {roc_auc:.2f})')
plt.plot([01], [01], color='gray', linestyle='--')
plt.xlim([0.01.0])
plt.ylim([0.01.05])
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.title('ROC Curve', fontsize=15)
plt.legend(loc="lower right")

# 学习曲线
plt.subplot(224)
plt.plot(train_sizes, train_scores_mean, 'o-', color="red", label="Training score")
plt.plot(train_sizes, test_scores_mean, 'o-', color="blue", label="Cross-validation score")
plt.title("Learning Curve", fontsize=15)
plt.xlabel("Training examples")
plt.ylabel("Score")
plt.legend(loc="best")

plt.tight_layout()
plt.show()

  1. 特征重要性图:展示模型中每个特征的重要性分数,有助于理解哪些特征对分类任务最为重要。这可以帮助我们进一步对数据进行优化,去掉不重要的特征。

  2. 混淆矩阵:显示预测结果的正确性与错误率。通过混淆矩阵,可以清晰地看到模型在分类中的精度、召回率、特异性等指标。

  3. ROC曲线与AUC值:ROC曲线反映了分类器的性能,AUC值则量化了模型的总体表现。它能够帮助评估模型对正负样本的区分能力,特别适用于不平衡分类任务。

  4. 学习曲线:展示随着训练集大小的增加,模型的表现如何变化。通过观察训练集和测试集的曲线走势,可以判断模型是否存在过拟合或欠拟合问题。

8. XGBoost

XGBoost(eXtreme Gradient Boosting)是梯度提升的一种优化实现,具有更高的效率和精度。它通过引入正则化项和基于二阶导数的信息加快收敛速度,并处理缺失值和不均衡数据。

原理

XGBoost 采用类似梯度提升的思想,但通过优化目标函数引入了正则化项,以控制模型复杂度,从而防止过拟合。目标函数为:

其中, 是正则化项,用于控制模型复杂度。

核心公式

目标函数的正则化项:

其中, 是叶子节点数, 是第  个叶子的权重。

通过二阶泰勒展开对损失函数近似:

其中, 和  分别是损失函数的梯度和Hessian矩阵。

推导

  1. 初始模型与梯度提升类似,拟合残差。
  2. 通过优化目标函数,使用二阶导数信息计算出每棵树的最佳分裂点。
  3. 引入正则化项控制模型复杂度,防止过拟合。

Python案例

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.metrics import confusion_matrix, roc_curve, auc, precision_recall_curve
from xgboost import XGBClassifier
from sklearn.metrics import ConfusionMatrixDisplay
from sklearn.preprocessing import LabelBinarizer

# 生成虚拟数据集
np.random.seed(42)
X = np.random.rand(100010)  # 1000个样本,10个特征
y = np.random.choice([01], size=1000)  # 二分类目标

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

# XGBoost模型训练
model = XGBClassifier(use_label_encoder=False, eval_metric='logloss')
model.fit(X_train, y_train)

# 预测
y_pred = model.predict(X_test)
y_pred_proba = model.predict_proba(X_test)[:, 1]

# 绘制图形
fig, axes = plt.subplots(22, figsize=(1212))  # 创建2x2的图形布局

# 图1:特征重要性
importances = model.feature_importances_
indices = np.argsort(importances)[::-1]
axes[00].bar(range(X_train.shape[1]), importances[indices], color='lightcoral', align='center')
axes[00].set_xticks(range(X_train.shape[1]))
axes[00].set_xticklabels(indices)
axes[00].set_title('Feature Importances', fontsize=14)
axes[00].set_xlabel('Feature Index')
axes[00].set_ylabel('Importance')

# 图2:混淆矩阵
cm = confusion_matrix(y_test, y_pred)
disp = ConfusionMatrixDisplay(confusion_matrix=cm)
disp.plot(ax=axes[01], cmap=plt.cm.Blues)
axes[01].set_title('Confusion Matrix', fontsize=14)

# 图3:ROC曲线
fpr, tpr, _ = roc_curve(y_test, y_pred_proba)
roc_auc = auc(fpr, tpr)
axes[10].plot(fpr, tpr, color='darkorange', lw=2, label=f'ROC curve (AUC = {roc_auc:.2f})')
axes[10].plot([01], [01], color='navy', lw=2, linestyle='--')
axes[10].set_xlim([0.01.0])
axes[10].set_ylim([0.01.05])
axes[10].set_xlabel('False Positive Rate')
axes[10].set_ylabel('True Positive Rate')
axes[10].set_title('Receiver Operating Characteristic (ROC)', fontsize=14)
axes[10].legend(loc='lower right')

# 图4:精确率-召回率曲线
precision, recall, _ = precision_recall_curve(y_test, y_pred_proba)
axes[11].plot(recall, precision, color='green', lw=2, label='Precision-Recall curve')
axes[11].set_xlabel('Recall')
axes[11].set_ylabel('Precision')
axes[11].set_xlim([0.01.0])
axes[11].set_ylim([0.01.05])
axes[11].set_title('Precision-Recall Curve', fontsize=14)
axes[11].legend(loc='lower left')

# 显示所有图形
plt.tight_layout()
plt.show()
  1. 数据集生成:我们使用 numpy 随机生成了一个1000个样本、10个特征的虚拟数据集,并生成了二分类目标变量 y
  2. 模型训练:使用XGBoost分类器(XGBClassifier)训练模型,采用默认的分类参数,并使用 train_test_split 划分训练集与测试集。

  • 特征重要性图展示了每个特征对模型预测结果的重要性。
  • 混淆矩阵显示了分类模型在测试集上的分类结果,包括TP、FP、TN、FN的情况。
  • ROC曲线展示了不同阈值下的模型表现,曲线下的面积(AUC)可以直观反映模型的区分能力。
  • 精确率-召回率曲线则是另一种权衡分析,尤其适合分析不平衡数据集。

9. 神经网络(Neural Networks)

神经网络是一种模拟人脑神经元工作的模型,包含多个相互连接的节点(神经元)。每个节点接收输入信号,并通过激活函数输出信号。

原理

神经网络的每一层由一组神经元组成,神经元之间通过权重相连。输入层接收原始数据,经过若干隐藏层的非线性变换,输出层生成最终的预测结果。常用的激活函数有 Sigmoid、ReLU 等。

核心公式

  1. 神经元输出

其中, 是激活函数, 是权重, 是偏置项。

  1. 反向传播

对于每个权重 ,其梯度为:

其中  是损失函数。

推导

  1. 前向传播:从输入层开始,逐层计算神经元的输出,直到得到最终的预测结果。
  2. 反向传播:通过链式法则,逐层计算损失函数对各个权重的梯度,并更新权重。

Python案例

import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import make_moons
from sklearn.model_selection import train_test_split
from sklearn.neural_network import MLPClassifier
from sklearn.metrics import accuracy_score

# 生成虚拟数据集(双月形)
X, y = make_moons(n_samples=1000, noise=0.2, random_state=42)

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

# 创建并训练神经网络分类器
clf = MLPClassifier(hidden_layer_sizes=(1010), max_iter=1000, alpha=0.001, random_state=42)
clf.fit(X_train, y_train)

# 预测测试集
y_pred = clf.predict(X_test)
accuracy = accuracy_score(y_test, y_pred)
print(f'Accuracy: {accuracy:.2f}')

# 生成图像网格用于绘制决策边界
x_min, x_max = X[:, 0].min() - 0.5, X[:, 0].max() + 0.5
y_min, y_max = X[:, 1].min() - 0.5, X[:, 1].max() + 0.5
xx, yy = np.meshgrid(np.arange(x_min, x_max, 0.01), np.arange(y_min, y_max, 0.01))

# 预测网格上每个点的分类
Z = clf.predict(np.c_[xx.ravel(), yy.ravel()])
Z = Z.reshape(xx.shape)

# 创建图形
fig, ax = plt.subplots(12, figsize=(166))

# 图1:散点图 + 决策边界
ax[0].contourf(xx, yy, Z, cmap=plt.cm.Spectral, alpha=0.8)  # 决策边界
ax[0].scatter(X_train[:, 0], X_train[:, 1], c=y_train, cmap=plt.cm.Set1, edgecolors='k', s=50, label='Train')
ax[0].scatter(X_test[:, 0], X_test[:, 1], c=y_test, cmap=plt.cm.Set2, marker='x', s=50, label='Test')
ax[0].set_title('Data Distribution & Decision Boundary')
ax[0].legend()

# 图2:损失函数变化曲线
ax[1].plot(clf.loss_curve_, color='red', lw=2, label='Loss')
ax[1].set_title('Loss Curve')
ax[1].set_xlabel('Iterations')
ax[1].set_ylabel('Loss')
ax[1].legend()

# 展示所有图形
plt.show()
  1. 生成虚拟数据集:使用make_moons函数生成一个具有噪声的双月形数据集,适用于二分类问题。
  2. 训练神经网络分类器:使用MLPClassifier,包含两个隐藏层,每层有10个神经元。训练时使用了L2正则化(alpha=0.001),并设置最大迭代次数为1000。

  • 散点图和决策边界:在第一个图中,我们使用不同的颜色显示训练集和测试集的点,同时用等高线图展示神经网络的决策边界。这有助于理解模型如何划分空间和分类不同的样本。
  • 损失函数变化曲线:第二个图展示了损失函数随训练迭代次数的变化,帮助我们评估模型训练的收敛速度和稳定性。

10. LightGBM

LightGBM(Light Gradient Boosting Machine)是一种高效的梯度提升框架,专为大规模数据集优化。它通过直方算法基于叶子生长的策略提高了训练速度和模型性能。

原理

LightGBM 采用了基于叶子生长的策略,即每次选择误差最大的叶节点进行分裂。这与传统的基于层的分裂策略不同,能够更好地拟合复杂数据。

核心公式

LightGBM 的目标函数与 XGBoost 类似,也引入了正则化项,用于控制模型复杂度:

LightGBM 特有的直方算法将连续特征离散化,减少计算量:

推导

  1. 直方算法:将连续特征离散化为直方图,减少计算每个特征的分裂点的时间复杂度。
  2. 基于叶子生长:每次选择误差最大的叶子节点进行分裂,而不是像 XGBoost 那样按层次生长。
  3. 多线程并行化:通过数据并行和特征并行加快训练速度。

Python案例

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
from sklearn.metrics import roc_curve, auc, confusion_matrix, ConfusionMatrixDisplay
import lightgbm as lgb
from sklearn.metrics import roc_auc_score
import shap

# 1. 生成虚拟数据集
X, y = make_classification(n_samples=1000, n_features=10, n_informative=6, n_classes=2, random_state=42)

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

# 3. LightGBM 模型训练
train_data = lgb.Dataset(X_train, label=y_train)
test_data = lgb.Dataset(X_test, label=y_test, reference=train_data)

params = {
    'objective''binary',
    'boosting_type''gbdt',
    'metric''binary_logloss',
    'verbosity'-1
}

lgb_model = lgb.train(params, train_data, valid_sets=[test_data], num_boost_round=100, early_stopping_rounds=10)

# 4. 特征重要性图
fig, axes = plt.subplots(22, figsize=(1412))
lgb.plot_importance(lgb_model, ax=axes[00], importance_type='gain', max_num_features=10)
axes[00].set_title("Feature Importance (Gain)")

# 5. ROC 曲线和 AUC
y_pred_prob = lgb_model.predict(X_test)
fpr, tpr, _ = roc_curve(y_test, y_pred_prob)
roc_auc = auc(fpr, tpr)
axes[01].plot(fpr, tpr, color='darkorange', lw=2, label=f'ROC curve (area = {roc_auc:.2f})')
axes[01].plot([01], [01], color='navy', lw=2, linestyle='--')
axes[01].set_xlim([0.01.0])
axes[01].set_ylim([0.01.05])
axes[01].set_xlabel('False Positive Rate')
axes[01].set_ylabel('True Positive Rate')
axes[01].set_title('Receiver Operating Characteristic (ROC)')
axes[01].legend(loc="lower right")

# 6. 混淆矩阵
y_pred = np.where(y_pred_prob > 0.510)
cm = confusion_matrix(y_test, y_pred)
ConfusionMatrixDisplay(cm).plot(ax=axes[10], cmap=plt.cm.Blues)
axes[10].set_title('Confusion Matrix')

# 7. SHAP分析
explainer = shap.Explainer(lgb_model)
shap_values = explainer(X_test)

# Create a summary plot without the color argument
shap.summary_plot(shap_values, X_test, plot_type="bar", show=False, plot_size=(64), max_display=10)
axes[11].set_title('SHAP Feature Importance')

# 调整子图间距
plt.tight_layout()
plt.show()

  1. 虚拟数据生成:我们使用 make_classification 函数生成一个有 1000 个样本、10 个特征的虚拟数据集,其中有 6 个信息性特征。我们将数据集分为训练集和测试集。

  2. LightGBM 模型训练:通过 LightGBM 的 train 方法训练二分类模型,设置早停(early stopping)来防止过拟合。

  3. 特征重要性图:LightGBM 可以生成基于特征“增益”的重要性图,这展示了模型在分裂数据时对不同特征的依赖程度。我们选择“增益”作为重要性度量,因为它能衡量每个特征对提升模型准确率的贡献。

  4. ROC 曲线与 AUC:这两者帮助我们评估模型的分类性能。ROC 曲线展示了模型在不同阈值下的 TPR 和 FPR 的关系,AUC 则表示 ROC 曲线下的面积,衡量分类器的性能。

  5. 混淆矩阵:展示分类的详细情况,包括真阳性、假阳性、真阴性和假阴性的数量,便于分析分类错误的具体情况。

  6. SHAP 图(解释性分析):我们用 SHAP 分析模型对特征的依赖性,以进一步解释模型的决策过程。

最后

以上就是今天所有的内容了。
获取本文PDF,点击名片回复「十大算法模型」即可~
 
另外, 我们整理了机器学习算法册子,总共16大块的内容,124个问题的总结点击领取!
如果对你来说比较有用,记得点赞、转发,收藏起来慢慢学习~
下期会有更多干货等着你!~

Python和机器学习初学者
Python和机器学习分享,只写干货,一起学习~
 最新文章