程序需要的数据集见文章结尾。
DSCAN算法:具有噪声的基于密度的聚类算法。
上一节的k-means算法的缺点之一就是K值的选取问题,这里DSCAN聚类算法不需要指定K值,这里的DSCAN算法需要指定两个参数:
epsilon:指定半径
Minpt:密度阈值
这里有两个概念需要解释:直接密度可达和密度可达
宇哥的视频中是这样讲解的
(忽略图丑)
左边这个图中p和q在一个圈里面,它们是直接密度可达的;右边这个图里面,p1和p2是直接密度可达,p2和p3是直接密度可达,这里p1和p3是密度可达(少了直接两个字),密度可达是直接密度可达的“传播”。
DSCAN聚类算法中需要两个参数
epsilon:指定半径
Minpt:密度阈值
那么这两个参数如何选择呢?关于半径,可以根据k距离来设定,寻找突变点,啥叫突变点呢?
假如将p0到p1-6的距离分别定为d1-d6,这里0.14到0.3跨度较大,所以0.3这里是突变点。
Minpt:K距离中k的值
https://www.naftaliharris.com/blog/visualizing-dbscan-clustering/
介绍DSCAN可视化比较好的一个网站,可以选择不同的数据形状,聚类。
DSCAN聚类的优点:
不需要指定k值;可以发现任意形状的簇;擅长找到离群点(适合做异常检测);两个参数就可以了。
对于这个笑脸数据,就可以分成很好的形状。
但是如果数据集直接比较密集,可能聚类出来的效果就不太好。
比如这个数据集。
然后,具体程序看一下kmeans和DSCAN如何实现聚类算法
首先样本数据集是20个样本的关于酒的数据。首先是读入数据--kmeans聚类--可视化--然后标准化数据--可视化结果;聚类实现了,如何评价聚类效果--轮廓系数--根据这个系数确定选取k
# beer dataset
import pandas as pd
beer = pd.read_csv('data.txt', sep=' ')
beer
#无监督学习,不需要标签,输入的是所有的特征
X = beer[["calories","sodium","alcohol","cost"]]
from sklearn.cluster import KMeans
km = KMeans(n_clusters=3).fit(X)
km2 = KMeans(n_clusters=2).fit(X)
#查看聚类以后的标签
km.labels_
然后查看聚类的中心
from pandas.tools.plotting import scatter_matrix
%matplotlib inline
cluster_centers = km.cluster_centers_
cluster_centers_2 = km2.cluster_centers_
聚类是3类和聚类是两类的中心点分别如下:
centers = beer.groupby("cluster").mean().reset_index()
#可视化展示
import matplotlib.pyplot as plt
#标题的字体大小
plt.rcParams['font.size'] = 14
import numpy as np
colors = np.array(['red', 'green', 'blue', 'yellow'])
#可视化展示calories和alcohol的聚类关系
plt.scatter(beer["calories"], beer["alcohol"],c=colors[beer["cluster"]])
plt.scatter(centers.calories, centers.alcohol, linewidths=3, marker='+', s=300, c='black')
plt.xlabel("Calories")
plt.ylabel("Alcohol")
如何展示多个变量之间的关系:scatter_matrix(beer['变量名'])
#分成3类的时候
scatter_matrix(beer[["calories","sodium","alcohol","cost"]],s=100, alpha=1, c=colors[beer["cluster"]], figsize=(10,10))
plt.suptitle("With 3 centroids initialized")
#分成2类的时候
scatter_matrix(beer[["calories","sodium","alcohol","cost"]],s=100, alpha=1, c=colors[beer["cluster2"]], figsize=(10,10))
plt.suptitle("With 2 centroids initialized")
之后尝试对数据做一些预处理(标准化),然后再聚类。
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
km = KMeans(n_clusters=3).fit(X_scaled)
beer["scaled_cluster"] = km.labels_
beer.sort_values("scaled_cluster")
beer.groupby("scaled_cluster").mean()
然后可视化各个变量之间的聚类效果图,参考前面没做标准化之前的作图。
如何评价聚类的效果呢?
使用轮廓系数
from sklearn import metrics
score_scaled = metrics.silhouette_score(X,beer.scaled_cluster)
score = metrics.silhouette_score(X,beer.cluster)
print(score_scaled, score)
这里没做标准化的聚类效果要优于做标准化之后的聚类效果(所以有时候并不是做标准化就一定好)
#查看不同k值的情况下的轮廓系数
scores = []
for k in range(2,20):
labels = KMeans(n_clusters=k).fit(X).labels_
score = metrics.silhouette_score(X, labels)
scores.append(score)
发现k=2的时候轮廓系数比较大,所以选择k=2比较好。
DBSCAN聚类算法(对于不规整数据集比较强大,简单数据集的效果可能还不如k-means)
from sklearn.cluster import DBSCAN
db = DBSCAN(eps=10, min_samples=2).fit(X)
labels = db.labels_
beer['cluster_db'] = labels
beer.sort_values('cluster_db')
beer.groupby('cluster_db').mean()
pd.scatter_matrix(X, c=colors[beer.cluster_db], figsize=(10,10), s=100)
数据集链接:https://pan.baidu.com/s/1hfR9CNV0DOhfBhnFy9accQ
提取码:x519