基于DBSCAN密度聚类算法的大学生上网行为分析
源代码及数据集:
链接:https://pan.baidu.com/s/1ywQCCo9JGTSggoI798v4BA
提取码:h2p3
Ⅰ、项目任务要求
*任务描述:*
随着互联网技术的快速发展以及教育信息化建设的逐步推进,校园网作为给师生提供教学、科研、交流的重要平台,已成为衡量高校现代化和信息化建设的重要指标。但伴随校园网规模的扩大和用户数量的持续增长,校园网也带来一些负面影响。比如有些学生过于沉迷网络,耗费了大量的时间与精力,占用了大量的带宽。因此,分析校园网用户行为是很有意义的。
本次实验通过对大学生上网时间、上网时长进行分析,挖掘得出学生的各种行为倾向与规律,以期能开发出一个大学生上网的行为分析系统。通过此系统分析出学生的行为特征,可以进行实时分析,还可以及时掌握学生的行为发展趋势。同时识别一些异常的网络行为,最后将可能有异常行为发生的用户列举,以便于学校采取对应的策略或者措施引导学生健康上网,从而使互联网真正成为学生获取知识的平台,从而来提高学生整体的综合素质。
此实验内容:****用DBSCAN算法对大学生上网日志数据集(月)按照上网时间、上网时长进行聚类,并写出实验结果分析。****
*主要任务要求:*
1、简述DBSCAN密度聚类算法思想和实现原理。
2、数据集****(*TestData.txt*)****介绍。
3、写出实验结果分析:
3.1 实验运行环境描述。如开发平台、编程语言、调参情况等。
3.2实验结果分析。
(1)按上网时间进行聚类并写出聚类效果;
(2)按上网时长进行聚类并写出聚类效果;
(3)采用轮廓系数评估上述两个聚类效果;
(4)结合两个聚类结果和评估结果对实验结果进行分析说明。
II、方法思想及实现原理陈述(20分)
markdown格式不支持很多文本的显示,自行百度或者下载源代码中有word版本
III、实验结果分析(30分)
3.1 实验运行环境描述。如开发平台、编程语言、调参情况等。
运行环境为python的sklearn平台
3.2实验结果分析。
(1)按上网时间进行聚类并写出聚类效果;
可观察到:上网时间大多聚集在22:00和23:00
(2)按上网时长进行聚类并写出聚类效果;
这里有个问题:如果我们直接进行聚类的话,结果所有数据都被划分为噪声数据,以至于没有一个核心点。
为此,绘制出原始数据的直方图分布,可看到原始数据是不适合用于聚类分析的,因此我们这里使用对数变换来解决该类问题:
对数变换后上网时长的聚类结果:
(3)采用轮廓系数评估上述两个聚类效果;
聚类评估算法-轮廓系数(Silhouette Coefficient )
对时间聚类的Silhouette Coefficient: 0.710
对时长聚类的Silhouette Coefficient: 0.227
(4)结合两个聚类结果和评估结果对实验结果进行分析说明。
从聚类数目和轮廓系数来看,时长聚类效果不如时间的聚类效果明显。
IV、代码实现(50分)
# -*- coding: utf-8 -*-
'''
对上网开始时间进行聚类
'''
import numpy as np
from sklearn.cluster import DBSCAN
from sklearn import metrics#计算方法
import matplotlib.pyplot as plt
# 解决中文显示问题
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
mac2id=dict()
onlinetimes=[]
f=open('TestData.txt',encoding='utf-8')
for line in f:
items = line.strip().split(",")
#mac地址
mac=items[2]
#上网时长
onlinetime=int(items[6])
#时间格式举例:2014-07-20 22:44:18.540000000
starttime=int(items[4].split(' ')[1].split(':')[0])#只保留时间的小时位
#保证onlinetime中对应一个mac地址有一个唯一的记录
if mac not in mac2id:
mac2id[mac]=len(onlinetimes)
onlinetimes.append((starttime,onlinetime))
else:
onlinetimes[mac2id[mac]]=(starttime,onlinetime)
real_X=np.array(onlinetimes).reshape((-1,2)) #-1代表行数由程序自行根据列数和总数据信息推算出
#***************************************************
# X=real_X[:,0:1]#只得到上网(开始)时间
# plt.hist(X,24)
# plt.title("上网(开始)时间原始数据")
# plt.savefig("上网(开始)时间原始数据.png")
# # plt.show()
# plt.clf()
# # 调用DBSCAN方法进行训练,labels为每个数据的簇标签
# db=DBSCAN(eps=0.01,min_samples=20).fit(X)
#***************************************************
X=real_X[:,1:]#只得到上网时长
plt.hist(X,24)
plt.title("原始数据分布")
plt.savefig("原始数据分布.png")
# plt.show()
plt.clf()
X=np.log(1+real_X[:,1:])#只得到上网时长,对数变换,这里+1是为了防止为0的情况
# X=real_X[:,1:]
plt.hist(X,24)
plt.title("对数变换后数据分布")
plt.savefig("对数变换后数据分布.png")
# plt.show()
plt.clf()
#************************************************
#调用DBSCAN方法进行训练,labels为每个数据的簇标签
db=DBSCAN(eps=0.14,min_samples=10).fit(X)
labels = db.labels_#返回的数据的簇标签,噪声数据标签为-1
print('Labels:\n',labels)
#计算标签为-1的数据(即噪声数据)的比例
raito=len(labels[labels[:] == -1]) / len(labels)
print('Noise raito:',format(raito, '.2%'))
#计算簇的个数
n_clusters_ = len(set(labels)) - (1 if -1 in labels else 0)
print('Estimated number of clusters: %d' % n_clusters_)
#评价聚类效果:轮廓系数si,原理可参考:http://blog.csdn.net/xueyingxue001/article/details/51966932
'''
si接近1,则说明样本i聚类合理;
si接近-1,则说明样本i更应该分类到另外的簇;
若si 近似为0,则说明样本i在两个簇的边界上。
'''
print("Silhouette Coefficient: %0.3f"% metrics.silhouette_score(X, labels))#聚类效果评价指标
# Silhouette Coefficient: 0.710
# Silhouette Coefficient: 0.227
#打印各簇标号以及各簇内数据
for i in range(n_clusters_):
print('number of data in Cluster %s is : %s'%(i,len(X[labels==i])))
#print(list(X[labels == i].flatten()))
#绘制直方图分析
plt.hist(X,24)
plt.title("聚类")
plt.savefig("聚类.png")
# plt.show()
plt.clf()
评论区