stanzaを使ってみる 9
以前の投稿でstanzaを使ってみたことをまとめた.
今回はその続きで構文の特徴(構文スタイル)に注目したクラスタリングをstanzaで行ってみたい.
コードは下記.
import stanza
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.cluster import KMeans
# ✅ ステップ1:Stanza日本語モデルの準備
stanza.download('ja')
nlp = stanza.Pipeline(lang='ja', processors='tokenize,pos,lemma,depparse')
# ✅ ステップ2:構文的・文体的にバラエティを持たせた文のリスト
texts = [
# 平叙文(中立)
"彼は本を読んだ。",
"本日は晴天なり。",
"私は音楽を聴きながら散歩するのが好きです。",
"猫が静かに眠っている。",
# 丁寧な挨拶・日常会話風
"おはようございます、今日も頑張りましょう!",
"それって本当にそうなの?",
"お忙しいところ失礼いたします。",
"今日はどちらまでお出かけですか?",
# 学術風・堅めの文体
"この研究では、統計的手法を用いて分析を行った。",
"結果として、有意な差が観測された。",
"実験群と対照群の間で明確な傾向が見られた。",
"我々の仮説は概ね支持されたと考えられる。",
# 物語風・描写重視
"窓の外には赤く染まった空が広がっていた。",
"少女は静かに湖のほとりに座っていた。",
"風が強く吹き、木々がざわめいた。",
"男は言葉もなく立ち尽くしていた。"
]
# ✅ ステップ3:依存関係ラベルを系列として抽出
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]
# ✅ ステップ4:BoWベクトル化 → クラスタリング(クラスタ数は調整可能)
vectorizer = CountVectorizer()
X = vectorizer.fit_transform(features)
kmeans = KMeans(n_clusters=4, random_state=42) # 多様性があるのでクラスタ数を4に
kmeans.fit(X)
# ✅ ステップ5:結果表示
for i, label in enumerate(kmeans.labels_):
print(f"文({i+1:>2}):「{texts[i]}」 → クラスタ: {label}")
Output例
文( 1):「彼は本を読んだ。」 → クラスタ: 2
文( 2):「本日は晴天なり。」 → クラスタ: 2
文( 3):「私は音楽を聴きながら散歩するのが好きです。」 → クラスタ: 1
文( 4):「猫が静かに眠っている。」 → クラスタ: 2
文( 5):「おはようございます、今日も頑張りましょう!」 → クラスタ: 2
文( 6):「それって本当にそうなの?」 → クラスタ: 0
文( 7):「お忙しいところ失礼いたします。」 → クラスタ: 2
文( 8):「今日はどちらまでお出かけですか?」 → クラスタ: 0
文( 9):「この研究では、統計的手法を用いて分析を行った。」 → クラスタ: 1
文(10):「結果として、有意な差が観測された。」 → クラスタ: 1
文(11):「実験群と対照群の間で明確な傾向が見られた。」 → クラスタ: 1
文(12):「我々の仮説は概ね支持されたと考えられる。」 → クラスタ: 1
文(13):「窓の外には赤く染まった空が広がっていた。」 → クラスタ: 1
文(14):「少女は静かに湖のほとりに座っていた。」 → クラスタ: 1
文(15):「風が強く吹き、木々がざわめいた。」 → クラスタ: 3
文(16):「男は言葉もなく立ち尽くしていた。」 → クラスタ: 3