引言
最近在读西瓜书,查阅了多方资料,恶补了数值代数、统计概率和线代,总算是勉强看懂了西瓜书中的公式推导。但是知道了公式以后还是要学会应用的,几经摸索发现python下的sklearn包把机器学习中经典的算法都封装好了,因此,打算写几篇博客记录一下sklearn包下的常用学习算法的使用,防止自己以后忘了,嘿嘿。
1.聚类
西瓜书中197页对“聚类”做了详细的解释,以下为摘录:
在无监督学习中,训练样本的标记信息是未知的,目标是通过对无标记训练样本来揭示数据的内在性质及 规律,为进一步的数据分析提供基础。此类学习任务中研究最多、应用最广的是‘聚类’。聚类试图将数据集中的样本划分为若干个通常是不相交的子集,每个子集称之为一个‘簇’。
简而言之,聚类就是仅根据数据本身,对大量的数据及进行分类标记,把数据化分为几类。其思想和前面的分类相似,只不过之前的分类任务我们是知道需要根据什么来进行分类,每一类应该是怎样的。而聚类则是仅仅提供数据,假设这些数据是可以分类的,让计算机来“探索”数据的分类特征。
2.聚类算法
目前急求恶习领域的聚类算法有KMeans,Birch,DBSCAN,层次聚类以及谱聚类等。
- KMeans:KMeans聚类算法又被称为K均值算法,他的思想是初始随机从数据点钟找出K个点作为初始簇中心,然后遍历每个数据点,距离哪个“中心”最近就归为哪一类,然后再从每个簇中随机选点进行迭代,直到达到最大迭代次数为止。
- Birch:Birch使用了一个树的结构来进行聚类,建立CF树结构并进行迭代输出结点。
- DBSCAN:西瓜书上给出了密度可达关系,DBSCAN算法就是基于密度可达关系的,尝试在样本点中找出若干个最大密度相连的簇,即为得到的聚类结果。
- 层次聚类:层次聚类通过不断比较数据点之间的相似程度,进行合并并以此迭代的方法,最终建立一棵树形聚类结构,如西瓜书216页图所示。
除此之外,还有很多先进的聚类算法,
5.谱聚类:谱聚类的思想即把数据点看作带权无向图,数据点之间的距离与权重成负相关,谱聚类的核心思想即尝试将图分割为若干子图,使得子图内的权值和尽可能大,子图间的权重尽可能小。
3.评价标准
本案例中使用经典的评价标准:calinski-harabasz指标(CH指标)来进行聚类结果的评价,其公式为:其中,n表示聚类的数目 ,k 表示当前的类, trB(k)表示类间离差矩阵的迹, trW(k) 表示类内离差矩阵的迹。对于同一类聚类算法的不同参结果,CH指标的值越大代表聚类的结果相对越好。
4.sklearn中的聚类算法
sklearn模块已经对上述聚类方法进行了封装,以下使用代码来分别进行演示:
1.KMeans聚类:
import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import make_blobs
from sklearn.cluster import KMeans
from sklearn import metrics
'''
使用make_blobs生成n类数据,n_samples代表总共样本点,
n_features是每个样本的维度,centers表示类别数(可传入每一类的中心列表),
cluster_std表示每个类别的方差,shuffle表示是否将数据打散(打散后聚类的难度更高)
random_state表示随机化种子,不穿的话默认每次生成的效果都不一样
make_blobs返回两个值,第一个值是坐标点数组,第二个值是一个列表,标定每个坐标点属于哪个类
'''
X, y = make_blobs(n_samples=1000, n_features=2, centers=3, cluster_std=0.5, shuffle=True, random_state=0)
#random_state关系到聚类中心的选择,如果选择不当会导致聚类结果大失所望
km = KMeans(n_clusters=3,random_state = 675)
y_pre = km.fit_predict(X)
score=metrics.calinski_harabasz_score(X, y_pre)
print(score)
#统计分类正确与错误的点,并生成颜色列表(后面可视化要用到)
def judge(y,y_pre):
blue=0
red=0
colorArr=[]
for i in range(len(y)):
if(y[i]==y_pre[i]):
blue=blue+1
colorArr.append('blue')
else:
red=red+1
colorArr.append('red')
print('分类正确:', blue, "分类错误:", red)
return colorArr
colrArr=judge(y,y_pre)
#将得到的结果进行整理,方便绘图
def split(arr):
x_axis=[]
y_axis=[]
for i in range(len(arr)):
x_axis.append(arr[i][0])
y_axis.append(arr[i][1])
return x_axis,y_axis
fig=plt.figure()
(x_axis,y_axis)=split(X)
#聚类正确的点标蓝色,聚类错误的点标红色
plt.scatter(x_axis,y_axis,c=colrArr,s=10)
plt.show()
Kmeans的重要参数是random_state,关系到初始簇中心的选择,选的不好的化聚类效果比较差,简单试了几下,在本例中选择random_state=676时聚类效果较好。运行结果如下图:
可视化结果如下,可以看到聚类结果很完美:
2.Birch聚类:
import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import make_blobs
from sklearn import metrics
from sklearn.cluster import Birch
X, y = make_blobs(n_samples=1000, n_features=2, centers=3, cluster_std=0.5, shuffle=True, random_state=0)
y_pre = Birch(n_clusters = 3).fit_predict(X)
y_pre=Birch(n_clusters = 3,threshold=0.2,branching_factor=20).fit_predict(X)
y_pre=Birch(n_clusters = 3,threshold=0.2,branching_factor=30).fit_predict(X)
y_pre=Birch(n_clusters = 3,threshold=0.5,branching_factor=20).fit_predict(X)
score=metrics.calinski_harabasz_score(X, y_pre)
print(score)
def judge(y,y_pre):
blue=0
red=0
colorArr=[]
for i in range(len(y)):
if(y[i]==y_pre[i]):
blue=blue+1
colorArr.append('blue')
else:
red=red+1
colorArr.append('red')
print('分类正确:', blue, "分类错误:", red)
return colorArr
colrArr=judge(y,y_pre)
def split(arr):
x_axis=[]
y_axis=[]
for i in range(len(arr)):
x_axis.append(arr[i][0])
y_axis.append(arr[i][1])
return x_axis,y_axis
fig=plt.figure()
(x_axis,y_axis)=split(X)
plt.scatter(x_axis,y_axis,c=colrArr,s=10)
plt.show()
Birch的主要参数是threshold和branching_factor,本案例中进行了4次调参,按结果次序排列如下:
上图可以看到,默认情况下的参数表现效果还是比较好的。
3.DBSCAN聚类:
import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import make_blobs
from sklearn import metrics
from sklearn.cluster import DBSCAN
X, y = make_blobs(n_samples=1000, n_features=2, centers=3, cluster_std=0.5, shuffle=True, random_state=0)
y_pre = DBSCAN().fit_predict(X)
y_pre = DBSCAN(eps=0.4,min_samples=15).fit_predict(X)
y_pre = DBSCAN(eps=0.9,min_samples=7).fit_predict(X)
y_pre = DBSCAN(eps=0.7,min_samples=15).fit_predict(X)
score=metrics.calinski_harabasz_score(X, y_pre)
print("CH=",score)
def judge(y,y_pre):
blue=0
red=0
colorArr=[]
for i in range(len(y)):
if(y[i]==y_pre[i]):
blue=blue+1
colorArr.append('blue')
else:
red=red+1
colorArr.append('red')
print('分类正确:', blue, "分类错误:", red)
return colorArr
colrArr=judge(y,y_pre)
def split(arr):
x_axis=[]
y_axis=[]
for i in range(len(arr)):
x_axis.append(arr[i][0])
y_axis.append(arr[i][1])
return x_axis,y_axis
fig=plt.figure()
(x_axis,y_axis)=split(X)
plt.scatter(x_axis,y_axis,c=colrArr,s=10)
plt.show()
DBSCAN算法的参数主要有两个,分别为eps和min_samples,前者表示点之间被认为同一类的阈值,点间距小于等于这个阈值就会被归为一类;后者表示被认为一类的点的个数,只有当满足阈值的点大于等于该值是当前点会被定为簇中心,本段代码中我调了多次参数,始终无法找到较完美聚类的参数,因此只放上最后一次结果的图片:
可以看到,由于DBSCAN是非监督的,不需要指定类别数,所以总是把数据结果分为两类,很难找到合适的参数。
4.层次聚类:
import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import make_blobs
from sklearn import metrics
from sklearn.cluster import AgglomerativeClustering
X, y = make_blobs(n_samples=1000, n_features=2, centers=3, cluster_std=0.5, shuffle=True, random_state=0)
y_pre = AgglomerativeClustering().fit_predict(X)
y_pre = AgglomerativeClustering(n_clusters=3).fit_predict(X)
y_pre = AgglomerativeClustering(n_clusters=3,linkage='ward').fit_predict(X)
y_pre = AgglomerativeClustering(n_clusters=3,linkage='average').fit_predict(X)
y_pre = AgglomerativeClustering(n_clusters=3,linkage='complete').fit_predict(X)
y_pre = AgglomerativeClustering(n_clusters=3,linkage='single').fit_predict(X)
score=metrics.calinski_harabasz_score(X, y_pre)
print(score)
def judge(y,y_pre):
blue=0
red=0
colorArr=[]
for i in range(len(y)):
if(y[i]==y_pre[i]):
blue=blue+1
colorArr.append('blue')
else:
red=red+1
colorArr.append('red')
print('分类正确:', blue, "分类错误:", red)
return colorArr
colrArr=judge(y,y_pre)
def split(arr):
x_axis=[]
y_axis=[]
for i in range(len(arr)):
x_axis.append(arr[i][0])
y_axis.append(arr[i][1])
return x_axis,y_axis
fig=plt.figure()
(x_axis,y_axis)=split(X)
plt.scatter(x_axis,y_axis,c=colrArr,s=10)
plt.show()
层次聚类sklearn中提供了AgglomerativeClustering函数,其主要参数为n_clusters和linkage,linkage表示连接方式,亦即相似度聚合方式,可选的值有[‘ward’,‘average’,’‘complete’,'single‘’],下面分别是几个值的结果:
由结果可知,在本数据集中当linkage选择complete时可以取得较好的聚类效果。
5.谱聚类:
import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import make_blobs
from sklearn import metrics
from sklearn.cluster import SpectralClustering
X, y = make_blobs(n_samples=1000, n_features=2, centers=3, cluster_std=0.5, shuffle=True, random_state=0)
# y_pre = SpectralClustering().fit_predict(X)
# y_pre = SpectralClustering(n_clusters=3).fit_predict(X)
# y_pre = SpectralClustering(n_clusters=3,gamma=1).fit_predict(X)
y_pre = SpectralClustering(n_clusters=3,gamma=2).fit_predict(X)
score=metrics.calinski_harabasz_score(X, y_pre)
print(score)
def judge(y,y_pre):
blue=0
red=0
colorArr=[]
for i in range(len(y)):
if(y[i]==y_pre[i]):
blue=blue+1
colorArr.append('blue')
else:
red=red+1
colorArr.append('red')
print('分类正确:', blue, "分类错误:", red)
return colorArr
colrArr=judge(y,y_pre)
def split(arr):
x_axis=[]
y_axis=[]
for i in range(len(arr)):
x_axis.append(arr[i][0])
y_axis.append(arr[i][1])
return x_axis,y_axis
fig=plt.figure()
(x_axis,y_axis)=split(X)
plt.scatter(x_axis,y_axis,c=colrArr,s=10)
plt.show()
谱聚类在sklearn中主要使用SpectralClustering函数,主要参数即为n_cluster和惩罚项gamma,此外还有n_neighbors,eigensolve等参数,在实际使用时需要逐一调节和组合,下面是gamma取2时对本例的聚类结果(最佳结果):
5.总结
本文使用5种聚类算法对对机生成的同一组数据进行聚类分析,分析得出:在积累方法中,初始参数的调节对最新红的聚类结果都有着很大的影响,因此,在使用聚类算法进行聚类计算时,应该尽可能调整参数的组合,尽可能逼近最佳结果。