【发布时间】:2017-11-10 16:34:54
【问题描述】:
我正在尝试使用 k-means 对数据集进行聚类。当我只用一次迭代运行我的算法时,它应该返回随机簇,但是当我尝试多次迭代时,它只返回 0。我使用的矩阵是一个 50k x 140 的二进制矩阵。每行代表一个用户,每列代表一个项目。
def clusterizator(matriz, nDeClusters, it=10): # matrix, number of clusters, number of iterations
nOfLines = matriz.shape[0] # number of lines (users)
nOfColumns = matriz.shape[1] # number of columns (items)
clusterCurrently = np.zeros((nOfLines, 1)) # currently cluster assigned to each user
listOfCurrentlyAssigneds = [] # list with numberOfClusters size, each element is a list of currently elements assigned to this cluster
clusterCentroid = [] # centroid of each cluster
clusterCentroid = np.random.randint(2, size=(nDeClusters, nOfColumns)) # starts with randoms centroids
for repeat in xrange(it): # number of iterations
listOfCurrentlyAssigneds = [[] for i in xrange(nDeClusters)] # create empty lists for each cluster
for i in xrange(nOfLines): # for each user
closestCentroid = clusterMaisProximo(matriz[i], clusterCentroid) # calculates the closest centroid
clusterCurrently[i] = closestCentroid # assign the user to closest centroid
listOfCurrentlyAssigneds[closestCentroid].append(matriz[i]) # put user on that centroid list
for i in xrange(nDeClusters): # for each cluster
if listOfCurrentlyAssigneds[i] != []: # if the list is not empty
clusterCentroid[i] = centeroidnp(listOfCurrentlyAssigneds[i]) # calculates the new centroid
return clusterCurrently # return 1-column matrix with user x cluster
def distanciaEucl(elemento1, elemento2):
return np.linalg.norm(elemento2-elemento1) #calculates the distance between to items (or one user and one cluster)
def clusterMaisProximo(elemento, listaDeClusters): # receive one user and the cluster's centroids list, return the closest one
closest = 0
closestDist = distanciaEucl(elemento, listaDeClusters[0]) # starts with the cluster[0]
for i in xrange(len(listaDeClusters)-1): # for each cluster
dist = distanciaEucl(elemento, listaDeClusters[i+1]) # get the distance to currently cluster's centroid
if dist < closestDist: # if it is closer to the element
closest = i+1 # update new closest element
closestDist = dist # update new closest distance
return closest # return closest
# from https://stackoverflow.com/questions/23020659/fastest-way-to-calculate-the-centroid-of-a-set-of-coordinate-tuples-in-python-wi
# by Retozi (adapted)
def centeroidnp(lista): # get a list of elements (number of elements x items)
shape = list(lista[0].shape)
shape[:0] = [len(lista)]
arr = np.concatenate(lista).reshape(shape) # get an array from the list
length = arr.shape[0]
somas = np.zeros(arr.shape[1])
for i in xrange(arr.shape[1]): # for each item (dimension)
somas[i] = (np.sum(arr[:, i]))/length # sum all elements and divide by number of elements
return somas # return array that will be the new centroid position
我评论了所有内容以试图弄清楚每一行在做什么,有些 cmets 很愚蠢,因为起初我的变量是用葡萄牙语写的,然后我翻译了以使其更清楚。
我是这样运行的:
clust = clusterizator(train, 10, 2)
示例矩阵:
train = [[0, 1, 1, 0], [1, 0, 0, 0], [0, 1, 1, 1], [1, 0, 0, 1], [1, 0, 0, 0]]
【问题讨论】:
-
没有“kNN 聚类”。您可能正在尝试实现 k-means。 (也有kNN分类)
标签: python cluster-analysis k-means