無料の Python 機械学習コース 9: K 平均法クラスタリング

無料の Python 機械学習コース 9: K 平均法クラスタリング

K-クラスタリングとはどういう意味ですか?

K-means クラスタリングは、最も人気があり、広く使用されている教師なし学習モデルです。データをクラスタリングすることで機能するため、クラスタリングとも呼ばれます。教師あり学習モデルとは異なり、教師なしモデルではラベル付きデータは使用されません。

このアルゴリズムはラベルを予測することを目的としたものではありません。データセットをより深く理解し、ラベルを付けることが重要です。

[[360705]]

k-means クラスタリングでは、データセットをさまざまなグループにクラスタ化します。

k平均法クラスタリングアルゴリズムの仕組み

(1)最初のステップは、いくつかの点をランダムに初期化することです。これらの点はクラスターの重心と呼ばれます。


上の画像では、赤と青の点がクラスターの重心です。

任意の数のクラスター重心を選択できます。ただし、クラスターの重心の数はデータ ポイントの合計数よりも少なくする必要があります。

(2)2番目のステップはクラスター割り当てステップである。このステップでは、各緑色のポイントを反復処理する必要があります。ポイントが赤いポイントに近いか青いポイントに近いかに応じて、どちらか一方に割り当てる必要があります。

つまり、緑の点は、青のクラスターの重心に近いか赤のクラスターの重心に近いかに応じて、赤または青に色付けされます。


(3)次のステップはクラスターの重心を移動することです。ここで、赤いクラスターの重心に割り当てられたすべての赤い点の平均を取り、赤いクラスターの重心をその平均に移動する必要があります。青いクラスターの重心に対しても同じことを行う必要があります。

これで、新しいクラスターの重心ができました。 2 番 (クラスター割り当て手順) に戻る必要があります。ポイントを新しいクラスターの重心に再配置する必要があります。その後3回目を繰り返します。

下の図に示すように、両方のクラスター重心が適切な位置にくるまで、手順 2 と 3 を数回繰り返す必要があります。


ご覧のとおり、すべての緑色の点を、それらに割り当てられたクラスターの重心によって単純に色分けしました。青いクラスターの重心は青いクラスターの中心にあり、赤いクラスターの重心は赤いクラスターの中心にあります。

アルゴリズムを開発していくと、これが少し明確になります。これについてはさらに詳しく議論します。

アルゴリズムの開発

このアルゴリズムに使用するデータセットは、Coursera の Andrew Ng の機械学習コースから取得しました。以下は、k-means アルゴリズムを開発するためのステップバイステップのガイドです。

(1)必要なパッケージとデータセットをインポートする

  1. pandasをpdとしてインポートする
  2. numpyをnpとしてインポートする
  3. df1 = pd .read_excel('dataset.xlsx', sheet_name = 'ex7data2_X' ,ヘッダー=なし)
  4. df1.head()

データセットには 2 つの列しかありません。視覚化しやすいため、2 つの注目データセットを使用しました。視覚的に見るとアルゴリズムが理解しやすくなります。ただし、同じアルゴリズムは多次元キューブにも適用されます。

プロセス中に他の配列も処理するため、DataFrame df1 を Numpy 配列に変換します。

  1. X = np .array(df1)

ここで、上で説明した 3 つの手順を実行します。

(2)最初のステップは、重心をランダムに初期化することです。

データセットから 3 つのポイントをランダムに初期化します。まず、0 からデータセットの長さまでの 3 つの数字を選択します。

  1. ランダムをインポートrandominit_centroids = random.sample(range(0, len(df1)), 3)
  2. 初期重心

出力:

  1. [95、30、17]

これら 3 つの数値をインデックスとして使用し、それらのインデックスのデータ ポイントを取得します。

  1. 重心= []
  2. init_centroids 内の i の場合:
  3. 重心.append(df1.loc[i])
  4. 重心

出力:

  1. [0 3.907793
  2. 1 5.094647
  3. 名前: 95、データ型: float64、
  4. 0 2.660466
  5. 1 5.196238
  6. 名前: 30、データ型: float64、
  7. 0 3.007089
  8. 1 4.678978
  9. 名前: 17、データ型: float64]

これら 3 つの点が初期の重心となります。

2D配列に変換しました。なぜなら、この形式の方が私にとって馴染み深いからです。

  1. 重心= np.array (重心)

出力:

  1. 配列([[3.90779317, 5.09464676],
  2. [2.66046572, 5.19623848],
  3. [3.00708934, 4.67897758]])

(3)クラスター割り当てステップを実装する。

このステップでは、データセット内のすべてのデータ ポイントを反復処理します。

データポイントはデータの行を表す

データの行を見て、このデータがどのようにクラスターに割り当てられるかを見てみましょう。

3 つの重心すべてのデータ距離を計算します。そのデータ ポイントは、最短距離の重心に割り当てられます。

ご覧のとおり、2 点間の距離を多数計算する必要があります。距離を計算する関数を開発しましょう。

  1. def calc_distance(X1, X2):
  2. (合計((X1 - X2)** 2))** 0.5を返す

各データ ポイントを重心に割り当てる関数を開発します。 「centroids」配列には 3 つの値しかありません。したがって、0、1、2 の 3 つのインデックスがあります。各データ ポイントにこれらのインデックスの 1 つを割り当てます。

  1. 定義: findClosestCentroids(ic, X):
  2. 割り当てられた重心= []
  3. i が X に含まれる場合:
  4. 距離= []
  5. icのjの場合:
  6. 距離.append(calc_distance(i, j))
  7. 割り当てられた重心.append(np.argmin(距離))
  8. 割り当てられた重心を返す

この関数は、データ ポイントをクラスターに割り当てます。この関数を使用して、各データ ポイントの重心を計算してみましょう。

  1. get_centroids = findClosestCentroids (重心, X)
  2. 重心を取得する

部分出力:

  1. [2,
  2. 0,
  3. 0,
  4. 2、
  5. 1、
  6. 2、
  7. 2、
  8. 2、
  9. 1、
  10. 1、
  11. 2、
  12. 2、
  13. 2、
  14. 2、
  15. 2、
  16. 2、
  17. 0,

総出力は非常に長いです。したがって、ここでは出力の一部を示します。出力の最初の重心は 2 です。これは、重心リストのインデックス 2 に割り当てられることを意味します。

(4)最後のステップは、データポイントの平均値に応じて重心を移動することです。

このステップでは、各重心のすべてのデータ ポイントの平均を取得し、重心をその平均に移動します。

たとえば、インデックス 2 の重心に割り当てられたすべてのポイントの平均を計算し、重心 2 を平均に移動します。インデックス 0 と 1 の重心に対しても同じ操作が実行されます。

これを実行する関数を定義しましょう:

  1. calc_centroids(クラスター, X):
  2. 新しい重心= []
  3. new_df = pd .concat([pd.DataFrame(X), pd.DataFrame(クラスター,= ['cluster'])],
  4. = 1 )
  5. set(new_df['cluster'])内のcの場合:
  6. current_cluster = new_df [new_df['cluster'] == c][new_df.columns[:-1]]
  7. cluster_mean = current_cluster .mean(= 0 )
  8. new_centroids.append(クラスター平均)
  9. new_centroidsを返す

これらはすべて開発する必要がある機能です。

先ほど説明したように、このクラスター割り当てプロセスを繰り返し、重心が適切な位置にくるまで重心を複数回移動する必要があります。

この問題では、このプロセスを 10 回繰り返すことを選択しました。これがどのように機能するかを視覚的に示せるように、各反復の後に重心とデータをプロットし続けます。

  1. iが範囲(10)内にある場合:
  2. get_centroids = findClosestCentroids (重心, X)
  3. 重心= calc_centroids (get_centroids, X)
  4. #print(重心)
  5. plt.figure()
  6. plt.scatter(np.array(重心)[:, 0], np.array(重心)[:, 1],= '黒' )
  7. plt.scatter(X[:, 0], X[:, 1],アルファ= 0.1 )
  8. plt.show()

5 回の反復後、重心は最適な位置に設定されます。したがって、それ以降は立場を変えることはありません。

次元削減を試す前に、上記のコードをすべて実行して、十分に学習させることをお勧めします。

そうしないと、圧倒されてしまうかもしれません。また、アルゴリズムについては詳しく説明したので、ここでは簡単に説明します。

次元削減

このアルゴリズムの使用例を少なくとも 1 つ説明したいと思います。非常に便利な使用例の 1 つは次元削減です。

画像について考えてみましょう。画像内に異なるピクセルが多すぎる可能性があります。どのようなコンピュータービジョンの問題でも、画像のサイズを縮小できれば、デバイスはそれをはるかに速く読み取ることができるようになります。そうではありませんか?

今開発したアルゴリズムを使用して、画像のサイズを縮小できます。

これを説明するためにカエルの写真を使います:

> 著者による画像

この写真をノートブックと同じフォルダにアップロードしました。これをインポートしてみましょう:

  1. cv2をインポート
  2. im = cv2.imread ('frog.png')
  3. 私は

出力:

  1. 配列([[[ 2, 57, 20],
  2. [2、57、20]、
  3. [2、57、21]、
  4. ...、
  5. [ 0, 5, 3],
  6. [8、12、11]、
  7. [ 91, 94, 93]], [[ 2, 56, 20],
  8. [ 1, 54, 20],
  9. [1, 56, 19],
  10. ...、
  11. [ 0, 2, 1],
  12. [7, 9, 8],
  13. [ 91, 92, 91]], [[ 2, 55, 20],
  14. [2、53、19]、
  15. [ 1, 54, 18],
  16. ...、
  17. [ 2, 4, 2],
  18. [8, 11, 9],
  19. [ 91, 93, 91]], ..., [[ 6, 76, 27],
  20. [6、77、26]、
  21. [6、78、28]、
  22. ...、
  23. [6、55、18]、
  24. [13、61、25]、
  25. [ 94, 125, 102]], [[ 9, 79, 31],
  26. [11、81、33]、
  27. [ 12, 82, 32],
  28. ...、
  29. [6、56、19]、
  30. [14、61、27]、
  31. [ 96, 126, 103]], [[ 43, 103, 63],
  32. [44、107、66]、
  33. [46、106、66]、
  34. ...、
  35. [37、81、50]、
  36. [47、88、59]、
  37. [118, 145, 126]]], dtype = uint8 )

配列の形状を確認します。

  1. im.sgape

出力:

  1. (155、201、3)

配列全体を 255 で割って、すべての値が 0 から 1 になるようにします。

次に、それを 155*201 x 3 に再形成して 2D 配列にします。なぜなら、2次元配列のすべての関数は以前に開発済みだからです。

  1. im = (im/255).reshape(155*201, 3)

上記のように、さまざまなピクセル値が存在します。これを減らして 10 ピクセルの値だけを保持します。

10個のランダムなインデックスを初期化しましょう。

  1. ランダムrandom_index = random.sample(range(0, len(im)), 10)

ここで、前の例のように重心を見つけます。

  1. 重心= []
  2. random_index 内の i の場合:
  3. 重心.append(im[i])
  4. 重心= np.array (重心)

出力:

  1. 配列([[0.00392157, 0.21176471, 0.06666667],
  2. [0.03529412, 0.2627451, 0.09803922],
  3. [0.29411765, 0.3254902, 0.26666667],
  4. [0.00784314, 0.18431373, 0.05882353],
  5. [0.29019608, 0.49411765, 0.28235294],
  6. [0.5254902, 0.61176471, 0.48627451],
  7. [0.04313725, 0.23921569, 0.09803922],
  8. [0.00392157, 0.23529412, 0.0745098 ],
  9. [0.00392157, 0.20392157, 0.04705882],
  10. [0.22352941, 0.48235294, 0.40784314]])

さて、「im」も配列に変換します。

  1. im = np.array (im)

データは準備完了です。これで、クラスタリング プロセスに進むことができます。しかし今回は視覚化は行いません。データがもはや 2 次元ではないためです。したがって、視覚化は容易ではありません。

  1. iが範囲(20)内にある場合:
  2. get_centroids = findClosestCentroids (重心、im)
  3. 重心= calc_centroids (get_centroids, im)

これで重心が更新されました。

  1. 重心

出力:

  1. [0 0.017726
  2. 1 0.227360
  3. 2 0.084389
  4. データ型: float64,
  5. 0 0.119791
  6. 1 0.385882
  7. 2 0.247633
  8. データ型: float64,
  9. 0 0.155117
  10. 1 0.492051
  11. 2 0.331497
  12. データ型: float64,
  13. 0 0.006217
  14. 1 0.048596
  15. 2 0.019410
  16. データ型: float64,
  17. 0 0.258289
  18. 1 0.553290
  19. 2 0.406759
  20. データ型: float64,
  21. 0 0.728167
  22. 1 0.764610
  23. 2 0.689944
  24. データ型: float64,
  25. 0 0.073519
  26. 1 0.318513
  27. 2 0.170943
  28. データ型: float64,
  29. 0 0.035116
  30. 1 0.273665
  31. 2 0.114766
  32. データ型: float64,
  33. 0 0.010810
  34. 1 0.144621
  35. 2 0.053192
  36. データ型: float64,
  37. 0 0.444197
  38. 1 0.617780
  39. 2 0.513234
  40. データ型: float64]

これが最後のステップです。これら 10 点のみを保持します。

get_centroids も印刷すると、クラスターの割り当てが表示されます。

ここで、配列 'im' 全体を反復処理し、データを対応するクラスター重心値に変更します。こうすることで、これらの重心値のみが得られます。

元の配列を変更するのではなく、コピーを作成してそこで変更を加えたいと思います。

  1. im im_recovered = im.copy()
  2. iが範囲内(len(im))の場合:
  3. im_recovered[i] = 重心[get_centroids[i]]

最初に画像のサイズを変更して 2 次元配列にしたことを覚えています。今度はそれを元の形に戻す必要があります。

  1. im_recovered im_recovered = im_recovered.reshape(155, 201, 3)

ここでは、違いを示すために、元の画像と縮小した画像を並べてプロットしています。

  1. im1 = cv2.imread ('frog.png')
  2. matplotlib.image を mpimg としてインポートします。
  3. 図、 ax = plt.subplots (1,2)
  4. ax[0].imshow(im1)
  5. ax[1].imshow(im_recovered)

> 著者による画像

ご覧のとおり、画像のサイズが大幅に縮小されました。カエルみたいですね!でもコンピューターの方がずっと速く読み取れますよ!

結論は

この記事では、k-means クラスタリングの仕組みと、k-means クラスタリング アルゴリズムをゼロから開発する方法について説明しました。このアルゴリズムを使用して画像サイズを縮小する方法についても説明しました。別の画像を試してください。

この記事で使用したデータセットへのリンクはこちらです。

https://github.com/rashida048/Machine-Learning-With-Python/blob/master/kmean.xlsx

コードは次のとおりです:

https://github.com/rashida048/Machine-Learning-With-Python/blob/master/k_mean_clustering_final.ipynb

<<:  初心者にも優しい!楽しくて簡単に始められる AI プロジェクト 10 選 (Python ソース コード付き)

>>:  AI列車に乗ってみよう!マーケティングに人工知能を活用する3つの方法

ブログ    

推薦する

MITの科学者が数時間でロボットヒトデを作る新システムを設計

水中の海洋生物を研究する場合、動物たちにとって不自然に見えて怖がらせないような装置を使うと役に立つで...

AIトレーニングの最大の障害は計算能力ではなく「メモリの壁」である

[[390958]]この記事はAI新メディアQuantum Bit(公開アカウントID:QbitAI...

技術革新により、AI人材が全国各地で活躍できるようになった

人力の60倍の速さで作業する送電線検査画像「認識者」、ベテラン並みの監視ビデオ「品質検査員」、さまざ...

グラフニューラルネットワークが深くなるほど、パフォーマンスは向上しますか?

数十または数百の層を持つニューラル ネットワークの応用は、ディープラーニングの重要な機能の 1 つで...

IBM Watson Healthの大規模レイオフによるAI導入の苦痛

少し前、The Register紙はIBMの内部情報筋が、ワトソン・ヘルス部門が従業員の約50%から...

金融業界における人工知能の革新的な応用トップ 10

[[438117]]人工知能は、よりスマートで、より便利で、より安全な方法でお金を投資、アクセス、...

説明可能なAI: 機械が自らを説明できるようにし、アルゴリズムによって生成されるバイアスを減らす

2018 年 5 月 25 日、一般データ保護規則 (GDPR) が欧州連合全域で発効し、組織による...

AIによる創薬は2024年までに急成長すると予想

1月7日の最大のニュースの一つは、Google DeepMindの創設者デミス・ハサビス氏が率いるG...

意思決定権を機械に委任することは可能でしょうか?

デジタルインテリジェンスは経営上の意思決定を促進し、驚くべき成果をもたらします名前が示すように、デー...

...

近い将来、人工知能によって劇的に変化する11の業界

人工知能(AI)は急速に、そしてシームレスに生活の一部となったため、私たちの多くは、それが社会にどれ...

小型モデルの意見も参考になります! GPT-4+AutoGPTオンライン意思決定:物を買うときにもう心配はいりません

この論文では、現実世界の意思決定タスクにおける Auto-GPT エージェントの包括的なベンチマーク...

新たなAI詐欺事件が発覚! 「人工知能」は「インテリジェントな人工知能」ほど優れていないのでしょうか?

AIが「コーダー」に取って代わるという現実はまだ実現していないが、その逆を行い、コーダーを使ってA...

賢明な企業はヘルスケアにおける認知AIの成功から学ぶことができる

認知技術は世界最大の課題を解決するために使用されています。この記事では、企業が認知 AI をどのよう...

脳に埋め込まれたAIチップはてんかん発作を予測し、2時間で充電して1週間持続する

脳にAIチップを埋め込むことで、てんかん発作をいつでも予測し、制御できるようになります。これは、我が...