###前提・実現したいこと
クラスタリングについて勉強しています。
その中のkmeans法を試そうとしています。
コードは、https://github.com/joelgrus/data-science-from-scratch/blob/master/code/clustering.pyにあります
###発生している問題・エラーメッセージ
下のコードにinputのデータを用意して関数classifyが何を返すか見た所、0,1,2が表示されました。
入力データと3つのself.meansとの距離を計算しminでその中の最小値を出しているので私は最小の距離が出力されると思っていました。
なぜreturnでo,1,2が返るのか教えていただきたいです。
###該当のソースコード
Python
1 2from __future__ import division 3import math, random 4import matplotlib.image as mpimg 5import matplotlib.pyplot as plt 6from functools import reduce 7import re, math, random 8from collections import defaultdict, Counter 9 10def vector_add(v, w): 11 """adds two vectors componentwise""" 12 return [v_i + w_i for v_i, w_i in zip(v,w)] 13 14def vector_subtract(v, w): 15 """subtracts two vectors componentwise""" 16 return [v_i - w_i for v_i, w_i in zip(v,w)] 17 18def vector_sum(vectors): 19 return reduce(vector_add, vectors) 20 21def scalar_multiply(c, v): 22 return [c * v_i for v_i in v] 23 24def vector_mean(vectors): 25 """compute the vector whose i-th element is the mean of the 26 i-th elements of the input vectors""" 27 n = len(vectors) 28 return scalar_multiply(1/n, vector_sum(vectors)) 29 30def dot(v, w): 31 """v_1 * w_1 + ... + v_n * w_n""" 32 return sum(v_i * w_i for v_i, w_i in zip(v, w)) 33 34def sum_of_squares(v): 35 """v_1 * v_1 + ... + v_n * v_n""" 36 return dot(v, v) 37 38def magnitude(v): 39 return math.sqrt(sum_of_squares(v)) 40 41def squared_distance(v, w): 42 return sum_of_squares(vector_subtract(v, w)) 43 44def distance(v, w): 45 return math.sqrt(squared_distance(v, w)) 46 47class KMeans: 48 """performs k-means clustering""" 49 50 def __init__(self, k): 51 self.k = k # number of clusters 52 self.means = None # means of clusters 53 54 55 def classify(self, input): 56 """return the index of the cluster closest to the input""" 57 58 return min(range(self.k), 59 key=lambda i: squared_distance(input, self.means[i])) 60 61 def train(self, inputs): 62 63 self.means = random.sample(inputs, self.k) 64 65 assignments = None 66 67 while True: 68 69 new_assignments = map(self.classify, inputs) 70 71 72 if assignments == new_assignments: 73 return 74 75 76 assignments = new_assignments 77 78 for i in range(self.k): 79 i_points = [p for p, a in zip(inputs, assignments) if a == i] 80 # avoid divide-by-zero if i_points is empty 81 if i_points: 82 self.means[i] = vector_mean(i_points) 83 84 85if __name__ == "__main__": 86 87 inputs = [[-14,-5],[13,13],[20,23],[-19,-11],[-9,-16],[21,27],[-49,15],[26,13],[-46,5],[-34,-1],[11,15],[-49,0],[-22,-16],[19,28],[-12,-8],[-13,-19],[-41,8],[-11,-6],[-25,-9],[-18,-3]] 88 89 90 random.seed(0) # so you get the same results as me 91 clusterer = KMeans(3) 92 try: 93 clusterer.train(inputs) 94 except: 95 val =+ 1 96 print ("3-means:") 97 print (clusterer.means) 98 99first,second = zip(*inputs) 100plt.scatter(first,second)
###補足情報(言語/FW/ツール等のバージョンなど)
Python3.5
もう少し具体的にどのような方法で 0,1,2を確認したのか書くと回答がつきやすいと思います。 > 関数classifyが何を返すか見た所、0,1,2が表示されました。