stanzaを使ってみる 10
以前の投稿でstanzaを使ってみたことをまとめた.
今回はその続きで構文の特徴(構文スタイル)に注目したクラスタリングをstanzaで行い可視化まで行う.
コードは下記.
import stanza
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.cluster import KMeans
from sklearn.manifold import TSNE
import matplotlib.pyplot as plt
# ✅ Stanza日本語モデルのダウンロード(初回のみ)
stanza.download('ja')
nlp = stanza.Pipeline(lang='ja', processors='tokenize,pos,lemma,depparse')
# ✅ 分類対象の日本語文(指定された16文)
texts = [
# 平叙文(中立)
"彼は本を読んだ。",
"本日は晴天なり。",
"私は音楽を聴きながら散歩するのが好きです。",
"猫が静かに眠っている。",
# 丁寧な挨拶・日常会話風
"おはようございます、今日も頑張りましょう!",
"それって本当にそうなの?",
"お忙しいところ失礼いたします。",
"今日はどちらまでお出かけですか?",
# 学術風・堅めの文体
"この研究では、統計的手法を用いて分析を行った。",
"結果として、有意な差が観測された。",
"実験群と対照群の間で明確な傾向が見られた。",
"我々の仮説は概ね支持されたと考えられる。",
# 物語風・描写重視
"窓の外には赤く染まった空が広がっていた。",
"少女は静かに湖のほとりに座っていた。",
"風が強く吹き、木々がざわめいた。",
"男は言葉もなく立ち尽くしていた。"
]
# ✅ 各文から依存関係ラベル(deprel)を抽出
def extract_deprels(text):
doc = nlp(text)
deprels = []
for sentence in doc.sentences:
deprels.extend([word.deprel for word in sentence.words])
return " ".join(deprels)
features = [extract_deprels(t) for t in texts]
# ✅ Bag-of-Wordsでベクトル化
vectorizer = CountVectorizer()
X = vectorizer.fit_transform(features)
# ✅ KMeansクラスタリング
n_clusters = 4
kmeans = KMeans(n_clusters=n_clusters, random_state=42)
labels = kmeans.fit_predict(X)
# ✅ t-SNEによる2次元可視化
tsne = TSNE(n_components=2, random_state=42, perplexity=5)
X_2d = tsne.fit_transform(X.toarray())
# ✅ 結果のプロット
plt.figure(figsize=(12, 8))
for i in range(n_clusters):
cluster_points = X_2d[labels == i]
plt.scatter(cluster_points[:, 0], cluster_points[:, 1], label=f'Cluster {i}', alpha=0.8)
# 文番号を表示(補助的)
for idx, (x, y) in enumerate(X_2d):
plt.text(x + 0.5, y, str(idx + 1), fontsize=9)
# ✅ グラフの設定(タイトルは英語)
plt.title("Syntactic Clustering of Japanese Sentences via Stanza + t-SNE", fontsize=14)
plt.xlabel("t-SNE Dimension 1")
plt.ylabel("t-SNE Dimension 2")
plt.legend()
plt.grid(True)
plt.tight_layout()
plt.show()
# ✅ 各文のクラスタ割り当てを表示
print("\n--- クラスタリング結果 ---")
for i, label in enumerate(labels):
print(f"文({i+1:>2}):「{texts[i]}」 → クラスタ: {label}")
