- 参数 n_clusters: 聚类个数,即k initCent: 质心初始化方式,可选"random"或指定一个具体的array,默认random,即随机初始化 max_iter: 最大迭代次数
| 10 | import numpy as np |
| 11 | |
| 12 | class KMeans(object): |
| 13 | """ |
| 14 | - 参数 |
| 15 | n_clusters: |
| 16 | 聚类个数,即k |
| 17 | initCent: |
| 18 | 质心初始化方式,可选"random"或指定一个具体的array,默认random,即随机初始化 |
| 19 | max_iter: |
| 20 | 最大迭代次数 |
| 21 | """ |
| 22 | def __init__(self,n_clusters=5,initCent='random',max_iter=300): |
| 23 | if hasattr(initCent, '__array__'): |
| 24 | n_clusters = initCent.shape[0] |
| 25 | self.centroids = np.asarray(initCent, dtype=np.float) |
| 26 | else: |
| 27 | self.centroids = None |
| 28 | |
| 29 | self.n_clusters = n_clusters |
| 30 | self.max_iter = max_iter |
| 31 | self.initCent = initCent |
| 32 | self.clusterAssment = None |
| 33 | self.labels = None |
| 34 | self.sse = None |
| 35 | |
| 36 | #计算两点的欧式距离 |
| 37 | def _distEclud(self, vecA, vecB): |
| 38 | return np.linalg.norm(vecA - vecB) |
| 39 | |
| 40 | #随机选取k个质心,必须在数据集的边界内 |
| 41 | def _randCent(self, X, k): |
| 42 | n = X.shape[1] #特征维数 |
| 43 | centroids = np.empty((k,n)) #k*n的矩阵,用于存储质心 |
| 44 | for j in range(n): #产生k个质心,一维一维地随机初始化 |
| 45 | minJ = min(X[:,j]) |
| 46 | rangeJ = float(max(X[:,j]) - minJ) |
| 47 | centroids[:,j] = (minJ + rangeJ * np.random.rand(k,1)).flatten() |
| 48 | return centroids |
| 49 | |
| 50 | def fit(self, X): |
| 51 | #类型检查 |
| 52 | if not isinstance(X,np.ndarray): |
| 53 | try: |
| 54 | X = np.asarray(X) |
| 55 | except: |
| 56 | raise TypeError("numpy.ndarray required for X") |
| 57 | |
| 58 | m = X.shape[0]#m代表样本数量 |
| 59 | self.clusterAssment = np.empty((m,2))#m*2的矩阵,第一列存储样本点所属的族的索引值, |
| 60 | #第二列存储该点与所属族的质心的平方误差 |
| 61 | if self.initCent == 'random': |
| 62 | self.centroids = self._randCent(X, self.n_clusters) |
| 63 | |
| 64 | clusterChanged = True |
| 65 | for _ in range(self.max_iter): |
| 66 | clusterChanged = False |
| 67 | for i in range(m):#将每个样本点分配到离它最近的质心所属的族 |
| 68 | minDist = np.inf; minIndex = -1 |
| 69 | for j in range(self.n_clusters): |