聚类
聚类 是一种无监督学习,它将相似对象归到一个簇中。
簇中的对象越相似,聚类的效果越好。
聚类跟分类的区别,分类事先知道分类的种类,聚类则预先未定义 ,聚类属于无监督分类
K-means(K-均值)算法
之所以称k-均值,是因为它将数据分为k个簇,且每个簇的中心是采用所包含对象的均值计算出来的....
给定一个有M个对象的数据集,构建一个具有k个簇的模型,其中k<=M。满足以下条件:
1、每个簇至少包含一个对象;
2、每个对象属于且仅属于一个簇;
3、将满足上述条件的k个簇成为一个合理的聚类划分;
基本思想:对于给定的类别数目k,首先给定初始划分,通过迭代改变样本和簇的隶属关系,使的每次处理后得到的划分方式比上一次的好(簇内数据集距离变小)
终止条件: 迭代次数, 最小平方误差MSE, 簇中心变化率
K-means算法的思考
K-means算法在迭代的过程中使用簇类中所有对象的均值作为新的质心,如果簇中存在异常点,会导致均值误差较大
eg: 簇中有 2, 4, 6, 8,100 K-means使用的新质点为24,显然误差较大,优化使用K-Mediods聚类(K中值聚类),采用中位数 6
k-means优缺点
缺点
1 k值是用户给定的,需要数据分析经验,不同的k值,分类的结果不一样
2 对初始簇中心点敏感
3 不适合发现非凸形状的簇或者大小差别较大的簇
4 异常值对模型影响较大
优点
1 当簇近似高斯分布时,效果较好
2 处理大数据集时,该算法可以保证较好的伸缩性和高效率
3 易理解 聚类效果不错
高斯分布数据生成(make_blobs的使用)
# -*- coding: utf-8 -*-
# @Time : 2019/1/11 10:39 AM
# @Author : scl
# @Email : 1163820757@qq.com
# @File : 高斯分布数据.py
# @Software: PyCharm
import matplotlib
matplotlib.use("TkAgg")
import matplotlib.pyplot as plt
from sklearn.datasets import make_blobs
'''
make_blobs: 产生一个服从给定均值和标准差的高斯分布
最终返回数据样本组成的x特征矩阵 以及样本对应的类别(当前数据属于哪个均值哪个标准差的数据分布)
'''
x,y = make_blobs(n_samples=50,n_features=2,centers=3)
# 50个样本 2个特征 3个簇中心
print(x)
print(y)
print(x.shape)
print(y.shape)
# (50, 2)
# (50,)
# s表示点的半径大小
plt.scatter(x[:, 0], x[:, 1], c=y, s=3)
plt.show()
模拟数据使用kmeans预测
# -*- coding: utf-8 -*-
# @Time : 2019/1/14 9:50 AM
# @Author : scl
# @Email : 1163820757@qq.com
# @File : 模拟数据使用kmeans算法.py
# @Software: PyCharm
import matplotlib
matplotlib.use("TkAgg")
import matplotlib.pyplot as plt
from sklearn.datasets import make_blobs
from sklearn.cluster import KMeans
from sklearn.model_selection import GridSearchCV
N = 1000
n_centers = 4
X,Y = make_blobs(n_samples=N,n_features=2,centers=n_centers,random_state=12)
# 1# 模型构建
# algo = KMeans(n_clusters=n_centers)
# algo.fit(X)
# 2 模型构建使用网格交叉验证
'''
定义: 将原始数据集划分为两部分 一部分分为训练集 训练模型 另一部分分为测试集合验证模型效果
交叉验证的目的是为了验证训练模型的拟合程度
网格交叉验证(网格搜索) GridSearchCV 对估计器的指定参数值穷举搜索 通过给定不同参数值的组合 验证选取一组最优的参数parameters
'''
parameters = {
'n_clusters':[2,3,4,5,6],
'random_state':[0,14,28]
}
model = KMeans(n_clusters=n_centers)
algo = GridSearchCV(estimator=model,param_grid=parameters,cv=5)
algo.fit(X)
# 数据预测
x_test =[
[-4, 8],
[-3, 7],
[0, 5],
[0, -5],
[8, -8],
[7, -9]
]
# 预测值:[2 2 3 3 1 1]
print('预测值:{}'.format(algo.predict(x_test)))
# print("中心点坐标{}".format(algo.cluster_centers_))
# print("目标函数的损失函数:(所有样本到簇中心点的距离平方和)")
#
# print(algo.inertia_)
# print(algo.inertia_/N)
## 交叉验证
print("最优模型参数{}".format(algo.best_params_))
print('中心点坐标{}'.format(algo.best_estimator_.cluster_centers_))
print("目标函数损失值{}".format(algo.best_estimator_.inertia_))
print(algo.best_estimator_.inertia_/N)
plt.scatter(X[:,0],X[:,1],c = Y,s=30)
plt.show()
公式
1.Jaccard(杰卡德相似系数)
如果J(A,B) 越趋近于1,表示A和B集合完全重合。如果J(A,B) 趋近于0,表示A和B集合几乎没有相交。
即J(A,B) 越接近于1,越相似。距离和相似程度反比,距离越小,相似程度越大。所以用 1-J(A,B) 来表示度量函数时,值越大,相似度越大。
1. Pearson相关系数(皮尔森相关系数)
定义为两个变量间的协方差与标准差的商
一般情况下:
若:|PXY|<0.3 则:X和Y不相关;
若:0.3<|PXY|<0.7 则: X和Y弱相关
若:0.7<|PXY|<1 则:X和Y强相关;
若:PXY>0 则:正相关;
若:PXY<0 则:负相关;
K-Means算法案例
# -*- coding: utf-8 -*-
# @Time : 2019/1/14 11:23 AM
# @Author : scl
# @Email : 1163820757@qq.com
# @File : K-Means算法.py
# @Software: PyCharm
import matplotlib
matplotlib.use("TkAgg")
import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl
import sklearn.datasets as ds
import matplotlib.colors
from sklearn.cluster import KMeans #引入kmeans
## 设置属性防止中文乱码
mpl.rcParams['font.sans-serif'] = [u'SimHei']
mpl.rcParams['axes.unicode_minus'] = False
# 1 生成模拟数据
N = 1500
centers = 4
# 产生等方差的数据集(中心点随机)
data1,y1 = ds.make_blobs(N,n_features=2,centers=centers,random_state=12)
# 产生指定中心点和方差的数据集
data2,y2 = ds.make_blobs(N,n_features=2,centers= [(-10,-8), (-5,8), (5,2), (8,-7)],cluster_std=[1.5, 2.5, 1.9, 1],random_state=12)
# 产生方差相同 样本数量不同的数据集
data3 = np.vstack((data1[y1 == 0][:200],
data1[y1 == 1][:100],
data1[y1 == 2][:10],
data1[y1 == 3][:50]))
y3 = np.array([0] * 200 + [1] * 100 + [2] * 10 + [3] * 50)
# 2 模型构建
km = KMeans(n_clusters=centers,init='random',random_state=12)
km.fit(data1)
# 模型预测
y_hat = km.predict(data1)
print('所有样本距离簇中心点的总距离和:',km.inertia_)
print('距离聚簇中的平均距离',(km.inertia_/N))
cluster_centers = km.cluster_centers_
print('聚簇中心点\n',cluster_centers)
y_hat2 = km.fit_predict(data2)
y_hat3 = km.fit_predict(data3)
def expandBorder(a,b):
d = (b - a) * 0.1
return a-d,b+d
# 绘图
cm = mpl.colors.ListedColormap(list('rgbmyc'))
plt.figure(figsize=(15, 9), facecolor='w')
plt.subplot(241)
plt.scatter(data1[:, 0], data1[:, 1], c=y1, s=30, cmap=cm, edgecolors='none')
x1_min, x2_min = np.min(data1, axis=0)
x1_max, x2_max = np.max(data1, axis=0)
x1_min, x1_max = expandBorder(x1_min, x1_max)
x2_min, x2_max = expandBorder(x2_min, x2_max)
plt.xlim((x1_min, x1_max))
plt.ylim((x2_min, x2_max))
plt.title(u'原始数据')
plt.grid(True)
plt.subplot(242)
plt.scatter(data1[:, 0], data1[:, 1], c = y_hat, s=30, cmap=cm, edgecolors='none')
plt.xlim((x1_min, x1_max))
plt.ylim((x2_min, x2_max))
plt.title(u'K-Means算法聚类结果')
plt.grid(True)
# 对数据做一个旋转
m = np.array(((1, -5), (0.5, 5)))
data_r = data1.dot(m)
y_r_hat = km.fit_predict(data_r)
plt.subplot(243)
plt.scatter(data_r[:, 0], data_r[:, 1], c=y1, s=30, cmap=cm, edgecolors='none')
x1_min, x2_min = np.min(data_r, axis=0)
x1_max, x2_max = np.max(data_r, axis=0)
x1_min, x1_max = expandBorder(x1_min, x1_max)
x2_min, x2_max = expandBorder(x2_min, x2_max)
plt.xlim((x1_min, x1_max))
plt.ylim((x2_min, x2_max))
plt.title(u'数据旋转后原始数据图')
plt.grid(True)
plt.subplot(244)
plt.scatter(data_r[:, 0], data_r[:, 1], c=y_r_hat, s=30, cmap=cm, edgecolors='none')
plt.xlim((x1_min, x1_max))
plt.ylim((x2_min, x2_max))
plt.title(u'数据旋转后预测图')
plt.grid(True)
plt.subplot(245)
plt.scatter(data2[:, 0], data2[:, 1], c=y2, s=30, cmap=cm, edgecolors='none')
x1_min, x2_min = np.min(data2, axis=0)
x1_max, x2_max = np.max(data2, axis=0)
x1_min, x1_max = expandBorder(x1_min, x1_max)
x2_min, x2_max = expandBorder(x2_min, x2_max)
plt.xlim((x1_min, x1_max))
plt.ylim((x2_min, x2_max))
plt.title(u'不同方差的原始数据')
plt.grid(True)
plt.subplot(246)
plt.scatter(data2[:, 0], data2[:, 1], c=y_hat2, s=30, cmap=cm, edgecolors='none')
plt.xlim((x1_min, x1_max))
plt.ylim((x2_min, x2_max))
plt.title(u'不同方差簇数据的K-Means算法聚类结果')
plt.grid(True)
plt.subplot(247)
plt.scatter(data3[:, 0], data3[:, 1], c=y3, s=30, cmap=cm, edgecolors='none')
x1_min, x2_min = np.min(data3, axis=0)
x1_max, x2_max = np.max(data3, axis=0)
x1_min, x1_max = expandBorder(x1_min, x1_max)
x2_min, x2_max = expandBorder(x2_min, x2_max)
plt.xlim((x1_min, x1_max))
plt.ylim((x2_min, x2_max))
plt.title(u'不同簇样本数量原始数据图')
plt.grid(True)
plt.subplot(248)
plt.scatter(data3[:, 0], data3[:, 1], c=y_hat3, s=30, cmap=cm, edgecolors='none')
plt.xlim((x1_min, x1_max))
plt.ylim((x2_min, x2_max))
plt.title(u'不同簇样本数量的K-Means算法聚类结果')
plt.grid(True)
plt.tight_layout(2, rect=(0, 0, 1, 0.97))
plt.suptitle(u'数据分布对KMeans聚类的影响', fontsize=18)
plt.show()
Figure_1.png
网友评论