一、聚类学习简介
聚类分析又称群分析,它是研究(样品或指标)分类问题的一种统计分析方法,同时也是数据挖掘的一个重要算法。
聚类(Cluster)分析是由若干模式(Pattern)组成的,通常,模式是一个度量(Measurement)的向量,或者是多维空间中的一个点。
聚类分析以相似性为基础,在一个聚类中的模式之间比不在同一聚类中的模式之间具有更多的相似性。
聚类算法是典型的无监督算法,主要用于将相似样本分到同一类别。(分类算法为监督学习)
使用不同的聚类准则,产生的聚类结果不同。
大神常见聚类算法讲解
二、K-Means
1、原理介绍
主要思想
在给定K值和K个初始类簇中心点的情况下,把每个点(亦即数据记录)分到离其最近的类簇中心点所代表的类簇中,所有点分配完毕之后,根据一个类簇内的所有点重新计算该类簇的中心点(取平均值),然后再迭代的进行分配点和更新类簇中心点的步骤,直至类簇中心点的变化很小,或者达到指定的迭代次数。
步骤
①设置k个特征空间内的点作为初始聚类中心
②对其他所有点,分别计算他们距离所有聚类中心的距离(欧氏距离),未知的点以距离他们最近的聚类中心作为其标记类别
③按照聚类之后的标记类别,分别计算出每个聚类的新中心点(平均值)
④若新老聚类中心点相同(理想状态下,一般为到达某个阈值之下即认为迭代完成),则算法收敛,若不同,回到②,重复上述操作(进行迭代)。
API
sklearn.cluster.KMeans()
n-cluster=8:分类簇的数量
init=‘k-means++’:接收待定的string。kmeans++表示该初始化策略选择的初始均值向量之间都距离比较远,它的效果较好;random表示从数据中随机选择K个样本最为初始均值向量;或者提供一个数组,数组的形状为(n_cluster,n_features),该数组作为初始均值向量。
n_init=10:算法的运行次数
max_iter=300:最大的迭代次数
tol=1e-4:接收float,表示算法收敛的阈值。
N_jobs :表示任务使用CPU数量。
random_state 表示随机数生成器的种子。
verbose=0:0表示不输出日志信息;1表示每隔一段时间打印一次日志信息。如果大于1,打印次数频繁。
algorithm=‘auto’:接收Boolean或者auto。表示是否提前计算好样本之间的距离,auto表示如果nsamples*n>12 million,则不提前计算。
2、示例
这里使用sklearn下datasets中的make_blobs模块来创建所需数据
# lenglu
#创建数据
from sklearn.datasets._samples_generator import make_blobs
#数据可视化
import matplotlib.pyplot as plt
#训练模型
from sklearn.cluster import KMeans
#模型评估
from sklearn.metrics import calinski_harabasz_score
X,Y=make_blobs(n_samples=2000,n_features=2,random_state=0,centers=[[0,0],[1,2],[-1,-1],[2,-1]],cluster_std=[0.4,0.3,0.2,0.2])
def datashow(X):
plt.scatter(X[:,0],X[:,1])
plt.show()
#fatashow(X)
estimator=KMeans(n_clusters=4,max_iter=500,random_state=0)
pre=estimator.fit_predict(X)
print(calinski_harabasz_score(X,pre))
plt.scatter(X[:,0],X[:,1],c=pre)
plt.show()
3、模型评估
SSH(误差平方和)
每个样本真实值减去预测值的平方求和后即为SSH,在KMeans算法中,SSH为每个样本值减去其所属的聚类中心点平方后求和,代表样本的松散度(SSH越大,证明样本越松散)
SSE随着KMeans迭代,SSE会越来越小,直到趋于稳定。
“肘”方法(Elbow method)—K值确定
轮廓系数法(SC系数)
结合了聚类的凝聚度、分离度,用于评估聚类的效果
目的:使得组内距离尽可能小,组间距离尽可能大。
某点轮廓系数越接近1,证明分类越正确,为0,则表示分类比较模糊,若为复数,则表示该点可能分类错误
CH系数(Calinski-Harabasz)
原理:利用协方差来判断,簇内协方差越小越好,簇间协方差越大越好
分数计算公式:
CH系数目的:用尽量少的类别,聚类尽量多的样本,同时使得聚类效果尽量好。
4、KMeans算法优化
KMeans优点
①原理简单,易于实现
②聚合能力中上(依赖于k的选择)
③空间复杂度o(N),时间复杂度o(KN)
ps:N为样本个数,I为迭代次数
缺点
①对离群点、噪声敏感(中心易偏移)
②很难发现大小差别很大的簇及进行增量计算
③很难做到全局最优,只能保证局部最优(与K值的选取与初始点的位置有关)
(1)Canopy算法
原理
①原始数据集合List按照一定的规则进行排序(这个规则是任意的,但是一旦确定就不再更改),初始距离阈值为T1、T2,且T1 > T2(T1、T2的设定可以根据用户的需要,或者使用交叉验证获得)。
②在List中随机挑选一个数据向量A,使用一个粗糙距离计算方式计算A与List中其他样本数据向量之间的距离d。
(3)根据第2步中的距离d,把d小于T1的样本数据向量划到一个canopy中,同时把d小于T2的样本数据向量从候选中心向量名单(这里可以理解为就是List)中移除。
(4)重复第2、3步,直到候选中心向量名单为空,即List为空,算法结束。
ps:这种方法可以防止一个现有的canopy点成为新的canopy中心。我们不希望在一个现有的canopy的附近生成一个冗余canopy。
优
改进了选取K值的问题,抗干扰能力变强,可以把某些较小点的簇直接去掉。
每个Canopy内的centerpoint作为K更加精确。
只是在每个canopy内做聚类,减少计算量
缺
仍然有可能落入局部最优解。
(2)K-Means++
原理
计算所选择点与其余样本点的距离,选取距离最远的点作为下一质心,可有效避免落入局部最优解的情况
距离计算:
(3)二分K-Means
原理
①将所有样本点作为一个大簇
②将这个大簇一分为二
③选取能最大限度降低聚类代价函数(误差平方和)的簇划分为两个簇
④不停迭代,直到簇的数目等于用户所给定的K的值
ps:聚类代价函数可以反应聚类好坏程度,越大,越证明该簇聚类效果不好,所以将其拆分为两个簇
优点
极大地减少了KMeans算法的相似度计算,每一步都是误差最小,由于不存在随机选取初始点的问题
(4)K-medoids(K-中心聚类算法)
K-medoids与K-Means对于中心点的选取不同
K-medois选取当前簇中距离其他所有点距离之和的最小的点作为中心点
K-Means选取当前簇内所有点的平均值作为中心点
ps:其他的KMeans聚类算法:
Kernel K-Means:将先进行将数据投射到高维的处理,再对处理过的数据使用K-Means算法进行聚类。
ISODATA:类别数随着聚类过程改变(当某一簇类内方差过大,所含样本点过多,进行“分裂”;反之进行“合并”)
Mini Batch K-Means:适合大数据的聚类算法(一般指样本数>1w),它使用了Mini Batch(分批处理)的方法对样本之间的距离进行计算,在计算过程中从不同类别中抽取一部分样本代表此类别进行计算(不使用所有样本),这样可以极大地提高效率,但同时精确度也会下降。
三 、特征降维
1、定义
在某些限定条件下,降低随机变量(特征)个数,得到一组“不相关”主变量的过程
2、降维方式
(1)特征选择
原始数据中包含着冗余、无关变量,旨在从原有特征中找到主要特征
①Filter(过滤式)
Filter(过滤式):主要探究特征本身特点,特征与特征、目标值之间的关联
方差选择法:低方差特征过滤
低方差意味所有样本该特征相差不大,无法有效用于预测,故删除低方差特征可有效减少计算量,提升机器学习效率。
API
sklearn.feature_selection.VarianceThreshold(threshold=0.0)
# lenglu
import pandas as pd
from sklearn.datasets import load_boston
from sklearn.feature_selection import VarianceThreshold
data=load_boston()
#查看数据集
data=pd.DataFrame(data=data.data,columns=data.feature_names)
print(data)
#方差选择法
transfer=VarianceThreshold(threshold=2)
newdata=transfer.fit_transform(data)
print(newdata)
删除所有低方差特征,训练集特征方差低于threshold的将被删除(默认为0.0,故默认删除所有样本都相同的特征)
可接收的数据类型为numpy array的数据,格式为[n_samples、n_features]
相关系数
皮尔逊相关系数法:反应变量之间相关关系密切程度的指标。
-1≤r≤1
当|r|<0.4时,被称为低度相关,当0.4<|r|<0.7时,被称为显著相关,当|r|>0.7时,被称为高度线性相关。r越接近于1,正相关性越强,越接近于-1,负相关性越强。
API
# lenglu
from scipy.stats import pearsonr
x=[1,2,3,4,5,6,7,89,9]
y=[2,4,9,7,9,4,6,8,9]
print(pearsonr(x,y))
返回两个值,第一个为皮尔逊相关系数,第二个为相关系数显著性,当数据较大时有参考意义(样本量大于500),越接近0证明相关性越高。
ps:相关性的强度确实是用相关系数的大小来衡量的,但相关大小的评价要以相关系数显著性的评价为前提,因此,要先检验相关系数的显著性,如果显著,证明相关系数有统计学意义,下一步再来看相关系数大小,如果相关系数没有统计学意义,那意味着你研究求得的相关系数也许是抽样误差或者测量误差造成的,再进行一次研究结果可
能就大不一样,此时讨论相关性强弱的意义就大大减弱了。
斯皮尔曼相关系数法:反应变量之间相关关系密切程度的指标。
from scipy.stats import spearmanr
x=[1,2,3,4,5,6,7,89,9]
y=[2,4,9,7,9,4,6,8,9]
print(spearmanr(x,y))
判断方法与皮尔曼系数相同,r越接近于1,正相关性越强,越接近于-1,负相关性越强。返回值也相同。使用等级差求解,更加通用。
②Embedded(嵌入式)
Embedded(嵌入式):算法自动选择特征,特征与目标值之间的关联
决策树:信息熵、信息增益
正则化:L1、L2
深度学习:卷积等
(2)主成分分析
定义:高维数据转化为低维数据的过程,在此过程中可能会舍弃原有数据,创建新的变量。
原理:数据维数压缩,尽可能降低原有数据维数(复杂度),损失少量信息。
应用:广泛应用在聚类分析及回归分析中。
API
sklearn.decomposition.PCA(n_components=3)
n_components:可传入整数或小数,若传入整数,表示要保留的维度数(特征数量),若为小数,则表示保留信息所占比例
# lenglu
#主成分分析
from sklearn.datasets import load_iris
from sklearn.decomposition import PCA
data=load_iris().data
print(data)
transfer=PCA(n_components=3)
newdata=transfer.fit_transform(data)
print(newdata)
四、K-Means案例(按用户喜好与商品分类划分商品)
目标:分析用户对不同商品的喜好,完成对用户喜好的预测(user_id与aisle之间的关系)
数据集:kaggle
数据分析:带有四个csv文件
aisles:有aisle_id、aisle两列数据,分别为类别id及类别名
departments:有department_id、department,分别对应商品分类与类别id
order_products__prior:有order_id、product_id、add_to_cart_order、reordered,均为用户购买数据,也是本题将要预测的数据
order_products__train:与order_products__prior内容相同,为训练数据
orders:order_id user_id、eval_set、order_number、order_dow order_hour_of_day、days_since_prior_order
products:product_id、product_name、aisle_id、department_id
先将所有数据合成一张大表,使用X_id与X之间的对应关系
再进行交叉合并,生成对应关系,最后进行模型训练
# lenglu
#数据处理
import pandas as pd
#特征工程(特征降维)
from sklearn.decomposition import PCA
#机器学习(KMeans)
from sklearn.cluster import KMeans
#模型评估
from sklearn.metrics import silhouette_score
#设置输出宽度
pd.set_option('display.max_columns',1000)
#读入数据
aisles=pd.read_csv(r'.\aisles.csv')
departments=pd.read_csv(r'.\departments.csv')
order_product=pd.read_csv(r'.\order_products__train.csv')
product=pd.read_csv(r'.\products.csv')
order=pd.read_csv(r'.\orders.csv')
#表格合并
table0=pd.merge(product,order_product,on=['product_id','product_id'])
table1=pd.merge(table0,departments,on=['department_id','department_id'])
table2=pd.merge(table1,aisles,on=['aisle_id','aisle_id'])
table3=pd.merge(table2,order,on=['order_id','order_id'])
print(table3.head())
print(table3.shape)
#交叉表合并
data=pd.crosstab(table3['user_id'],table3['aisle'])
print(data.shape)
#print(data.head())
#数据截取(数据集过大,选取一部分进行简单训练)
data=data[:2000]
#特征降维
transfer=PCA(n_components=0.9)
transferdata=transfer.fit_transform(data)
print(transferdata.shape)
#机器学习
estimator=KMeans(n_clusters=4)
y_pre=estimator.fit_predict(transferdata)
print(y_pre)
print(silhouette_score(transferdata,y_pre))