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}")
    

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です