# 第一个代码:KNN 鸢尾花分类

使用 sklearn

# 基础库  
import matplotlib.pyplot as plt  
  
import matplotlib  
matplotlib.rcParams['font.sans-serif'] = ['SimHei']  
matplotlib.rcParams['axes.unicode_minus'] = False  
  
# sklearn 模块  
from sklearn import datasets  
from sklearn.model_selection import train_test_split  
from sklearn.preprocessing import StandardScaler  
from sklearn.neighbors import KNeighborsClassifier  
from sklearn.metrics import accuracy_score, confusion_matrix  
  
# 加载内置数据集(鸢尾花)  
iris = datasets.load_iris()  
X = iris.data  # 特征 (150 个样本 x 4 个特征)  
y = iris.target  # 标签 (0,1,2 对应三种花)  
  
# 查看数据  
print("特征名:", iris.feature_names)  
print("标签名:", iris.target_names)  
  
# 划分训练集 / 测试集 (70% 训练,30% 测试)  
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)  # 注意:使用相同的 scaler 转换  
  
# 初始化 KNN 分类器(k=3)  
model = KNeighborsClassifier(n_neighbors=3)  
  
# 训练模型  
model.fit(X_train, y_train)  
  
# 预测测试集  
y_pred = model.predict(X_test)  
  
# 计算准确率  
accuracy = accuracy_score(y_test, y_pred)  
print(f"模型准确率: {accuracy:.2%}")  
  
# 混淆矩阵(可视化错误)  
cm = confusion_matrix(y_test, y_pred)  
print("混淆矩阵:\n", cm)  
  
# 选择两个特征进行二维可视化(可选)  
plt.scatter(X_test[:, 0], X_test[:, 1], c=y_pred, cmap='viridis', s=50)  
plt.xlabel(iris.feature_names[0])  
plt.ylabel(iris.feature_names[1])  
plt.title("鸢尾花分类结果 (KNN)")  
plt.colorbar(ticks=[0,1,2], label='花种类')  
plt.show()

这个代码是 ds 写的。

# 简要流程

# 1. 数据集引入与划分

  • 需要导入特征与标签。以本代码为例,特征有四个维度,标签有三类:
特征名: ['sepal length (cm)', 'sepal width (cm)', 'petal length (cm)', 'petal width (cm)']
标签名: ['setosa' 'versicolor' 'virginica']
  • 此外,还需要进行训练集与测试集的划分。我们使用 train_test_split 函数
    • random_state  :机器学习中控制随机性的关键参数。核心作用:保证结果可复现性
    • 就相当于一个种子,你固定了这个种子,那它后面划分训练集与测试集就只会以这种方式划分。

# 2. 特征标准化

scaler = StandardScaler()  # 创建标准化器
X_train = scaler.fit_transform(X_train)  # 训练并转换训练集
X_test = scaler.transform(X_test)  # 转换测试集(使用训练集的参数)
  1. 中心化处理(Centering)
    • 将每个特征的均值变为 0
    • 计算公式: x_new = (x - μ)
    • 其中 μ 是特征的均值
  2. 缩放处理(Scaling)
    • 将每个特征的标准差变为 1
    • 计算公式: x_new = (x - μ) / σ
    • 其中 σ 是特征的标准差

标准化后的特征满足:

  • 均值 = 0
  • 标准差 = 1
  • 分布形状不变(只是平移和缩放)

为什么需要标准化?

  1. 解决特征尺度不一致问题
    • 例如鸢尾花数据集中:
      • 萼片长度:4.3-7.9 cm
      • 萼片宽度:2.0-4.4 cm
    • 若不标准化,范围大的特征会主导距离计算
  2. 提高算法性能
    • 基于距离的算法(KNN、SVM):避免大范围特征主导距离计算
    • 基于梯度的算法(线性回归、神经网络):加速收敛,避免振荡
    • 正则化模型:使正则化项对所有特征公平作用
  3. 提高数值稳定性
    • 防止计算中出现极大或极小的数值
    • 减少浮点数计算误差

步骤分解:
1.  scaler = StandardScaler()

  • 创建一个标准化转换器对象
  • 此时尚未计算任何统计量
    2.  X_train = scaler.fit_transform(X_train)
  • 两步操作合二为一
    1. fit() :计算训练集的统计量
      • 计算每个特征的均值 (μ) 和标准差 (σ)
      • 公式:
        μ=Σxi/Nμ = Σx_i / N
        σ=[Σ(xiμ)²/N]σ = √[Σ(x_i - μ)² / N]
    2. transform() :应用转换
      • 对每个特征值:xnew=(xμ)/σx_new = (x - μ) / σ
      • 转换后:每个特征的均值 = 0,标准差 = 1
        3.  X_test = scaler.transform(X_test)
  • 仅使用训练集计算的参数
    • 使用训练集计算出的 μ 和 σ
    • 不对测试集重新计算统计量(根本原因:防止数据泄露

# 3. 模型训练

model = KNeighborsClassifier(n_neighbors=3)
model.fit(X_train, y_train)
  • 作用:创建 KNN 分类器并训练模型
  • 对应环节:模型训练
  • 关键点
    • KNN 算法原理:根据最近邻的 K 个样本投票决定分类
    • n_neighbors=3  是超参数(可调整)
    • fit()  方法学习训练数据的特征模式

# 4. 模型评估

  • 作用:评估模型在未知数据上的表现
  • 对应环节:模型评估
  • 关键点
    • 准确率 = 正确预测数 / 总样本数
    • 混淆矩阵显示:
      • 行:真实类别
      • 列:预测类别
      • 对角线:正确分类的样本
        比如:
预测类别
         类0    类1    类2
真 类0 [ 19,    0,     0  ]
实 类1 [  0,   13,     0  ]
类 类2 [  0,    0,    13  ]

# 第二个代码:乳腺癌判断

还是 ds 写的代码。

# === 1. 导入库 ===import numpy as np  
import pandas as pd  
import matplotlib.pyplot as plt  
import matplotlib  
  
# 设置中文字体  
matplotlib.rcParams['font.sans-serif'] = ['SimHei', 'Microsoft YaHei']  
matplotlib.rcParams['axes.unicode_minus'] = False  
  
from sklearn.datasets import load_breast_cancer  
from sklearn.model_selection import train_test_split, cross_val_score  
from sklearn.preprocessing import StandardScaler  
from sklearn.svm import SVC  
from sklearn.naive_bayes import GaussianNB  # PGM 的代表(朴素贝叶斯)  
from sklearn.tree import DecisionTreeClassifier, plot_tree  
from sklearn.metrics import accuracy_score, confusion_matrix, classification_report  
from mlxtend.plotting import plot_decision_regions  # 决策边界可视化  
  
# === 2. 加载和探索数据 ===data = load_breast_cancer () # 数据集  
X = data.data # 特征  
y = data.target # 标签  
feature_names = data.feature_names # 特征名  
target_names = data.target_names # 标签名  
  
print(f"数据集形状: {X.shape}") 
print(f"特征数: {len(feature_names)}")  
print(f"类别分布: {np.bincount(y)} (0={target_names[0]}, 1={target_names[1]})")  
  
# 创建 DataFrame 便于分析  
df = pd.DataFrame(X, columns=feature_names) #  
df['target'] = y  
print("\n特征统计信息:")  
print(df.describe())  
  
# === 3. 数据预处理 ===# 划分训练集 / 测试集  
# stratify=y 表示在划分数据时保持每个类别的比例与原数据集一致  
X_train, X_test, y_train, y_test = train_test_split(  
    X, y, test_size=0.2, random_state=42, stratify=y  
)  
  
# 特征标准化  
scaler = StandardScaler()  
X_train_scaled = scaler.fit_transform(X_train)  
X_test_scaled = scaler.transform(X_test)  
  
# 选择两个主要特征进行可视化 (平均半径和平均纹理)  
X_train_vis = X_train_scaled[:, :2]  # 前两个特征  
X_test_vis = X_test_scaled[:, :2]  
  
  
# === 4. 训练多种模型 ===# 向量机,朴素贝叶斯,决策树  
models = {  
    "SVM": SVC(kernel='rbf', C=1.0, gamma='scale', probability=True, random_state=42),  
    "Naive Bayes (PGM)": GaussianNB(),  
    "Decision Tree": DecisionTreeClassifier(max_depth=3, random_state=42)  
}  
  
# 训练并评估每个模型  
results = {}  
for name, model in models.items():  
    # 训练模型  
    model.fit(X_train_scaled, y_train)  
  
    # 预测  
    y_pred = model.predict(X_test_scaled)  
  
    # 评估  
    accuracy = accuracy_score(y_test, y_pred)  
    cm = confusion_matrix(y_test, y_pred)  
    report = classification_report(y_test, y_pred, target_names=target_names)  
  
    # 存储结果  
    results[name] = {  
        'model': model,  
        'accuracy': accuracy,  
        'confusion_matrix': cm,  
        'report': report  
    }  
  
    # 交叉验证  
    cv_scores = cross_val_score(model, X_train_scaled, y_train, cv=5)  
  
    print(f"\n=== {name} ===")  
    print(f"测试集准确率: {accuracy:.2%}")  
    print(f"5折交叉验证平均准确率: {np.mean(cv_scores):.2%} ± {np.std(cv_scores):.2%}")  
    print("分类报告:\n", report)  
  
# === 5. 可视化比较 ===plt.figure (figsize=(18, 12))  
  
# 绘制决策边界  
for i, (name, result) in enumerate(results.items(), 1):  
    model = result['model']  
  
    # 为可视化重新训练只使用前 2 个特征的模型  
    if name == "SVM":  
        model_vis = SVC(kernel='rbf', C=1.0, gamma='scale', probability=True, random_state=42)  
        model_vis.fit(X_train_vis, y_train)  
    elif name == "Naive Bayes (PGM)":  
        model_vis = GaussianNB()  
        model_vis.fit(X_train_vis, y_train)  
    elif name == "Decision Tree":  
        model_vis = DecisionTreeClassifier(max_depth=3, random_state=42)  
        model_vis.fit(X_train_vis, y_train)  
  
    plt.subplot(2, 3, i)  
    plot_decision_regions(X_train_vis, y_train, clf=model_vis, legend=2)  
    plt.title(f"{name} 决策边界")  
    plt.xlabel(feature_names[0])  
    plt.ylabel(feature_names[1])  
  
    # 添加测试集点  
    plt.scatter(X_test_vis[:, 0], X_test_vis[:, 1], c=y_test,  
                edgecolors='k', alpha=0.7, marker='o', s=80,  
                cmap=plt.cm.coolwarm, label='测试集')  
  
  
# 绘制决策树结构  
plt.subplot(2, 3, 4)  
plot_tree(models["Decision Tree"],  
          feature_names=feature_names,  
          class_names=target_names,  
          filled=True, rounded=True,  
          fontsize=10)  
plt.title("决策树结构")  
  
# 绘制特征重要性 (决策树)  
plt.subplot(2, 3, 5)  
tree_model = models["Decision Tree"]  
importances = tree_model.feature_importances_  
indices = np.argsort(importances)[::-1][:10]  # 取前 10 个重要特征  
  
plt.barh(range(len(indices)), importances[indices], align='center')  
plt.yticks(range(len(indices)), [feature_names[i] for i in indices])  
plt.xlabel('特征重要性')  
plt.title('决策树 - 特征重要性 (Top 10)')  
  
# 绘制 SVM 支持向量  
plt.subplot(2, 3, 6)  
svm_model = models["SVM"]  
plt.scatter(X_train_scaled[:, 0], X_train_scaled[:, 1], c=y_train, cmap=plt.cm.coolwarm, s=30)  
plt.scatter(svm_model.support_vectors_[:, 0], svm_model.support_vectors_[:, 1],  
            s=100, facecolors='none', edgecolors='k', label='支持向量')  
plt.title("SVM支持向量")  
plt.xlabel(feature_names[0])  
plt.ylabel(feature_names[1])  
plt.legend()  
  
plt.tight_layout()  
plt.show()  
  
# === 6. 模型比较总结 ===print ("\n=== 模型性能总结 ===")  
for name, result in results.items():  
    print(f"{name}: 准确率 = {result['accuracy']:.2%}")

几个注意点:

# 数据集构成

print(f"数据集形状: {X.shape}") 
print(f"特征数: {len(feature_names)}")  
print(f"类别分布: {np.bincount(y)} (0={target_names[0]}, 1={target_names[1]})")

数据集形状: (569, 30) 表示该数据集共有 569 条样本,每条样本有 30 个特征。
类别分布: [212 357] 表示分类结果的分布情况:

  • 0 (恶性肿瘤):212 例
  • 1 (良性肿瘤):357 例

# dataframe 表示

# 创建 DataFrame 便于分析  
df = pd.DataFrame(X, columns=feature_names) #  
df['target'] = y  
print("\n特征统计信息:")  
print(df.describe())

DataFrame 结构

df = pd.DataFrame(
    data=X,          # 原始数据矩阵
    columns=feature_names  # 列名称列表
)
  • 结果:创建一个二维表格
    • 行:每个样本(569 行)
    • 列:每个特征(30 列)

df['target'] = y # y是标签向量

  • 添加新列 'target'
  • 包含每个样本的类别标签(0 = 恶性,1 = 良性)

结果 DataFrame 示例:

mean radiusmean texture...worst fractal dimensiontarget
17.9910.38...0.11890
20.5717.77...0.08900
19.6921.25...0.08760
...............
7.7624.54...0.07031

统计分析功能print(df.describe())
describe() 生成描述性统计信息,包括:

  • count: 非缺失值数量
  • mean: 平均值
  • std: 标准差
  • min: 最小值
  • 25%: 第一四分位数
  • 50%: 中位数
  • 75%: 第三四分位数
  • max: 最大值

describe () 输出示例:

mean radius  mean texture  ...  worst fractal dimension    target
count   569.000000    569.000000  ...               569.000000  569.0000
mean     14.127292     19.289649  ...                 0.083946    0.6274
std       3.524049      4.301036  ...                 0.018061    0.4839
min       6.981000      9.710000  ...                 0.055040    0.0000
25%      11.700000     16.170000  ...                 0.071460    0.0000
50%      13.370000     18.840000  ...                 0.080040    1.0000
75%      15.780000     21.800000  ...                 0.092080    1.0000
max      28.110000     39.280000  ...                 0.207500    1.0000

列是特征,行代表由 569 个样本算出来的各个指标。

# 数据预处理

# === 3. 数据预处理 ===# 划分训练集 / 测试集  
# stratify=y 表示在划分数据时保持每个类别的比例与原数据集一致  
X_train, X_test, y_train, y_test = train_test_split(  
    X, y, test_size=0.2, random_state=42, stratify=y  
)  
  
# 特征标准化  
scaler = StandardScaler()  
X_train_scaled = scaler.fit_transform(X_train)  
X_test_scaled = scaler.transform(X_test)  
  
# 选择两个主要特征进行可视化 (平均半径和平均纹理)  
X_train_vis = X_train_scaled[:, :2]  # 前两个特征  
X_test_vis = X_test_scaled[:, :2]
  • stratify 是用于分层抽样的参数
  • 使用 stratify=y 后,训练集和测试集中恶性 / 良性肿瘤的比例会保持与原始数据集相同
  • 这有助于避免因随机划分导致的类别分布偏差,尤其适用于不平衡数据集
  • 例如:如果原始数据集中有 60% 的良性样本,在测试集中也会保持大约 60% 的良性样本

X_train_vis = X_train_scaled[:, :2] # 前两个特征
X_test_vis = X_test_scaled[:, :2]
这两行代码的作用是: 从标准化后的训练集和测试集特征中,只选取前两个特征(即 “平均半径” 和 “平均纹理”),
用于后续的二维可视化(比如决策边界图)。 这样做可以让模型在二维空间中展示分类效果,便于直观观察和比较不同算法的决策边界。

# 模型训练

# 向量机,朴素贝叶斯,决策树  
models = {  
    "SVM": SVC(kernel='rbf', C=1.0, gamma='scale', probability=True, random_state=42),  
    "Naive Bayes (PGM)": GaussianNB(),  
    "Decision Tree": DecisionTreeClassifier(max_depth=3, random_state=42)  
}

这里定义了三个模型及其参数,具体解释如下:

  • SVC(kernel='rbf', C=1.0, gamma='scale', probability=True, random_state=42)
    • kernel='rbf' :使用径向基函数(高斯核)作为核函数,适合非线性分类。
    • C=1.0 :正则化参数,控制误差容忍度,值越大越倾向于拟合训练集。
    • gamma='scale' :核函数的系数,自动根据特征数和方差调整。
    • probability=True :支持概率输出(如 predict_proba 方法)。
    • random_state=42 :随机种子,保证结果可复现。
  • GaussianNB()
    • 朴素贝叶斯分类器,假设特征服从高斯分布。无特殊参数,默认设置即可。
  • DecisionTreeClassifier(max_depth=3, random_state=42)
    • max_depth=3 :决策树最大深度,限制树的复杂度,防止过拟合。
    • random_state=42 :随机种子,保证结果可复现。

# 模型评估

# 评估  
accuracy = accuracy_score(y_test, y_pred)  
cm = confusion_matrix(y_test, y_pred)  
report = classification_report(y_test, y_pred, target_names=target_names)  
  
# 存储结果  
results[name] = {  
    'model': model,  
    'accuracy': accuracy,  
    'confusion_matrix': cm,  
    'report': report  
}  
  
# 交叉验证  
cv_scores = cross_val_score(model, X_train_scaled, y_train, cv=5)  
  
print(f"\n=== {name} ===")  
print(f"测试集准确率: {accuracy:.2%}")  
print(f"5折交叉验证平均准确率: {np.mean(cv_scores):.2%} ± {np.std(cv_scores):.2%}")  
print("分类报告:\n", report)

# 准确率 (Accuracy)

accuracy = accuracy_score(y_test, y_pred)

  • 公式:正确预测数 / 总样本数
    Accuracy=TP+TNTP+TN+FP+FN\text{Accuracy} = \frac{\text{TP} + \text{TN}}{\text{TP} + \text{TN} + \text{FP} + \text{FN}}
  • 含义:模型整体预测正确的比例
  • 解读
    • 值范围:0.0(全错)~ 1.0(全对)
    • 在乳腺癌数据集中,98.25% 准确率表示 100 个样本中有 98 个被正确分类
  • 优点:直观易懂
  • 局限:在类别不平衡数据中可能误导(如 99% 负样本,模型全预测负也有 99% 准确率)

# 混淆矩阵 (Confusion Matrix)

cm = confusion_matrix(y_test, y_pred)
上面讲过了,略

# 分类报告 (Classification Report)

report = classification_report(y_test, y_pred, target_names=target_names)

输出三个核心指标(按类别计算):
a) 精确率 (Precision)

  • 公式:TP / (TP + FP)
    Precision=TPTP+FP\text{Precision} = \frac{\text{TP}}{\text{TP} + \text{FP}}
  • 含义:预测为正的样本中,实际为正的比例
  • 业务意义:减少误报(如减少健康人被误诊为癌症)

b) 召回率 (Recall / 灵敏度)

  • 公式:TP / (TP + FN)
    Recall=TPTP+FN\text{Recall} = \frac{\text{TP}}{\text{TP} + \text{FN}}
  • 含义:实际为正的样本中,被正确预测的比例
  • 业务意义:减少漏诊(如确保癌症患者不被漏诊)

c) F1 分数

  • 公式:2 × (Precision × Recall) / (Precision + Recall)
    F1=2×Precision×RecallPrecision+RecallF_1 = 2 \times \frac{\text{Precision} \times \text{Recall}}{\text{Precision} + \text{Recall}}
  • 含义:精确率和召回率的调和平均
  • 特点:综合衡量模型性能,特别适合不平衡数据

d) 分类报告示例输出

precision    recall  f1-score   support
     malignant       0.98      0.96      0.97        47
        benign       0.97      0.99      0.98        67
    accuracy                           0.98       114
   macro avg       0.98      0.97      0.97       114
weighted avg       0.98      0.98      0.98       114

解读

  1. 恶性类别 (malignant)
    • 精确率 98%:预测为恶性的样本中 98% 确实恶性
    • 召回率 96%:真实恶性样本有 96% 被正确识别
    • F1 分数 97%:综合表现优秀
  2. 良性类别 (benign)
    • 精确率 97%:预测良性的样本 97% 正确
    • 召回率 99%:真实良性样本 99% 被正确识别
  3. 整体统计
    • accuracy :总体准确率 98%
    • macro avg :各类别指标的简单平均
    • weighted avg :按样本量加权的平均

support 这一列代表的是每个类别在测试集中实际的样本数量
accuracy 的 0.98 与列无关,展示的整体的准确率

# 交叉验证 (Cross Validation)

cv_scores = cross_val_score(model, X_train_scaled, y_train, cv=5)
print(f"5折交叉验证平均准确率: {np.mean(cv_scores):.2%} ± {np.std(cv_scores):.2%}")

  • 原理:将训练集分成 5 份,轮流用 4 份训练,1 份验证,重复 5 次
  • 输出
    • 平均准确率:模型性能的稳定估计
    • 标准差:模型性能的波动范围
  • 重要性
    • 减少因单次数据分割带来的随机性
    • 检测模型是否过拟合
    • 比单次测试集评估更可靠
  • 解读示例
    • "97.59% ± 0.82%" 表示:
      • 平均准确率 97.59%
      • 波动范围在 ±0.82% 之间 → 模型稳定

# 项目实践

项目实践:SMS 垃圾邮件分类

更新于 阅读次数

请我喝[茶]~( ̄▽ ̄)~*

北沐清 微信支付

微信支付

北沐清 支付宝

支付宝