こんにちは。コミュニケーションIT事業部 ITソリューション部の英です。
普段はWebアプリやスマホアプリの案件などを担当しています。あと、趣味でAIを勉強しています。
突然ですが、AIの勉強をしているとk-means法とk近傍法って混同しませんか?
不意に尋ねられた際にぱっと答えられる自信がありません。
なので、今回から2回に渡ってk-means法とk近傍法のそれぞれを実際に検証して身に付けようと思います。
まず、今回はk-means法を使って簡単なクラスタリングを行い、可視化してみようと思います。
次回はk近傍法(k-NN)について解説します。
この記事で学べること
- クラスタリング手法
- k-means法
- 次元削減手法
- PCA (Principal Component Analysis)
- t-SNE (t-distributed Stochastic Neighbor Embedding)
k-means法とは
データをk個のクラスターに分けるクラスタリングアルゴリズムです。まず、データポイントからk個の中心点をランダムに選びます。各データポイントは最も近い中心点に割り当てられます。その後、各クラスタの新しい中心点を計算し、データポイントの割り当てを再調整します。このプロセスを中心点の位置が変わらなくなるまで(収束するまで)繰り返します。主にパターン認識やデータ解析に用いられます。
次元削減手法とは
高次元データをより低次元に変換し、データの本質的な特徴を保持しながら、計算の効率化や可視化を容易にする技術です。ノイズの除去やデータの圧縮にも有用です。また、次元削減を行うことで、人がデータを直感的に理解しやすくなります。人の目で認識できるのはせいぜい3次元空間までですから、高次元データを可視化したい場合にはこれらの手法を用いて次元を落とす必要があります。
PCAとは (Principal Component Analysis)
データの分散を最大化する方向(主成分)を見つけ、それに基づいてデータを再表現する次元削減手法です。データの共分散行列を計算し、その固有ベクトルと固有値を求め、固有値の大きい順に主成分を選びます。これにより、元の高次元データを少数の主成分で表現できます。主成分分析と呼びます。
t-SNEとは (t-distributed Stochastic Neighbor Embedding)
高次元空間のデータポイント間のペアワイズ類似度を確率分布としてモデル化し、低次元空間でも同様の類似度分布を再現するようにデータを配置します。クラスタリングやパターンの視覚的理解に優れていますが、計算コストが高いです。今回の検証でもPCAよりt-SNEのほうが計算に時間を要しました。t-SNEは高次元空間でのペアワイズ類似度をガウス分布、低次元空間でのペアワイズ類似度をt分布でモデル化します。この手法により、データポイントAとBが高次元空間で近い場合、低次元空間でも近く配置される確率が高くなります。
ここから本題
ECサイトの購入や閲覧の履歴からユーザーをクラスタリングする検証を行います。
STEP1:ライブラリのインポート
必要なライブラリをインポートします。
STEP2:データ生成の準備
ユーザー数やアイテム数、グループ、アイテムのカテゴリ数などを定義します。
特定のグループには好みがあるものとし、好みのカテゴリに応じたアイテムを閲覧したり購入しやすいものとします。
STEP3:データ生成
全ユーザーと全アイテムを掛け合わせ、好みに応じて各アイテムの閲覧と購入させます。
STEP4:データフレームの生成
先ほど生成した閲覧と購入のデータをpandasのデータフレームに当てはめます。
STEP5:データの結合
データフレーム2つを1つのinteraction_dfとして結合します。
STEP6:interaction_matrixの作成
ユーザー(1000行)×アイテム(500列)のマトリクスを作成します。
閲覧を1、購入を2として重み付けして集計(sum)します。
STEP7:クラスタリングの実行
今回は分析する前からクラスタ数が10個であることが分かり切っているため、n_clustersには10をセットします。(※STEP2を参照)
わずか数秒でクラスタリングが完了しました。
STEP8:クラスタリング精度の評価
クラスタリング精度は3つの指標で数値的に評価できます。
- Silhouette Score
データポイントがどれだけ適切にクラスタに分類されているかを評価します。スコアは-1から1の範囲で、1に近いほど良いクラスタリングです。 - Calinski-Harabasz Score
クラスタ内の分散とクラスタ間の分離のバランスを評価します。スコアが高いほど、クラスタ内のデータが緻密で、クラスタ間の分離が良いことを示します。 - Davies-Bouldin Score
クラスタ内の密集度とクラスタ間の分離度を評価します。スコアが低いほど、クラスタ内のデータが密集し、クラスタ間の分離が良いことを示します。スコアは0に近いほど良いクラスタリングです。
STEP9:クラスタリング結果の保存
次回の記事で使用するため、結果を保存しておきます。
CSVファイルの中身は以下のとおりです。
STEP10:PCAによる次元削減と可視化
まず、PCAで可視化してみます。
STEP11:t-SNEによる次元削減と可視化
次にt-SNEで可視化してみます。
STEP12:テストデータを加工して再実施
先ほどの例ではクラスタ同士が離れすぎており、あまり現実的なデータではありませんでした。
アイテムの購入や閲覧の確率を微調整して再度クラスタリングを実施してみます。
「好みだけど買わない(見ない)、好みじゃないけど買う(見る)」の割合を増やします。
for user_id, preferences in user_preferences.items(): for item_id in item_categories_keys: # 各カテゴリに基づく確率設定 purchase_prob = 0.2 + 0.6 * random.random() # より広い範囲の確率設定 view_prob = 0.3 + 0.6 * random.random() # より広い範囲の確率設定 if item_categories[item_id] in preferences: # 好みに基づく確率で購入・閲覧 if random.random() < purchase_prob: purchase_history.append([user_id, item_id, item_categories[item_id], 'purchase']) if random.random() < view_prob: view_history.append([user_id, item_id, item_categories[item_id], 'view']) else: # その他のカテゴリも高確率で購入・閲覧 if random.random() < 0.3: # 0.1から0.3に変更 purchase_history.append([user_id, item_id, item_categories[item_id], 'purchase']) if random.random() < 0.4: # 0.2から0.4に変更 view_history.append([user_id, item_id, item_categories[item_id], 'view'])
その結果がこちら。それっぽいクラスタリングができているかと思います。
当然ながら各スコアは目に見えて低下します。
STEP13:クラスタ数を変更して再実施
次はクラスタ数を変更して可視化してみましょう。
クラスタ数:5
クラスタ数:15
このように比べてみると、クラスタ数が10だった頃がもっともクラスタ間の境目がはっきりしており、各クラスタの密度も高いことが分かると思います。
実データを取り扱う場合にはこのようにクラスタ数を変更し、可視化やスコアを用いて最適なクラスタ数を見つけていくステップが重要になります。
さいごに
k-meansによるクラスタリングと、次元削減手法のPCAとt-SNEを使った可視化を行いました。
お気づきかもしれませんが、今回はデータ準備の段階でクラスタ数が10個であることが明確だったので簡単にクラスタリングができています。実データを取り扱う際にはクラスタ数も含め、ハイパーパラメータを調整しながら検証してください。
→ k-meansのハイパーパラメータ
また、今回の検証の副産物としてクラスタリング済みのusers.csvが手に入ったので、次回はこれを教師データとしたk近傍法(k-NN)の検証をしたいと思います。
これからもAWS×AIの検証記事をたくさん書いていきます。
↓ のスターを押していただけると嬉しいです。励みになります。
最後まで読んでいただき、ありがとうございました。
私たちは一緒に働いてくれる仲間を募集しています!
執筆:英 良治 (@hanabusa.ryoji)、レビュー:@nagamatsu.yuji
(Shodoで執筆されました)