概要
このガイドでは、 Scikit-Learnを使用した階層的クラスタリングアルゴリズム マーケティングの問題を解決するために。
ガイドを読んだ後、あなたは理解するでしょう:
- 階層的クラスタリングをいつ適用するか
- データセットを視覚化して、クラスタリングに適しているかどうかを理解する方法
- データセットに基づいて機能を前処理し、新しい機能を設計する方法
- PCAを使用してデータセットの次元を削減する方法
- 樹状図を使用して読み取り、グループを分離する方法
- 樹状図とクラスタリングアルゴリズムに適用されるさまざまなリンク方法と距離メトリックは何ですか
- 凝集的で分裂的なクラスタリング戦略とは何ですか、そしてそれらはどのように機能しますか
- Scikit-Learnを使用して凝集型階層的クラスタリングを実装する方法
- クラスタリングアルゴリズムを扱うときに最も頻繁に発生する問題とその解決方法
注: このガイドのすべてのコードを含むノートブックをダウンロードできます こちら.
動機
あなたがマーケティング部門と連携するデータサイエンスチームの一員であるシナリオを想像してみてください。 マーケティングはしばらくの間顧客の買い物データを収集してきました、そして彼らは収集されたデータに基づいて、もしあれば理解したいと思っています 顧客間の類似点。 これらの類似点は、顧客をグループに分割し、顧客グループを持つことは、キャンペーン、プロモーション、コンバージョンのターゲティング、およびより良い顧客関係の構築に役立ちます。
どの顧客が類似しているかを判断するのに役立つ方法はありますか? それらの何人が同じグループに属していますか? そして、いくつの異なるグループがありますか?
これらの質問に答えるXNUMXつの方法は、 クラスタリング K-Means、DBSCAN、階層的クラスタリングなどのアルゴリズム。一般的に、クラスタリングアルゴリズムは、データポイント間の類似性を見つけ、それらをグループ化します。
この場合、当社のマーケティングデータはかなり小さいです。 たった200人の顧客に関する情報があります。 マーケティングチームを考えると、クラスターの数に基づいて決定がどのように行われたかを明確に説明できることが重要です。したがって、アルゴリズムが実際にどのように機能するかを説明できます。
私たちのデータは小さく、説明可能性が主要な要因であるため、活用できます 階層的クラスタリング この問題を解決するために。 このプロセスは、 階層的クラスタリング分析(HCA).
HCAの利点のXNUMXつは、解釈可能であり、小さなデータセットでうまく機能することです。
このシナリオで考慮すべきもうXNUMXつのことは、HCAは 監督されない アルゴリズム。 データをグループ化する場合、ユーザーが特定のグループに属していることを正しく識別していることを確認する方法はありません(グループはわかりません)。 結果を比較するためのラベルはありません。 グループを正しく特定した場合は、後でマーケティング部門によって日常的に確認されます(ROI、コンバージョン率などの指標で測定)。
解決しようとしている問題とその解決方法を理解したので、データを確認し始めることができます。
簡単な探索的データ分析
注: このガイドで使用されているデータセットをダウンロードできます こちら.
データセットをダウンロードした後、それが CSV(カンマ区切り値) と呼ばれるファイル shopping-data.csv
。 データの探索と操作を容易にするために、データをにロードします。 DataFrame
パンダの使用:
import pandas as pd
path_to_file = 'home/projects/datasets/shopping-data.csv'
customer_data = pd.read_csv(path_to_file)
マーケティングは、200の顧客レコードを収集したと述べました。 ダウンロードしたデータが200行で完了しているかどうかを確認するには、 shape
属性。 それぞれ、行と列の数がわかります。
customer_data.shape
この結果:
(200, 5)
すごい! 私たちのデータは200行で完了しています (クライアントレコード) また、5つの列があります (特徴)。 マーケティング部門が顧客から収集した特性を確認するには、列名を次のように表示します。 columns
属性。 これを行うには、次を実行します。
customer_data.columns
上記のスクリプトは次を返します。
Index(['CustomerID', 'Genre', 'Age', 'Annual Income (k$)',
'Spending Score (1-100)'],
dtype='object')
ここでは、マーケティングが CustomerID
、集めた Genre
, Age
, Annual Income
(数千ドル)、および Spending Score
1人の顧客ごとに100から200になります。 説明を求められたとき、彼らは Spending Score
列は、ある人が1から100のスケールでモールでお金を使う頻度を示します。つまり、顧客のスコアが0の場合、その人は決してお金を使いません。スコアが100の場合、最高の支出者。
このスコアの分布を簡単に見て、データセット内のユーザーの消費習慣を調べてみましょう。 それはパンダがいるところです hist()
メソッドが役立ちます:
customer_data['Spending Score (1-100)'].hist()
ヒストグラムを見ると、35人以上の顧客が 40
& 60
、その後、25未満のスコアが 70
& 80
。 だから私たちの顧客のほとんどは バランスの取れた消費者、続いて中程度から高額の支出者。 後に線があることもわかります 0
、分布の左側、および100の前の別の行、分布の右側。 これらの空白スペースは、おそらくディストリビューションに非支出者が含まれていないことを意味します。 0
、およびスコアが高い支出者もいないこと 100
.
それが正しいかどうかを確認するために、分布の最小値と最大値を調べることができます。 これらの値は記述統計の一部として簡単に見つけることができるので、 describe()
他の数値分布を理解するための方法:
customer_data.describe().transpose()
これにより、データセットの他の値の分布を読み取ることができるテーブルが得られます。
count mean std min 25% 50% 75% max
CustomerID 200.0 100.50 57.879185 1.0 50.75 100.5 150.25 200.0
Age 200.0 38.85 13.969007 18.0 28.75 36.0 49.00 70.0
Annual Income (k$) 200.0 60.56 26.264721 15.0 41.50 61.5 78.00 137.0
Spending Score (1-100) 200.0 50.20 25.823522 1.0 34.75 50.0 73.00 99.0
私たちの仮説が確認されました。 The min
の値 Spending Score
is 1
そして最大は 99
。 だから私たちは持っていません 0
or 100
消費者をスコアします。 次に、転置された他の列を見てみましょう describe
テーブル。 見ると mean
& std
列、私たちはそれを見ることができます Age
mean
is 38.85
と std
約です 13.97
。 同じことが起こります Annual Income
と mean
of 60.56
& std
26.26
、および用 Spending Score
また、 mean
of 50
& std
of 25.82
。 すべての機能について、 mean
標準偏差からかけ離れていることを示しています 私たちのデータは変動性が高い.
データがどのように変化するかをよりよく理解するために、 Annual Income
分布:
customer_data['Annual Income (k$)'].hist()
それは私たちに与えるでしょう:
ヒストグラムでは、35を超える顧客のほとんどのデータが、数の近くに集中していることに注意してください。 60
、私たちに mean
、横軸。 しかし、配布の終わりに近づくとどうなるでしょうか? 平均 $60.560 から左に向かうと、次の値は $34.300 になります。つまり、平均 ($60.560) から標準偏差 ($26.260) を引いたものです。 データ分布からさらに左に行くと、同様のルールが適用され、現在の値 ($26.260) から標準偏差 ($34.300) が差し引かれます。 したがって、$8.040 という値が表示されます。 データが 60 ドルから 8 ドルに急速に増加したことに注目してください。 毎回 26.260 ドル「ジャンプ」しており、変動が大きく、変動性が非常に高いのはそのためです。
ほとんどのクラスタリングアルゴリズムの距離測定はデータの大きさに敏感であるため、データの変動性とサイズはクラスタリング分析で重要です。 サイズの違いにより、あるポイントが実際よりも別のポイントに近づいたり遠ざかったりして、実際のデータのグループ化が歪むため、クラスタリングの結果が変わる可能性があります。
これまでのところ、データの形状、その分布の一部、および記述統計を見てきました。 Pandasを使用すると、データタイプを一覧表示して、200行すべてが入力されているかどうかを確認することもできます。 null
値:
customer_data.info()
この結果:
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 200 entries, 0 to 199
Data columns (total 5 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 CustomerID 200 non-null int64
1 Genre 200 non-null object
2 Age 200 non-null int64
3 Annual Income (k$) 200 non-null int64
4 Spending Score (1-100) 200 non-null int64
dtypes: int64(4), object(1)
memory usage: 7.9+ KB
ここでは、 null
データ内の値と、カテゴリ列がXNUMXつしかないこと– Genre
。 この段階では、クラスタリングモデルに追加するのが面白そうな機能を念頭に置くことが重要です。 モデルにジャンル列を追加する場合は、その値をから変換する必要があります。 カテゴリー 〜へ 数値.
方法を見てみましょう Genre
データの最初の5つの値をざっと見て、次のように入力します。
customer_data.head()
この結果:
CustomerID Genre Age Annual Income (k$) Spending Score (1-100)
0 1 Male 19 15 39
1 2 Male 21 15 81
2 3 Female 20 16 6
3 4 Female 23 16 77
4 5 Female 31 17 40
しか持っていないようです Female
& Male
カテゴリ。 そのユニークな価値観を見て、それを確信することができます。 unique
:
customer_data['Genre'].unique()
これは私たちの仮定を確認します:
array(['Male', 'Female'], dtype=object)
これまでのところ、モデルでこの機能を使用する場合、ジャンルはXNUMXつしかないことがわかっています。 Male
に変換することができます 0
& Female
〜へ 1
。 また、ジャンル間の比率をチェックして、バランスが取れているかどうかを確認することも重要です。 私たちはそれを行うことができます value_counts()
メソッドとその引数 normalize=True
間のパーセンテージを表示するには Male
& Female
:
customer_data['Genre'].value_counts(normalize=True)
これは出力します:
Female 0.56
Male 0.44
Name: Genre, dtype: float64
データセットには女性の56%、男性の44%が含まれています。 それらの違いはわずか16%であり、データは50/50ではありませんが 十分にバランスが取れている トラブルを起こさないように。 結果が70/30、60 / 40の場合、より多くのデータを収集するか、その比率をよりバランスのとれたものにするために何らかのデータ拡張手法を採用する必要があった可能性があります。
今まで、すべての機能が Age
、簡単に調査されました。 何が懸念されるのか Age
、通常、年齢層に基づいて顧客をセグメント化できるように、それをビンに分割することは興味深いことです。 その場合、モデルに追加する前に、年齢カテゴリを15つの数値に変換する必要があります。 そうすれば、20〜XNUMX年のカテゴリを使用する代わりに、 15-20
カテゴリ、それはと呼ばれる新しい列の番号になります 15-20
.
アドバイス: このガイドでは、簡単な探索的データ分析のみを紹介します。 しかし、あなたはさらに先に進むことができますし、さらに先に進むべきです。 ジャンルや年齢による収入差や得点差があるかがわかります。 これにより、分析が充実するだけでなく、モデルの結果が向上します。 探索的データ分析の詳細については、次をご覧ください。 「EDAの章住宅価格の実践的な予測–Pythonでの機械学習「 ガイド付きプロジェクト。
カテゴリカル、またはカテゴリカルの両方で何ができるかを推測した後、 Genre
& Age
列、議論されたことを適用しましょう。
エンコーディング変数と特徴工学
分割することから始めましょう Age
10のグループに分けられるので、20〜30、30〜40、40〜50などになります。 最年少の顧客は15歳であるため、15で開始し、データで最も古い顧客の年齢である70で終了することができます。 15から始まり、70で終わると、15〜20、20〜30、30〜40、40〜50、50〜60、および60〜70の間隔になります。
グループ化または ビン Age
これらの間隔に値を入れると、パンダを使用できます cut()
それらをビンにカットしてから、新しいビンに割り当てるメソッド Age Groups
カラム:
intervals = [15, 20, 30, 40, 50, 60, 70]
col = customer_data['Age']
customer_data['Age Groups'] = pd.cut(x=col, bins=intervals)
customer_data['Age Groups']
この結果:
0 (15, 20]
1 (20, 30]
2 (15, 20]
3 (20, 30]
4 (30, 40]
...
195 (30, 40]
196 (40, 50]
197 (30, 40]
198 (30, 40]
199 (20, 30]
Name: Age Groups, Length: 200, dtype: category
Categories (6, interval[int64, right]): [(15, 20] < (20, 30] < (30, 40] < (40, 50] < (50, 60] < (60, 70]]
列の値を見ると、6つのカテゴリがあり、すべてのビニングされたデータ間隔が表示されていることを示す行もあることに注意してください。 このようにして、以前の数値データを分類し、新しいデータを作成しました Age Groups
特徴。
また、各カテゴリには何人の顧客がいますか? 列をグループ化し、値を次のようにカウントすることで、すぐにそれを知ることができます。 groupby()
& count()
:
customer_data.groupby('Age Groups')['Age Groups'].count()
この結果:
Age Groups
(15, 20] 17
(20, 30] 45
(30, 40] 60
(40, 50] 38
(50, 60] 23
(60, 70] 17
Name: Age Groups, dtype: int64
ほとんどの顧客が30〜40歳であり、次に20〜30歳の顧客、次に40〜50歳の顧客であることが簡単にわかります。これは、マーケティング部門にとっても有益な情報です。
現在、XNUMXつのカテゴリ変数があります。 Age
& Genre
、モデルで使用できるように数値に変換する必要があります。 その変革を行うには多くの異なる方法があります-私たちはパンダを使用します get_dummies()
間隔とジャンルごとに新しい列を作成し、その値を0と1で埋めるメソッド-この種の操作は呼び出されます ワンホットエンコーディング。 それがどのように見えるか見てみましょう:
customer_data_oh = pd.get_dummies(customer_data)
customer_data_oh
これにより、結果のテーブルの概要がわかります。
出力を使用すると、列が Genre
列に分割されました– Genre_Female
& Genre_Male
。 お客様が女性の場合、 Genre_Female
等しい 1
、そして顧客が男性の場合、それは等しい 0
.
また、 Age Groups
列は6つの列に分割され、次のように各間隔にXNUMXつずつあります。 Age Groups_(15, 20]
, Age Groups_(20, 30]
、 等々。 と同じように Genre
、お客様が18歳の場合、 Age Groups_(15, 20]
値は 1
他のすべての列の値は 0
.
利点 ワンホットエンコーディングの利点は、列の値を簡単に表現できることですが、何が起こっているのかを理解するのは簡単です。 不利益 これで、すでに持っていた列と合計するために、8つの追加の列が作成されました。
警告:ワンホットエンコードされた列の数が行の数を超えるデータセットがある場合は、データの次元の問題を回避するために別のエンコード方法を採用するのが最善です。
ワンホットエンコーディングはまた、データに0を追加し、データをよりスパースにします。これは、データのスパース性に敏感な一部のアルゴリズムでは問題になる可能性があります。
クラスタリングのニーズについては、ワンホットエンコーディングが機能しているようです。 ただし、データをプロットして、クラスター化する個別のグループが実際に存在するかどうかを確認できます。
基本的なプロットと次元削減
データセットには11列あり、そのデータを視覚化する方法はいくつかあります。 10つ目は、XNUMX次元でプロットすることです(幸運を祈ります)。 なぜなら Customer_ID
列は考慮されていません。 10つ目は、最初の数値特徴をプロットすることによるもので、2つ目は、XNUMX個の特徴をXNUMXに変換することによるものです。したがって、次元削減を実行します。
データの各ペアをプロットする
10次元をプロットすることは少し不可能なので、XNUMX番目のアプローチを選択します。最初の特徴をプロットします。 クラスタリング分析には、そのうちのXNUMXつを選択できます。 すべてのデータペアを組み合わせて確認するXNUMXつの方法は、Seabornを使用することです。 pairplot()
:
import seaborn as sns
customer_data = customer_data.drop('CustomerID', axis=1)
sns.pairplot(customer_data)
表示されるもの:
一目で、データのグループを持っているように見える散布図を見つけることができます。 興味深いと思われるのは、組み合わせた散布図です。 Annual Income
& Spending Score
。 他の可変散布図の間に明確な分離がないことに注意してください。 せいぜい、ポイントがXNUMXつ集中していることがわかります。 Spending Score
vs Age
散布図。
で構成される両方の散布図 Annual Income
& Spending Score
本質的に同じです。 x軸とy軸が入れ替わっているため、XNUMX回見ることができます。 それらのいずれかを見ると、XNUMXつの異なるグループのように見えるものがわかります。 Seabornを使用してこれらXNUMXつの機能だけをプロットしてみましょう scatterplot()
詳細を確認するには:
sns.scatterplot(x=customer_data['Annual Income (k$)'],
y=customer_data['Spending Score (1-100)'])
よく見ると、5つの異なるデータグループを明確に区別できます。 私たちの顧客は、XNUMX年間の収益と支出に基づいて、クラスター化できるようです。 これは、私たちの分析におけるもうXNUMXつの関連するポイントです。 クライアントをグループ化するために考慮しているのはXNUMXつの機能だけであることが重要です。 それらについて私たちが持っている他の情報は、方程式に入力されていません。 これは分析に意味を与えます–クライアントがどれだけ稼いで費やすかを知っていれば、必要な類似点を簡単に見つけることができます。
それは素晴らしいことです! これまでのところ、モデルを構築するためのXNUMXつの変数がすでにあります。 これが表すものに加えて、モデルをより単純で、簡潔で、より説明しやすくします。
ベストプラクティス、業界で認められた標準、および含まれているチートシートを含む、Gitを学習するための実践的で実用的なガイドを確認してください。 グーグルGitコマンドを停止し、実際に 学ぶ それ!
注: データサイエンスは通常、可能な限り単純なアプローチを好みます。 ビジネスの説明が簡単であるだけでなく、より直接的であるため、2つの機能と説明可能なモデルにより、モデルが何を実行し、どのように機能しているかが明確になります。
PCA使用後のデータのプロット
XNUMX番目のアプローチがおそらく最善のようですが、XNUMX番目のアプローチも見てみましょう。 次元が多すぎるためにデータをプロットできない場合、またはデータが集中していないか、グループに明確に分離されていない場合に役立ちます。 このような状況が発生した場合は、次の方法でデータのサイズを減らすことをお勧めします。 主成分分析(PCA).
注: ほとんどの人は、視覚化の前に次元削減のためにPCAを使用します。 クラスタリングの前にデータを視覚化するのに役立つ他の方法があります。 ノイズのあるアプリケーションの密度ベースの空間クラスタリング(DBSCAN) & 自己組織化マップ(SOM) クラスタリング。 どちらもクラスタリングアルゴリズムですが、データの視覚化にも使用できます。 クラスタリング分析には黄金の基準がないため、さまざまな視覚化とさまざまなアルゴリズムを比較することが重要です。
PCAは、可能な限り多くの情報を保持しようとしながら、データのサイズを縮小します。 最初にPCAがどのように機能するかについて考えてみましょう。次に、データを減らすデータディメンションの数を選択できます。
機能の各ペアについて、PCAは、一方の変数の大きい方の値がもう一方の変数の大きい方の値に対応するかどうかを確認し、小さい方の値についても同じことを行います。 したがって、基本的に、特徴値が互いにどの程度変化するかを計算します。 共分散。 次に、これらの結果はマトリックスに編成され、 共分散行列.
共分散行列を取得した後、PCA はそれを最もよく説明する特徴の線形結合を見つけようとします。 分散量.
Note:PCAは線形変換であり、線形性はデータのスケールに敏感です。 したがって、PCAは、すべてのデータ値が同じスケールである場合に最適に機能します。 これは、列を減算することで実行できます 意味する その値から、結果を標準偏差で除算します。 それは呼ばれています データの標準化。 PCAを使用する前に、データがスケーリングされていることを確認してください。 方法がわからない場合は、 「Scikitを使用したデータのスケーリング機能-Pythonでの機械学習のための学習」!
最適な線(線形結合)が見つかると、PCAはその軸の方向を取得します。 固有ベクトル、およびその線形係数、 固有値。 固有ベクトルと固有値の組み合わせ、または軸の方向と係数は、 主成分 PCAの。 そして、それは、各特徴の説明された分散に基づいて次元の数を選択できるときです。どの主成分がどの程度の分散を説明するかに基づいて、どの主成分を保持または破棄するかを理解することによってです。
主成分を取得した後、PCAは固有ベクトルを使用して、データを元の軸から主成分によって表される軸に再配向する特徴のベクトルを形成します。これにより、データの次元が縮小されます。
注: ここで考慮すべき重要な詳細のXNUMXつは、線形性のため、PCAは説明された分散のほとんどを最初の主成分に集中させることです。 したがって、説明された分散を見ると、通常、最初のXNUMXつのコンポーネントで十分です。 ただし、場合によっては誤解を招く可能性があります。したがって、クラスタリング時にさまざまなプロットとアルゴリズムを比較し続けて、同様の結果が得られるかどうかを確認してください。
PCAを適用する前に、次のいずれかを選択する必要があります。 Age
列または Age Groups
以前にワンホットでエンコードされたデータの列。 両方の列が同じ情報を表すため、それをXNUMX回導入すると、データの分散に影響します。 の場合 Age Groups
列が選択されている場合は、単に削除します Age
パンダを使用した列 drop()
メソッドとそれをに再割り当てします customer_data_oh
変数:
customer_data_oh = customer_data_oh.drop(['Age'], axis=1)
customer_data_oh.shape
現在、データには 10 列あります。つまり、列ごとに XNUMX つの主成分を取得し、XNUMX つの新しい次元を導入することでデータ分散がどの程度説明されるかを測定することで、使用する主成分の数を選択できます。
Scikit-Learnでそれをやってみましょう PCA
。 次の式で与えられる各次元の説明された分散を計算します。 explained_variance_ratio_
、次にそれらの累積合計を cumsum()
:
from sklearn.decomposition import PCA
pca = PCA(n_components=10)
pca.fit_transform(customer_data_oh)
pca.explained_variance_ratio_.cumsum()
説明された累積分散は次のとおりです。
array([0.509337 , 0.99909504, 0.99946364, 0.99965506, 0.99977937,
0.99986848, 0.99993716, 1. , 1. , 1. ])
最初のディメンションがデータの50%を説明し、99番目のディメンションと組み合わせると2%パーセントを説明していることがわかります。 これは、最初の99つのディメンションがすでにデータの2%を説明していることを意味します。 したがって、XNUMXつのコンポーネントでPCAを適用し、主成分を取得してプロットすることができます。
from sklearn.decomposition import PCA
pca = PCA(n_components=2)
pcs = pca.fit_transform(customer_data_oh)
pc1_values = pcs[:,0]
pc2_values = pcs[:,1]
sns.scatterplot(x=pc1_values, y=pc2_values)
PCA後のデータプロットは、PCAなしでXNUMX列のデータのみを使用しているプロットと非常によく似ています。 グループを形成しているポイントがより近く、PCAの後で以前よりも少し集中していることに注意してください。
樹状図による階層構造の視覚化
これまで、データ、ワンホットエンコードされたカテゴリ列を調査し、クラスタリングに適した列を決定し、データの次元を減らしてきました。 プロットは、データに5つのクラスターがあることを示していますが、ポイント間の関係を視覚化し、クラスターの数を決定するのに役立つ別の方法もあります。 樹状図 (通常、デンドグラムのスペルが間違っています)。 デンドロ 手段 ツリー ラテン語で。
樹状図 データセット内のポイントのリンクの結果です。 これは、階層的クラスタリングプロセスを視覚的に表したものです。 そして、階層的クラスタリングプロセスはどのように機能しますか? ええと…状況によります–おそらくデータサイエンスですでにたくさん聞いたことがある答えでしょう。
階層的クラスタリングを理解する
時 階層的クラスタリングアルゴリズム(HCA) ポイントのリンクとクラスターの検索を開始します。最初にポイントを2つの大きなグループに分割し、次にそれらの2つのグループをそれぞれ小さな4つのグループに分割して、合計XNUMXつのグループを作成します。 分裂的 & トップダウン アプローチで回避できます。
または、逆のこともできます。すべてのデータポイントを調べ、互いに近い2つのポイントを見つけてリンクし、それらのリンクされたポイントに最も近い他のポイントを見つけて、2つのグループを構築し続けることができます。から 一気飲み。 どちらですか 凝集性 私たちが開発するアプローチ。
凝集型階層的クラスタリングを実行する手順
凝集アプローチをさらに明確にするために、次の手順があります。 凝集型階層的クラスタリング(AHC) アルゴリズム:
- 最初に、各データポイントをXNUMXつのクラスターとして扱います。 したがって、開始時のクラスターの数はKになりますが、Kはデータポイントの数を表す整数です。
- 最も近い1つのデータポイントを結合してクラスターを形成し、K-XNUMXクラスターを作成します。
- 最も近い2つのクラスターを結合して、より多くのクラスターを形成し、K-XNUMXクラスターを作成します。
- XNUMXつの大きなクラスターが形成されるまで、上記のXNUMXつの手順を繰り返します。
Note:簡単にするために、手順2と3で「最も近いXNUMXつの」データポイントを示しています。ただし、後で説明するように、ポイントをリンクする方法は他にもあります。
ACH アルゴリズムのステップを逆にして、4 から 1 にすると、* へのステップになります。分裂的階層クラスタリング (DHC)*.
HCAは、分割型でトップダウン型、または凝集型でボトムアップ型のいずれかであることに注意してください。 トップダウンDHCアプローチは、クラスターが少ないが大きい場合に最適に機能するため、計算コストが高くなります。 一方、ボトムアップAHCアプローチは、小さなクラスターが多数ある場合に適しています。 これは、計算がより単純で、より使用され、より利用可能です。
注: トップダウンまたはボトムアップのいずれかで、クラスタリングプロセスの樹状図表現は、常にXNUMXつの分割で始まり、基礎となる構造がXNUMX分木になると、個々のポイントが識別されて終了します。
データの階層関係を視覚化するために、顧客データの樹状図をプロットしてみましょう。 今回は、 scipy
データセットの樹状図を作成するためのライブラリ:
import scipy.cluster.hierarchy as shc
import matplotlib.pyplot as plt
plt.figure(figsize=(10, 7))
plt.title("Customers Dendrogram")
selected_data = customer_data_oh.iloc[:, 1:3]
clusters = shc.linkage(selected_data,
method='ward',
metric="euclidean")
shc.dendrogram(Z=clusters)
plt.show()
スクリプトの出力は次のようになります。
上記のスクリプトでは、ポイントを使用してクラスターとサブクラスターを生成し、ポイントがどのようにリンクするかを定義しました( ward
方法)、およびポイント間の距離を測定する方法( euclidean
メトリック)。
樹状図のプロットを使用して、DHCおよびAHCの説明されたプロセスを視覚化できます。 トップダウンアプローチを視覚化するには、樹状図の上部から開始して下に移動し、逆に、下から上に移動してボトムアップアプローチを視覚化します。
リンケージメソッド
他にも多くのリンク方法がありますが、それらがどのように機能するかを理解することで、ニーズに合った適切な方法を選択できるようになります。 それに加えて、それらのそれぞれは、適用されたときに異なる結果をもたらします。 クラスタリング分析には決まったルールはありません。可能であれば、問題の性質を調べて、どれが最適かを確認し、さまざまな方法をテストして、結果を調べてください。
リンケージ方法のいくつかは次のとおりです。
- シングルリンケージ:別名 最近傍(NN)。 クラスタ間の距離は、最も近いメンバー間の距離によって定義されます。
- 完全なリンケージ:別名 最も遠い隣人(FN), 最も遠い点のアルゴリズムまたは VoorHeesアルゴリズム。 クラスター間の距離は、最も遠いメンバー間の距離によって定義されます。 この方法は計算コストがかかります。
- 平均リンケージ: としても知られている UPGMA (算術平均を使用した非加重ペアグループ法)。 各クラスターのポイント数のパーセンテージは、XNUMXつのクラスターがマージされた場合のポイント数に対して計算されます。
- 加重リンケージ: としても知られている WPGMA (算術平均を使用した加重ペアグループ法)。 XNUMXつのクラスターの個々のポイントは、小さいクラスターと大きいクラスターの間の合計距離に寄与します。
- セントロイドリンケージ:別名 UPGMC (重心を使用した非加重ペアグループ法)。 すべてのポイントの平均によって定義されるポイント(重心)がクラスターごとに計算され、クラスター間の距離はそれぞれの重心間の距離になります。
- ワードリンケージ: としても知られている ミスク (二乗和の最小増加)。 XNUMXつのクラスター間の距離を指定し、二乗和誤差(ESS)を計算し、小さい方のESSに基づいて次のクラスターを連続して選択します。 ウォード法は、各ステップでのESSの増加を最小限に抑えることを目的としています。 したがって、エラーを最小限に抑えます。
距離メトリック
リンケージに加えて、最も使用される距離メトリックのいくつかを指定することもできます。
- ユークリッド:別名 ピタゴラスまたは直線 距離。 空間内のXNUMX点間の距離を、それらの間を通過する線分の長さを測定することによって計算します。 ピタゴラスの定理を使用し、距離の値が結果になります (c) 方程式の:
$$
c ^ 2 = a ^ 2 + b ^ 2
$$
- マンハッタン: とも呼ばれている 街区、タクシー 距離。 これは、XNUMX点のすべての次元におけるメジャー間の絶対差の合計です。 これらの寸法がXNUMXの場合、XNUMXブロック歩くときに右から左に移動するのと似ています。
- ミンコフスキー:これは、ユークリッド距離とマンハッタン距離の両方を一般化したものです。 これは、ミンコフスキー計量の次数との絶対差に基づいて距離を計算する方法です。 p。 それはすべてのために定義されていますが p> 0、1、2、および∞(無限)以外の値に使用されることはめったにありません。 ミンコフスキー距離は、マンハッタン距離と同じです。 p = 1、およびユークリッド距離と同じ場合 p = 2.
$$
Dleft(X、Yright)= left(sum_ {i = 1} ^ n | x_i-y_i | ^ pright)^ {frac {1} {p}}
$$
- チェビシェフ: としても知られている チェス盤 距離。 ミンコフスキー距離の極端なケースです。 パラメータの値として無限大を使用する場合 p(p =∞)、最終的には、距離を座標間の最大絶対差として定義するメトリックになります。
- 余弦:これは、XNUMXつの点のシーケンスまたはベクトル間の角度余弦距離です。 コサイン類似度は、ベクトルの内積を長さの積で割ったものです。
- ジャッカード:点の有限集合間の類似性を測定します。 これは、各セット(交差)の共通ポイントの合計ポイント数(カーディナリティ)を、両方のセット(和集合)の合計ポイントの合計ポイント数(カーディナリティ)で割ったものとして定義されます。
- イェンセン・シャノン:カルバック・ライブラー発散に基づいています。 ポイントの確率分布を考慮し、それらの分布間の類似性を測定します。 これは、確率論と統計の一般的な方法です。
選択しました ウォード & ユークリッド 樹状図は、最も一般的に使用される方法とメトリックであるためです。 Wardはエラーの最小化に基づいてポイントをリンクし、Euclideanは低次元でうまく機能するため、通常は良好な結果が得られます。
この例では、マーケティングデータの200つの特徴(列)と200の観測値または行を処理しています。 観測数が特徴数(2> XNUMX)より多いため、低次元空間で作業しています。
機能の数が (f)は、 観測数よりも大きい (N) –主に次のように書かれています f >> N、それは私たちが持っていることを意味します 高次元空間.
より多くの属性を含める場合、200を超えるフィーチャがある場合、ユークリッド距離はあまりうまく機能しない可能性があります。これは、大きくなるだけの非常に大きな空間ですべての小さな距離を測定することが難しいためです。 言い換えると、ユークリッド距離アプローチでは、データを操作するのが困難です。 スパース性。 これはと呼ばれる問題です 次元の呪い。 距離の値は、より大きな空間で「希釈」され、0になるまで歪んでいるかのように非常に小さくなります。
注: でデータセットに遭遇した場合 f >> p、おそらく他の距離メトリックを使用します。 マハラノビス 距離。 または、を使用してデータセットのディメンションを縮小することもできます 主成分分析(PCA)。 この問題は、生物学的シーケンスデータをクラスタリングする場合に特に頻繁に発生します。
メトリック、リンケージ、およびそれらのそれぞれが結果にどのように影響するかについては、すでに説明しました。 樹状図分析を続けて、データセット内のクラスターの数をどのように示すことができるかを見てみましょう。
樹状図で興味深い数のクラスターを見つけることは、垂直線がない最大の水平空間(垂直線が最も長い空間)を見つけることと同じです。 これは、クラスター間の分離がより多くなることを意味します。
その最長距離を通過する水平線を引くことができます。
plt.figure(figsize=(10, 7))
plt.title("Customers Dendogram with line")
clusters = shc.linkage(selected_data,
method='ward',
metric="euclidean")
shc.dendrogram(clusters)
plt.axhline(y = 125, color = 'r', linestyle = '-')
水平線を見つけた後、垂直線が交差した回数を数えます。この例では、5回です。 したがって、5は、クラスター間の距離が最も長いクラスターの数を示す良い指標のようです。
Note:樹状図は、クラスターの数を選択するために使用される場合の参照としてのみ考慮されるべきです。 それは簡単にその数を減らすことができ、リンケージのタイプと距離メトリックに完全に影響されます。 詳細なクラスター分析を行うときは、さまざまなリンケージとメトリックを持つ樹状図を確認し、クラスター間の距離が最も長い最初のXNUMX行で生成された結果を確認することをお勧めします。
凝集型階層的クラスタリングの実装
元のデータの使用
これまでのところ、初期分析と PCA 分析を裏付ける、データセットのクラスターの推奨数を計算しました。 これで、Scikit-Learn を使用して凝集型の階層クラスタリング モデルを作成できます AgglomerativeClustering
とマーケティングポイントのラベルを見つける labels_
:
from sklearn.cluster import AgglomerativeClustering
clustering_model = AgglomerativeClustering(n_clusters=5, affinity='euclidean', linkage='ward')
clustering_model.fit(selected_data)
clustering_model.labels_
この結果:
array([4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3,
4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 1,
4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 2, 1, 2, 0, 2, 0, 2,
1, 2, 0, 2, 0, 2, 0, 2, 0, 2, 1, 2, 0, 2, 1, 2, 0, 2, 0, 2, 0, 2,
0, 2, 0, 2, 0, 2, 1, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2,
0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2,
0, 2])
この点に到達するために、私たちは多くのことを調査しました。 そして、これらのラベルはどういう意味ですか? ここでは、データの各ポイントに0から4までのグループとしてラベルが付けられています。
data_labels = clustering_model.labels_
sns.scatterplot(x='Annual Income (k$)',
y='Spending Score (1-100)',
data=selected_data,
hue=data_labels,
pallete="rainbow").set_title('Labeled Customer Data')
これが最終的なクラスター化されたデータです。 XNUMXつのクラスターの形で色分けされたデータポイントを見ることができます。
右下のデータポイント(ラベル: 0
、紫色のデータポイント)は、給与は高いが支出は少ない顧客のものです。 これらは慎重にお金を使う顧客です。
同様に、右上の顧客(ラベル: 2
、グリーンデータポイント)は、給与と支出が高い顧客です。 これらは、企業がターゲットとするタイプの顧客です。
真ん中の顧客(ラベル: 1
、青いデータポイント)は、平均収入と平均支出のデータポイントです。 最も多くの顧客がこのカテゴリに属しています。 彼らが膨大な数であるという事実を考えると、企業はこれらの顧客をターゲットにすることもできます。
左下の顧客(ラベル: 4
、赤)は、給与と支出が少ない顧客であり、プロモーションを提供することで魅力を感じる可能性があります。
そして最後に、左上の顧客(ラベル: 3
、オレンジ色のデータポイント)は、高収入で低支出のデータポイントであり、マーケティングの対象となるのが理想的です。
PCAからの結果の使用
別のシナリオでは、データの次元を削減する必要がありました。 クラスター化されたPCAの結果を簡単にプロットすることもできます。 これは、別の凝集クラスタリングモデルを作成し、主成分ごとにデータラベルを取得することで実行できます。
clustering_model_pca = AgglomerativeClustering(n_clusters=5, affinity='euclidean', linkage='ward')
clustering_model_pca.fit(pcs)
data_labels_pca = clustering_model_pca.labels_
sns.scatterplot(x=pc1_values,
y=pc2_values,
hue=data_labels_pca,
palette="rainbow").set_title('Labeled Customer Data Reduced with PCA')
両方の結果が非常に似ていることに注意してください。 主な違いは、元のデータを使用した最初の結果の説明がはるかに簡単なことです。 顧客は、年収と支出スコアによってXNUMXつのグループに分類できることは明らかです。 PCAアプローチでは、すべての機能を考慮に入れていますが、それぞれの機能によって説明される差異を確認できる限り、これは、特にマーケティング部門に報告する場合、理解するのが難しい概念です。
データを変換する必要が少ないほど、優れています。
クラスタリングの前に次元削減を実行する必要がある非常に大規模で複雑なデータセットがある場合は、各特徴とその残差の間の線形関係を分析して、PCAの使用をバックアップし、プロセスの説明可能性を高めてください。 機能のペアごとに線形モデルを作成することにより、機能がどのように相互作用するかを理解できるようになります。
データ量が非常に多い場合、特徴のペアをプロットし、データのサンプルを可能な限り正規分布に近いバランスで選択し、最初にサンプルの分析を実行し、理解し、微調整することが不可能になります。それ–そして後でそれをデータセット全体に適用します。
データの性質(線形、非線形)に応じて、いつでもさまざまなクラスタリング視覚化手法を選択し、必要に応じてそれらすべてを組み合わせたり、テストしたりできます。
まとめ
クラスタリング手法は、ラベルのないデータに関しては非常に便利です。 実世界のほとんどのデータにはラベルがなく、データに注釈を付けるにはコストがかかるため、クラスタリング手法を使用してラベルのないデータにラベルを付けることができます。
このガイドでは、クラスタリング手法が主にマーケティング分析(および生物学的分析)で使用されているため、実際のデータサイエンスの問題を取り上げました。 また、優れた階層的クラスタリングモデルに到達するための調査手順の多くと、樹状図の読み取り方法について説明し、PCAが必要な手順であるかどうかを質問しました。 私たちの主な目的は、階層的クラスタリングを見つけることができるいくつかの落とし穴とさまざまなシナリオをカバーすることです。
ハッピークラスタリング!