DBSCAN聚类算法

一、DBSCAN算法是一种基于密度的聚类算法,聚类的时候不需要预先指定簇的个数,最终簇的个数不确定。
DBSCAN算法将数据点分为三类:
1、核心点:在半径Eps内含有超过MinPts数目的点。
2、边界点:在半径Eps内点的数量小于MinPts,但是落在核心点的邻域内的点。
3、噪音点:既不是核心点也不是边界点的点。
DBSCAN聚类算法_第1张图片
DBSCAN算法流程:
1、将所有点标记为核心点、边界点或噪声点;
2、删除噪声点;
3、为距离在Eps之内的所有核心点之间赋予一条边;
4、每组连通的核心点形成一个簇;
5、将每个边界点指派到一个与之关联的核心点的簇中(哪一个核心点的半径范围之内)。
二、以中国MOOC大学《Python机器学习基础》课程练习材料实现,通过DBSCAN聚类,分析学生上网时间和上网时长的模式。原始数据集是校园网的日志数据,单条记录格式如下:
DBSCAN聚类算法_第2张图片
原始数据处理相关代码如下:

import numpy as np
import sklearn.cluster as skc
from sklearn import metrics
import matplotlib.pyplot as plt

onlinetimes = []    #存储开始上网时间和上网时长
f = open('Dbscan_Data.txt', encoding='utf-8')  #读取数据
for line in f:
    line = line.split(',')
    onlinetime = int(line[6])   #读取每条数据中的上网时长
    starttime = int(line[4].split(' ')[1].split(':')[0])    #读取每条数据中的开始上网时间
    onlinetimes.append((starttime, onlinetime)) 
real_X = np.array(onlinetimes).reshape((-1, 2)) #将列表转化为两列的矩阵

开始上网时间聚类实现相关代码如下:

X = real_X[:, 0:1]  #截取第一列,即开始上网时间
db = skc.DBSCAN(eps=0.01, min_samples=20).fit(X)    #调用DBSCAN方法进行训练,eps是两个样本被看作邻居节点的最大距离,min_sample是簇的样本数
labels = db.labels_ #获得每个数据的簇标签
ratio = len(labels[labels[:] == -1]) / len(labels)  #计算噪声数据(label为-1)所占的比例
print('Noise ratio:', format(ratio, '.2%'))
n_clusters_ = len(set(labels)) - (1 if -1 in labels else 0) #计算簇的个数
print('Estimated number of clusters: %d' % n_clusters_)
print('Silhouette Coefficient: %0.3f' % metrics.silhouette_score(X, labels))    #聚类效果评价,轮廓系数取值为[-1,1],越趋近于1代表内聚度和分离度都相对较优
for i in range(n_clusters_):    #打印各簇标号以及各簇内数据
    print('Cluster ', i, ':')
    print(list(X[labels == i].flatten()))

其聚类结果如下:
DBSCAN聚类算法_第3张图片
可以看到学生上网时间主要集中在早上7:00-8:00、晚上20:00-23:00,其中晚上22:00和23:00数量尤其显著。
上网时长聚类实现相关代码如下:

x=real_X[:,1:]   #截取第二列,即上网时长
#plt.hist(x)
#plt.show()
X=np.log(1+x)   #进行对数变换,改进数据分布
#plt.hist(X)
#plt.show()
db=skc.DBSCAN(eps=0.14,min_samples=10).fit(X)   #调用DBSCAN方法进行训练
labels=db.labels_   #获得每个数据的簇标签
ratio=len(labels[labels[:]==-1])/len(labels)    #计算噪声数据(label为-1)所占的比例
print('Noise ratio:',format(ratio,'.2%'))
n_clusters_=len(set(labels))-(1 if -1 in labels else 0) #计算簇的个数
print('Estimated number of clusters: %d'%n_clusters_)
print('Silhouette Coefficient: %0.3f' % metrics.silhouette_score(X, labels)) #聚类效果评价
for i in range(n_clusters_):	#统计每个簇内的样本个数、均值、标准差
    print('Cluster ', i, ':')
    count = len(X[labels == i])
    mean = np.mean(x[labels == i])
    std = np.std(x[labels == i])
    print('\t number of sample: ', count)
    print('\t mean of sample: ', format(mean, '.1f'))
    print('\t std of sample: ', format(std, '.1f'))

其聚类结果如下:
DBSCAN聚类算法_第4张图片
可以看到学生上网时长存在百位级、千位级和万位级,时间跨度较大,并且千位级和万位级数量居多。而根据聚类效果评价指标轮廓系数,上网时长的聚类效果表现一般。

(结语个人日记:这两天老吴沉迷魔方,无法自拔,竟然现在才发现这么好玩的东西。看了几遍B站的视频教程,总算可以在小孩子面前偷偷显摆一下了哈哈哈。发现专注某件事情的时候,真得很享受,就没有心思在意其他杂七杂八的东西了哈哈哈。)

你可能感兴趣的:(聚类,python,算法)