はじめに
この実験では、一様に分布するランダムなラベリングがいくつかのクラスタリング評価指標の挙動に与える影響を調べます。クラスタリングアルゴリズムは基本的に無監督学習手法であり、生成されたクラスタの品質を定量化するために「監督」された正解情報を利用する評価指標です。ただし、調整されていないクラスタリング評価指標は、完全にランダムな微細なラベリングに対して大きな値を出力するため、誤解を招く可能性があります。したがって、調整された指標のみを、データセットのさまざまな重複サブサンプルに対する k の特定の値に対するクラスタリングアルゴリズムの平均安定性を評価するコンセンサス指標として安全に使用できます。
VM のヒント
VM の起動が完了したら、左上隅をクリックしてノートブックタブに切り替え、Jupyter Notebook を使って練習しましょう。
Jupyter Notebook の読み込みには数秒かかる場合があります。Jupyter Notebook の制限により、操作の検証は自動化できません。
学習中に問題が発生した場合は、Labby にお問い合わせください。セッション後にフィードバックを提供してください。すぐに問題を解決いたします。
評価するメトリックのリストを定義する
まず、クラスタリングアルゴリズムを評価するために使用するメトリックのリストを定義します。このようなメトリックの例としては、V-measure、Rand index、調整済み Rand index (ARI)、相互情報 (MI)、正規化相互情報 (NMI)、および調整済み相互情報 (AMI) が挙げられます。
from sklearn import metrics
score_funcs = [
("V-measure", metrics.v_measure_score),
("Rand index", metrics.rand_score),
("ARI", metrics.adjusted_rand_score),
("MI", metrics.mutual_info_score),
("NMI", metrics.normalized_mutual_info_score),
("AMI", metrics.adjusted_mutual_info_score),
]
実験 1 - 固定された正解ラベルとクラスタ数の増加
一様に分布するランダムなラベリングを作成し、random_labels関数を使用して、n_classesに分布する固定された正解ラベルのセット (labels_a) を作成し、次に、与えられたn_clustersでの特定のメトリックの変動性を評価するために、いくつかのランダムに「予測」されたラベルのセット (labels_b) にスコアを付けます。
rng = np.random.RandomState(0)
def random_labels(n_samples, n_classes):
return rng.randint(low=0, high=n_classes, size=n_samples)
def fixed_classes_uniform_labelings_scores(
score_func, n_samples, n_clusters_range, n_classes, n_runs=5
):
scores = np.zeros((len(n_clusters_range), n_runs))
labels_a = random_labels(n_samples=n_samples, n_classes=n_classes)
for i, n_clusters in enumerate(n_clusters_range):
for j in range(n_runs):
labels_b = random_labels(n_samples=n_samples, n_classes=n_clusters)
scores[i, j] = score_func(labels_a, labels_b)
return scores
実験 1 の結果をプロットする
matplotlib と seaborn ライブラリを使って、最初の実験の結果をプロットします。Rand index は n_clusters > n_classes のときに飽和します。V-Measure などの他の調整されていない指標は、クラスタ数とサンプル数の間に線形依存関係を示します。ARI や AMI などの偶然に対する調整済み指標は、サンプル数とクラスタ数に関係なく、平均スコア 0.0 を中心としたいくつかのランダムな変動を表示します。
import matplotlib.pyplot as plt
import seaborn as sns
n_samples = 1000
n_classes = 10
n_clusters_range = np.linspace(2, 100, 10).astype(int)
plots = []
names = []
sns.color_palette("colorblind")
plt.figure(1)
for marker, (score_name, score_func) in zip("d^vx.,", score_funcs):
scores = fixed_classes_uniform_labelings_scores(
score_func, n_samples, n_clusters_range, n_classes=n_classes
)
plots.append(
plt.errorbar(
n_clusters_range,
scores.mean(axis=1),
scores.std(axis=1),
alpha=0.8,
linewidth=1,
marker=marker,
)[0]
)
names.append(score_name)
plt.title(
"Clustering measures for random uniform labeling\n"
f"against reference assignment with {n_classes} classes"
)
plt.xlabel(f"Number of clusters (Number of samples is fixed to {n_samples})")
plt.ylabel("Score value")
plt.ylim(bottom=-0.05, top=1.05)
plt.legend(plots, names, bbox_to_anchor=(0.5, 0.5))
plt.show()
実験 2 - クラス数とクラスタ数を変化させる
このセクションでは、2 つの一様に分布するランダムなラベリングに対していくつかのメトリックを使ってスコア付けする同様の関数を定義します。この場合、n_clusters_range の各可能な値に対して、クラス数と割り当てられたクラスタ数を一致させます。
def uniform_labelings_scores(score_func, n_samples, n_clusters_range, n_runs=5):
scores = np.zeros((len(n_clusters_range), n_runs))
for i, n_clusters in enumerate(n_clusters_range):
for j in range(n_runs):
labels_a = random_labels(n_samples=n_samples, n_classes=n_clusters)
labels_b = random_labels(n_samples=n_samples, n_classes=n_clusters)
scores[i, j] = score_func(labels_a, labels_b)
return scores
実験 2 の結果をプロットする
matplotlib ライブラリを使って、第 2 の実験の結果をプロットします。第 1 の実験と同様の結果が観察されます:偶然に対する調整済みメトリックは一定でゼロに近く、他のメトリックは細かい粒度のラベリングで大きくなる傾向があります。ランダムなラベリングの平均 V-measure は、クラスタ数が測定に使用されたサンプルの総数に近づくにつれて大幅に増加します。
n_samples = 100
n_clusters_range = np.linspace(2, n_samples, 10).astype(int)
plt.figure(2)
plots = []
names = []
for marker, (score_name, score_func) in zip("d^vx.,", score_funcs):
scores = uniform_labelings_scores(score_func, n_samples, n_clusters_range)
plots.append(
plt.errorbar(
n_clusters_range,
np.median(scores, axis=1),
scores.std(axis=1),
alpha=0.8,
linewidth=2,
marker=marker,
)[0]
)
names.append(score_name)
plt.title(
"Clustering measures for 2 random uniform labelings\nwith equal number of clusters"
)
plt.xlabel(f"Number of clusters (Number of samples is fixed to {n_samples})")
plt.ylabel("Score value")
plt.legend(plots, names)
plt.ylim(bottom=-0.05, top=1.05)
plt.show()
まとめ
この実験では、一様に分布するランダムなラベリングがいくつかのクラスタリング評価メトリックの挙動に与える影響を調査しました。結果は、調整されていないクラスタリング評価メトリックは誤解を招く可能性があり、調整された指標のみを、データセットのさまざまな重複するサブサンプルに対する特定の k 値に対するクラスタリングアルゴリズムの平均安定性を評価するコンセンサス指標として安全に使用できることを示しています。