一、有监督学习和无监督学习
1. 有监督学习
监督学习(supervised learning):通过已有的训练样本(即已知数据以及其对应的输出)来训练,从而得到一个最优模型,再利用这个模型将所有新的数据样本映射为相应的输出结果,对输出结果进行简单的判断从而实现分类的目的,那么这个最优模型也就具有了对未知数据进行分类的能力。
监督学习中只要输入样本集,机器就可以从中推演出制定目标变量的可能结果.如协同过滤推荐算法,通过对训练集进行监督学习,并对测试集进行预测,从而达到预测的目的.
2. 无监督学习
现实生活中常常会有这样的问题:缺乏足够的先验知识,因此难以人工标注类别或进行人工类别标注的成本太高。很自然地,我们希望计算机能代我们完成这些工作,或至少提供一些帮助。根据类别未知(没有被标记)的训练样本解决模式识别中的各种问题,称之为无监督学习
聚类算法是一种典型的无监督学习算法,主要用于将相似的样本自动归到一个类别中,典型的分割聚类算法有K-means算法, K-medoids算法、CLARANS算法。聚类算法与分类算法最大的区别是:聚类算法是无监督的学习算法,而分类算法属于监督的学习算法。
在聚类算法中根据样本之间的相似性,将样本划分到不同的类别中,对于不同的相似度计算方法,会得到不同的聚类结果,常用的相似度计算方法有欧式距离法。
二、k-means介绍
基本K-Means算法的思想很简单,事先确定常数K,常数K意味着最终的聚类类别数,首先随机选定初始点为质心,并通过计算每一个样本与质心之间的相似度(这里为欧式距离),将样本点归到最相似的类中,接着,重新计算每个类的质心(即为类中心),重复这样的过程,知道质心不再改变,最终就确定了每个样本所属的类别以及每个类的质心。由于每次都要计算所有的样本与每一个质心之间的相似度,故在大规模的数据集上,K-Means算法的收敛速度比较慢。
三、K-means算法的流程
1.初始化常数K,随机选取初始点为质心
2.重复计算一下过程,直到每个样本所属的类不再改变
1)计算样本与每个质心之间的相似度,将样本归类到最相似的类中
2)重新计算质心
3.输出最终的质心以及每个类
四、python实现k-means
1. 数据介绍
如下面数据所示(仅部分数据),第1、2列分别代表数据坐标(x,y),第3列代表数据所属于的类,即label(该列并不会使用)。
注意:聚类算法不需要知道数据的标签的,而是自动划分该样本到相应的类中
-0.017612 14.053064 0
-1.395634 4.662541 1
-0.752157 6.538620 0
-1.322371 7.152853 0
0.423363 11.054677 0
0.406704 7.067335 1
0.667394 12.741452 0
2. 目标
使用python实现k-means算法,将数据划分到不同的类中,并用图形显示
3. python实现
#!/usr/bin/python
# -*- coding: UTF-8 -*-
from numpy import *
import random
import matplotlib.pyplot as plt
#计算两个样本之间的欧式距离
#参数是矩阵
def calDistance(vec1,vec2):
vec1=array(vec1);#转为数组
vec2 = array(vec2);
return sqrt(sum(pow(vec1-vec2,2)));
#随机选取初始质心
def getInitCentroid(dataSet,k):
m,n=shape(dataSet);
centroid=zeros((k,n));#初始化k个质心
for i in range(k):
index=random.uniform(0,len(dataSet));
centroid[i,:]=dataSet[int(index),:];
return mat(centroid);
#核心算法
def kmeans(dataSet,k):
m,n=shape(dataSet);
clusterAssment=mat(zeros((m,1)))#初始化簇m行,1列,第一列为元素所属的簇 说明:簇也就是所属的类,类就是我们常说的标签
centroid=getInitCentroid(dataSet,k)#获得初始质心
isEnd=True;
while isEnd:
isEnd=False;
for i in range(len(dataSet)):#对于每一个样本
minDistance=100000;
minindex=-1;
for j in range(k):#寻找离质心最近的簇
distance=calDistance(dataSet[i,:],centroid[j,:])
if distance<minDistance:
minDistance=distance;
minindex=j#寻找到了离质心最近的簇
if clusterAssment[i,0] != minindex:#若簇有变化,更新簇
isEnd=True;
clusterAssment[i,0]=minindex
for n in range(k):#更新每个质心
test1=clusterAssment[:, 0].A==n#获得与质心类型相同的簇
test2=nonzero(test1);
test3=test2[0];#获得与质心类型相同簇元素的下标
test4=dataSet[test3]
centroid[n,:]=mean(test4,axis=0);#相同的簇,计算平均值即为新的质心,axis=0为对列求平均值
return centroid,clusterAssment
#加载数据
def loadData(filePath):
dataSet=[];
with open(filePath) as f:
for line in f.readlines():
lines=line.split("\t");
dataSet.append([float(lines[0]),float(lines[1])]);
return mat(dataSet)
#画图
def showCluster(dataSet, k, centroids, clusterAssment):
numSamples, dim = dataSet.shape
if dim != 2:
print("Sorry! I can not draw because the dimension of your data is not 2!")
return 1
#颜色
mark = ['or', 'ob', 'og', 'ok', '^r', '+r', 'sr', 'dr', '<r', 'pr']
if k > len(mark):
print("Sorry! Your k is too large! please contact Zouxy")
return 1
#画样本
for i in range(numSamples):
markIndex = int(clusterAssment[i, 0]) # 每个样本所属族群
plt.plot(dataSet[i, 0], dataSet[i, 1], mark[markIndex])
mark = ['Dr', 'Db', 'Dg', 'Dk', '^b', '+b', 'sb', 'db', '<b', 'pb']
#画质心
for i in range(k):
plt.plot(centroids[i, 0], centroids[i, 1], mark[i], markersize=6)
plt.show()
if __name__=='__main__':
dataSet=loadData("D:\\testSet.txt");#加载数据
centroid, clusterAssment=kmeans(dataSet,2)#knn算法,返回质心以及簇
showCluster(dataSet,2,centroid,clusterAssment);#作图
4.实验结果
(1)质心个数为2,即划分为2类,k=2
(2)质心个数为3,即划分为3类,k=3