1.sklearn简介
Scikit learn 也简称 sklearn, 是机器学习领域当中最知名的 python 模块之一.
sklearn库共分为6大部分,分别用于完成分类任务、回归任务、聚类任务、降维任务、模型选择以及数据的预处理
其中分类任务:
回归任务:
聚类任务:
降维任务:
3.聚类任务
聚类(clustering)就是根据数据的相似性,将数据分为多类的过程。而相似性的定义一般用距离在表示,距离越近表明两者越相似。
距离计算方法:
①欧氏距离:最常见的两点之间或多点之间的距离表示法,又称之为欧几里得度量,它定义于欧几里得空间中,如点 x = (x1,...,xn) 和 y = (y1,...,yn) 之间的距离为:
(1)二维平面上两点a(x1,y1)与b(x2,y2)间的欧氏距离:
(2)三维空间两点a(x1,y1,z1)与b(x2,y2,z2)间的欧氏距离:
(3)两个n维向量a(x11,x12,…,x1n)与 b(x21,x22,…,x2n)间的欧氏距离:
也可以用表示成向量运算的形式:
②曼哈顿距离:我们可以定义曼哈顿距离的正式意义为L1-距离或城市区块距离,也就是在欧几里得空间的固定直角坐标系上两点所形成的线段对轴产生的投影的距离总和。例如在平面上,坐标(x1, y1)的点P1与坐标(x2, y2)的点P2的曼哈顿距离为:,要注意的是,曼哈顿距离依赖座标系统的转度,而非系统在座标轴上的平移或映射。
通俗来讲,想象你在曼哈顿要从一个十字路口开车到另外一个十字路口,驾驶距离是两点间的直线距离吗?显然不是,除非你能穿越大楼。而实际驾驶距离就是这个“曼哈顿距离”,此即曼哈顿距离名称的来源,同时,曼哈顿距离也称为城市街区距离(City Block distance)。
(1)二维平面两点a(x1,y1)与b(x2,y2)间的曼哈顿距离
(2)两个n维向量a(x11,x12,…,x1n)与 b(x21,x22,…,x2n)间的曼哈顿距离
③马氏距离:
(1)马氏距离定义
有M个样本向量X1~Xm,协方差矩阵 记为S,均值记为向量μ,则其中样本向量X到u的马氏距离表示为:
而其中向量Xi与Xj之间的马氏距离定义为:
(协方差矩阵中每个元素是各个矢量元素之间的协方差Cov(X,Y),Cov(X,Y) = E{ [X-E(X)] [Y-E(Y)]},其中E为数学期望)
若协方差矩阵是单位矩阵(各个样本向量之间独立同分布),则公式就成了:![]()
也就是欧氏距离了。![]()
若协方差矩阵是对角矩阵,公式变成了标准化欧氏距离。
(2)马氏距离的优缺点:量纲无关,排除变量之间的相关性的干扰。
④夹角余弦(两个向量(线段)的相似度):几何中夹角余弦可用来衡量两个向量方向的差异,机器学习中借用这一概念来衡量样本向量之间的差异。
(1)在二维空间中向量A(x1,y1)与向量B(x2,y2)的夹角余弦公式:
(2) 两个n维样本点a(x11,x12,…,x1n)和b(x21,x22,…,x2n)的夹角余弦
类似的,对于两个n维样本点a(x11,x12,…,x1n)和b(x21,x22,…,x2n),可以使用类似于夹角余弦的概念来衡量它们间的相似程度,即:
夹角余弦取值范围为[-1,1]。夹角余弦越大表示两个向量的夹角越小,夹角余弦越小表示两向量的夹角越大。当两个向量的方向重合时夹角余弦取最大值1,当两个向量的方向完全相反夹角余弦取最小值-1。
4.聚类算法
sklearn.cluster模块提供各聚类算法函数可以使用不同的数据形式作为输入:
①数据的标准输入格式:[样本个数,特征个数] 定义的矩阵形式
②相似性矩阵输入格式:由[样本数目]定义的矩阵形式,矩阵中的每一个元素为两个样本的相似度,如DBSCAN,AffinityPropagation(近邻传播算法)接收这种输入,如果以余弦相似度为例,则对角线元素全为1。矩阵中每个元素的取值范围为[0,1]。
5.具体算法及实例
①K-means算法
K-meas算法以k为参数,把n个对象分为k个簇,使得簇内相似度较高,簇间相似度较低
步骤:
1.随机选取k个点作为初始聚类的中心
2.对于剩下的点,根据其与聚类中的距离,将其归入最近的簇
3.对每个簇,计算所有点的均值作为新的聚类中心。
4.重复2.3步骤,直至聚类中心不再改变
下面是31个省市家庭消费情况的聚类分析,具体数据及代码可以到点击打开链接这里下载
#导入工具库 import os import io import sklearn import numpy as np from sklearn.cluster import KMeans from sklearn.datasets import load_boston import json import sys #这里采用json def loadData(filePath): file=open(filePath,"r+",encoding='UTF-8') content=file.read() file.close() jsonData=json.loads(content) # outType(content) # outType(jsonData) retData=[] retCityName=[] for item in jsonData: retData.append(item["amount"]) retCityName.append(item["city"]) return retData,retCityName def outType(clz): print(type(clz)) if __name__=='__main__': #加载文件 data,cityName=loadData("city.json") #实例化一个初始3个中心的kmeas算法 km=KMeans(n_clusters=3) data=[[i] for i in data] # print("data",data) # print("cityName",cityName) #训练获得标签 lable=km.fit_predict(data) expenses=np.sum(km.cluster_centers_,axis=1) CityCluster=[[],[],[]] for i in range(len(cityName)): #将城市按照label分成设定的簇 CityCluster[lable[i]].append(cityName[i]) for i in range(len(CityCluster)): print("Expenses:%.2f" % expenses[i]) print(CityCluster[i])
运行结果:
Expenses:2200.60 ['天津', '江苏', '海南', '重庆', '四川'] Expenses:1592.38 ['河北', '山西', '内蒙古', '辽宁', '吉林', '湖北', '湖北', '贵州'] Expenses:3242.00 ['北京', '上海', '广东']
根据显示结果,分为三类,其实也可以分为4类、或者5类,但是运行代码发现并不支持,其实是由于数据的原因,划分为三类为最优解,所以其实这是K-means算法的一个缺点,我们并不知道要将其分为几类,这其实很大影响了聚类结果,在使用该算法时,我们应尽量多尝试几个数值,选择最优值。
②DBSCAN算法
算法步骤:
DBSCAN的应用实例:
现有大学校园网的日志数据,290条大学生的校园网使用情况数据,数据包 括用户ID,设备的MAC地址,IP地址,开始上网时间,停止上网时间,上 网时长,校园网套餐等。利用已有数据,分析学生上网的模式。
实验目的: 通过DBSCAN聚类,分析学生上网时间和上网时长的模式。
DBSCAN主要参数:
eps: 两个样本被看作邻居节点的最大距离
min_samples: 簇的样本数
metric:距离计算方式
例:sklearn.cluster.DBSCAN(eps=0.5, min_samples=5, metric='euclidean')
import numpy as np from sklearn.cluster import DBSCAN import sklearn.cluster as skc from sklearn import metrics import matplotlib.pyplot as plt #mac2id定义为一个字典类型 mac2id = dict() onlinetimes = [] f = open('TestData.txt',encoding='UTF-8') for line in f: #读取mac地址,spit函数就是将字符串按照括号内的字符分开,形成一个数组,[2]代表是 #数组的第三个元素 mac =line.split(',')[2] #上网时长 onlinetime =int(line.split(',')[6]) #开始上网时间 starttime =int(line.split(',')[4].split(' ')[1].split(':')[0]) if mac not in mac2id: mac2id[mac]=len(onlinetimes) onlinetimes.append((starttime,onlinetime)) else: #mac2id字典,key是mac地址,value是对应mac地址的上网时长以及开始上网的时间 onlinetimes[mac2id[mac]]=[(starttime,onlinetime)] real_X =np.array(onlinetimes).reshape((-1,2)) X =real_X[:,0:1] #调用DBSCAN方法进行训练,labels为每个数据的标签 db =skc.DBSCAN(eps=0.01,min_samples=20).fit(X) labels =db.labels_ print("Labels:") print(labels) #计算标签为-1所占的比例,即噪声数据的比例 ratio =len(labels[labels[:]==-1])/len(labels) print("Noise ratio:",format(ratio,'.2%')) #计算簇的个数 n_clusters = len(set(labels))-(1 if -1 in labels else 0) print("Estimeated number of cluster:%d" %n_clusters) print("Silhouette Coefficient: %0.3f" %metrics.silhouette_score(X,labels)) for i in range(n_clusters): print('Cluster ',i,':') print(list(X[labels==i].flatten()))
运行结果:
Labels: [ 0 -1 0 1 -1 1 0 1 2 -1 1 0 1 1 3 -1 -1 3 -1 1 1 -1 1 3 4 -1 1 1 2 0 2 2 -1 0 1 0 0 0 1 3 -1 0 1 1 0 0 2 -1 1 3 1 -1 3 -1 3 0 1 1 2 3 3 -1 -1 -1 0 1 2 1 -1 3 1 1 2 3 0 1 -1 2 0 0 3 2 0 1 -1 1 3 -1 4 2 -1 -1 0 -1 3 -1 0 2 1 -1 -1 2 1 1 2 0 2 1 1 3 3 0 1 2 0 1 0 -1 1 1 3 -1 2 1 3 1 1 1 2 -1 5 -1 1 3 -1 0 1 0 0 1 -1 -1 -1 2 2 0 1 1 3 0 0 0 1 4 4 -1 -1 -1 -1 4 -1 4 4 -1 4 -1 1 2 2 3 0 1 0 -1 1 0 0 1 -1 -1 0 2 1 0 2 -1 1 1 -1 -1 0 1 1 -1 3 1 1 -1 1 1 0 0 -1 0 -1 0 0 2 -1 1 -1 1 0 -1 2 1 3 1 1 -1 1 0 0 -1 0 0 3 2 0 0 5 -1 3 2 -1 5 4 4 4 -1 5 5 -1 4 0 4 4 4 5 4 4 5 5 0 5 4 -1 4 5 5 5 1 5 5 0 5 4 4 -1 4 4 5 4 0 5 4 -1 0 5 5 5 -1 4 5 5 5 5 4 4] Noise ratio: 22.15% Estimeated number of cluster:6 Silhouette Coefficient: 0.710 Cluster 0 : [22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22] Cluster 1 : [23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23] Cluster 2 : [20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20] Cluster 3 : [21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21] Cluster 4 : [8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8] Cluster 5 : [7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7]
根据上网时间聚类:
import numpy as np from sklearn.cluster import DBSCAN import sklearn.cluster as skc from sklearn import metrics import matplotlib.pyplot as plt #mac2id定义为一个字典类型 mac2id = dict() onlinetimes = [] f = open('TestData.txt',encoding='UTF-8') for line in f: #读取mac地址,spit函数就是将字符串按照括号内的字符分开,形成一个数组,[2]代表是 #数组的第三个元素 mac =line.split(',')[2] #上网时长 onlinetime =int(line.split(',')[6]) #开始上网时间 starttime =int(line.split(',')[4].split(' ')[1].split(':')[0]) if mac not in mac2id: mac2id[mac]=len(onlinetimes) onlinetimes.append((starttime,onlinetime)) else: #mac2id字典,key是mac地址,value是对应mac地址的上网时长以及开始上网的时间 onlinetimes[mac2id[mac]]=[(starttime,onlinetime)] real_X =np.array(onlinetimes).reshape((-1,2)) X= np.log(1+real_X[:,1:]) db = skc.DBSCAN(eps=0.14,min_samples=10).fit(X) labels =db.labels_ print("Labels:") print(labels) #计算标签为-1所占的比例,即噪声数据的比例 ratio =len(labels[labels[:]==-1])/len(labels) print("Noise ratio:",format(ratio,'.2%')) n_clusters = len(set(labels))-(1 if -1 in labels else 0) print("Estimeated number of cluster:%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(real_X[labels==i][:,1]) std =np.mean(real_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'))
结果:
Labels: [ 0 1 0 4 1 2 0 2 0 3 -1 0 -1 -1 0 3 1 0 3 2 2 1 2 0 1 1 -1 -1 0 0 0 0 1 0 -1 0 0 0 2 0 1 0 -1 -1 0 0 0 3 2 0 -1 1 0 1 0 0 -1 2 0 0 0 1 3 3 0 2 0 -1 3 0 0 2 0 0 0 2 1 -1 0 0 0 0 0 0 1 -1 0 3 1 0 1 1 0 1 0 1 0 0 -1 1 1 0 0 2 0 0 0 2 2 0 0 0 -1 0 0 4 0 1 2 -1 0 1 0 2 0 -1 -1 -1 0 1 1 3 -1 0 1 0 2 0 0 2 1 1 0 0 0 0 4 -1 0 0 0 0 2 0 0 0 0 -1 2 0 0 0 0 4 0 0 -1 0 2 0 0 -1 0 1 4 0 0 -1 1 1 0 0 2 0 0 3 -1 -1 -1 1 0 0 2 1 0 -1 -1 3 2 2 0 0 3 0 1 0 0 0 3 2 0 -1 0 1 -1 -1 0 2 2 1 4 0 0 1 0 2 0 0 0 0 1 1 0 0 1 0 4 -1 -1 0 0 0 -1 -1 1 -1 4 -1 0 2 2 -1 2 1 2 -1 0 -1 0 2 2 1 -1 0 1 2 -1 -1 1 -1 2 -1 -1 1 4 2 3 1 0 4 0 0 4 2 4 0 0 2 -1] Noise ratio: 16.96% Estimeated number of cluster:5 Silhouette Coefficient: 0.227 Cluster 0 : number of sample: 128 mean of sample 5864.304688 std of sample 2941.6 Cluster 1 : number of sample: 46 mean of sample 36835.065217 std of sample 18424.3 Cluster 2 : number of sample: 40 mean of sample 843.250000 std of sample 430.8 Cluster 3 : number of sample: 14 mean of sample 16581.642857 std of sample 8299.4 Cluster 4 : number of sample: 12 mean of sample 338.416667 std of sample 176.3