哈喽,我是小白~
今儿和大家聊聊指标评估方法的内容,非常详细,非常重要,记得点赞收藏~
指标评估方法在机器学习实验中至关重要,因为指标评估能客观衡量模型的性能,帮助我们理解模型的优势和局限性。通过评估指标如准确率、精确率、召回率等,能指导模型的优化与调优。此外,正确选择评估指标能够确保模型在实际应用中具有可靠性和泛化能力。
今天设计到的10个指标评估方法有:
准确率(Accuracy) 精确率(Precision) 召回率(Recall) F1-Score ROC曲线和AUC(ROC Curve & AUC) 平均绝对误差(MAE, Mean Absolute Error) 均方误差(MSE, Mean Squared Error) R² 决定系数(R-squared) 轮廓系数(Silhouette Score) 混淆矩阵(Confusion Matrix)
咱们从原理到最后的案例,大家一定会有一个整体的认识~
1. 准确率
准确率(Accuracy)是最基本的分类性能评估指标之一。它用于衡量模型对所有样本的预测正确程度,即模型正确分类的样本占总样本的比例。
原理
准确率可以直观地反映模型的整体性能,但在类别不平衡的数据集上,准确率可能产生误导。例如,在一个99%为负类的数据集中,模型全部预测为负类就能达到99%的准确率,但模型并没有识别出任何正类。这说明准确率不适合类不平衡问题。
核心公式
(True Positive): 模型正确预测为正类的数量 (True Negative): 模型正确预测为负类的数量 (False Positive): 模型错误预测为正类的数量 (False Negative): 模型错误预测为负类的数量
推导
准确率的推导基于所有可能的分类结果。假设我们有总样本数量 ,那么每个样本会有四种可能的结果:预测正确(正类或负类)和预测错误(正类或负类)。通过公式,我们能够推导出:
这个公式直接反映了模型的总体预测能力。
Python案例
我们使用虚拟数据集模拟二分类问题,并通过调整分类阈值:
1. 准确率随阈值的变化曲线:显示模型的准确率如何随着决策阈值的变化而变化。
2. 混淆矩阵随阈值的变化图:展示不同阈值下的混淆矩阵情况。
3. ROC曲线:显示不同阈值下的真阳性率和假阳性率。
import numpy as np
import matplotlib.pyplot as plt
from sklearn.metrics import accuracy_score, confusion_matrix, roc_curve, auc
# 生成虚拟数据集
np.random.seed(42)
y_true = np.random.randint(0, 2, size=1000) # 真实标签
y_scores = np.random.rand(1000) # 分类器输出的概率得分
# 设置阈值范围
thresholds = np.linspace(0, 1, 100)
# 准确率、假阳性率、真阳性率存储
accuracies = []
conf_matrices = []
fpr_list = []
tpr_list = []
# 计算ROC曲线
fpr, tpr, roc_thresholds = roc_curve(y_true, y_scores)
roc_auc = auc(fpr, tpr)
# 遍历不同阈值计算混淆矩阵和准确率
for threshold in thresholds:
y_pred = (y_scores >= threshold).astype(int)
acc = accuracy_score(y_true, y_pred)
accuracies.append(acc)
# 混淆矩阵 (TP, FP, FN, TN)
conf_matrices.append(confusion_matrix(y_true, y_pred))
tn, fp, fn, tp = confusion_matrix(y_true, y_pred).ravel()
# ROC相关数据
fpr_list.append(fp / (fp + tn) if (fp + tn) > 0 else 0)
tpr_list.append(tp / (tp + fn) if (tp + fn) > 0 else 0)
# 绘制图像
fig, (ax1, ax2, ax3) = plt.subplots(1, 3, figsize=(18, 6))
# 1. 准确率随阈值变化图
ax1.plot(thresholds, accuracies, color='blue', label='Accuracy')
ax1.set_title('Accuracy vs Threshold', fontsize=14)
ax1.set_xlabel('Threshold', fontsize=12)
ax1.set_ylabel('Accuracy', fontsize=12)
ax1.legend()
ax1.grid(True)
# 2. 混淆矩阵的变化
colors = ['red', 'green', 'blue', 'purple']
for i, thr in enumerate([0.2, 0.5, 0.8]):
conf_matrix = conf_matrices[np.searchsorted(thresholds, thr)]
tn, fp, fn, tp = conf_matrix.ravel()
ax2.bar([i * 4, i * 4 + 1, i * 4 + 2, i * 4 + 3], [tn, fp, fn, tp], color=colors, width=0.8,
label=f'Threshold={thr:.1f}')
ax2.set_xticks([i * 4 + 1.5 for i in range(3)]) # 调整为每组的中心位置
ax2.set_xticklabels(['TN/FP', 'FN/TP', 'TP/FN'], fontsize=12)
ax2.set_title('Confusion Matrix Components at Different Thresholds', fontsize=14)
ax2.legend()
ax2.grid(True)
# 3. ROC曲线
ax3.plot(fpr, tpr, color='orange', label=f'ROC curve (area = {roc_auc:.2f})')
ax3.plot([0, 1], [0, 1], color='grey', linestyle='--')
ax3.set_title('ROC Curve', fontsize=14)
ax3.set_xlabel('False Positive Rate', fontsize=12)
ax3.set_ylabel('True Positive Rate', fontsize=12)
ax3.legend()
ax3.grid(True)
plt.tight_layout()
plt.show()
1. 生成虚拟数据集:y_true
是真实标签,y_scores
是模拟的分类器得分。
2. 阈值变化曲线:通过遍历多个不同的阈值来计算每个阈值下的准确率,并且绘制准确率随阈值的变化曲线。
3. 混淆矩阵变化图:选择了 0.2、0.5 和 0.8 三个阈值,展示不同阈值下混淆矩阵中的各个组件(TN、FP、FN、TP)的变化。
左图:展示了模型的准确率随阈值变化的趋势。 中图:展示了混淆矩阵中TN、FP、FN、TP的值在不同阈值下的变化情况。 右图:展示了ROC曲线,并标注了AUC值。
2. 精确率(Precision)
精确率(Precision)主要用于二分类问题,特别适用于当假阳性(FP)的代价较高时。精确率衡量在所有被预测为正类的样本中,真正为正类的比例。
原理
精确率适用于降低误报的场景,特别是当假阳性成本高昂时。例如在电子邮件分类中,如果将一封重要的邮件误判为垃圾邮件(FP),用户可能会错过重要信息。因此,我们希望在这种场景下提高精确率。
核心公式
推导
精确率定义为在预测为正类的样本中,真实的正类比例。推导的步骤如下:
1. 分母 表示模型预测为正类的所有样本数。这包括了正确预测为正类的样本 和错误预测为正类的样本 。
2. 分子 表示模型正确预测为正类的样本。
因此,精确率表示在所有预测为正类的样本中,正确预测的比例。
高精确率意味着模型在标记正类样本时更加保守,减少了错误警报。
Python案例
创建两个场景,一个是高精确率的情况,一个是低精确率的情况,并在同一张图中对这两种情况进行比较。
import numpy as np
import matplotlib.pyplot as plt
from sklearn.metrics import precision_score
# 设置随机种子以确保结果可重复
np.random.seed(42)
# 虚拟数据集: 场景1 (高精确率)
y_true_1 = np.random.randint(0, 2, 100)
y_pred_1 = y_true_1.copy() # 完全匹配,精确率高
# 虚拟数据集: 场景2 (低精确率)
y_true_2 = np.random.randint(0, 2, 100)
y_pred_2 = np.random.randint(0, 2, 100) # 随机预测,精确率低
# 计算精确率
precision_1 = precision_score(y_true_1, y_pred_1)
precision_2 = precision_score(y_true_2, y_pred_2)
# 绘图部分
fig, axs = plt.subplots(2, 1, figsize=(10, 12))
# 情境1:高精确率的可视化
axs[0].scatter(range(len(y_true_1)), y_true_1, color='green', label='True Labels', alpha=0.6)
axs[0].scatter(range(len(y_pred_1)), y_pred_1, color='blue', label='Predicted Labels', alpha=0.6)
axs[0].set_title(f"High Precision Scenario (Precision = {precision_1:.2f})", fontsize=14)
axs[0].legend(loc="upper right")
# 情境2:低精确率的可视化
axs[1].scatter(range(len(y_true_2)), y_true_2, color='green', label='True Labels', alpha=0.6)
axs[1].scatter(range(len(y_pred_2)), y_pred_2, color='red', label='Predicted Labels', alpha=0.6)
axs[1].set_title(f"Low Precision Scenario (Precision = {precision_2:.2f})", fontsize=14)
axs[1].legend(loc="upper right")
# 柱状图对比精确率
width = 0.3
x = np.array([1, 2])
plt.figure(figsize=(8, 6))
plt.bar(x[0], precision_1, width, color='blue', label='High Precision')
plt.bar(x[1], precision_2, width, color='red', label='Low Precision')
plt.xticks(x, ['High Precision', 'Low Precision'])
plt.ylim(0, 1)
plt.ylabel('Precision Score')
plt.title('Precision Comparison', fontsize=14)
plt.legend()
# 显示图像
plt.show()
1. 数据集生成:场景1:我们创建了一个虚拟数据集,预测值与真实标签完全匹配,精确率非常高。场景2:预测值与真实标签随机分配,导致精确率较低。
2. 精确率计算:使用 precision_score
计算两个场景的精确率。
1. 第一幅图 将展示两个散点图,一个显示高精确率场景,另一个显示低精确率场景。颜色鲜艳,易于区分。
2. 第二幅图 为柱状图,直观对比了不同情境下的精确率。
3. 召回率(Recall, 查全率)
召回率(Recall)表示在所有实际为正类的样本中,模型正确识别为正类的比例。它衡量模型识别正类样本的能力,适用于假阴性(FN)代价较高的场景。
原理
召回率侧重于捕获所有正类样本的能力。当假阴性的代价很高时(例如,癌症筛查漏掉病人的情况),召回率是非常重要的指标。在这种场景下,我们更愿意提高召回率,即使会增加假阳性(FP)。
核心公式
推导
召回率是基于真实为正类的样本总数计算的,推导过程如下:
1. 分母 表示所有真实为正类的样本数。包括了被正确预测为正类的样本 和被错误预测为负类的样本 。
2. 分子 表示被正确预测为正类的样本。
因此,召回率表示在所有真实为正类的样本中,模型正确预测为正类的比例:
高召回率意味着模型能够捕获更多的正类样本,但可能会导致更多的假阳性(FP)。
Python案例
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.metrics import confusion_matrix, precision_recall_curve, recall_score, precision_score
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.ensemble import RandomForestClassifier
# 生成虚拟数据集
X, y = make_classification(n_samples=1000, n_features=20, 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)
# 创建两个模型:逻辑回归和随机森林
model1 = LogisticRegression()
model2 = RandomForestClassifier()
# 训练模型
model1.fit(X_train, y_train)
model2.fit(X_train, y_train)
# 预测
y_pred1 = model1.predict(X_test)
y_pred2 = model2.predict(X_test)
# 计算混淆矩阵
cm1 = confusion_matrix(y_test, y_pred1)
cm2 = confusion_matrix(y_test, y_pred2)
# 计算每个模型的召回率
recall1 = recall_score(y_test, y_pred1)
recall2 = recall_score(y_test, y_pred2)
# 计算 Precision-Recall 曲线
precision1, recall_curve1, _ = precision_recall_curve(y_test, model1.predict_proba(X_test)[:, 1])
precision2, recall_curve2, _ = precision_recall_curve(y_test, model2.predict_proba(X_test)[:, 1])
# 创建画布,绘制多个图表
fig, axes = plt.subplots(2, 2, figsize=(14, 12))
# 1. 绘制第一个模型的混淆矩阵
sns.heatmap(cm1, annot=True, fmt='d', cmap='Blues', ax=axes[0, 0])
axes[0, 0].set_title(f'Confusion Matrix - Model 1 (Logistic Regression)')
axes[0, 0].set_xlabel('Predicted')
axes[0, 0].set_ylabel('Actual')
# 2. 绘制第二个模型的混淆矩阵
sns.heatmap(cm2, annot=True, fmt='d', cmap='Greens', ax=axes[0, 1])
axes[0, 1].set_title(f'Confusion Matrix - Model 2 (Random Forest)')
axes[0, 1].set_xlabel('Predicted')
axes[0, 1].set_ylabel('Actual')
# 3. 召回率对比条形图
axes[1, 0].bar(['Model 1 (Logistic Regression)', 'Model 2 (Random Forest)'],
[recall1, recall2], color=['skyblue', 'lightgreen'])
axes[1, 0].set_ylim([0, 1])
axes[1, 0].set_ylabel('Recall Score')
axes[1, 0].set_title('Recall Score Comparison')
# 4. 绘制 Precision-Recall 曲线
axes[1, 1].plot(recall_curve1, precision1, label='Model 1 (Logistic Regression)', color='blue', lw=2)
axes[1, 1].plot(recall_curve2, precision2, label='Model 2 (Random Forest)', color='green', lw=2)
axes[1, 1].set_title('Precision-Recall Curve')
axes[1, 1].set_xlabel('Recall')
axes[1, 1].set_ylabel('Precision')
axes[1, 1].legend()
# 显示图形
plt.tight_layout()
plt.show()
1. 数据生成:使用 make_classification
生成一个虚拟的二分类问题。
2. 模型训练:训练了两个分类模型(逻辑回归和随机森林)。
3. 混淆矩阵:展示每个模型的混淆矩阵,通过颜色和数字直观地展示模型分类的效果。
4. 召回率对比:通过条形图比较两个模型的召回率。
5. Precision-Recall 曲线:展示 precision 和 recall 的变化,分析模型在不同阈值下的权衡。
左上图和右上图是模型1(逻辑回归)和模型2(随机森林)的混淆矩阵。 左下图是两个模型的召回率对比。 右下图是两个模型的 Precision-Recall 曲线,展示精度和召回率在不同阈值下的关系。
4. F1-Score
F1-Score 是精确率(Precision)和召回率(Recall)的调和平均数,适用于需要在精确率和召回率之间进行权衡的情况。F1-Score 适用于类别不平衡的数据集。
原理
F1-Score 是精确率和召回率之间的折中。它避免了单独使用精确率或召回率可能带来的偏差,因为在某些情况下,提高精确率会降低召回率,反之亦然。F1-Score 提供了一个折中的指标来综合评估模型。
核心公式
推导
F1-Score 是精确率和召回率的调和平均数,它比算术平均数更能平衡两个指标的影响。其推导过程如下:
调和平均数公式为:
其中 和 。
将精确率和召回率代入调和平均数公式,可以得到:
F1-Score 在精确率和召回率之间找到了一个平衡,当这两个值差异较大时,F1-Score 会趋向较小的那个值。
Python案例
import numpy as np
import matplotlib.pyplot as plt
from sklearn.metrics import f1_score, precision_recall_curve, roc_curve, confusion_matrix
import seaborn as sns
# Generating a virtual dataset
np.random.seed(42)
y_true = np.random.randint(0, 2, size=100)
y_pred_prob = np.random.rand(100)
# Converting probabilities to binary predictions using a threshold
threshold = 0.5
y_pred = (y_pred_prob >= threshold).astype(int)
# Calculating F1-Score
f1 = f1_score(y_true, y_pred)
# Precision-Recall Curve
precision, recall, _ = precision_recall_curve(y_true, y_pred_prob)
# ROC Curve
fpr, tpr, _ = roc_curve(y_true, y_pred_prob)
# Confusion Matrix
cm = confusion_matrix(y_true, y_pred)
# Plotting
fig, ax = plt.subplots(1, 3, figsize=(18, 6))
# Plot Precision-Recall Curve
ax[0].plot(recall, precision, marker='o', color='purple', label='Precision-Recall Curve', linewidth=2)
ax[0].set_title('Precision-Recall Curve', fontsize=14)
ax[0].set_xlabel('Recall', fontsize=12)
ax[0].set_ylabel('Precision', fontsize=12)
ax[0].legend()
# Plot ROC Curve
ax[1].plot(fpr, tpr, marker='x', color='green', label='ROC Curve', linewidth=2)
ax[1].plot([0, 1], [0, 1], linestyle='--', color='gray')
ax[1].set_title('ROC Curve', fontsize=14)
ax[1].set_xlabel('False Positive Rate', fontsize=12)
ax[1].set_ylabel('True Positive Rate', fontsize=12)
ax[1].legend()
# Plot Confusion Matrix
sns.heatmap(cm, annot=True, fmt='d', cmap='Blues', ax=ax[2], cbar=False)
ax[2].set_title(f'Confusion Matrix (F1-Score: {f1:.2f})', fontsize=14)
ax[2].set_xlabel('Predicted', fontsize=12)
ax[2].set_ylabel('Actual', fontsize=12)
plt.tight_layout()
plt.show()
上面是一个虚拟数据集上的F1-Score评估的示例。图中包含的三种指标分析图形:
1. Precision-Recall Curve(精确率-召回率曲线):展示了不同阈值下模型的精确率和召回率之间的权衡。
2. ROC Curve(接收者操作特征曲线):展示了模型在不同阈值下的假阳性率和真正例率。
3. Confusion Matrix(混淆矩阵):提供了模型预测结果的详细分类情况,并且在图中标注了F1-Score的值。
5. ROC 曲线和 AUC(ROC Curve & AUC)
ROC 曲线(Receiver Operating Characteristic Curve)展示了分类模型在不同阈值下的性能表现。AUC(Area Under Curve)则是 ROC 曲线下面的面积,用来衡量模型的整体分类性能。
原理
ROC 曲线绘制了假阳性率(FPR)和真阳性率(TPR)之间的关系,AUC 则衡量模型区分正负类的能力。AUC 的取值范围是 0 到 1,1 表示完美分类器,0.5 表示随机猜测。
核心公式
真阳性率(TPR 或 Recall):
假阳性率(FPR):
AUC 是 ROC 曲线下面的面积,通过数值积分计算。
推导
1. ROC 曲线的绘制:通过调整分类阈值(如逻辑回归中的决策阈值),计算不同阈值下的真阳性率和假阳性率,绘制出 ROC 曲线。
2. AUC 的计算:AUC 是 ROC 曲线下的面积,表示模型在不同阈值下区分正类和负类的能力。AUC 的几何意义为,当随机选择一个正类样本和一个负类样本时,模型将正类样本排在负类样本前面的概率。
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.linear_model import LogisticRegression
from sklearn.metrics import roc_curve, auc, confusion_matrix
import seaborn as sns
# 创建虚拟数据集
X, y = make_classification(n_samples=1000, n_features=20, 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)
# 创建并训练逻辑回归模型
model = LogisticRegression()
model.fit(X_train, y_train)
# 预测概率
y_probs = model.predict_proba(X_test)[:, 1] # 获取正类的概率
y_pred = model.predict(X_test)
# 计算ROC曲线
fpr, tpr, thresholds = roc_curve(y_test, y_probs)
roc_auc = auc(fpr, tpr)
# 计算混淆矩阵
cm = confusion_matrix(y_test, y_pred)
# 创建第二个虚拟模型(为了展示不同的ROC和AUC)
y_probs_2 = np.random.uniform(0, 1, size=len(y_test)) # 模拟一个随机模型
fpr_2, tpr_2, thresholds_2 = roc_curve(y_test, y_probs_2)
roc_auc_2 = auc(fpr_2, tpr_2)
# 创建图像
plt.figure(figsize=(14, 6))
# ROC曲线子图
plt.subplot(1, 2, 1)
plt.plot(fpr, tpr, color='darkorange', lw=2, label=f'Model 1 ROC curve (AUC = {roc_auc:.2f})')
plt.plot(fpr_2, tpr_2, color='blue', lw=2, label=f'Model 2 ROC curve (AUC = {roc_auc_2:.2f})')
plt.plot([0, 1], [0, 1], color='navy', lw=2, linestyle='--')
plt.xlim([0.0, 1.0])
plt.ylim([0.0, 1.05])
plt.xlabel('False Positive Rate', fontsize=14)
plt.ylabel('True Positive Rate', fontsize=14)
plt.title('Receiver Operating Characteristic (ROC)', fontsize=16)
plt.legend(loc="lower right")
# 混淆矩阵热力图子图
plt.subplot(1, 2, 2)
sns.heatmap(cm, annot=True, fmt='d', cmap='coolwarm', cbar=False, annot_kws={"size": 16})
plt.title('Confusion Matrix', fontsize=16)
plt.xlabel('Predicted Label', fontsize=14)
plt.ylabel('True Label', fontsize=14)
# 调整布局并显示图像
plt.tight_layout()
plt.show()
1. 虚拟数据集的创建:我们使用make_classification
生成一个包含1000个样本和20个特征的二分类数据集。
2. 模型训练:使用逻辑回归模型(Logistic Regression)在训练数据上进行训练。
3. 预测与评估:
计算逻辑回归模型的ROC曲线和AUC值。 生成第二个模型的ROC曲线,该模型是一个随机预测模型,用来对比不同模型的性能。
左侧为两个模型的ROC曲线及其AUC。 右侧为逻辑回归模型的混淆矩阵热力图。
6. 平均绝对误差(MAE, Mean Absolute Error)
MAE 是一种用于回归任务的评估指标。它衡量预测值与实际值之间的绝对误差的平均值。
原理
MAE 提供了对误差的线性衡量方式,即每个预测误差对整体误差的贡献相同。相比于平方误差,MAE 对异常值不敏感。
核心公式
推导
MAE 是每个预测与实际值之差的绝对值的平均值。通过对 个样本的误差求和并取平均,我们得到:
其中, 是第 个样本的真实值, 是第 个样本的预测值。MAE 计算的是误差的绝对值,确保所有误差的正负符号不会相互抵消。
Python案例
两个不同场景:
1. 线性回归的预测误差:使用随机生成的数据,拟合一条线性模型,然后计算 MAE。
2. 时间序列预测误差:模拟一个简单的时间序列,计算预测值和真实值的 MAE。
import numpy as np
import matplotlib.pyplot as plt
from sklearn.metrics import mean_absolute_error
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_split
# 设置随机种子以便复现
np.random.seed(42)
# 案例 1: 线性回归预测误差
# 生成随机线性数据
X = 2 * np.random.rand(100, 1)
y_true = 4 + 3 * X + np.random.randn(100, 1)
# 拆分数据集
X_train, X_test, y_train, y_test = train_test_split(X, y_true, test_size=0.2)
# 创建线性模型并训练
lin_reg = LinearRegression()
lin_reg.fit(X_train, y_train)
# 预测
y_pred = lin_reg.predict(X_test)
# 计算 MAE
mae_linear = mean_absolute_error(y_test, y_pred)
# 案例 2: 时间序列预测误差
# 生成简单的时间序列数据
time = np.arange(0, 50)
true_series = np.sin(time) + 0.1 * np.random.randn(50)
predicted_series = np.sin(time) + 0.2 * np.random.randn(50)
# 计算 MAE
mae_series = mean_absolute_error(true_series, predicted_series)
# 画图部分
fig, ax = plt.subplots(2, 2, figsize=(12, 8))
fig.suptitle('MAE Error Analysis for Different Cases', fontsize=16)
# 案例 1: 线性回归的散点图和回归线
ax[0, 0].scatter(X_test, y_test, color='blue', label='Actual')
ax[0, 0].plot(X_test, y_pred, color='red', label='Predicted', linewidth=2)
ax[0, 0].set_title('Linear Regression Fit')
ax[0, 0].set_xlabel('X')
ax[0, 0].set_ylabel('y')
ax[0, 0].legend()
ax[0, 0].grid(True)
# 案例 1: 残差图
residuals = y_test - y_pred
ax[0, 1].scatter(X_test, residuals, color='green', label='Residuals')
ax[0, 1].axhline(0, color='red', linestyle='--', linewidth=2)
ax[0, 1].set_title(f'Residuals (MAE: {mae_linear:.2f})')
ax[0, 1].set_xlabel('X')
ax[0, 1].set_ylabel('Residuals')
ax[0, 1].legend()
ax[0, 1].grid(True)
# 案例 2: 时间序列图
ax[1, 0].plot(time, true_series, color='blue', label='Actual Series', marker='o')
ax[1, 0].plot(time, predicted_series, color='red', linestyle='--', label='Predicted Series', marker='x')
ax[1, 0].set_title('Time Series Prediction')
ax[1, 0].set_xlabel('Time')
ax[1, 0].set_ylabel('Value')
ax[1, 0].legend()
ax[1, 0].grid(True)
# 案例 2: 时间序列误差
time_residuals = true_series - predicted_series
ax[1, 1].plot(time, time_residuals, color='purple', label='Residuals', marker='s')
ax[1, 1].axhline(0, color='black', linestyle='--', linewidth=2)
ax[1, 1].set_title(f'Time Series Residuals (MAE: {mae_series:.2f})')
ax[1, 1].set_xlabel('Time')
ax[1, 1].set_ylabel('Residuals')
ax[1, 1].legend()
ax[1, 1].grid(True)
# 显示图像
plt.tight_layout(rect=[0, 0, 1, 0.96])
plt.show()
1. 线性回归案例:
生成一个简单的线性模型并加入噪声。 拆分训练和测试集,并使用线性回归模型进行拟合和预测。 绘制散点图和回归线、残差图,计算 MAE。
2. 时间序列案例:
使用 sin()
函数模拟一个周期性时间序列,并加上噪声来生成真实值和预测值。绘制真实和预测的时间序列图、残差图,并计算 MAE。
第一行(线性回归案例):左图为散点图和回归线,右图为残差图。 第二行(时间序列案例):左图为时间序列预测图,右图为时间序列残差图。
7. 均方误差(MSE, Mean Squared Error)
MSE 是另一种回归任务的评估指标。它计算预测值与实际值之间差异的平方和的平均值。
原理
与 MAE 不同,MSE 给大误差分配了更大的惩罚,因为误差是平方的,因此它对异常值更敏感。在某些场景下,MSE 被广泛应用于优化目标函数。
核心公式
推导
MSE 是预测值与实际值之间差异的平方的平均值。具体推导如下:
通过对误差平方求和,MSE 能够强调较大的误差对总体误差的影响,因此在应对异常值时表现敏感。
Python案例
这个案例比较了线性回归模型和多项式回归模型的预测效果,并计算了它们各自的MSE。最后,我们绘制出两个图形:真实数据和预测数据的散点图,以及误差随模型复杂度的变化图。
import numpy as np
import matplotlib.pyplot as plt
from sklearn.linear_model import LinearRegression
from sklearn.preprocessing import PolynomialFeatures
from sklearn.metrics import mean_squared_error
# 生成虚拟数据
np.random.seed(0)
X = np.sort(5 * np.random.rand(80, 1), axis=0)
y = np.sin(X).ravel() + np.random.normal(0, 0.2, X.shape[0])
# 线性回归模型
linear_regressor = LinearRegression()
linear_regressor.fit(X, y)
y_pred_linear = linear_regressor.predict(X)
# 多项式回归模型(2阶、4阶、6阶)
degrees = [2, 4, 6]
mse_values = []
plt.figure(figsize=(12, 6))
# 绘制真实数据和线性回归拟合数据
plt.subplot(1, 2, 1)
plt.scatter(X, y, color='blue', label="True data", alpha=0.6)
plt.plot(X, y_pred_linear, color='green', linewidth=2, label="Linear Regression", alpha=0.8)
# 多项式拟合
colors = ['red', 'orange', 'purple']
for i, degree in enumerate(degrees):
poly = PolynomialFeatures(degree=degree)
X_poly = poly.fit_transform(X)
poly_regressor = LinearRegression()
poly_regressor.fit(X_poly, y)
y_pred_poly = poly_regressor.predict(X_poly)
plt.plot(X, y_pred_poly, color=colors[i], linewidth=2, label=f"Poly degree {degree}", alpha=0.8)
# 计算并存储MSE
mse = mean_squared_error(y, y_pred_poly)
mse_values.append(mse)
# 设置图像属性
plt.title('True Data vs Model Predictions')
plt.xlabel('X')
plt.ylabel('y')
plt.legend(loc='best', fontsize=10)
plt.grid(True)
# 绘制模型复杂度(阶数)与MSE的关系图
plt.subplot(1, 2, 2)
plt.plot([1] + degrees, [mean_squared_error(y, y_pred_linear)] + mse_values, marker='o', color='black', linewidth=2)
plt.title('Model Complexity (Degree) vs MSE')
plt.xlabel('Polynomial Degree')
plt.ylabel('Mean Squared Error')
plt.xticks([1] + degrees)
plt.grid(True)
# 显示图像
plt.tight_layout()
plt.show()
1. 数据生成:生成了随机的虚拟数据,X值在0到5之间,y值是X的正弦值加上噪声。
2. 模型构建:使用了线性回归和多项式回归模型,分别拟合数据,其中多项式回归有2阶、4阶和6阶的不同复杂度。
3. MSE计算:对每种模型,计算其MSE,比较模型的拟合效果。
通过左边的图,我们可以直观地看到线性回归和不同阶数的多项式回归的拟合效果。 通过右边的图,我们可以分析模型复杂度与MSE的关系,观察到随着多项式阶数增加,MSE的变化情况。
8. R² 决定系数(R-squared)
R² 是一种评估回归模型拟合优度的指标。它表示模型解释了多少方差,值范围为 0 到 1。
原理
R² 衡量模型对数据的拟合效果,值越接近 1 表示模型对数据的拟合越好,值为 0 表示模型与随机猜测无异。
核心公式
推导
R² 的推导基于残差平方和()与总平方和():
其中, 是残差平方和,表示模型的预测误差; 是总平方和,表示数据的总变异性。
Python案例
以下是一个包含不同R²(决定系数)评估的案例,涉及两个模型:一个是线性回归模型,另一个是多项式回归模型。我们将通过虚拟数据集展示它们的拟合效果,并使用图像分析这两个模型的拟合程度。
import numpy as np
import matplotlib.pyplot as plt
from sklearn.linear_model import LinearRegression
from sklearn.preprocessing import PolynomialFeatures
from sklearn.metrics import r2_score
# 生成虚拟数据集
np.random.seed(42)
X = np.linspace(0, 10, 100).reshape(-1, 1) # 特征
y = 0.5 * X**2 + X + 2 + np.random.randn(100, 1) * 5 # 目标值,带有噪声的二次方程
# 线性回归模型
linear_model = LinearRegression()
linear_model.fit(X, y)
y_pred_linear = linear_model.predict(X)
# 多项式回归模型(2阶多项式)
poly_features = PolynomialFeatures(degree=2)
X_poly = poly_features.fit_transform(X)
poly_model = LinearRegression()
poly_model.fit(X_poly, y)
y_pred_poly = poly_model.predict(X_poly)
# 计算 R² 值
r2_linear = r2_score(y, y_pred_linear)
r2_poly = r2_score(y, y_pred_poly)
# 绘图
plt.figure(figsize=(10, 6))
# 原始数据的散点图
plt.scatter(X, y, color='blue', label='Data (with noise)', alpha=0.6)
# 线性回归拟合曲线
plt.plot(X, y_pred_linear, color='red', linewidth=2, label=f'Linear Fit (R² = {r2_linear:.2f})')
# 多项式回归拟合曲线
plt.plot(X, y_pred_poly, color='green', linewidth=2, label=f'Polynomial Fit (R² = {r2_poly:.2f})')
# 图像标题和标签
plt.title('Linear vs Polynomial Regression', fontsize=16, fontweight='bold')
plt.xlabel('X', fontsize=14)
plt.ylabel('y', fontsize=14)
plt.legend(fontsize=12)
# 显示图像
plt.grid(True)
plt.show()
1. 生成数据:我们生成了100个点的虚拟数据集,遵循二次方程 y = 0.5 * X^2 + X + 2
,并添加了一些噪声,使数据更复杂且更具挑战性。
2. 线性回归:使用 LinearRegression
对数据进行线性回归拟合,计算出其 R² 值。
3. 多项式回归:使用 PolynomialFeatures
生成2阶多项式特征,并使用线性回归进行拟合,计算其 R² 值。
4. 绘图:在同一个图中绘制原始数据的散点图、线性拟合曲线、多项式拟合曲线,并在图例中标注每个模型的 R² 值。
蓝色点:代表原始的带噪声数据。 红色线:线性回归的拟合曲线。 绿色线:多项式回归的拟合曲线。
通过这个案例,可以看到多项式回归模型比线性回归模型更好地拟合了数据,因此它的 R² 值会更高。
9. 轮廓系数(Silhouette Score)
轮廓系数是一种评估聚类结果的指标。它度量样本与其所属簇的相似度与其与最近邻簇之间的相似度的差异。
原理
轮廓系数的取值范围为 -1 到 1,值越接近 1 表示聚类效果越好。
核心公式
其中:
是样本 到其所属簇内其他点的平均距离。 是样本 到最近邻簇的平均距离。
推导
轮廓系数计算了样本与其所属簇的相似度()和与最近簇的相似度()。通过计算两个值的差异并归一化,轮廓系数能够衡量聚类的紧密性和分离性。
Python案例
轮廓系数(Silhouette Score)用于评估聚类结果的质量。它的值介于 -1 到 1 之间,值越接近 1 表示聚类效果越好,越接近 -1 表示样本被错误聚类,接近 0 表示样本可能在两个簇的边界上。
生成一个包含两个类别的数据集,然后分别使用 KMeans 和 Agglomerative Clustering 对数据进行聚类,接着计算它们的轮廓系数,并将结果可视化。
import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import make_blobs
from sklearn.cluster import KMeans, AgglomerativeClustering
from sklearn.metrics import silhouette_score, silhouette_samples
import matplotlib.cm as cm
# 生成虚拟数据集
n_samples = 1000
n_features = 2
n_clusters = 4
random_state = 42
X, y = make_blobs(n_samples=n_samples, centers=n_clusters, n_features=n_features, random_state=random_state)
# 定义聚类算法
kmeans = KMeans(n_clusters=n_clusters, random_state=random_state)
agglo = AgglomerativeClustering(n_clusters=n_clusters)
# 聚类结果
y_kmeans = kmeans.fit_predict(X)
y_agglo = agglo.fit_predict(X)
# 计算轮廓系数
silhouette_avg_kmeans = silhouette_score(X, y_kmeans)
silhouette_avg_agglo = silhouette_score(X, y_agglo)
# 计算每个样本的轮廓系数
sample_silhouette_values_kmeans = silhouette_samples(X, y_kmeans)
sample_silhouette_values_agglo = silhouette_samples(X, y_agglo)
# 创建子图
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(18, 8))
fig.suptitle('Silhouette Analysis for KMeans and Agglomerative Clustering', fontsize=16, fontweight='bold')
# 左图:KMeans聚类的轮廓分析
ax1.set_xlim([-0.1, 1])
ax1.set_ylim([0, len(X) + (n_clusters + 1) * 10])
# 绘制每个簇的轮廓系数条形图
y_lower = 10
for i in range(n_clusters):
ith_cluster_silhouette_values = sample_silhouette_values_kmeans[y_kmeans == 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) / n_clusters)
ax1.fill_betweenx(np.arange(y_lower, y_upper), 0, ith_cluster_silhouette_values, facecolor=color, edgecolor=color, alpha=0.7)
ax1.text(-0.05, y_lower + 0.5 * size_cluster_i, str(i))
y_lower = y_upper + 10
ax1.set_title(f"KMeans Silhouette Score: {silhouette_avg_kmeans:.2f}")
ax1.set_xlabel("Silhouette Coefficient Values")
ax1.set_ylabel("Cluster Label")
ax1.axvline(x=silhouette_avg_kmeans, color="red", linestyle="--")
ax1.set_yticks([])
# 右图:Agglomerative Clustering的轮廓分析
ax2.set_xlim([-0.1, 1])
ax2.set_ylim([0, len(X) + (n_clusters + 1) * 10])
# 绘制每个簇的轮廓系数条形图
y_lower = 10
for i in range(n_clusters):
ith_cluster_silhouette_values = sample_silhouette_values_agglo[y_agglo == 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) / n_clusters)
ax2.fill_betweenx(np.arange(y_lower, y_upper), 0, ith_cluster_silhouette_values, facecolor=color, edgecolor=color, alpha=0.7)
ax2.text(-0.05, y_lower + 0.5 * size_cluster_i, str(i))
y_lower = y_upper + 10
ax2.set_title(f"Agglomerative Clustering Silhouette Score: {silhouette_avg_agglo:.2f}")
ax2.set_xlabel("Silhouette Coefficient Values")
ax2.set_ylabel("Cluster Label")
ax2.axvline(x=silhouette_avg_agglo, color="red", linestyle="--")
ax2.set_yticks([])
# 绘制散点图
fig, (ax3, ax4) = plt.subplots(1, 2, figsize=(18, 8))
colors = cm.nipy_spectral(y_kmeans.astype(float) / n_clusters)
ax3.scatter(X[:, 0], X[:, 1], marker='o', s=50, lw=0, alpha=0.7, c=colors, edgecolor='k')
ax3.set_title("KMeans Clustering", fontsize=14)
ax3.set_xlabel("Feature 1")
ax3.set_ylabel("Feature 2")
colors = cm.nipy_spectral(y_agglo.astype(float) / n_clusters)
ax4.scatter(X[:, 0], X[:, 1], marker='o', s=50, lw=0, alpha=0.7, c=colors, edgecolor='k')
ax4.set_title("Agglomerative Clustering", fontsize=14)
ax4.set_xlabel("Feature 1")
ax4.set_ylabel("Feature 2")
plt.tight_layout()
plt.show()
1. 数据生成:使用 make_blobs
生成了一个包含 4 个中心的虚拟数据集,每个样本有 2 个特征。
2. 聚类:使用 KMeans
和 Agglomerative Clustering
进行了两次聚类。
3. 轮廓系数计算:分别计算了两种聚类方法的轮廓系数(Silhouette Score)以及每个样本的轮廓系数。
左右两幅图展示了 KMeans 和 Agglomerative Clustering 的轮廓系数分析。 每个簇用不同的颜色表示,并且图中显示了每个簇的轮廓系数分布。 两幅图的红色虚线表示轮廓系数的平均值。 下方的两幅散点图展示了 KMeans 和 Agglomerative Clustering 的聚类结果。
10. 混淆矩阵(Confusion Matrix)
混淆矩阵用于评估分类模型的性能。它展示了模型预测结果与真实结果的比较。
原理
混淆矩阵不仅包含正确分类的样本数,还详细列出了误分类的样本数,使得我们能更好地理解模型的性能。
核心公式
混淆矩阵是一个 的矩阵(对于二分类问题),包含以下四个值:
: 真阳性 : 真阴性 : 假阳性 : 假阴性
推导
混淆矩阵通过展示四类结果()来详细描述模型预测的结果,便于进一步计算其他指标如精确率、召回率等。
Python案例
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.metrics import confusion_matrix, classification_report
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
# 设置随机种子
np.random.seed(42)
# 生成虚拟二分类数据集
X, y = make_classification(n_samples=1000, n_features=20, n_classes=2, n_clusters_per_class=2, flip_y=0.03)
# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
# 使用随机森林模型进行训练
clf = RandomForestClassifier(random_state=42)
clf.fit(X_train, y_train)
# 进行预测
y_pred = clf.predict(X_test)
# 计算混淆矩阵
cm = confusion_matrix(y_test, y_pred)
# 打印分类报告
print(classification_report(y_test, y_pred))
# 设置图形的大小和布局
plt.figure(figsize=(14, 7))
# 第一个图:混淆矩阵的热力图
plt.subplot(1, 2, 1)
sns.heatmap(cm, annot=True, fmt='d', cmap='coolwarm', cbar=False, annot_kws={"size": 16}, linewidths=2, linecolor='black')
plt.title('Confusion Matrix Heatmap', fontsize=18)
plt.xlabel('Predicted Label', fontsize=14)
plt.ylabel('True Label', fontsize=14)
# 第二个图:预测结果的柱状图
plt.subplot(1, 2, 2)
unique, counts = np.unique(y_pred, return_counts=True)
sns.barplot(x=unique, y=counts, palette="Set2")
plt.title('Prediction Result Bar Chart', fontsize=18)
plt.xlabel('Predicted Class', fontsize=14)
plt.ylabel('Count', fontsize=14)
# 调整布局
plt.tight_layout()
# 显示图像
plt.show()
1. 数据生成:我们使用 make_classification
来生成一个具有 1000 个样本、20 个特征、2 个类别的数据集,并引入了一定的噪声。
2. 模型训练:使用 RandomForestClassifier
对数据进行训练,并对测试集进行预测。
混淆矩阵:使用 confusion_matrix
来生成混淆矩阵,并通过 seaborn
的 heatmap
进行可视化,使用鲜艳的颜色显示矩阵中的分类情况。
柱状图:统计预测结果的数量分布,并使用柱状图进行可视化。
最后