前言
在机器学习的世界里,有监督学习与无监督学习如同“两条腿”并驾齐驱。而朴素贝叶斯(Naïve Bayes) 和K-Means聚类,分别是这两大分支中最为经典、应用广泛的入门级算法。
朴素贝叶斯基于贝叶斯定理,借助“特征条件独立”这一强力假设,将复杂的联合概率计算大大简化,在文本分类、垃圾邮件过滤、情感分析等任务中表现高效且稳健。
K-Means聚类则是一种典型的无监督学习算法,通过迭代寻找最优的聚类中心,将相似的样本自动归为一类,在用户画像、图像分割、异常检测等场景中扮演重要角色。
朴素贝叶斯
朴素贝叶斯介绍
常见的概率公式
条件概率:表示事件A在另外一个事件B已经发生条件下的发生概率,P(A|B)
在女神喜欢的条件下,职业是程序员的概率?
- 女神喜欢条件下,有 2、3、4、7 共 4 个样本
- 4 个样本中,有程序员 3、4 共 2 个样本
- 则 P(程序员|喜欢) = 2/4 = 0.5
联合概率:表示多个条件同时成立的概率,P(AB) = P(A) P(B|A)
特征条件独立性假设:P(AB) = P(A) P(B)
职业是程序员并且体型匀称的概率?
- 数据集中,共有 7 个样本
- 职业是程序员有 1、3、4 共 3 个样本,则其概率为:3/7
- 在职业是程序员,体型是匀称有 3 共 1 个样本,则其概率为:1/3
- 则即是程序员又体型匀称的概率为:3/7 * 1/3 = 1/7
联合概率 + 条件概率:
在女神喜欢的条件下,职业是程序员、体重超重的概率? P(AB|C) = P(A|C) P(B|AC)
- 在女神喜欢的条件下,有 2、3、4、7 共 4 个样本
- 在这 4 个样本中,职业是程序员有 3、4 共 2 个样本,则其概率为:2/4=0.5
- 在在 2 个样本中,体型超重的有 4 共 1 个样本,则其概率为:1/2 = 0.5
- 则 P(程序员, 超重|喜欢) = 0.5 * 0.5 = 0.25
简言之:
条件概率:在去掉部分样本的情况下,计算某些样本的出现的概率,表示为:P(B|A)
联合概率:多个事件同时发生的概率是多少,表示为:P(AB) = P(B)*P(A|B)
贝叶斯公式
- P© 表示 C 出现的概率
- P(W|C) 表示 C 条件 W 出现的概率
- P(W) 表示 W 出现的概率
- P(C|W) = P(喜欢|程序员,超重)
- P(W|C) = P(程序员,超重|喜欢)
- P© = P(喜欢)
- P(W) = P(程序员,超重)
- 根据训练样本估计先验概率P©:P(喜欢) = 4/7
- 根据条件概率P(W|C)调整先验概率:P(程序员,超重|喜欢) = 1/4
- 此时我们的后验概率P(C|W)为:P(程序员,超重|喜欢) * P(喜欢) = 4/7 * 1/4 = 1/7
- 那么该部分数据占所有既为程序员,又超重的人中的比例是多少呢?
- P(程序员,超重) = P(程序员) * P(超重|程序员) = 3/7 * 2/3 = 2/7
- P(喜欢|程序员, 超重) = 1/7 ➗ 2/7 = 0.5
朴素贝叶斯
贝叶斯概率计算过程中,需要计算 P(程序员,超重|喜欢) 和 P(程序员, 超重) 等联合概率,为了简化联合概率的计算,朴素贝叶斯在贝叶斯基础上增加:特征条件独立假设,即:特征之间是互为独立的。
此时,联合概率的计算即可简化为:
- P(程序员,超重|喜欢) = P(程序员|喜欢) * P(超重|喜欢)
- P(程序员,超重) = P(程序员) * P(超重)
拉普拉斯平滑系数
- α 是拉普拉斯平滑系数,一般指定为 1
- Ni是 F1 中符合条件 C 的样本数量
- N 是在条件 C 下所有样本的总数
- m 表示所有独立样本的总数
为了避免概率值为 0,在分子和分母分别加上一个数值,这就是拉普拉斯平滑系数的作用。
情感分析案例
api介绍
sklearn.naive_bayes.MultinomialNB(alpha = 1.0)
- 朴素贝叶斯分类
- alpha:拉普拉斯平滑系数
商品评论情感分析
已知商品评论数据,根据数据进行情感分类(好评、差评
步骤分析
- 1)获取数据
- 2)数据基本处理
- 2.1) 取出内容列,对数据进行分析
- 2.2) 判定评判标准
- 2.3) 选择停用词
- 2.4) 把内容处理,转化成标准格式
- 2.5) 统计词的个数
- 2.6)准备训练集和测试集
- 3)模型训练
- 4)模型评估
代码实现
importpandasaspdimportnumpyasnpimportjiebaimportmatplotlib.pyplotaspltfromsklearn.feature_extraction.textimportCountVectorizerfromsklearn.naive_bayesimportMultinomialNBdata=pd.read_csv("../data/书籍评价.csv",encoding='gbk')# 数据预处理# 添加labels列,充当标签列 1:好评 ,0:差评data['labels']=np.where(data['评价']=='好评',1,0)# 抽取labels列作为标签y=data['labels']# 对用户的评价内容做分词comment_list=[','.join(jieba.lcut(comment))forcommentindata['内容']]# 加载停用词列表,即:里面记录的词,不需要参与模型训练,预测,要被删除的词,例如:的,啊,哈,从,都withopen("../data/stopwords.txt",'r',encoding='utf-8')asf:# 一次性读取所有行stopwords_list=f.readlines()# 删除最后的\nstopwords_list=[stopword.strip()forstopwordinstopwords_list]# 对停用词列表进行去重stopwords_list=list(set(stopwords_list))# 创建向量化对象,从评论切词列表中删除停用词,并且统计词频transfer=CountVectorizer(stop_words=stopwords_list)# 参数:停用词列表# 统计词频矩阵x=transfer.fit_transform(comment_list).toarray()print(x)x_train=x[:10]y_train=y[:10]x_test=x[10:]y_test=y[10:]# 特征工程# 模型训练estimator=MultinomialNB()# 创建朴素贝叶斯对象estimator.fit(x_train,y_train)# 模型预测y_pre=estimator.predict(x_test)print(f"模型预测结果:{y_pre}")# 模型评估print(f"准确率:{accuracy_score(y_test,y_pre)}")[[0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0] [0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0] [0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 1 1] [0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 1 0 0 0 1 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0] [0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0] [0 0 0 1 1 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0] [0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 1 1 0 0] [1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0] [0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 1 0 0] [0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0] [0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0] [0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 1 0 0] [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0]] 模型预测结果:[0 0 0] 准确率:1.0聚类算法
聚类算法简介
聚类算法介绍
一种典型的无监督学习算法,主要用于将相似的样本自动归到一个类别中。
在聚类算法中根据样本之间的相似性,将样本划分到不同的类别中,对于不同的相似度计算方法,会得到不同的聚类结果,常用的相似度计算方法有欧式距离法。
聚类算法在现实中的应用
- 用户画像,广告推荐,Data Segmentation,搜索引擎的流量推荐,恶意流量识别
- 基于位置信息的商业推送,新闻聚类,筛选排序
- 图像分割,降维,识别;离群点检测;信用卡异常消费;发掘相同功能的基因片段
分类
聚类API的初步使用
api介绍
sklearn.cluster.KMeans(n_clusters=8)
- 参数:
- n_clusters:开始的聚类中心数量
- 整型,缺省值=8,生成的聚类数,即产生的质心(centroids)数。
- n_clusters:开始的聚类中心数量
- 方法:
- estimator.fit(x)
- estimator.predict(x)
- estimator.fit_predict(x)
- 计算聚类中心并预测每个样本属于哪个类别,相当于先调用fit(x),然后再调用predict(x)
案例
随机创建不同二维数据集作为训练集,并结合k-means算法将其聚类,你可以尝试分别聚类不同数量的簇,并观察聚类效果:
importmatplotlib.pyplotaspltfromsklearn.datasetsimportmake_blobs# 默认会按照高斯分布生成数据集,只需要指定均值,标准差fromsklearn.clusterimportKMeans# 聚类的API,采用指定质心来分簇fromsklearn.metricsimportcalinski_harabasz_score# 评价指标,值越大,聚类效果越好# 准备数据集#参1:样本数量 参2:样本特征数量 参3:样本标签数量 参4:标准差 参5:随机种子x,y=make_blobs(n_samples=1000,n_features=2,centers=[[-1,-1],[0,0],[1,1],[2,2]],cluster_std=[0.4,0.2,0.2,0.2],random_state=23)# 绘制上述的图形# 参1:横坐标 参2:纵坐标 参3:颜色plt.scatter(x[:,0],x[:,1])plt.show()# 创建KMeans对象estimator=KMeans(n_clusters=4,random_state=23)# 模型训练和预测y_pre=estimator.fit_predict(x)# 预测值# 绘制预测结果plt.scatter(x[:,0],x[:,1],c=y_pre)plt.show()# 评价指标print(f'评价指标:{calinski_harabasz_score(x,y_pre)}')# 越大越好Kmeans算法流程
k-means聚类流程
1、随机设置K个特征空间内的点作为初始的聚类中心
2、对于其他每个点计算到K个中心的距离,未知的点选择最近的一个聚类中心点作为标记类别
3、接着对着标记的聚类中心之后,重新计算出每个聚类的新中心点(平均值)
4、如果计算得出的新中心点与原中心点一样(质心不再移动),那么结束,否则重新进行第二步过程
通过下图解释实现流程:
k-means聚类动态效果图:
案例练习
1、随机设置K个特征空间内的点作为初始的聚类中心(本案例中设置p1和p2)
2、对于其他每个点计算到K个中心的距离,未知的点选择最近的一个聚类中心点作为标记类别
3、接着对着标记的聚类中心之后,重新计算出每个聚类的新中心点(平均值)
注意:这里P2′=(2.3,3.3),下同。
4、如果计算得出的新中心点与原中心点一样(质心不再移动),那么结束,否则重新进行第二步过程【经过判断,需要重复上述步骤,开始新一轮迭代】
5、当每次迭代结果不变时,认为算法收敛,聚类完成,K-Means一定会停下,不可能陷入一直选质心的过程。
评价指标
SSE-误差平方和
- K 表示聚类中心的个数
- Ci表示簇
- p 表示样本
- mi表示簇的质心
SSE 越小,表示数据点越接近它们的中心,聚类效果越好。
SC 系数
结合了聚类的凝聚度(Cohesion)和分离度(Separation),用于评估聚类的效果。
其计算过程如下:
- 计算每一个样本 i 到同簇内其他样本的平均距离 ai,该值越小,说明簇内的相似程度越大
- 计算每一个样本 i 到最近簇 j 内的所有样本的平均距离 bij,该值越大,说明该样本越不属于其他簇 j
- 计算所有样本的平均轮廓系数
- 轮廓系数的范围为:[-1, 1],值越大聚类效果越好
肘部法
肘部法可以用来确定 K 值.
- 对于n个点的数据集,迭代计算 k from 1 to n,每次聚类完成后计算 SSE
- SSE 是会逐渐变小的,因为每个点都是它所在的簇中心本身。
- SSE 变化过程中会出现一个拐点,下降率突然变缓时即认为是最佳 n_clusters 值。
- 在决定什么时候停止训练时,肘形判据同样有效,数据通常有更多的噪音,在增加分类无法带来更多回报时,我们停止增加类别。
CH 系数
CH 系数结合了聚类的凝聚度(Cohesion)和分离度(Separation)、质心的个数,希望用最少的簇进行聚类。
SSW 的含义:
- Cpi表示质心
- xi表示某个样本
- SSW 值是计算每个样本点到质心的距离,并累加起来
- SSW 表示表示簇内的内聚程度,越小越好
- m 表示样本数量
- k 表示质心个数
SSB 的含义:
- Cj表示质心,X 表示质心与质心之间的中心点,nj表示样本的个数
- SSB 表示簇与簇之间的分离度,SSB 越大越好
聚类评估的使用
# 定义函数,演示:SSE + 肘部法defdm01_sse():# 定义sse列表,记录每个k值的SSE值sse_list=[]# 生成数据集 参1:样本数量 参2:样本特征数量 参3:样本标签数量 参4:标准差 参5:随机种子x,y=make_blobs(n_samples=1000,n_features=2,centers=[[-1,-1],[0,0],[1,1],[2,2]],cluster_std=[0.4,0.2,0.2,0.2],random_state=23)# for循环遍历,获取每个k值,计算其对应的sse值,并添加到sseforkinrange(1,100):# 创建KMeans对象,指定 k值,迭代次数,随机种子estimator=KMeans(n_clusters=k,max_iter=100,random_state=23)# 训练模型estimator.fit(x)# 模型预测y_pred=estimator.predict(x)# 获取每个簇的sse值sse_value=estimator.inertia_# 将每个k值对应的sse值,添加到sse_list列表中sse_list.append(sse_value)# 绘制SSE曲线-数据可视化plt.figure(figsize=(20,10))plt.title("SSE value")plt.xticks(range(0,100,3))plt.xlabel('k')plt.ylabel('sse')plt.grid()# 参1:k值 参2:该k值对应的SSE值plt.plot(range(1,100),sse_list)plt.show()fromsklearn.datasetsimportmake_blobsfromsklearn.clusterimportKMeansimportmatplotlib.pyplotaspltfromsklearn.metricsimportsilhouette_scorefromsklearn.metricsimportcalinski_harabasz_scoreif__name__=='__main__':x,y=make_blobs(n_samples=1000,n_features=2,centers=[[-1,-1],[0,0],[1,1],[2,2]],cluster_std=[0.4,0.2,0.2,0.2],random_state=9)plt.figure(figsize=(18,8),dpi=80)plt.scatter(x[:,0],x[:,1],c=y)plt.show()estimator=KMeans(n_clusters=4,random_state=0)estimator.fit(x)y_pred=estimator.predict(x)# 1. 计算 SSE 值print('SSE:',estimator.inertia_)# 2. 计算 SC 系数print('SC:',silhouette_score(x,y_pred))# 3. 计算 CH 系数案例
案例介绍
已知:客户性别、年龄、年收入、消费指数
需求:对客户进行分析,找到业务突破口,寻找黄金客户
数据集共包含顾客的数据, 数据共有 4 个特征, 数据共有 200 条。接下来,使用聚类算法对具有相似特征的的顾客进行聚类,并可视化聚类结果。
案例实现
# 定义函数 找聚类的质心数(K值)defdm01_find_k():# 加载数据集data=ps.read_csv("../data/customers.csv")# 定义sse_list,sc_list,记录:不同k值的评估效果sse_list=[]#sse: 只考虑簇内,越小越好sc_list=[]# sc:考虑簇内和簇间,越大越好# 抽取特征x=data.iloc[:,3:5]# 定义for训练,测试不同k值的评估效果forkinrange(2,20):# 创建KMeans对象,指定 k值,迭代次数,随机种子estimator=KMeans(n_clusters=k,max_iter=100,random_state=23)# 训练模型estimator.fit(x)# 模型预测y_pred=estimator.predict(x)# 获取每个簇的sse值sse_value=estimator.inertia_# 将每个k值对应的sse值,添加到sse_list列表中sse_list.append(sse_value)sc_value=silhouette_score(x,y_pred)# 将每个k值对应的sc值,添加到sc_list列表中sc_list.append(sc_value)# 绘制折线图,看看k值哪个最好plt.figure(figsize=(20,10))plt.plot(range(2,20),sse_list,label='SSE')plt.legend()plt.show()plt.figure(figsize=(20,10))plt.plot(range(2,20),sc_list,label='SC')plt.legend()plt.show()# 结论:k=5的时候,效果最好# 定义函数,实现:模型训练,模型预测、模型评估defdm02():data=ps.read_csv("../data/customers.csv")x=data.iloc[:,3:5]# k=5是之前通过上面方法获取到的estimator=KMeans(n_clusters=5,max_iter=100,random_state=23)estimator.fit(x)# 模型预测y_pre=estimator.predict(x)# 绘制5个簇的样本点 ->散点图plt.scatter(x.values[y_pre==0,0],x.values[y_pre==0,1],s=100,c='red',label='Standard')# [[15,39],[15, 81]...] 0号簇plt.scatter(x.values[y_pre==1,0],x.values[y_pre==1,1],s=100,c='blue',label='Traditional')# 1号簇plt.scatter(x.values[y_pre==2,0],x.values[y_pre==2,1],s=100,c='green',label='Normal')# 2号簇plt.scatter(x.values[y_pre==3,0],x.values[y_pre==3,1],s=100,c='cyan',label='Youth')# 3号簇plt.scatter(x.values[y_pre==4,0],x.values[y_pre==4,1],s=100,c='magenta',label='TA')# 4号簇# 绘制5个簇的质心 -> 散点图plt.scatter(estimator.cluster_centers_[:,0],estimator.cluster_centers_[:,1])plt.title('Clusters of Customers')plt.xlabel('Annual Income (k$)')plt.ylabel('Spending Score (1-100)')plt.legend()plt.show()x.values[y_pre == 0, 0]:
x.values:因为 x 是 Pandas 的 DataFrame(带表头),而 plt.scatter 只认 Numpy 数组,所以用 .values 把它变成纯粹的二维数组(200行,2列)。第 0 列是“年收入”,第 1 列是“消费指数”。
y_pre == 0:y_pre 里存的是每个客户的组别(0,1,2,3,4)。y_pre == 0 会生成一个布尔掩码(Boolean Mask),比如 [True, False, True, …],长度为200。相当于一个“筛选器”,告诉程序“只要属于 0 号簇的行”。
合在一起 x.values[布尔掩码, 0]:在 Numpy 中,逗号前面管“行”,逗号后面管“列”。
它先根据布尔掩码,把属于 0 号簇的那些行挑出来;
然后 , 0 表示只取这些行的第 0 列(年收入),作为散点图的 X 轴数据。
同理,x.values[y_pre == 0, 1] 就是取这些行的第 1 列(消费指数),作为 Y 轴。
总结
机器学习不仅在于“调包”,更在于理解算法背后的数学逻辑与适用边界。希望本文能帮助你建立起从理论到实践的桥梁,在未来面对分类或聚类任务时,能够从容选择、高效实现。欢迎在评论区交流你的实战心得或疑问,让我们共同进步!