自然言語処理で思想家の文書特徴を把握する
今回のプログラムのねらい
主だった近代日本思想家から「経験」にまつわる論文を選び、それらの文書特徴を把握する。
自然言語処理でよく使われる手法である、re.subを使った正規表現によるクレンジング、janome.tokenizerによる形態素解析、part_of_speechによる特定品詞の抽出、ストップワード削除、word2vecによる単語のベクトル化、などによって特徴把握を目指します。
環境
Python 3.8.10
Google Colaboratory
プログラムの作成手順
①データの抽出
青空文庫トップページから、1 哲学 > 12 東洋思想 > 121 日本思想の中から抽出しました。
②データの前処理
正規表現によって、今回の解析結果に不要と思われる、英数字、記号類、改行などを削除します。
import re
text = open("/content/drive/MyDrive/ColabNotebooks/test-text/text_nishida_zen.txt","r")
cont = text.read()
text.close()
cont = re.sub("[a-xA-Z0-9_]","",cont)
cont = re.sub("[!-/:-@[-`{-~]","",cont)
cont = re.sub(u'\n\n', '\n', cont)
cont = re.sub(u'\r', '', cont)
③形態素解析
janomeという形態素解析エンジンを使います。テキストを、意味をもつ表現要素の最小単位である形態素ごとに分割します。品詞の判定、分かち書き(単語に分割)を実行します。
# janomeのTokenizerモジュールをインポートします。
from janome.tokenizer import Tokenizer
# Tokenizerインスタンスを生成し、形態素解析したい文章をtokenizeメソッドに渡します。
t = Tokenizer()
tokens = t.tokenize(cont)
for token in tokens:
print(token)
例えば西田幾多郎『善の研究』の冒頭部分を上記のコードによって形態素解析すると、以下のように出力されます。
この中から今回使用する、名詞・動詞・形容詞・形容動詞だけを抽出します。
また、動詞・形容詞・形容動詞については、活用形を含んだままだと解析しづらいので、基本形を使用するようにします。
def tokenize(cont):
t = Tokenizer()
tokens = t.tokenize(cont)
# 取り出した品詞が入るための空の箱word = []を作っておきます。
word = []
stop_word = create_stop_word()
for token in tokens:
part_of_speech = token.part_of_speech.split(",")[0]
print(part_of_speech)
if part_of_speech == "名詞":
print('名詞:', token.surface)
if not token.surface in stop_word:
word.append(token.surface)
if part_of_speech == "動詞":
if not token.base_form in stop_word:
word.append(token.base_form)
if part_of_speech == "形容詞":
if not token.base_form in stop_word:
word.append(token.base_form)
if part_of_speech == "形容動詞":
if not token.base_form in stop_word:
word.append(token.base_form)
return word
④ストップワードの作成
今回のねらいに関係なさそうな言葉をストップワードとして省きます。
まず、日本語のストップワードが既に登録されているSlothlibを使って取り除きたいと思います。
さらに、自分で不要そうなワードを、変数my_stop_wordに格納してストップワードリストに追加します。
def create_stop_word():
target_url = "http://svn.sourceforge.jp/svnroot/slothlib/CSharp/Version1/SlothLib/NLP/Filter/StopWord/word/Japanese.txt"
r =requests.get(target_url)
stop_word=str(r).split()
my_stop_word=['もの', 'なる', 'する', 'れる', 'こと', 'できる', 'いる', 'これ']
stop_word.extend(my_stop_word)
return stop_word
⑤word2vecで学習
Word2Vecとは、文章に含まれるワードを「数値ベクトル」に変換し、その意味を把握していくという自然言語処理の手法です。
Word2Vecのモデルによって、ワード間の意味的な距離を定量的に表したり、単語同士で意味の足し算や引き算ができたりします。
sentence = [tokenize(cont)]
model = word2vec.Word2Vec(sentence, size=200, min_count=4, window=4, iter=50)
⑥類似度を計算する
most_similarによって、入力したワード(下のコードでは'経験')に対して意味的に近いワード、およびどれほど近いかを数値で出力してくれます。
topn=10で、1位~10位までを出力してくれます。
print(model.wv.most_similar(positive=[u"経験"], topn=10))
手順①〜⑥までをまとめると
作成したプログラム
from janome.tokenizer import Tokenizer
from gensim.models import word2vec
import re
import requests
text = open("書類のパス","r")
cont = text.read()
text.close()
cont = re.sub("[a-xA-Z0-9_]","",cont)
cont = re.sub("[!-/:-@[-`{-~]","",cont)
cont = re.sub(u'\n\n', '\n', cont)
cont = re.sub(u'\r', '', cont)
def tokenize(cont):
t = Tokenizer()
tokens = t.tokenize(cont)
word = []
stop_word = create_stop_word()
for token in tokens:
part_of_speech = token.part_of_speech.split(",")[0]
print(part_of_speech)
if part_of_speech == "名詞":
print('名詞:', token.surface)
if not token.surface in stop_word:
word.append(token.surface)
if part_of_speech == "動詞":
if not token.base_form in stop_word:
word.append(token.base_form)
if part_of_speech == "形容詞":
if not token.base_form in stop_word:
word.append(token.base_form)
if part_of_speech == "形容動詞":
if not token.base_form in stop_word:
word.append(token.base_form)
return word
def create_stop_word():
target_url = "http://svn.sourceforge.jp/svnroot/slothlib/CSharp/Version1/SlothLib/NLP/Filter/StopWord/word/Japanese.txt"
r =requests.get(target_url)
stop_word=str(r).split()
my_stop_word=['もの', 'なる', 'する', 'れる', 'こと', 'できる', 'いる', 'これ']
stop_word.extend(my_stop_word)
return stop_word
sentence = [tokenize(cont)]
model = word2vec.Word2Vec(sentence, size=200, min_count=4, window=4, iter=50)
print(model.wv.most_similar(positive=[u"経験"], topn=10))
プログラム実行の結果
西田幾多郎の実行結果
西田の『善の研究』第1章(1911年)において、「経験」に近い言葉上位10単語を示します。
1位:'純粋', 0.8694230318069458
2位:'主客', 0.8483998775482178
3位:'判断', 0.8320882320404053
4位:'現前', 0.8295841217041016
5位:'直接', 0.8282835483551025
6位:'事実', 0.8262712955474854
7位:'範囲', 0.8198851346969604
8位:'入れる', 0.801323652267456
9位:'別', 0.7928428649902344
10位:'超越', 0.7881696224212646
第1位の'純粋'は「純粋経験」という単語が分かれて抽出されていますので、モデルの調整が必要ですね。第2位以降を見ると、直接の事実、まさに現前するものという特徴が見られそうです。
戸坂潤の実行結果
戸坂の「哲学の現代的意義」(1966年)において、「経験」に近い言葉上位10単語を示します。
1位:'過去', 0.9673113822937012
2位:'人々', 0.9379932880401611
3位:'形態', 0.9264334440231323
4位:'ロゴス', 0.9061765670776367
5位:'かくれる', 0.8870216012001038
6位:'知能', 0.8865772485733032
7位:'趣味', 0.8761657476425171
8位:'彼', 0.8757074475288391
9位:'従う', 0.8677871227264404
10位:'意識', 0.858801007270813
「ロゴス」「知能」「意識」などからは、経験と知識や論理的思考との結びつきという特徴が見られます。
三木清の実行結果
三木の『人生論ノート』(1954年)において、「経験」に近い言葉上位10単語を示します。
1位:'新しい', 0.8461295366287231
2位:'浪漫', 0.7994835376739502
3位:'新た', 0.7598129510879517
4位:'漂泊', 0.7372455596923828
5位:'既知', 0.7275353670120239
6位:'機械', 0.7264443635940552
7位:'習慣', 0.7163444757461548
8位:'近い', 0.7129574418067932
9位:'あわただしい', 0.7056584358215332
10位:'感', 0.7038125395774841
「新しい」「新た」や「浪漫」「機械」など、経験に無関係そうなワードが抽出されています。そもそも、意味的な距離を示す数値が第1位でも0.846と低いので、特徴を捉えるには他の手法も取り入れる必要がありそうです。