无监督的算法在训练的时候只需要特征矩阵X,不需要标签。无监督学习的代表算法有聚类算法、降维算法
聚类分析仅根据在数据中发现的描述对象及其关系的信息,将数据对象分组。其目标是,组内的对象相互之间是相似的(相关的),而不同组中的 对象是不同的(不相关的)。组内的相似性(同质性)越大,组间差别越大,聚类就越好。
Kmeans计算过程:
创建k个点作为初始质心(通常是随机选择)
当任意一个点的簇分配结果发生改变时:
对数据集中的每个点:
对每个质心:
计算质心与数据点之间的距离
将数据点分配到距其最近的簇
对每个簇,计算簇中所有点的均值并将均值作为新的质心
直到簇不再发生变化或者达到最大迭代次数
对于一个簇来说,所有样本点到质心得距离之和越小,我们就认为这个簇中的样本越相似,簇内差异就越小。⽽而距离的衡量方法有多种,令x 表示簇中的⼀一个样本点, μ表示该簇中的质心,n表示每个样本点中的特征数目,i表示组成点 的每个特征,则该样本点到质心的距离可以由以下距离来度量。
轮廓系数是最常用的聚类算法的评价指标,它是对每个样本来定义的,它能够同时衡量:
(1)样本与其自身所在的簇中的其他样本的相似度a,等于样本与同一簇中所有其他点之间的平均距离
(2)样本与其他簇中的样本的相似度b,等于样本与下一个最近的簇中的所有点之间的平均距离
根据聚类的要求“簇内差异小,簇外差异大”,我们希望b永远大于a,并且大的越多越好
单个样本的轮廓系数计算为:
很容易理解轮廓系数范围是(-1,1),其中值越接近1表示样本与自己所在的簇中的样本很相似,并且与其他簇中的样本不相似,当样本点与簇外的样本更相似的时候,轮廓系数就为负。当轮廓系数为0时,则代表两个簇中的样本相似度一致,两个簇本应该是一个簇。
如果簇中的大多数样本具有比较高的轮廓系数,则簇会有较高的总轮廓系数,则整个数据集的平均轮廓系数越高,则聚类是合适的。如果许多样本点具有低轮廓系数甚至负值,则聚类是不合适的,聚类的超参数K可能设定得太大或太小。
在sklearn中,我们使用模板metrics中的类silhouette_score来计算轮廓系数,它返回的是一个数据集中,所有样本的轮廓系数的均值。但我们还有同在metrics模块中的silhouette_sample,它的参数与轮廓系数一致,但返回的是数据集中每个样本自己的轮廓系数。
DBSCAN基本原理
密度的基于中心的方法使得我们可以将点分类为:
(1)核心点:这些点在基于密度的簇内部。点的领域由距离函数和用户指定的距离参数Eps决定。核心点的定义是,如果该点的给定领域内的点的个数超过给定的阈值MinPts,其中MinPts也是一个用户指定的参数。
(2)边界点
(3)噪声点
任意两个足够靠近(相互之间的距离在Eps之内)的核心点将放在同一个簇中,同样,任何与核心点足够靠近的边界点也放到与核心点相同的簇中,噪声点被丢弃。
DBSCAN算法:
(1)将所有点标记为核心点、边界点和噪声点
(2)删除噪声点
(3)为距离在Eps之内的所有核心点之间赋予一条边
(4)每个彼此联通的核心点组成一个簇
(5)将每个边界点指派到一个与之关联的核心点的簇当中
#导入一些包
import numpy as np
import pandas as pd
import matplotlib as mpl
import matplotlib.pyplot as plt
%matplotlib inline
from sklearn.datasets import make_blobs
#模拟出一些数据集出来
r=4
k=3
x,y=make_blobs(n_samples=300,
cluster_std=[0.3,0.3,0.3],
centers=[[0,0],[1,1],[-1,1]],
random_state=r
)
sim_data=pd.DataFrame(x,columns=['x1','x2'])
datasets=sim_data.copy()
plt.scatter(sim_data['x1'],sim_data['x2'])
#手动生成随机的k个质心点出来
centers=[
[-1.5,0.5],
[1.5,0],
[1,-0.5]
]
centers=pd.DataFrame(centers,
columns=['x1','x2'],
index=['blue','green','red'])
#取出其中一个质心点,尝试计算每一个点到这个质心点的距离
tmp_centers=centers.loc['blue',:]
#直接使用数据-质心点的方式尝试计算每个点到质心点的距离
np.power(datasets-tmp_centers,2).sum(axis=1)
l=[]
for i in centers.index:
tmp_centers=centers.loc[i,:]
l.append(np.power(datasets-tmp_centers,2).sum(axis=1))
d_to_centers=pd.concat(l,axis=1)
d_to_centers.columns=centers.index
curr_group=d_to_centers.idxmin(axis=1)
#当每一个点有一个新的簇的时候,就可以计算新的质心点的位置了
tmp_data=datasets.copy()
tmp_data['curr_group']=curr_group
centers=tmp_data.groupby('curr_group').mean()
#创建一个空的SSE_list,用来存SSE的
#初始化质心点
centers=[
[-1,0.5],
[1,0],
[1,-1]
]
centers=pd.DataFrame(centers,
columns=['x1','x2'],
index=['blue','green','red'])
SSE_list=[]
SSE=-1
#开始迭代
while True:
#保持质心点不变,更新类别
l=[]
#记录上一次迭代中centers,SSE的值
last_centers=centers.copy()
last_SSE=SSE
for i in centers.index:
tmp_centers=centers.loc[i,:]
l.append(np.power(datasets-tmp_centers,2).sum(axis=1))
d_to_centers=pd.concat(l,axis=1)
SSE=d_to_centers.min(axis=1).sum()
SSE_list.append(SSE)
if SSE==last_SSE:
break
d_to_centers.columns=centers.index
curr_group=d_to_centers.idxmin(axis=1)
#保持类别不变,更新质心点
tmp_data=datasets.copy()
tmp_data['curr_group']=curr_group
centers=tmp_data.groupby('curr_group').mean()
plt.scatter(datasets['x1'],datasets['x2'],c=curr_group)
plt.scatter(centers.iloc[:,0],centers.iloc[:,1],c='black',marker='x')
#所有代码和函数集合起来
def initial_centers(datasets,k=3):
cols=datasets.columns
data_content=datasets.loc[:,cols!='label']
range_info=data_content.describe().loc[['min','max']]
k_randoms=[np.random.uniform(range_info[i]['min'],
range_info[i]['max'],k)
for i in range_info.columns]
centers=pd.DataFrame(k_randoms,index=range_info.columns)
return centers.T
def cal_distant(dataset,centers):
data=dataset.loc[:,dataset.columns!='label']
d_to_centers=[np.power(data-centers.loc[i],2).sum(axis=1)
fro i in centers.index]
return pd.concat(d_to_centers,axis=1)
def iterate(dataset,centers):
d_to_centers=cal_distant(dataset,centers)
curr_group=d_to_centers.idxmin(axis=1)
SSE=d_to_centers.min(axis=1).sum()
centers=dataset.loc[:,dataset.columns !='label'].groupby(curr_group).mean()
return curr_group,SSE,centers
def Kmeans_regular(data,k=3):
SSE_list=[0]
centers=initial_centers(data,k=k)
while True:
curr_group,SSE,centers=iterate(data,centers)
if SSE_list[-1]==SSE:
break
SSE_list.append(SSE)
return curr_group,SSE_list,centers
#DBSCAN
from sklearn.datasets import make_moons
X,y=make_moons(200,noise=0.05,random_state=0)
plt.scatter(X[:,0],X[:,1],c=y)
from sklearn.cluster import KMeans
kmeans=KMeans(n_cluster=2)
kmeans.fit(X)
kmeans.labels_
centers=kmeans.cluster_centers_
#尝试使用轮廓系数来查看
from sklearn.cluster import KMeans
from sklearn.metrics import silhouette_score,silhouette_samples
import matplotlib.pyplot as plt
import matplotlib.cm as cm
import numpy as np
from sklearn.datasets import make_blobs
#创建数据集
X,y=make_blobs(n_sample=500,n_features=2,centers=4,random_state=1)
plt.scatter(X[:,0],X[:,1],marker='o',s=8)
data=pd.DataFrame(X)
data['label']=y
#先设定我们要分成的簇数
n_clusters=4
#创建一个画布,画布上共有一行两列两个图
fig,(ax1,ax2)=plt.subplots(1,2)
#画布尺寸
fig.set_size_inches(18,7)
ax1.set_xlim([-0.1,1])
ax1.set_ylim([0,X.shape[0]+(n_cluster+1)*10])
#开始建模,调用聚类好的标签
clusterer=KMeans(n_clusters=n_clusters,random_state=10).fix(X)
cluster_labels=clusterer.labels_
silhouette_avg=silhouette_score(X,cluster_labels)
sample_silhouette_values=silhouette_sample(X,cluster_labels)
y_lower=10
for i in range(n_clusters):
ith_cluster_silhouette_values=sample_silhouette_values[cluster_labels==i]
ith_cluster_silhouette_values.sort()
size_cluster_i=ith_cluster_silhouette_values.shape[0]
y_upper=y_lower+size_cluster_i
color=cm.nipy_spectral(float(i)/n_clusters)
ax1.fill_betweenx(np.arange(y_lower,y_upper),
ith_cluster_silhouette_values,
facecolor=color,
alpha=0.7)
#text的参数为(要显示编号的位置的横坐标,要显示标号的位置的纵坐标,要显示的编号内容)
ax1.text(-0.05,y_lower+0.5*size_cluster_i,str(i))
y_lower=y_upper+10
ax1.set_title('The silhouette plot for the various clusters.')
ax1.set_xlabel('The silhouette coefficient values')
ax1.set_ylabel('Cluster label')
ax1.axvline(x=silhouette_avg,color='red',linestyle='--')
#让y轴不显示任何刻度
ax1.set_yticks([])
#让x轴上的刻度显示为我们规定的列表
ax1.set_xticks([-0.1,0,0.2,0.4,0.6,0.8,1])
colors=cm.nipy_spectral(cluster_labels.astype(float)/n_clusters)
ax2.scatter(X[:,0],X[:,1],marker='o',s=8,c=colors)
centers=clusterer.cluster_centers_
ax2.scatter(centers[:,0],centers[:,1],marker='x',c='red',alpha=1,s=200)
ax2.set_title("The visualization of the clustered data.")
ax2.set_xlabel("Feature space for the 1st feature")
ax2.set_ylabel("Feature space for the 2nd feature")
#为整个图设置标题
plt.suptitle(("Silhouette analysis for KMeans clustering on sample data "
"with n_clusters = %d" % n_clusters),
fontsize=14, fontweight='bold')
plt.show()
暂无数据