【机器学习】人像识别(三)——K-Means聚类
2017-02-08 19:11
197 查看
简介
K-Means聚类是一种非监督的聚类方式,原理参看数据挖掘十大算法 | k-means。代码
import sys import random import numpy as np from sklearn.decomposition import IncrementalPCA imgNum = 10 # 几张图片 KNum = 2 # 分成几类 n = 2 # 每张图片都是n×n dimension = 2016 # 每张图片的维数 dst_dimension = 10 # 想降到的维数 bound = 10 # 前后两次迭代结果之差小于这个时可以停止 maxRecurseTime = 10 # 最多迭代次数 centroids = [] # 存放KNum个质心的n维坐标向量 last_centroids = [] # 上一次递归得到的质心坐标们 ori_dots = [] # 存放每个点的n维坐标向量 dots = [] # 降维之后的点的坐标 clusters = [] # 存放每个类中有哪些点, clusters[i]中存放的是第i类中的点的下标,第i类的中心是centroids[i] selected = [] Distance = lambda v: np.linalg.norm(v) # 初始化点的坐标,并进行降维,返回降维后的向量集 def InitDots(): # 读入imgNum个点的坐标,存放在dots当中 for i in range(imgNum): ori_dots.append([]) # 读入向量集并降维 ReadFiles(ori_dots) return PCA(ori_dots) # 初始化质心信息 def InitCentroids(): # 初始化质心信息 for i in range(KNum): centroids.append([]) centroids[i] = np.array([float(0)] * dimension) # 初始化为全零 clusters.append([]) # 随机挑选初始时的‘质心’坐标 for i in range(KNum): _ = random.randrange(imgNum) while _ in selected: _ = random.randrange(imgNum) selected.append(_) selected.sort() print('selected:' , selected) for i in range(KNum): centroids[i] = dots[selected[i]] print('centroids 0:', centroids) # 读入imgNum个图的坐标向量 def ReadFiles(dots): path = r'C:\Users\Owner\Documents\Visual Studio 2015\Projects\Python\K-Means\K-Means\\' fd = open(path + 'input.txt', 'r') _ = fd.read() # 一次读进所有 fd.close() _ = _.split() for i in range(len(_)): dots[i % imgNum].append(255 - float(_[i])) tmp = [2, 5] for i in tmp: for j in range(len(dots[i])): dots[i][j] *= 0.9 # 降维操作 def PCA(dots): X = np.array(dots) ipca = IncrementalPCA(n_components = dst_dimension) ipca.fit(X) Y = ipca.transform(X) print('y = ', Y, '\n') for i in range(len(Y)): Y[i] = np.array(Y[i]) return Y # 对于每个cluster,计算质心 def CalcCentroids(KNum, dimension, centroids, dots, clusters): # 先把上一次得到的质心存放到last_centroids当中 last_centroids = centroids # centroids = [] 这会导致传不回去 for i in range(KNum): v = np.array([float(0)] * dst_dimension) for _ in clusters[i]: v += dots[_] l = len(clusters[i]) centroids[i] = (v / l) # 聚类,判断每个点属于哪个类 def Cluster(imgNum, KNum, dots, clusters): # 清空原有数据 for i in range(KNum): clusters[i] = [] # 计算每个点到每个质心的距离,并将他们放到相应的cluster中 for i in range(imgNum): store = [] # 存放当前的点到每个质心的距离 for j in range(KNum): store.append(Distance(dots[i] - centroids[j])) cluster_index = store.index(min(store)) # store中最小的数是min(store),找这个最小数的下标用store.index() clusters[cluster_index].append(i) dots = InitDots() InitCentroids() temp = sys.stdout log_root = r'C:\Users\Owner\Documents\Visual Studio 2015\Projects\Python\K-Means\K-Means\Log_'+str(dst_dimension)+'\\' sys.stdout = open(log_root + str(selected) + '.txt','w') for i in range(bound): print('ROUND ' + str(i) + ': ') print('centroids: ', centroids) Cluster(imgNum, KNum, dots, clusters) print('clusters', 4000 clusters, '\n') CalcCentroids(KNum, dimension, centroids, dots, clusters) print('centroids: ', centroids) print('clusters: ', clusters) sys.stdout = temp
遇到的问题
计算两点之间的欧氏距离可以用numpy库中的函数:dist = numpy.linalg.norm(vec1 - vec2)
经常发现ROUND 2之后,质心就不再变了。对此,我心中不太踏实,踟蹰于聚类速度是否当真如此之快。不过数据集这样小,结果也正确,姑且将此归功于K-Means的有效性吧。
在阅读log文档时,发现编号为2和5的图总是被归到一组,然而恢复出灰度图后,发现这两张图并不是一个人,但有一个共同点——色调较暗。因此在读入数据后,将这两张图的灰度值乘了系数0.9,之后聚类结果就基本稳定了。
相关文章推荐
- 【机器学习】人像识别(二)——PCA降维
- 机器学习实践之手写数字识别 - 数据初识
- 机器学习--kNN算法识别手写字母
- 模式识别和机器学习 笔记
- [机器学习案例1]基于KNN手写数字识别
- 模式识别与机器学习(5)
- 机器学习(10.1)--手写数字识别的不同算法比较(1)--mnist数据集不同版本解析及平均灰度实践
- PRML笔记:模式识别与机器学习
- 机器学习实战-----八大分类器识别树叶带源码
- 【机器学习(1)】图像识别中的最近邻分类和knn分类
- 机器学习初学者—手把手教你做数字图像识别:Kaggle—Digit Recognizer
- 今天开始学模式识别与机器学习(PRML),章节5.1,Neural Networks神经网络-前向网络。
- 机器学习--knn手写数字识别系统
- 机器学习(4)——KNN算法及手写数字的识别(二)
- 【转】机器学习教程 十四-利用tensorflow做手写数字识别
- SphinX人像识别 -- 联想笔记本人脸识别系统 (适合所有带摄像头的电脑)
- 机器学习之svm---车牌识别
- 纯java JJIL脸部识别人像识别
- 机器学习零基础?手把手教你用TensorFlow搭建图像识别系统
- 基于Tensorflow训练物体、人像识别的模型