🗂

プログラマーが自然言語処理に入門してみる

2023/03/31に公開

こんにちは。最近ChatGPTがすごい話題ですね。言わずもがな、私も課金してお世話になっています。そんな私ですが、色々触っているうちにその裏側の仕組みや理論に興味を持ってきました。この記事では、普段Webエンジニアをやっている私が自然言語処理について簡単に入門してみた、触ってみたメモを書いていこうと思います。
自分の理解のために書いたメモなので、正確性は保証できません・・・もし理解が間違っているところがあればコメントいただけると助かります。

はじめに

自然言語処理(Natural Language Processing, NLP)とは、人工知能の分野の一つで、人間が日常的に使用する自然言語(例えば日本語や英語)をコンピュータに処理させる技術のことです。自然言語処理の技術は幅広い分野で使われており、例えば音声認識や自動翻訳、文章データを解析することによるトレンド分析などにも使われています。また、法律の文書を解析するという取り組みも行われています。

自然言語処理の具体的な手法

自然言語処理と一言で言っても、幅広い分野が存在します。その中から3つの手法を紹介します。

形態素解析

形態素解析とは、文章を単語に分割し、各単語の品詞や活用形などの情報を付与する処理のことです。例えば、ある文章を分析したいと思ったとします。その時に、私たちがまずやるべきことは、その文章を単語の単位に分けることです。例えば、英語の文章

I live in Tokyo.

があるとしましょう。この文章を単語に分けようとすると、どうすれば良いでしょうか。これは簡単で、スペースで区切れば良いです。

I / live / in / Tokyo.

それでは、日本語だとどうでしょうか。

私は東京都に住んでいます。

この文章を単語に分けようとすると、案外難しいことに気づきます。もちろんスペースでは分けられないですし、コンピューターに認識させるとしてもどのようにルールを定めるのかは自明ではなさそうです。

このような日本語の文章の単語分割をコンピューターに行わせる時の最も基本的なアプローチが形態素解析です。実際にPythonのjanomeというライブラリを用いて形態素解析をしてみましょう。実行環境はGoogle Colaboratoryを用いています。

!pip install janome
from janome.tokenizer import Tokenizer
t = Tokenizer()
text = '私は東京都に住んでいます。'

for token in t.tokenize(text):
  print(token)

実行結果

私	名詞,代名詞,一般,*,*,*,私,ワタシ,ワタシ
は	助詞,係助詞,*,*,*,*,は,ハ,ワ
東京	名詞,固有名詞,地域,一般,*,*,東京,トウキョウ,トーキョー
都	名詞,接尾,地域,*,*,*,都,ト,ト
に	助詞,格助詞,一般,*,*,*,に,ニ,ニ
住ん	動詞,自立,*,*,五段・マ行,連用タ接続,住む,スン,スン
で	助詞,接続助詞,*,*,*,*,で,デ,デ
い	動詞,非自立,*,*,一段,連用形,いる,イ,イ
ます	助動詞,*,*,*,特殊・マス,基本形,ます,マス,マス
。	記号,句点,*,*,*,*,。,。,。

形態素解析のアルゴリズムも色々考えだされているようですが、これはまたそのうち深掘りしたいと思います。

Word2vec

Word2vecは、単語をベクトルによって表現して自然言語を解析しようという手法の一つです。Word2vecでは単語を低次元のベクトル空間にマッピングします。(例えば、辞書の単語一つ一つをベクトルの要素とするのが一番ナイーブなベクトルによる単語の表現ですが、それをより低次元で表現します。)Word2vecは単語の意味を踏まえたベクトル表現になっています。例えばある単語に似た単語たちを列挙することができます。
以下はWord2vecの計算する、「健康」という単語に似た単語たちです。

# コードの例
similar_words = model.most_similar('健康')
for words in similar_words:
  print(str(words[0]) + " " + str(words[1]))
生活習慣病 0.820671021938324
食生活 0.8077179789543152
生活習慣 0.8046577572822571
妊産婦 0.795288622379303
QOL 0.7952781915664673
クオリティ・オブ・ライフ 0.7945042848587036
生活の質 0.7869585752487183
予防 0.7868747115135193
福祉 0.7815116047859192
公衆衛生 0.7773566246032715

二列目の数字は、健康という単語との類似度を示しています。

また、有名な例として、単語の引き算ができます。
「王様」-「男」+「女」=「女王」
というような計算ができるようです。こちらを実際にやってみた結果をお見せします。

# コード例
model.most_similar(negative=['王様', '男'], positive=['女'])
[('一宮市立図書館', 0.18184061348438263),
 ('浜松市立図書館', 0.17823383212089539),
 ('公共図書館', 0.17287039756774902),
 ('大垣市立図書館', 0.16877682507038116),
 ('粒子線', 0.16735519468784332),
 ('大津市民病院', 0.16306260228157043),
 ('滋賀県立図書館', 0.16110964119434357),
 ('川崎市立図書館', 0.16020454466342926),
 ('京都府立図書館', 0.15899613499641418),
 ('県立長野図書館', 0.15710137784481049)]

あれ、全然うまくいかないですね・・・王様は男だという偏見は通じない世の中になったのかもしれません。
学習しているモデルの関係もありそうです。

まとめ

今回は本当に簡単に自然言語処理の入門的な技術に触れてみました。やはり実際に動かして触ってみると面白いです。
次回はもう少し中身に踏み込みつつ、自然言語処理の広い世界に触れられたらなと思っています。

Discussion