自然言語処理というか、文書を特徴ベクトルに変換するまでの tips などを書いていきます
してる→unicode型に変換しましょう
# 例:EUC-JPの場合
text = text.decode('euc-jp')
してない→文字コードを自動判別しましょう。
日本語の文書であることがはっきりしている場合、nkf、pykf などが便利です。
nkf for python: http://city.plala.jp/moin/NkfPython
pykf: http://memo.jj-net.jp/jjnet_sandbox/pykf/pykf-0.3.4.tgz(有志によるミラー)
SourceForge? にも pykf のソースはありますが、そっちはファイルが足りないらしくコンパイルが通りませんでした。
日本語以外の文書が含まれてる場合、chardet が便利です。
chardet: http://chardet.feedparser.org/
ただし、chardet も完璧ではないので try and error で変換を一つ一つ試した方がいい場合もあります。
Python で文字列操作(置換、切り出しなど)をする場合、必ず unicode 型に変換してから行うようにしましょう。扱ってる変数が unicode 型か str 型かはっきりしないときは
print type(text)
で確認することができます。
string.replace() で文字の置換が可能です。
text = text.replace('\r\n','\n')
text = text.replace('\r','\n')
# さらに改行コードを除去する場合
text = text.replace('\n','')
Mac と Macなどのような半角文字と全角文字はそれぞれ別物として扱われます. 人間から見た場合は同じ意味の単語なので,できるだけ一つの表記に統一させた方がいいです.
normalize 関数は半角カナ→全角カナ、全角英数→半角英数へと正規化します。
import unicodedata
text = u'MacMac123123アア'
text = unicodedata.normalize('NFKC', text)
print text
zenhan.py の使い方について: http://straitmouth.jp/blog/setomits/139
最新版(2009/11/7時点): http://straitmouth.jp/blog/setomits/877
数字だけ半角にする、など unicodedata に比べて細かい指定が可能です。
extractcontent という本文抽出モジュールを使うのがお手軽です。
単純な方法としては、re モジュールを使って
import re
htmltag = re.compile(r'<.*?>', re.I | re.S)
text = htmltag.sub('', html)
こんな感じで取り除くことができます。
スクレイピングをしたい場合は Beautiful Soup などの HTML パーサーを使うと便利です。
http://www.crummy.com/software/BeautifulSoup/
HTML特殊文字とは、< などの文字のことです。
私は下記のページの htmlentity2unicode() を使わせていただいてます。
http://www.programming-magic.com/20080820002254/
# などの記号は MeCab? では「名詞、サ変接続」などと判別されてしまうので形態素解析にかける前に 取り除いておいた方がいいと思います。
日本語→MeCab?
http://mecab.sourceforge.net/
Python 用のラッパーも一緒に配布されてます。
英語、フランス語、ドイツ語など→TreeTagger?
http://www.ims.uni-stuttgart.de/projekte/corplex/TreeTagger/
Python 用のラッパーは以下から。
http://www.limsi.fr/Individu/pointal/python/treetaggerwrapper-doc/
確認しようとしたところソース本体は403…。(09/11/7)
文書の言語判定を行いましょう
guess-language: http://pypi.python.org/pypi/guess-language/
UTF-8のみの対応っぽい
ngram.py と Lingua::LanguageGuesser? の言語モデルを組み合わせる
ngram.py: http://thomas.mangin.me.uk/
ページ右側の検索窓で ngram.py で検索するとダウンロードリンクを見つけることができます。
もしくは
http://thomas.mangin.me.uk/data/source/ngram.py
から直接。
Lingua::LanguageGuesser?
http://gensen.dl.itc.u-tokyo.ac.jp/LanguageGuesser/hajimete_monogatari.html
この二つのモジュールは TextCat? という Perl で書かれた言語判定スクリプトの
という関係性があります。
ngram.py を動かすには言語モデル(言語ごとのプロファイル)を記録したファイルが必要です。配布元では TextCat? の言語モデルを使用するように、とされてますがこれに Lingua::LanguageGuesser? の言語モデルを使用することで UTF-8 へ対応できるようにします。
HTMLの場合,HTMLタグがついたままだと精度が著しく落ちます.
そのため,HTMLタグを除去する必要があるのですが str 型のままだと文字列操作できないので
文字コード判定 → Unicode に変換 → HTMLタグ除去 → UTF-8 にエンコード → 言語判定
という手順になると思います.
HEADタグ中の文字コードや言語コードなどのメタ情報を利用するのも一つの手段です
(というか,先にそっちをやるべき)
デフォルト (ipadicなど) だけだと上手く単語が切り出せない場合は他の辞書を併用するなり自分で単語を追加するなりしましょう.
単語の追加や辞書作成についてはこちらで.
http://mecab.sourceforge.net/dic.html
文書における特徴ベクトルは,多くの場合文書中の単語を要素,重みとして出現頻度やTF-IDFによって表現されます.
「文書における特徴ベクトルの要素は文書中の単語です」という文を実際に特徴ベクトルに変換してみます.
% mecab 文書における特徴ベクトルの要素は文書中の単語です 文書 名詞,一般,*,*,*,*,文書,ブンショ,ブンショ における 助詞,格助詞,連語,*,*,*,における,ニオケル,ニオケル 特徴 名詞,一般,*,*,*,*,特徴,トクチョウ,トクチョー ベクトル 名詞,固有名詞,一般,*,*,*,*,はてなキーワード の 助詞,連体化,*,*,*,*,の,ノ,ノ 要素 名詞,一般,*,*,*,*,要素,ヨウソ,ヨーソ は 助詞,係助詞,*,*,*,*,は,ハ,ワ 文書 名詞,一般,*,*,*,*,文書,ブンショ,ブンショ 中 名詞,接尾,副詞可能,*,*,*,中,チュウ,チュー の 助詞,連体化,*,*,*,*,の,ノ,ノ 単語 名詞,一般,*,*,*,*,単語,タンゴ,タンゴ です 助動詞,*,*,*,特殊・デス,基本形,です,デス,デス
mecab の結果から,文中に出てきた単語と出現頻度を得ることができます.
| 単語 | 出現頻度 |
| 文書 | 2 |
| における | 1 |
| 特徴 | 1 |
| ベクトル | 1 |
| の | 2 |
| 要素 | 1 |
| は | 1 |
| 中 | 1 |
| 単語 | 1 |
| です | 1 |
この表が「文書における特徴ベクトルの要素は文書中の単語です」という文の特徴ベクトルです.
Python で実装してみるとこんな感じです.
#!/usr/bin/env python
# -*- coding:utf-8 -*-
"""
feature_vector.py
指定されたファイル中の文章を解析して
単語とその出現頻度を返す
使い方(コマンドラインから)
% python feature_vector.py file
使い方 2(Pythonスクリプト中で)
import feature_vector
text = '単語とその出現頻度を返す'
result = feature_vector.analyse(text)
"""
import MeCab
def analyse(text):
mecab = MeCab.Tagger() ## MeCab のインスタンス作成
feature_vector = {} ## 結果を納める辞書
node = mecab.parseToNode(text) ## 解析を実行
while node:
print node.surface, node.feature ## それぞれ単語とその情報(品詞など)
surface = node.surface.decode('utf-8')
feature_vector[surface] = feature_vector.get(surface, 0) + 1 # 辞書に単語を追加
node = node.next
return feature_vector
if __name__ == '__main__':
import sys
filename = sys.argv[1]
file = open(filename).read()
feature_vector = analyse(file)
for word,freq in feature_vector.items():
print "%s\t%d" % (word,freq)
実行結果
yono@orca% cat test.txt
文書における特徴ベクトルの要素は文書中の単語です
yono@orca% python feature_vector.py test.txt
BOS/EOS,*,*,*,*,*,*,*,*
文書 名詞,一般,*,*,*,*,文書,モンショ,モンショ
における 助詞,格助詞,連語,*,*,*,における,ニオケル,ニオケル特徴 名詞,一般,*,*,*,*,特徴,トクチョウ,トクチョー
ベクトル 名詞,一般,*,*,*,*,ベクトル,ベクトル,ベクトル
の 助詞,連体化,*,*,*,*,の,ノ,ノ
要素 名詞,一般,*,*,*,*,要素,ヨウソ,ヨーソ
は 助詞,係助詞,*,*,*,*,は,ハ,ワ
文書 名詞,一般,*,*,*,*,文書,モンショ,モンショ
中 名詞,接尾,副詞可能,*,*,*,中,ナカ,ナカ
の 助詞,連体化,*,*,*,*,の,ノ,ノ
単語 名詞,一般,*,*,*,*,単語,タンゴ,タンゴ
です 助動詞,*,*,*,特殊・デス,基本形,です,デス,デス
BOS/EOS,*,*,*,*,*,*,*,*
2
要素 1
ベクトル 1
中 1
は 1
の 2
単語 1
です 1
文書 2
特徴 1
における 1
同じものを github にも置いておきますので,参考程度に.
http://gist.github.com/231879
MeCab? と MeCab? 用の Python ラッパーをインストールしておく必要があります.
(テキストの文字コードをUTF-8に決め打ちしたりなど適当な点があるので,実際に使う際には適宜書き換えてください)
MeCab? だと「労働者」という単語が「労働」「者」と分かれてしまいます.
yono@orca% mecab 労働者 労働 名詞,サ変接続,*,*,*,*,労働,ロウドウ,ロードー 者 名詞,接尾,一般,*,*,*,者,モノ,モノ EOS
「可能性」も同様に「可能」「性」と分かれます.
可能性 可能 名詞,形容動詞語幹,*,*,*,*,可能,カノウ,カノー 性 名詞,接尾,一般,*,*,*,性,セイ,セイ EOS
「第二次」という単語は「第」「二」「次」と分かれます.
第二次 第 接頭詞,数接続,*,*,*,*,第,ダイ,ダイ 二 名詞,数,*,*,*,*,二,ニ,ニ 次 名詞,接尾,助数詞,*,*,*,次,ジ,ジ EOS
これらはいずれも接頭語,接尾語が分解されるからです.
場合によりけりですが,労働者や可能性などは一つの単語として用いた方が都合がいいと思われます.
そこで,これらを一つの単語として扱うためのスクリプトを書いたので github に置いておきました.(ただし,正常に動作しないと思われます.時間があったら後で修正します.)追記: 修正しました.上記の例に関しては全て連結されるようになりました.
http://gist.github.com/271862
上記のスクリプトは
というルールに基づいてます. ただし,このルールだけだと適切でない接続も多く発生すると思われます.