コードは各リストで最小のアイテムを見つけます。そのデータポイントを、元のリストに基づいてリストに追加します。また、各クラスターの平均を見つけられるようにしたいと思います。
import numpy as np
centroids = np.array([[3,44],[5,15],[99,12]])
dataPoints = np.array([[2,4],[17,4],[45,2],[45,7],[16,32],[32,14],[20,56],[68,33]])
def size(vector):
return np.sqrt(sum(x**2 for x in vector))
def distance(vector1, vector2):
return size(vector1 - vector2)
def distances(array1, array2):
lists = [[distance(vector1, vector2) for vector2 in array2] for vector1 in array1]
x = 1
for i in lists:
print ('Distance from Centroid {}:{}\n'.format(x,i))
x=x+1
print map(min, zip(*lists))
distances(centroids,dataPoints)
私の出力:
Distance from Centroid 1:[40.01249804748511, 42.379240200834182, 59.396969619669989, 55.97320787662612, 17.691806012954132, 41.725292090050132, 20.808652046684813, 65.924198895398035]
Distance from Centroid 2:[11.401754250991379, 16.278820596099706, 42.059481689626182, 40.792156108742276, 20.248456731316587, 27.018512172212592, 43.657759905886145, 65.520989003524662]
Distance from Centroid 3:[97.329337817535773, 82.389319696183918, 54.918120870983927, 54.230987451824994, 85.37564055396598, 67.029844099475568, 90.426765949026404, 37.443290453698111]
[11.401754250991379, 16.278820596099706, 42.059481689626182, 40.792156108742276, 17.691806012954132, 27.018512172212592, 20.808652046684813, 37.443290453698111]
追加の望ましい出力:
Cluster 1: [[16,32],[20,56]]
Cluster 2: [[2,4],[17,4],[45,2],[45,7],[32,14]]
Cluster 3: [[68,33]]
List of means :[[18,44],[28.2,6.2],[68,33]]
この例では、重心/クラスターの量が定義されています。それらが動的であり、クラスターリストをその場で作成する必要がある場合はどうなりますか?
「zipされているリストから要素がどこから来たのか」を伝えたい一般的な状況にあるとしましょう。それを追跡する必要があります。
>>> import random
>>> from pprint import pprint
>>> ls = [[random.randint(80,200) for _ in range(8)] for _ in range(3)]
>>> pprint(ls)
[[114, 196, 185, 192, 129, 183, 150, 189],
[173, 173, 116, 135, 109, 87, 80, 88],
[159, 173, 139, 189, 100, 107, 102, 188]]
>>> [min(zip(l,range(len(l)))) for l in zip(*ls)]
[(114, 0), (173, 1), (116, 1), (135, 1), (100, 2), (87, 1), (80, 1), (88, 1)]
あなたの状況に適用:
>>> import numpy as np
>>>
>>> centroids = np.array([[3,44],[5,15],[99,12]])
>>> dataPoints = np.array([[2,4],[17,4],[45,2],[45,7],[16,32],[32,14],[20,56],[68,33]])
>>>
>>> def size(vector):
... return np.sqrt(sum(x**2 for x in vector))
...
>>> def distance(vector1, vector2):
... return size(vector1 - vector2)
...
>>> lists = [[distance(vector1, vector2) for vector2 in dataPoints] for vector1 in centroids]
>>> pprint(lists)
[[40.01249804748511,
42.379240200834182,
59.396969619669989,
55.97320787662612,
17.691806012954132,
41.725292090050132,
20.808652046684813,
65.924198895398035],
[11.401754250991379,
16.278820596099706,
42.059481689626182,
40.792156108742276,
20.248456731316587,
27.018512172212592,
43.657759905886145,
65.520989003524662],
[97.329337817535773,
82.389319696183918,
54.918120870983927,
54.230987451824994,
85.37564055396598,
67.029844099475568,
90.426765949026404,
37.443290453698111]]
>>> smallest = [min(zip(l,range(len(l)))) for l in zip(*lists)]
>>> smallest
[(11.401754250991379, 1), (16.278820596099706, 1), (42.059481689626182, 1), (40.792156108742276, 1), (17.691806012954132, 0), (27.018512172212592, 1), (20.808652046684813, 0), (37.443290453698111, 2)]
私たちは賢くて最小値を持っていなかったかもしれませんが、それは実際には問題ではありません。
セントリオドはいくつもある可能性があるため、動的にするには、変数を使用せず、コンテナーを使用します。リストでもかまいませんが、dict
簡単です。
>>> clusters = {}
>>> for j, (_, i) in enumerate(smallest):
... clusters.setdefault(i,[]).append(dataPoints[j])
...
最後に、
>>> pprint(clusters)
{0: [array([16, 32]), array([20, 56])],
1: [array([2, 4]),
array([17, 4]),
array([45, 2]),
array([45, 7]),
array([32, 14])],
2: [array([68, 33])]}
最後に、リストまたはnp.arraysのいずれかに固執します。両方が適切であることはめったにありません。また、それぞれの長所と短所を理解して、問題に適切なデータ構造がどれであるかを理解する必要があります。これは、コードを書く上で非常に重要な側面です。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加