Python NLTKを使用した自然言語処理入門(日本語処理への応用と注意点)
自然言語処理(NLP)は、人間が日常的に使用する言語(自然言語)をコンピューターに理解させ、処理させるための技術分野です。Pythonの代表的なNLPライブラリであるNLTK (Natural Language Toolkit) は、研究や教育の現場で広く利用されており、豊富な機能と使いやすさが特徴です。この記事では、基本的な自然言語処理の方法として、環境準備からデータの前処理、品詞のタグ付け、固有表現抽出、構文解析といった具体的な処理、日本語への対応方法と注意点を解説します。
- 1. NLTKの概要とインストール方法
- 2. テキストの前処理
- 3. 品詞タグ付け
- 4. 固有表現抽出 (Named Entity Recognition)
- 5. 構文解析 (Parsing)
- 6. 日本語の自然言語処理
- 7. よくあるエラーとその対処法
- まとめ
1. NLTKの概要とインストール方法
NLTKは、Pythonで自然言語処理を行うためのライブラリです。トークン化、品詞タグ付け、固有表現抽出、構文解析など、様々な機能を提供しています。
インストール
ターミナルまたはコマンドプロンプトで以下のコマンドを実行します。
pip install nltk
必要なリソースのダウンロード
NLTKの一部の機能を使用するには、追加のデータやモデルをダウンロードする必要があります。Pythonのインタラクティブシェルを開き、以下のコードを実行します。
import nltk nltk.download('punkt') # トークン化に必要なデータ nltk.download('averaged_perceptron_tagger') # 品詞タグ付けに必要なデータ nltk.download('wordnet') # WordNet(英語の辞書) nltk.download('omw-1.4') # Open Multilingual Wordnet (多言語WordNet) nltk.download('maxent_ne_chunker') # 固有表現抽出に必要なデータ nltk.download('words') # 固有表現抽出に必要なデータ
2. テキストの前処理
自然言語処理では、生のテキストデータをそのまま扱うのではなく、前処理を行うことが一般的です。
2.1 トークン化
トークン化とは、テキストを単語や文などの単位(トークン)に分割する処理です。
単語トークン化の例
import nltk from nltk.tokenize import word_tokenize text = "This is a sample sentence. This is another sentence." tokens = word_tokenize(text) print(tokens)
出力
['This', 'is', 'a', 'sample', 'sentence', '.', 'This', 'is', 'another', 'sentence', '.']
word_tokenize関数は、与えられたテキストを単語と句読点に分割します。
文トークン化の例
文のトークン化にはsent_tokenize 関数を使います。
from nltk.tokenize import sent_tokenize text = "This is a sample sentence. This is another sentence." sentences = sent_tokenize(text) print(sentences)
出力
['This is a sample sentence.', 'This is another sentence.']
sent_tokenize関数は、与えられたテキストを文に分割します。
2.2 ステミング
ステミングとは、単語の語尾変化(例:running, runs, ran)を共通の語幹(run)に変換する処理です。これにより、異なる活用形の単語を同じ単語として扱うことができます。
from nltk.stem import PorterStemmer stemmer = PorterStemmer() word = "running" stemmed_word = stemmer.stem(word) print(stemmed_word) # 出力: run
PorterStemmerは、NLTKで最も一般的に使用されるステミングアルゴリズムです。
2.3 見出し語化(Lemmatization)
見出し語化は、単語を辞書の見出し語(基本形)に変換する処理です。ステミングよりも正確な変換が可能ですが、処理速度は遅くなる傾向があります。
from nltk.stem import WordNetLemmatizer lemmatizer = WordNetLemmatizer() word = "better" lemmatized_word = lemmatizer.lemmatize(word, pos='a') # 品詞(形容詞)を指定 print(lemmatized_word) # 出力: good
WordNetLemmatizerを使用する際には、pos引数で品詞を指定することが重要です。品詞を指定しないと、正しい見出し語が得られない場合があります。上記の例ではpos='a'で形容詞を指定しています。
3. 品詞タグ付け
品詞タグ付けは、文中の各単語に対して、名詞、動詞、形容詞などの品詞情報を付与する処理です。
import nltk from nltk.tokenize import word_tokenize text = "This is a sample sentence." tokens = word_tokenize(text) tagged_tokens = nltk.pos_tag(tokens) print(tagged_tokens)
出力
[('This', 'DT'), ('is', 'VBZ'), ('a', 'DT'), ('sample', 'JJ'), ('sentence', 'NN'), ('.', '.')]
pos_tag関数は、トークンのリストを受け取り、各トークンとその品詞タグのタプルを返します。品詞タグの意味は、以下の表を参照してください。
| タグ | 意味 | 例 |
|---|---|---|
| DT | Determiner(限定詞) | the, a, an |
| VBZ | Verb, 3rd person singular present(三人称単数現在形) | is, runs, sings |
| JJ | Adjective(形容詞) | big, small, red |
| NN | Noun, singular(単数名詞) | cat, dog, house |
| . | 句読点 | . , ? ! |
4. 固有表現抽出 (Named Entity Recognition)
固有表現抽出は、テキスト中から人名、組織名、地名、日付、時間、金額などの固有表現を抽出する処理です。
import nltk from nltk.tokenize import word_tokenize text = "Barack Obama was born in Hawaii." tokens = word_tokenize(text) tagged_tokens = nltk.pos_tag(tokens) entities = nltk.chunk.ne_chunk(tagged_tokens) print(entities)
出力:
(S (PERSON Barack/NNP) (PERSON Obama/NNP) was/VBD born/VBN in/IN (GPE Hawaii/NNP) ./.)
ne_chunk関数は、品詞タグ付きのトークンリストを受け取り、固有表現を認識してツリー構造で返します。 上記の例では、"Barack Obama" が人名 (PERSON)、"Hawaii" が地名 (GPE) として認識されています。
5. 構文解析 (Parsing)
構文解析は、文の構造を解析し、単語間の関係を明らかにする処理です。NLTKでは、Stanford Parserなどの外部パーサーと連携して構文解析を行うことができます。
Stanford Parserのセットアップ (少し複雑なので、必要に応じて後回しにしても構いません)
- Stanford Parserのダウンロード: Stanford NLPのウェブサイトからStanford Parserをダウンロードします。
- Javaのインストール: Stanford ParserはJavaで動作するため、Java Development Kit (JDK) がインストールされている必要があります。
- 環境変数の設定:
Pythonコード例
import os from nltk.parse.stanford import StanfordParser # Stanford Parserのパスを設定(環境に合わせて変更してください) stanford_parser_dir = '/path/to/stanford-parser/' # Stanford Parserを解凍したディレクトリ stanford_parser_jar = os.path.join(stanford_parser_dir, 'stanford-parser.jar') stanford_models_jar = os.path.join(stanford_parser_dir, 'stanford-parser-*-models.jar') # -* 部分はバージョンによって変わります # Stanford Parserの初期化 parser = StanfordParser(path_to_jar=stanford_parser_jar, path_to_models_jar=stanford_models_jar) # 構文解析の実行 sentence = "The quick brown fox jumps over the lazy dog." result = parser.raw_parse(sentence) # 結果の表示(ツリー構造) for tree in result: print(tree)
出力例
(ROOT
(S
(NP (DT The) (JJ quick) (JJ brown) (NN fox))
(VP (VBZ jumps)
(PP (IN over)
(NP (DT the) (JJ lazy) (NN dog))))
(. .)))
この出力は、文の構文構造を木構造で表しています。S (文)、NP (名詞句)、VP (動詞句)、PP (前置詞句) などの構文要素が示されています。
6. 日本語の自然言語処理
NLTKで日本語を扱う際の注意点と他のツールとの連携
NLTKは主に英語の処理を対象としており、日本語のテキストを直接処理する機能は限定的です。特に、日本語のトークン化(形態素解析)には、MeCabやJuman++といった専用のツールが必要になります。日本語処理には、向いていないと言えますが、先述のツールの組み合わせ等により、使うことはできますので少し解説したいと思おいます。より高度な日本語処理を行う場合は、spaCy、SudachiPy、GiNZAなどの日本語に対応、特化した別のライブラリの使用を検討してください。
6.1 なぜNLTKは日本語処理に直接向かないのか
- 単語分割の仕組みの違い: 英語はスペースで単語が区切られますが、日本語は単語間にスペースがありません。NLTKの
word_tokenizeは、この違いに対応していません。 - 日本語の文法的特性: 日本語は膠着語(単語に接辞が付いて文法的役割を示す言語)であり、語尾変化が複雑です。NLTKのステミングや見出し語化は、英語の語尾変化には対応していますが、日本語には対応していません。
6.2 日本語の形態素解析 (MeCabの利用)
日本語のテキストを処理するためには、まず形態素解析器を使ってテキストを単語に分割し、各単語に品詞などの情報を付与する必要があります。ここでは、広く利用されているMeCabを例に紹介します。
MeCabのインストール (例)
pip install mecab-python3
mecab-ipadic-NEologd(辞書) も必要に応じてインストールしてください。
import MeCab text = "これは日本語の文章です。" tagger = MeCab.Tagger() # -Owakati: 分かち書き出力 print(tagger.parse(text)) #詳細な形態素解析 tagger = MeCab.Tagger() print(tagger.parse(text))
出力(分かち書き):
これ は 日本語 の 文章 です 。
出力(詳細):
これ 名詞,代名詞,一般,*,*,*,これ,コレ,コレ は 助詞,係助詞,*,*,*,*,は,ハ,ワ 日本 名詞,固有名詞,地域,国,*,*,日本,ニホン,ニホン 語 名詞,接尾,一般,*,*,*,語,ゴ,ゴ の 助詞,連体化,*,*,*,*,の,ノ,ノ 文章 名詞,一般,*,*,*,*,文章,ブンショウ,ブンショー です 助動詞,*,*,*,特殊・デス,基本形,です,デス,デス 。 記号,句点,*,*,*,*,。,。,。 EOS
6.3 NLTKとMeCabの連携 (形態素解析後の処理)
MeCabなどで形態素解析を行った結果を、NLTKで活用することができます。以下に、いくつかの例を示します。
頻度分析: MeCabでトークン化した単語リストをNLTKの
FreqDistクラスに渡し、単語の出現頻度を分析します。import MeCab import nltk from nltk import FreqDist text = "これは日本語の文章です。この文章はサンプルです。" tagger = MeCab.Tagger("-Owakati") # 分かち書き wakati_text = tagger.parse(text) tokens = wakati_text.split() # スペースで分割 fdist = FreqDist(tokens) print(fdist.most_common(3)) # 出現頻度上位3件共起ネットワーク: NLTKの
collocationsモジュールを使って、単語の共起関係(一緒に現れやすい単語のペア)を分析します。(ただし、collocationsは英語向けに設計されているため、日本語での利用には注意が必要です)WordCloudの作成 MeCab などで分かち書きにした結果を WordCloud で可視化できます。 ```python from wordcloud import WordCloud import matplotlib.pyplot as plt
# MeCabで分かち書きされたテキスト wakati_text = "これ は 日本語 の 文章 です 。"
# WordCloudオブジェクトの作成 wordcloud = WordCloud(font_path='/path/to/your/font.ttf').generate(wakati_text) # 日本語フォントのパスを指定
# WordCloudの表示 plt.imshow(wordcloud, interpolation='bilinear') plt.axis("off") plt.show()
```
7. よくあるエラーとその対処法
LookupError: Resource [リソース名] not found.
このエラーは、必要なNLTKのリソース(データやモデル)がダウンロードされていない場合に発生します。エラーメッセージに表示されたリソース名を指定して、
nltk.download()を実行してください。例:
LookupError: Resource punkt not found.解決策:nltk.download('punkt')を実行Stanford Parser のエラー Java のバージョンが古い場合、パスが通っていない場合などにエラーが発生することがあります。 Java のバージョンを確認し、パスを再設定してください。
まとめ
この記事では、PythonのNLTKライブラリを使用した基本的な自然言語処理の方法と、日本語処理における注意点、MeCabとの連携について解説しました。NLTKは、自然言語処理の入門として、また、英語のテキスト処理には非常に便利なツールです。一方日本語処理においては、対応していない機能もあるため、他のツールとの連携・置き換えを意識しながら活用していくことが重要です。
Pythonによる自然言語処理の学習コンテンツを紹介します。
[PR]