質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Python 3.x

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

Q&A

1回答

2905閲覧

関数classifyがどのように動いているのかわかりません

mi56

総合スコア14

Python 3.x

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

0グッド

0クリップ

投稿2017/05/23 10:17

編集2017/05/23 11:57

###前提・実現したいこと
クラスタリングについて勉強しています。
その中の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

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tell_k

2017/05/24 08:57

もう少し具体的にどのような方法で 0,1,2を確認したのか書くと回答がつきやすいと思います。 > 関数classifyが何を返すか見た所、0,1,2が表示されました。
guest

回答1

0

python

1 def classify(self, input): 2 """return the index of the cluster closest to the input""" 3 4 return min(range(self.k), 5 key=lambda i: squared_distance(input, self.means[i]))

この関数のことだと思うんですが、例えば self.k=3 だった場合 min(range(3)) を実行しているのと同じです。 これを実行するとわかりますが。 range(3) => [0,1,2] から 最小の値を取得するということです。 また第二引数に key を渡すと keyの順序にしたがって値を取り出してくれます。

https://docs.python.jp/3/library/functions.html#min

python

1min(range(3)) # => [0,1,2] の最小の値は 0なので常に0が返ってくる 2 3# key に各要素に「-」をつけて逆順になるような lambda関数を指定する 4min(range(3), key=lambda i: -i) # => 常に 2 が返ってくる

ここまでくれば下記コードが何をやってるのか読み取れると思います。

python

1 return min(range(self.k), key=lambda i: squared_distance(input, self.means[i]))

これは ksquared_distance で距離を計算して、その中で 何番目の距離が最小だったかを返す関数となります。 つまり 0 が返って来たら、1回目の距離が最小だったということを意味しますし、2だったら、3回目の距離が最小だったということを意味します。

投稿2017/05/24 09:19

tell_k

総合スコア2120

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問