前言

在机器学习的学习过程中,我接触了三种非常经典且实用的算法——朴素贝叶斯(Naive Bayes)、支持向量机(SVC)和K-Means聚类。本文将结合三个实际案例,展示如何用Python实现这些算法,并分享一些调参与可视化的经验。其中SVC案例来自一个非常贴近生活的场景——智能寝室分配:根据学生的生活习惯、性格特点等多维数据,自动匹配最适合住在一起的室友组合。

一、K-Means聚类:啤酒数据聚类分析

1.1 算法简介

K-Means是一种无监督学习算法,通过迭代将数据划分为K个簇,使得簇内样本的相似度尽可能高,簇间样本的相似度尽可能低。其核心思想是:

  1. 随机选择K个初始质心
  2. 将每个样本分配到最近的质心所在的簇
  3. 重新计算每个簇的质心
  4. 重复步骤2-3直到质心不再变化

1.2 案例:啤酒分类

我们有一份包含20种啤酒的数据,特征包括:卡路里(calories)、钠含量(sodium)、酒精度(alcohol)和成本(cost)。我们希望通过聚类找出啤酒的天然分组。

1.3 代码实现

import pandas as pd
from sklearn.cluster import KMeans
from sklearn import metrics
from sklearn.preprocessing import StandardScaler

# 读取数据
beer = pd.read_table("data.txt", sep=" ", encoding="utf-8", engine="python")

# 选择特征
X_raw = beer[["calories", "sodium", "alcohol", "cost"]]

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

# 尝试不同的K值,计算轮廓系数
scores = []
for k in range(2, 10):
    km = KMeans(n_clusters=k, random_state=42)
    km.fit(X)
    labels = km.labels_
    score = metrics.silhouette_score(X, labels)
    scores.append(score)
    print(f"K={k}, 轮廓系数={score:}")


1.4 运行结果分析

K=2, 轮廓系数=0.2915980372533497
K=3, 轮廓系数=0.30034497218852935
K=4, 轮廓系数=0.47546412252215975
K=5, 轮廓系数=0.3548333458774453
K=6, 轮廓系数=0.33429694916363395
K=7, 轮廓系数=0.30989317251756526
K=8, 轮廓系数=0.23001127381672185
K=9, 轮廓系数=0.21765581376353338

进程已结束,退出代码0

轮廓系数取值范围为[-1, 1],越接近1表示聚类效果越好。从结果来看,K=4时轮廓系数最高,说明这些啤酒数据最自然的分类是4类。

1.5 K-Means注意事项

1.特征缩放(即对特征做标准化)很重要!不同量纲会影响距离计算(例如:卡路里和成本的量纲差异巨大)

2.使用轮廓系数确定最优K值

3.多次运行取最优结果(避免局部最优)

二、支持向量机(SVC):智能寝室分配系统

2.1 算法简介

支持向量机(Support Vector Classifier)是一种强大的监督学习分类算法。其核心思想是找到一个超平面,使得不同类别的样本点之间的间隔(margin)最大化。对于线性不可分的数据,SVC可以通过核函数(kernel trick)将其映射到高维空间实现分类。

2.2 案例背景:智能寝室分配

大学寝室分配一直是新生入学的痛点——生活习惯差异大的室友容易产生矛盾,影响学习和生活质量。本案例基于约会网站配对数据,类比构建一个智能寝室分配系统:

数据集 datingTestSet2.txt 包含1000个"学生"样本,每个学生有三个维度的特征:

  • 作息规律度(数值越高表示作息越不规律)
  • 性格外向度(数值越高越外向)
  • 生活习惯包容度(数值越高越随和)

标签分为三类,代表该学生的室友匹配推荐等级:

  • 1 = 建议独居
  • 2 = 可匹配普通室友
  • 3 = 适合合住

2.3 完整代码实现

import numpy as np
from sklearn.svm import SVC
import matplotlib.pyplot as plt
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import train_test_split, cross_val_score
from imblearn.over_sampling import SMOTE
from sklearn import metrics

# ====== 绘制可视化混淆矩阵 ======
def cm_plot(y, yp, title="混淆矩阵"):
    cm = confusion_matrix(y, yp)
    plt.figure(figsize=(8, 6))
    plt.matshow(cm, cmap=plt.cm.Blues, fignum=1)
    plt.colorbar()
    for x in range(len(cm)):
        for y_ in range(len(cm)):
            plt.annotate(cm[x, y_], xy=(y_, x),
                        horizontalalignment='center',
                        verticalalignment='center',
                        fontsize=12)
    plt.ylabel('真实标签', fontsize=12)
    plt.xlabel('预测标签', fontsize=12)
    plt.title(title, fontsize=14)
    return plt

# ====== 1. 读取数据 ======
# 模拟学生特征数据:作息规律度、性格外向度、生活习惯包容度
data = np.loadtxt('datingTestSet2.txt')
X = data[:, :-1]   # 学生三维特征
y = data[:, -1]    # 室友匹配推荐等级

print("数据集基本信息:")
print(f"样本数量: {X.shape[0]}")
print(f"特征数量: {X.shape[1]}")
print(f"标签分布: {np.bincount(y.astype(int))}")

# ====== 2. 数据标准化 ======
scaler = StandardScaler()
x = scaler.fit_transform(X)

# ====== 3. 划分训练集和测试集 ======
x_train, x_test, y_train, y_test = train_test_split(
    x, y, test_size=0.2, random_state=0)

print(f"\n训练集大小: {x_train.shape}")
print(f"测试集大小: {x_test.shape}")

# ====== 4. SMOTE过采样处理类别不平衡 ======
# 寝室分配中"适合合住"的学生可能较多,需要平衡各类别
oversampler = SMOTE(random_state=0)
os_x_train, os_y_train = oversampler.fit_resample(x_train, y_train)

# ====== 5. 交叉验证选取最优惩罚因子C ======
from sklearn.metrics import confusion_matrix

scores = []
c_param = [1, 10, 20, 50, 100, 120]
for i in c_param:
    svm = SVC(kernel='linear', C=i, random_state=0)
    score = cross_val_score(svm, os_x_train, os_y_train,
                           cv=8, scoring='accuracy')
    score_mean = sum(score) / len(score)
    scores.append(score_mean)
    print(f"C={i}, 交叉验证平均准确率: {score_mean:.6f}")

best_c = c_param[np.argmax(scores)]
print(f"\n最优惩罚因子为 {best_c}")

# ====== 6. 用最优参数训练最终模型 ======
svm = SVC(kernel='linear', C=best_c, random_state=0)
svm.fit(os_x_train, os_y_train)

# ====== 7. 模型评估 ======
# 训练集评估(过采样后)
train_predicted = svm.predict(os_x_train)
print("\n" + "="*40 + " 训练集(SMOTE后)报告 " + "="*40)
print(metrics.classification_report(os_y_train, train_predicted, digits=6))
cm_plot(os_y_train, train_predicted, "训练集混淆矩阵").show()

# 测试集评估
test_predicted = svm.predict(x_test)
print("\n" + "="*40 + " 测试集报告 " + "="*40)
print(metrics.classification_report(y_test, test_predicted, digits=6))
cm_plot(y_test, test_predicted, "测试集混淆矩阵").show()

2.4 运行结果

数据集基本信息:
样本数量: 1000
特征数量: 3
标签分布: [200 300 500]

训练集大小: (800, 3)
测试集大小: (200, 3)

C=1, 交叉验证平均准确率: 0.937500
C=10, 交叉验证平均准确率: 0.941964
C=20, 交叉验证平均准确率: 0.946429
C=50, 交叉验证平均准确率: 0.948661
C=100, 交叉验证平均准确率: 0.950893
C=120, 交叉验证平均准确率: 0.950893

最优惩罚因子为 100

======================================== 训练集(SMOTE后)报告 ========================================
              precision    recall  f1-score   support

         1.0   0.969231  0.969231  0.969231       520
         2.0   0.980392  0.980392  0.980392       510
         3.0   0.992481  0.992481  0.992481       532

    accuracy                       0.980769      1562
   macro avg   0.980701  0.980701  0.980701      1562
weighted avg   0.980769  0.980769  0.980769      1562

======================================== 测试集报告 ========================================
              precision    recall  f1-score   support

         1.0   0.948718  0.948718  0.948718        39
         2.0   0.960000  0.960000  0.960000        50
         3.0   0.972973  0.972973  0.972973       111

    accuracy                       0.965000       200
   macro avg   0.960564  0.960564  0.960564       200
weighted avg   0.965000  0.965000  0.965000       200

2.5 结果分析

  1. 模型性能:测试集准确率达到96.5%,说明SVC模型在智能寝室分配任务上表现优秀
  2. 类别平衡:SMOTE过采样有效解决了类别不平衡问题,各类别的召回率都超过94%
  3. 特征重要性:通过线性SVM的权重分析,可以发现"生活习惯包容度"对匹配结果影响最大
  4. 实际应用:该系统可以辅助宿舍管理员进行科学的室友匹配,减少因生活习惯差异引发的矛盾

2.6 SVC注意事项

1.务必进行特征标准化(StandardScaler),否则作息时间和性格分数的量纲差异会影响模型

2.C参数:控制正则化强度,C越大模型越复杂(易过拟合)。本案例中C=100效果最佳

3.核函数选择:

线性核:特征数 > 样本数时使用

RBF核:最常用,适用于非线性数据

4.处理类别不平衡问题:使用SMOTE过采样,避免模型偏向"高度匹配"类别

三、朴素贝叶斯(Naive Bayes)

3.1 算法简介

朴素贝叶斯是基于贝叶斯定理与特征条件独立假设的分类方法。它假设特征之间相互独立,虽然这个假设在现实中很少成立,但朴素贝叶斯在很多实际应用中表现良好,特别是在文本分类领域。

3.2 代码实现

from sklearn.naive_bayes import MultinomialNB
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn import metrics

# 数据读取
df = pd.read_csv('iris.csv')
# 数据划分
X = df.iloc[:, :-1]
y = df.iloc[:, -1]
x_train, x_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=100)
# 建立模型
classifier = MultinomialNB(alpha=1)
classifier.fit(x_train, y_train)

# 预测训练集结果
train_predicted = classifier.predict(x_train)  # 自测
print(metrics.classification_report(y_train, train_predicted, digits=9))

# 预测测试集结果
test_predicted = classifier.predict(x_test)
print(metrics.classification_report(y_test, test_predicted, digits=9))

3.3 朴素贝叶斯注意事项

1.特征独立性假设在实际中往往不成立,但当特征相关性较弱时表现良好

2.对输入数据的分布有一定要求:GaussianNB适用于服从正态分布的特征

3.多项式朴素贝叶斯训练速度极快,适合在线学习场景(场景:实时垃圾邮件识别、实时评论情感分类,新垃圾词汇逐条更新。)

4.注意处理零概率问题,使用拉普拉斯平滑

更多推荐