🥨

データサイエンスで楽々ドイツ語学習 その4 新聞記事をネットワーク解析

に公開

この記事の概要

ドイツ語で読んだ新聞記事の語彙を、意味のつながりに基づいてネットワークとして可視化してみました。
単語同士の関係が図として現れることで、文脈やテーマの理解が深まるだけでなく、語彙学習の効率も高まると感じています。
本記事では、その取り組みの手順とそこから得られた気づきを紹介します。

出来上がったネットワークはこちらです。

前回のあらすじ

  • ドイツ語学習の単語を覚えるという地道な作業をいかに楽して行えないか…
  • データサイエンスの知識アップもしたい…

という、どうしようもない欲深い私が、遠回りしながらも、データサイエンスでドイツ語学習をする記録をつづってきました。
今回は、前回行った単語のネットワーク解析を、新聞記事に対して行ってみます。

前回の記事その3(単語のネットワーク解析)
前回の記事その0(なぜドイツ語とデータサイエンス?)

動機

ドイツ語の新聞読んでいますか?
語学学習に効果的だとわかっていても、私はなかなか読む気になれません。海外で日々生活するだけで精いっぱい。数少ない余暇の時間まで、ドイツ語の新聞読むのは、正直つらいのです。
そんな私が唯一読む機会があるのは、義父が日本に関するドイツ語の記事を送ってくれるときです。
ありがたいことに、日本関連の記事であれば、多少は興味わくし、読んでみようかな、と思えます。ただし、義父への返信というプレッシャーも同時に発生し、それが重くのしかかります。
頑張って読んだら確かに面白いし、学びにもなるし、ためになるのは理解しているものの、この義務感によって、学習効果は超薄い気がしています。
というのも、人間、嫌々する勉強は身につかないということが証明されているからです。
外的報酬(テストの点や叱られたくないなど、私の場合、義父からのプレッシャー)に基づく「外発的動機付け」は、「内発的動機付け(自分の意思で学ぶ)」よりも、記憶の定着・理解・創造性の面で学習効果が薄いとされますし、「やらされ感」はストレスホルモン(コルチゾール)を高め、記憶形成に関わる海馬の機能を阻害することが知られているそうです。
人間は、自発的な学習のほうが記憶への定着が圧倒的に効果が高いのです。
「どうにかして楽しみながら学べる方法に変換したい!」そんな思いから、今回は新聞記事を題材に、データサイエンスを活用した語彙ネットワークを構築してみることにしました。

記事の紹介

今回取り扱う記事は、Frankfurter Allegemeine に2025年6月15日に体裁された「Eine Stunde anstehen, um ein Selfie zu machen」という記事 で、日本のオーバーツーリズムについての内容で、非常に興味深いものでした。

新聞記事のSemantic Network解析

1. PDFファイルからtxtファイルの変換

PDFの文章はコピペできないため、Claudeを使ってサクッとテキストファイルを取得します。詳しくはこの記事を参照。
前回の記事その1(非構造データをClaudeで構造データに変換)

本当は、コピペできないなら、自分で手入力で一つ一つ文章や単語を確認しながら、ドイツ語を打ち込めば、それが勉強になるのでしょうが、時間をなるべく使わず、コスパ良く、効率的に勉強するのが、目的の一つでもあるため、そんなことはしません!本当にドイツ語を勉強する気がある方はぜひ手入力でコピーくださいね。

2. 文章の前処理

自然言語処理できるように、文章を前処理していきます。
私はNLPは全くの初心者なので、chatGPTさんの指導の下、処理しました。
手順としては、以下です。
1.txtファイルの読み込み
2.小文字化・記号削除
3.トークン化

import nltk
from nltk.corpus import stopwords
from nltk.tokenize import word_tokenize
import re

with open(path + "overtourism.txt", "r", encoding="utf-8") as file:
    text = file.read()

# 小文字化 + 記号削除
text_cleaned = re.sub(r'[^a-zA-ZäöüÄÖÜß\s]', '', text.lower())

# トークン化
tokens = word_tokenize(text_cleaned, language='german')

# ストップワード除去
tokens = [w for w in tokens if w not in stopwords.words('german')]

# TF-IDF用に文字列に戻す
processed_text = " ".join(tokens)

# TF-IDFベクトル化
from sklearn.feature_extraction.text import TfidfVectorizer
vectorizer = TfidfVectorizer()
X = vectorizer.fit_transform([processed_text])
vocab = vectorizer.get_feature_names_out()

3. FastTextモデルを使って類似度計算

FastTextのモデルを使って、各単語ベクトル間のコサイン類似度を計算します。

from gensim.models import KeyedVectors
import numpy as np
from sklearn.metrics.pairwise import cosine_similarity
model = KeyedVectors.load_word2vec_format(path_model + "wordvec/cc.de.300.vec", binary=False)
filtered_vocab = [w for w in vocab if w in model]
word_vecs = np.array([model[w] for w in filtered_vocab])
sim_matrix = cosine_similarity(word_vecs)

4. ネットワークの構築

類似度0.6以上の単語ペアにエッジを追加。

import networkx as nx

tfidf_scores = dict(zip(vocab, X.toarray()[0]))
G = nx.Graph()

# ノードを追加
for word in filtered_vocab:
    G.add_node(word, weight=tfidf_scores[word])

# 類似度の閾値以上のペアのみエッジとして追加
threshold = 0.6
for i in range(len(filtered_vocab)):
    for j in range(i+1, len(filtered_vocab)):
        sim = sim_matrix[i][j]
        if sim >= threshold:
            G.add_edge(filtered_vocab[i], filtered_vocab[j], weight=sim)

5. ネットワークの可視化(VOSviewer)

VSOviewerで可視化するため、ネットワークをtextファイルで出力します。

with open(path + "vosviewer_network.txt", "w", encoding="utf-8") as f:
    for u, v, data in G.edges(data=True):
        f.write(f"{u}\t{v}\t{data['weight']:.4f}\n")


こんな感じで、単語同士の関係値のファイルです。
ネットワークを構築するときに、類似度が0.6以上の組み合わせに限定したので、0.6以上のものだけがここにあります。
これをいざ、VOSviewerで可視化すると…

うーん、immer, shon, oft, eigentlich などの頻繁に使われる簡単な副詞や形容詞ばかりのマップになってしまいました。

知らない単語を、他の単語との関係性で覚えたいという目的には合わないです。
ということで、もう少し前処理が必要なようです。

6. 重要語の抽出

実は2.前処理で、TF-IDFベクトル化というのを計算していました。
TF-IDF(Term Frequency – Inverse Document Frequency) は、「その単語が文書内でどれくらい重要か」を数値化する方法です。

  • Term Frequency は、単語が文書に何回出てくるか(頻度)
  • IDF (Inverse Document Frequency)は、その単語がどれだけ珍しいか(他の文書にどれだけ出てこないか)

を計算しています。これを使えば、文書において、単語がどのくらい重要かの指標になります。
例えば、今回の文書内で一番TF-IDFが高い単語5個は、touristen, viele, jahr, japan, tokio
という結果になりました。

vectorizer = TfidfVectorizer(max_feature=150)

で重要語上位150個だけを残すようにフィルターをかけ、
さらに、ネットワーク構築時の類似度フィルターを

threshold = 0

に変更すると、
こんな風に変わります。

重要語を大きく表示しているため、ノードとその繋がりを見るだけで、記事の全体像や語彙の意味的まとまりが視覚的に浮かび上がってきます。

ただし、語彙を効率よく覚えるという本来の目的に対してはまだ課題が残ります。

今後の展望

特に覚えたい、B2~C2相当の語彙だけに絞って、表示をしたいのですが、CEFRレベル月の単語リストは公開されておらず、難単語のフィルタが簡単にできません。
そんな中、Leipzig大学のこんな語彙データベース を見つけました。このサイトでは、各語の共起後やネットワーク表示、例文などが確認できます。

学習時に、このDBを併用すれば、意味の近い単語同士を関連付けながら記憶することができそうです。

まとめ

新聞記事を語彙ネットワークとして可視化することで、語の意味的なまとまりや使われ方のパターンがより立体的に見えるようになりました。

ドイツ語の語彙を効率的に覚えたい方、語学学習とデータサイエンスを組み合わせてみたい方にとって、少しでも参考になれば幸いです。

まだ一つの記事だけですが、他の記事も試してみたいと思っています。
この記事を試してみて!などご要望があれば、亀速度になるかもしれませんが、対応したいと思いますので、ぜひコメントいただけると嬉しいです。

Discussion