云计算百科
云计算领域专业知识百科平台

初识机器学习(朴素贝叶斯和K-means聚类)

一、机器学习十大常见算法

朴素贝叶斯它通过已知的标签数据,学习如何对新的样本进行分类。

K-Means聚类正是聚类算法中最核心、最常用的技术之一。

如果说朴素贝叶斯是在有标准答案的情况下做预测,那么K-Means就是在没有标准答案的情况下做探索。两者代表了机器学习的两大方向,本篇主要介绍这两种算法。

二、朴素贝叶斯(Naive Bayes)

2.1 什么是朴素贝叶斯

朴素贝叶斯是一种基于贝叶斯定理的简单而高效的概率分类算法。它的核心思想是:通过已知的某些特征,来计算某个事件发生的概率,并选择概率最高的类别作为预测结果。

朴素贝叶斯的“朴素”之处在于一个关键假设:所有特征之间是相互独立的。也就是说,在判断决策是否适合或正确时,每个特征对你的决策影响是互不相关的。虽然在现实中,特征之间常有联系,但这个简化的假设让计算变得非常高效。

2.2 核心原理:贝叶斯定理

要理解朴素贝叶斯,必须先了解它的基石——贝叶斯定理。贝叶斯定理描述了在已知一些条件的情况下,如何更新某个事件发生的概率。

贝叶斯公式如下:

P(A|B) = \\frac{P(B|A) \\times P(A)}{P(B)}

公式看起来可能有点抽象,我们用判断一封邮件是否是垃圾邮件的例子来理解它:

A:邮件是“垃圾邮件”这个事件。

B:邮件中包含“免费”这个词这个特征。

P(A):先验概率——任意一封邮件是垃圾邮件的概率。比如根据历史数据,100封邮件里有20封是垃圾邮件,那么 P(垃圾邮件)=0.2P(垃圾邮件)=0.2。

P(B|A):条件概率(似然)——在已知邮件是垃圾邮件的情况下,其中出现“免费”这个词的概率。比如垃圾邮件中80%都包含“免费”,那么 P(免费∣垃圾邮件)=0.8P(免费∣垃圾邮件)=0.8。

P(B):证据——任意一封邮件中出现“免费”这个词的总概率。

P(A|B):后验概率——我们最终想求的:在已知邮件包含“免费”这个词的条件下,这封邮件是垃圾邮件的概率。

贝叶斯定理的精髓在于:它利用了我们已经知道的信息(垃圾邮件的普遍规律 P(A) 和垃圾邮件用词习惯 P(B∣A)),结合新观察到的证据(这封邮件里有“免费”),来修正我们对这个具体事件的判断(这封邮件是垃圾邮件的可能性 P(A∣B))。

2.3 “朴素”在哪里?

真正的贝叶斯分类器在计算 P(B∣A)时,需要考虑所有特征 B1,B2,B3… 的联合概率 P(B1,B2,B3…∣A),这非常复杂。

朴素贝叶斯做出了一个强大的简化假设:所有特征都相互条件独立。这意味着:

P(B_1, B_2, B_3... | A) \\approx P(B_1|A) \\times P(B_2|A) \\times P(B_3|A) \\times ...

这个假设将复杂的联合概率计算,简化成了多个简单概率的乘法,极大地降低了计算成本。

2.4 朴素贝叶斯的三种常见变体

根据特征数据类型的不同,朴素贝叶斯主要有以下几种变体:

分类器类型适用特征数据类型核心假设与说明典型应用场景
高斯朴素贝叶斯 连续型数据 假设每个特征在每个类别下服从高斯分布(正态分布) 根据身高、体重分类性别;根据花瓣尺寸分类鸢尾花品种
多项式朴素贝叶斯 离散型计数数据 假设特征是由多项式分布生成的 垃圾邮件过滤、新闻主题分类、情感分析
伯努利朴素贝叶斯 二值型数据(0/1) 假设特征是二值的,关注“是否出现”而非“出现多少次” 文本中关键词是否出现的二值特征场景

2.5 多项式朴素贝叶斯实战:鸢尾花分类

下面通过鸢尾花数据集来展示如何使用 MultinomialNB(多项式朴素贝叶斯)进行分类:

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

# 读取数据
data = pd.read_csv("iris.csv")
x = data.iloc[:, :-1] # 特征:花萼长度、花萼宽度、花瓣长度、花瓣宽度
y = data.iloc[:, -1] # 目标:鸢尾花品种

# 划分训练集和测试集(80%训练,20%测试)
train_x, test_x, train_y, test_y = train_test_split(
x, y, test_size=0.2, random_state=0
)

# 创建多项式朴素贝叶斯模型,alpha=1 为拉普拉斯平滑参数
model = MultinomialNB(alpha=1)
model.fit(train_x, train_y)

# 训练集预测与评估
train_pred = model.predict(train_x)
print(metrics.classification_report(train_y, train_pred))

# 测试集预测与评估
test_pred = model.predict(test_x)
print(metrics.classification_report(test_y, test_pred))

数据读取:使用 pandas.read_csv 加载鸢尾花数据集。鸢尾花数据集包含150个样本,每个样本有4个连续型特征(花萼长度、花萼宽度、花瓣长度、花瓣宽度)和1个标签(Setosa、Versicolour、Virginica 三个品种)。

数据划分:train_test_split 将数据随机划分为训练集(80%)和测试集(20%),random_state=0 保证每次运行划分结果一致。

模型构建:MultinomialNB(alpha=1) 创建多项式朴素贝叶斯分类器。参数 alpha 是拉普拉斯平滑系数,用于解决某些特征值在训练集中未出现导致概率为零的问题。alpha=1 是常用默认值,平滑程度适中。

训练:model.fit(train_x, train_y) 让模型学习训练数据中特征与标签的关系。对于多项式朴素贝叶斯,它会统计每个类别下各特征的计数,并计算相应的条件概率。

预测:model.predict() 对训练集和测试集分别进行预测,返回预测类别标签。

评估:classification_report 输出精确率(Precision)、召回率(Recall)、F1-score 等详细指标,帮助我们全面了解模型的分类性能。

三、K-Means聚类

3.1 什么是聚类

在机器学习中,聚类要做的是完全靠特征自发地分出类别。它是一种无监督学习方法,目标是在没有预先标注答案(即没有“标签”)的数据中,发现其内在的结构和分组。

聚类的核心思想是:将数据集中的样本划分成若干个互不相交的子集(称为簇),使得同一个簇内的样本彼此相似,而不同簇中的样本彼此不相似。这里的“相似”通常通过数学上的距离来衡量(如欧氏距离),距离越近,相似度越高。

3.2 K-Means算法原理

K-Means是最著名、最常用的聚类算法之一,其思想直观,实现相对简单。

我们可以把K-Means的过程想象成竞选代表并重新划区:

第一步:确定簇的数量 K
首先,你需要决定想把数据分成几类。这个 K 值需要预先指定,这是 K-Means 的一个关键参数。

第二步:初始化代表(质心)
随机在数据空间中选取 K 个点,作为每个簇的初始“中心点”,我们称之为质心。

第三步:分配居民(样本)
计算数据集中每一个样本点到这 K 个质心的距离。遵循“近者归其类”的原则,将每个样本分配给距离它最近的那个质心所在的簇。

第四步:改选新代表(更新质心)
现在,每个簇里都有了一批样本。重新计算每个簇的质心,新的质心就是该簇内所有样本点的平均值(均值点)。

第五步:重复与收敛
重复第三步和第四步,直到质心的位置不再发生显著变化(即算法收敛)。

3.3 K-Means的关键参数

在 sklearn 的 KMeans 中,以下参数最为关键:

参数含义说明
n_clusters 簇的数量 K 最重要的参数,需要预先指定
init 初始化方法 可选 'k-means++'(默认)、'random'
n_init 初始化次数 算法会运行多次并选择最优结果,默认10次
max_iter 最大迭代次数 默认300次
random_state 随机种子 设置后可保证结果可复现

3.4 如何选择最佳K值?

选择最佳的 K 值是 K-Means 中最关键的问题之一。常用的方法有:

  • 肘部法则(Elbow Method):计算不同 K 值下的簇内误差平方和(SSE),随着 K 增大,SSE 会逐渐减小。当 SSE 的下降速度突然变缓时,对应的 K 值就是“肘部”点,通常被认为是最佳 K 值。

  • 轮廓系数(Silhouette Coefficient):衡量样本与其所在簇的相似度与其他簇的差异度,取值范围在 [-1, 1] 之间,值越大表示聚类效果越好。

3.5 K-Means聚类实战:酒品种自动分群

下面通过一个实际数据集来演示如何利用轮廓系数自动选择最佳K值,并进行聚类:

import pandas as pd
import numpy as np
from sklearn.cluster import KMeans
from sklearn import metrics
from sklearn.model_selection import train_test_split

# 1. 读取数据(假设数据文件为 data.txt,用空格分隔,包含'name'列和若干特征列)
data = pd.read_table("data.txt", sep=" ", encoding="utf-8", engine="python")
# 去掉'name'列(非数值特征),剩余列为特征数据
x = data.drop("name", axis=1)

# 2. 划分训练集和测试集(用于验证聚类模型的稳定性)
train_x, test_x = train_test_split(x, test_size=0.2, random_state=0)

# 3. 通过轮廓系数选择最佳K值(K范围2~9)
scores = []
for i in range(2, 10):
model = KMeans(n_clusters=i, random_state=0)
# 计算训练集的轮廓系数,metric='euclidean'表示使用欧氏距离
score = metrics.silhouette_score(train_x, model.fit_predict(train_x), metric='euclidean')
scores.append(score)

# 4. 选出轮廓系数最高的K值
best_k = [2, 3, 4, 5, 6, 7, 8, 9][np.argmax(scores)]
print(f"最佳K值为:{best_k}")

# 5. 使用最佳K值重新训练模型
model = KMeans(n_clusters=best_k, random_state=0)
model.fit(train_x)

# 6. 对训练集和测试集进行预测
train_pred = model.predict(train_x)
test_pred = model.predict(test_x)

# 7. 分别计算训练集和测试集的轮廓系数,评估聚类效果
train_score = metrics.silhouette_score(train_x, train_pred)
test_score = metrics.silhouette_score(test_x, test_pred)

print(f"训练集轮廓系数:{train_score}")
print(f"测试集轮廓系数:{test_score}")

数据加载:pd.read_table 读取以空格分隔的文本文件。data.txt 包含一列 name(可能是样本ID或名称)和若干数值特征。我们使用 drop("name", axis=1) 移除非数值列,只保留特征用于聚类。

数据划分:train_test_split 将特征数据分为训练集和测试集。虽然聚类是无监督学习,但划分测试集可以评估模型在未见样本上的稳定性——如果训练集和测试集的轮廓系数相近,说明聚类结构是稳定的。

轮廓系数(Silhouette Score):对于每个样本,轮廓系数 s(i) 定义为:

s(i) = \\frac{b(i) - a(i)}{\\max\\{a(i), b(i)\\}}

其中 a(i)a(i) 是样本与同簇其他点的平均距离(簇内凝聚度),b(i)b(i) 是样本与最近其他簇的平均距离(簇间分离度)。整体轮廓系数取所有样本的平均值,范围 [-1, 1],值越大表示聚类效果越好。

循环选择K值:在 K=2 到 9 的范围内,对每个K值训练 KMeans 模型,计算训练集的轮廓系数,保存在 scores 列表中。

选取最佳K:使用 np.argmax(scores) 找到最大轮廓系数对应的索引,再从预定义的K值列表 [2,3,4,5,6,7,8,9] 中取出对应的K值。

最终模型训练与评估:用最佳K值重新训练 KMeans 模型,对训练集和测试集分别预测聚类标签,并计算各自的轮廓系数。两个分数相近且都较高,说明聚类结果稳定且有效。

3.6 K-Means的优缺点

优点缺点
算法简单,易于理解和实现 需要预先指定 K 值
计算效率高,适合大规模数据 对初始质心的选择敏感
收敛速度快 对异常值敏感
结果易于解释 只适用于球形簇,对复杂形状的簇效果不佳
赞(0)
未经允许不得转载:网硕互联帮助中心 » 初识机器学习(朴素贝叶斯和K-means聚类)
分享到: 更多 (0)

评论 抢沙发

评论前必须登录!