Edited at

素人の言語処理100本ノック:52

More than 1 year has passed since last update.

言語処理100本ノック 2015の挑戦記録です。環境はUbuntu 16.04 LTS + Python 3.5.2 :: Anaconda 4.1.1 (64-bit)です。過去のノックの一覧はこちらからどうぞ。


第6章: 英語テキストの処理


英語のテキスト(nlp.txt)に対して,以下の処理を実行せよ.



52. ステミング


51の出力を入力として受け取り,Porterのステミングアルゴリズムを適用し,単語と語幹をタブ区切り形式で出力せよ. Pythonでは,Porterのステミングアルゴリズムの実装としてstemmingモジュールを利用するとよい.



出来上がったコード:


main.py

# coding: utf-8

import re
import snowballstemmer

fname = 'nlp.txt'

def nlp_lines():
'''nlp.txtを1文ずつ読み込むジェネレータ
nlp.txtを順次読み込んで1文ずつ返す

戻り値:
1文の文字列
'''
with open(fname) as lines:

# 文切り出しの正規表現コンパイル
pattern = re.compile(r'''
(
^ # 行頭
.*? # 任意のn文字、最少マッチ
[\.|\;|\:|\?|\!] # . or ; or : or ? or !
)
\s # 空白文字
(
[A-Z].* # 英大文字以降(=次の文以降)

)
''', re.MULTILINE + re.VERBOSE + re.DOTALL)

for line in lines:

line = line.strip() # 前後の空白文字除去
while len(line) > 0:

# 行から1文を取得
match = pattern.match(line)
if match:

# 切り出した文を返す
yield match.group(1) # 先頭の文
line = match.group(2) # 次の文以降

else:

# 区切りがないので、最後までが1文
yield line
line = ''

def nlp_words():
'''nlp.txtを1単語ずつ返すジェネレータ
文の終わりでは空文字を返す。

戻り値:
1単語、ただし文の終わりでは空文字を返す
'''
for line in nlp_lines():

# 単語に分解、終端の区切り文字は除去して返す
for word in line.split(' '):
yield word.rstrip('.,;:?!')

# 文の終わりは空文字
yield ''

# 読み込み
stemmer = snowballstemmer.stemmer('english')
for word in nlp_words():

# 元の結果とステミング結果を出力
print('{}\t{}'.format(word, stemmer.stemWord(word)))



実行結果:

長いので先頭部分の抜粋です。


端末:先頭部分

Natural Natur

language languag
processing process

From From
Wikipedia Wikipedia
the the
free free
encyclopedia encyclopedia

Natural Natur
language languag
processing process
(NLP) (NLP)
is is
a a
field field
of of
computer comput
science scienc
artificial artifici
intelligence intellig
and and
linguistics linguist
concerned concern
with with
the the
interactions interact
between between
computers comput
and and
human human
(natural) (natural)
languages languag

As As
such such
NLP NLP
is is
related relat
to to
the the
area area
of of
humani-computer humani-comput
interaction interact

Many Mani
challenges challeng
in in
NLP NLP
involve involv
natural natur
language languag
understanding understand
that that
is is
enabling enabl
computers comput
to to
derive deriv
meaning mean
from from
human human
or or
natural natur
language languag
input input
and and
others other
involve involv
natural natur
language languag
generation generat


全体の結果はGitHubにアップしています。


ステミングライブラリのインストール

問題で紹介されているstemmingモジュールは、Python3.5には対応していないらしいので、別のものを探す必要があります。そこで、まずはcondaを「stem」というキーワードで探してみました。


端末:condaで検索

segavvy@ubuntu:~$ conda search stem

Fetching package metadata .......
snowballstemmer 1.2.0 py26_0 defaults
1.2.0 py27_0 defaults
1.2.0 py33_0 defaults
1.2.0 py34_0 defaults
1.2.0 py35_0 defaults
1.2.1 py27_0 defaults
1.2.1 py34_0 defaults
* 1.2.1 py35_0 defaults
system 5.8 0 defaults
5.8 1 defaults
5.8 2 defaults

お、*が付いているので、すでに「snowballstemmer」というのが入っていますね。Anacondaで入ったようです。説明を見ると16種類のステミングアルゴリズムがセットになっていて、英語はPorterのアルゴリズムのようです。これなら問題文の条件も満たしますので、これでいきましょう。


語幹とステミング

語幹とは、語尾が変化する単語の、変化しない前方部分を指すそうです。そして、単語から語幹を抽出する処理がステミングです。今回使っているPorterのアルゴリズは、経験則により語幹を抽出する仕組みとのことでした。詳細はググってみてください。

なお、今回のコードはほぼ前問のままで、最後に語幹の抽出を加えただけです。snowballstemmerの使い方は、オフィシャルサイトのHow to use libraryを見るとわかります。シンプルでいいですね。

 

53本目のノックは以上です。誤りなどありましたら、ご指摘いただけますと幸いです。


実行結果には、100本ノックで用いるコーパス・データで配布されているデータの一部が含まれます。この第6章で用いているデータのライセンスはクリエイティブ・コモンズ 表示-継承 3.0 非移植日本語訳)です。