2,500件のユーザーペインを UMAP × HDBSCAN + LLM自動命名で高精度クラスタリングしてみた
前回の記事では、ネットの投稿から OpenAI Structured Outputs と text-embedding-3-small (1536次元) を用いて「お金を払ってでも解決したいペイン」を自動抽出し、PostgreSQL (pgvector) に保存する手法を紹介しました。
今回は、蓄積された 2,500件のペインベクトルデータを UMAP × HDBSCAN + LLM自動命名 でクラスタリング し、市場に存在する課題領域を全自動で可視化したデータ分析手法を解説します。
🛠️ なぜ K-Means や DBSCAN ではなく HDBSCAN なのか?
文章の埋め込みベクトル(Embedding)をクラスタリングする際、定番のアルゴリズムには以下のような課題があります。
| アルゴリズム | 課題・デメリット |
|---|---|
| K-Means | 最初にクラスタ数 $K$ を人間が指定する必要があり、未知の課題領域の発見に向かない。 |
| DBSCAN | 距離しきい値 eps を固定で指定する必要があり、データの密度が均一でない場合に全データが1つの巨大クラスタに結合してしまう(今回の初期検証で全データが1クラスタに結合する問題が発生)。 |
| HDBSCAN |
eps の固定指定が不要。異なる密度のクラスタを階層的に自動検出し、ノイズ(単発のお悩み)を綺麗に除外できる。 |
🐍 分析パイプラインの実装コード
import numpy as np
from sklearn.preprocessing import normalize
from umap import UMAP
import hdbscan
from openai import OpenAI
def run_clustering(embeddings: np.ndarray, min_cluster_size: int = 5, min_samples: int = 3):
"""
1. L2 正規化
2. UMAP による次元削減 (1536次元 -> 10次元)
3. HDBSCAN による密度ベースのクラスタリング
"""
# 1. L2 正規化 (コサイン類似度ベースにするため)
normed = normalize(embeddings, norm="l2")
# 2. UMAP 次元削減
reducer = UMAP(
n_components=10,
n_neighbors=15,
min_dist=0.0,
metric="cosine",
random_state=42
)
reduced = reducer.fit_transform(normed)
# 3. HDBSCAN クラスタリング
clusterer = hdbscan.HDBSCAN(
min_cluster_size=min_cluster_size,
min_samples=min_samples,
metric="euclidean",
cluster_selection_method="eom"
)
labels = clusterer.fit_predict(reduced)
return labels
🤖 LLM (gpt-4o-mini) によるクラスタ自動命名
HDBSCAN で分割された各クラスタ(cluster_id)に含まれる上位のペイン文言をまとめて gpt-4o-mini に渡し、「このクラスタは何の課題群か」を自動で命名・要約させます。
def name_cluster_with_llm(openai_client: OpenAI, cluster_id: int, pain_items: list) -> str:
items_text = "\n".join([
f"- {item['core_pain']} (タグ: {', '.join(item['pain_keywords'])})"
for item in pain_items[:6]
])
prompt = f"""以下は同一クラスタに分類された複数のユーザーペインの一覧です。
これらのペインを端的にまとめた「クラスタ名(15文字以内)」と「要約(1文)」をJSONで出力してください。
ペイン一覧:
{items_text}
"""
res = openai_client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "user", "content": prompt}],
response_format={"type": "json_object"},
)
return res.choices[0].message.content
📊 2,520件の実際の分析結果サマリー
2,520件の全データセットを通した結果、138個の非常に具体的で鮮明な課題クラスタ が自動生成されました。
| クラスタID | LLM自動命名クラスタ | 件数 | 平均収益化スコア | 平均切実度 |
|---|---|---|---|---|
| #100 | ニキビ跡・クレーターの自力治療限界 | 22件 | 0.79 | 0.88 |
| #63 | 多汗症・手汗・ワキガの日常支障ケア | 10件 | 0.77 | 0.81 |
| #74 | 酒さ・赤ら顔の皮膚バリアケア | 13件 | 0.75 | 0.76 |
| #8 | PMDD(重度月経前不快障害)と定期処方 | 9件 | 0.74 | 0.84 |
| #103 | AGA・薄毛の継続治療と月額定額ニーズ | 7件 | 0.74 | 0.87 |
💡 まとめと考察
- 次元削減 + HDBSCAN の相性が抜群: 高次元なEmbeddingベクトルをUMAPで10次元に圧縮してからHDBSCANにかけることで、密度の異なる細かい悩み(ニキビ跡、手汗、PMDDなど)が綺麗に分離されました。
-
ノイズの排除: 単発の雑談や分類不能な疑問は
cluster_id = -1(ノイズ)として自動除外されるため、純度の高いペインだけを抽出できます。
次回は、抽出されたクラスタから「単発で終わるペイン」と「毎月継続課金(サブスク)されるペイン」のビジネス構造の違いを分析します。