正規表現・自然言語処理
研究室の勉強会で正規表現と自然言語処理について話したのでそれのまとめ.
正規表現
クロールしたWebページのテキストから時間に関する部分だけを抽出したい,
といった時に機械的にパターンに当てはまる部分を抽出するための表現.
メタ文字
- .:任意の一文字
- [~]:括弧内の任意の一文字
- [^~]:括弧内の~以外の任意の一文字
- ?:0or1回
- *:0回以上
- +:1回以上
- |:or
- (~):グループ化
- {1, 3}:1回以上3回以下
- ?を付けるとなるべく少なくなるように取得
文字クラス
- \s:空白文字
- \w:[a-zA-Z0-9_]
- \d:[0-9]
- \b:スペース
ちなみに漢字は文字コードの連続から以下のように表すことが可能.もちろん漢字はこれだけではない.
- [一-龠] ... [一丁丂…龟龠](u’\u4e00’〜u’\u9fa0’)
正規表現における注意点
or を表す | は処理が遅い.
- (a|b|c|d|e|f)
- (?:a|b|c|d|e|f)
- [a-f]
という3つだと2.は1.の3倍,3.は1.の20倍の速度が出る,らしい.
2.は1.からキャプチャ機能を省いたもの.
re
pythonでreモジュールを用いる.
In [1]: import re In [2]: text = (u'pythonとはlightweightな,' u'programming言語である').encode('utf-8') In [3]: pattern = '\w+' In [4]: regex = re.compile(pattern) In [5]: match = regex.finditer(text) In [6]: for m in match: ...: print m.group() ...: python lightweight programming In [7]: matches = regex.findall(text) In [8]: print matches ['python', 'lightweight', 'programming'] In [9]: pattern = r"(\w+)\W*(\w+)\W*(\w+)" In [10]: regex = re.compile(pattern) In [11]: match = regex.search(text) In [12]: print match.group(0) pythonとはlightweightな,programming In [13]: print match.group(1) python In [14]: print match.group(2) lightweight In [15]: print match.group(3) programming In [16]: p2 = "(?P<one>\w+)\W*(?P<two>\w+)” In [17]: print match2.group('two') lightweight
最後のp2のように?P
この程度知っておけば簡単な正規表現は使えるはず.
自然言語処理
自然言語(しぜんげんご、英: Natural language)とは、人間によって日常の意思疎通のために用いられる、文化的背景を持って自然に発展してきた記号体系である。大別すると音声による話し言葉と文字や記号として書かれる書き言葉がある。
となっている.
この自然言語を機械的に処理するためには
といったプロセスがある.
形態素解析
形態素解析とは語の品詞を特定することである.
例えば,
という文章は
すもも:名詞, も:助詞, もも:名詞, も:助詞, もも:名詞, の:助詞, うち:名詞
と分析することが出来る.
形態素解析器にはMeCabや茶筅,JUMANなどがある.
MeCabをpythonで使うには以下のようにする.
In [1]: import MeCab In [2]: tagger = MeCab.Tagger() In [3]: text = u'すもももももももものうち'.encode('utf-8') In [4]: node = tagger.parseToNode(text) In [5]: while node.next: ...: node = node.next ...: print node.feature, node.surface, node.posid ...: 名詞,一般,*,*,*,*,すもも,スモモ,スモモ すもも 38 助詞,係助詞,*,*,*,*,も,モ,モ も 16 名詞,一般,*,*,*,*,もも,モモ,モモ もも 38 助詞,係助詞,*,*,*,*,も,モ,モ も 16 名詞,一般,*,*,*,*,もも,モモ,モモ もも 38 助詞,連体化,*,*,*,*,の,ノ,ノ の 24 名詞,非自立,副詞可能,*,*,*,うち,ウチ,ウチ うち 66 BOS/EOS,*,*,*,*,*,*,*,* 0
- node.surface:文字列
- node.feature:文字列の品詞
- node.posid:文字列の品詞ID
品詞IDについては品詞IDの定義を参照.
語の正規化
英単語の大文字・小文字の変換を行う.
In [1]: print 'Python'.lower() python In [2]: print 'PYTHON'.lower() python In [3]: print 'python'.capitalize() Python In [4]: print 'python'.upper() PYTHON
ステミング処理
語の語幹を取り出す処理のこと.
複数形と単数形や派生語を同じものとして扱うために行う.
database, databases ⇒ databas initial, initialize, initialization ⇒ initi
pythonで行うには以下のように.
In [1]: import nltk In [2]: stemmer = nltk.PorterStemmer() In [3]: print stemmer.stem(’database') databas In [4]: print stemmer.stem(’databases') databas In [5]: print stemmer.stem('initial') initi In [6]: print stemmer.stem('initialization') initi In [7]: print stemmer.stem('Pythonic') Python
nltk.PorterStemmer()の他にはnltk.LancasterStemmer()などもある.
語の見出し語化
与えられた語の、辞書における見出し語を求める.
レンマ化,とも言われる.
women ⇒ woman databases ⇒ database
pythonで使うには以下のように.
In [1]: import nltk In [2]: lemmatizer = nltk.WordNetLemmatizer() In [3]: lemmatizer.lemmatize('women') Out[3]: 'woman' In [4]: lemmatizer.lemmatize('corpora') Out[4]: 'corpus'
見出し語化は処理が重い...
WordNet
英語の概念辞書(意味辞書)である.
英単語をSynsetと呼ばれる同義語のグループに分類し,簡単な定義や他のグループとの関係等が記述してある.
ざっくり言えば,語のDB.圧縮後で12M程度.
人力で用意されているので精度が良い.
名詞について以下のようなものが用意されている.
- 上位語(hypernym): すべてのXがYの種類の一であるならYはXの上位語である。
- 下位語(hyponym): すべてのYがXの種類の一であるならYはXの下位語である。
- 同族語(coordinate term): XとYの上位語が同じなら、YはXの同族語である。
- holonym: XがYの一部であるなら、YはXのholonymである。
- meronym: YがXの一部であるなら、YはXのmeronymである。
動詞や形容詞にも同様に同義語が設定されている.
pythonでは以下のように.
In [1]: from nltk.corpus import wordnet In [2]: print wordnet.synsets('dog') [Synset('dog.n.01'), Synset('frump.n.01'), Synset('dog.n.03'), Synset('cad.n.01'), Synset('frank.n.02'), Synset('pawl.n.01'), Synset('andiron.n.01'), Synset('chase.v.01')] In [3]: dog = wordnet.synset('dog.n.01') In [4]: dog.definition Out[4]: 'a member of the genus Canis (probably descended from the common wolf) that has been domesticated by man since prehistoric times; occurs in many breeds’ In [5]: dog.examples Out[5]: ['the dog barked all night'] In [6]: dog.lemma_names Out[6]: ['dog', 'domestic_dog', 'Canis_familiaris'] In [7]: dog.pos Out[7]: 'n’ In [8]: print wordnet.lemmas('dog') [Lemma('dog.n.01.dog'), Lemma('frump.n.01.dog'), Lemma('dog.n.03.dog'), Lemma('cad.n.01.dog'), Lemma('frank.n.02.dog'), Lemma('pawl.n.01.dog'), Lemma('andiron.n.01.dog'), Lemma('chase.v.01.dog')]
少し説明すると,
wordnet.synsets(word):wordの同義語集合を返す wordnet.synset(~):上で得たうちのものを引数に渡して1つのsynsetについての情報を得る .definition:~の定義 .examples:~の例文 .pos:~の品詞 .lemma_names:~の同義語集合に属している見出し語 wordnet.lemmas(word):wordの同義語集合全てを返す.
これらは基本的なもので,上位語・下位語などは以下のように.
In [1]: from nltk.corpus import wordnet as wn In [2]: pc = wn.synset('personal_computer.n.01') In [3]: pc.definition Out[3]: 'a small digital computer based on a microprocessor and designed to be used by one person at a time' In [4]: pc.hypernyms() Out[4]: [Synset('digital_computer.n.01')] In [5]: pc.hyponyms() Out[5]: [Synset('desktop_computer.n.01'), Synset('portable_computer.n.01')] In [6]: desktop = wn.synset('desktop_computer.n.01') In [7]: desktop.hyponyms() Out[7]: [] In [8]: desktop.hypernyms() Out[8]: [Synset('personal_computer.n.01')] In [9]: desktop.path_similarity(pc) Out[9]: 0.5
- hypernyms():上位語
- hyponyms():下位語
- path_similarity():共通の上位階層経由のパスの長さに基づく同義語集合間の類似度
となっている.
注意点としては,WordNetのデータは人力で設定されているため,あらゆる語を網羅しているわけではないため
抜けがある,ということである.
補足
nltk(natural language tool kit)のcorpusなどを使うには
nltk.download()
を実行しましょう.