質問編集履歴

1 コードの修正

mi56

mi56 score 14

2017/05/23 20:57  投稿

関数classifyがどのように動いているのかわかりません
###前提・実現したいこと
クラスタリングについて勉強しています。
その中の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
from __future__ import division
import math, random
import matplotlib.image as mpimg
import matplotlib.pyplot as plt
from functools import reduce
import re, math, random
from collections import defaultdict, Counter
def vector_add(v, w):
   """adds two vectors componentwise"""
   return [v_i + w_i for v_i, w_i in zip(v,w)]
def vector_subtract(v, w):
   """subtracts two vectors componentwise"""
   return [v_i - w_i for v_i, w_i in zip(v,w)]
def vector_sum(vectors):
   return reduce(vector_add, vectors)
def scalar_multiply(c, v):
   return [c * v_i for v_i in v]
def vector_mean(vectors):
   """compute the vector whose i-th element is the mean of the
   i-th elements of the input vectors"""
   n = len(vectors)
   return scalar_multiply(1/n, vector_sum(vectors))
def dot(v, w):
   """v_1 * w_1 + ... + v_n * w_n"""
   return sum(v_i * w_i for v_i, w_i in zip(v, w))
def sum_of_squares(v):
   """v_1 * v_1 + ... + v_n * v_n"""
   return dot(v, v)
def magnitude(v):
   return math.sqrt(sum_of_squares(v))
def squared_distance(v, w):
   return sum_of_squares(vector_subtract(v, w))
def distance(v, w):
   return math.sqrt(squared_distance(v, w))
class KMeans:
   """performs k-means clustering"""
   def __init__(self, k):
       self.k = k         # number of clusters
       self.means = None  # means of clusters
       
       
   def classify(self, input):
       """return the index of the cluster closest to the input"""
     
       return min(range(self.k),
                  key=lambda i: squared_distance(input, self.means[i]))
                 
   def train(self, inputs):
   
       self.means = random.sample(inputs, self.k)
     
       assignments = None
       
       while True:
           
           new_assignments = map(self.classify, inputs)
         
           if assignments == new_assignments:               
               return
         
           assignments = new_assignments   
           for i in range(self.k):
               i_points = [p for p, a in zip(inputs, assignments) if a == i]
               # avoid divide-by-zero if i_points is empty
               if i_points:                               
                   self.means[i] = vector_mean(i_points)   
   
if __name__ == "__main__":
   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]]
   
   random.seed(0) # so you get the same results as me
   clusterer = KMeans(3)
   try:
       clusterer.train(inputs)
   except:
       val =+ 1
   print ("3-means:")
   print (clusterer.means)
first,second = zip(*inputs)
plt.scatter(first,second)
```
###
###補足情報(言語/FW/ツール等のバージョンなど)
Python3.5
  • Python 3.x

    15336 questions

    Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

思考するエンジニアのためのQ&Aサイト「teratail」について詳しく知る