2016-07-09

NLTKのFreqDistオブジェクトのkeys()メソッドで頻出単語がソートされない

オライリーの入門自然言語処理のP.19で文章の中からもっとも頻出する50の単語を取り出すコードが記載されているけど、なぜかうまくソートされない。

調べてみるとNLTK3では頻出順にソートされなくなったようで、同じことをしたければmost_common()メソッドを使わなければならない。


    fdist1 = FreqDist(text1)
    vocaburary1 = fdist1.keys()
    print vocabulary1[:50]

オライリーのサンプルコードは上のようになっているけど、これだと頻出単語順にソートされていない。

mosot_common()を使って以下のように変更する。


    fdist1 = FreqDist(text1)
    print fdist1.most_common(50)

するとうまく頻出単語順にソートされて表示される。


[(u',', 18713), (u'the', 13721), (u'.', 6862), (u'of', 6536), (u'and', 6024), (u'a', 4569), (u'to', 4542), (u';', 4072), (u'in', 3916), (u'that', 2982), (u"'", 2684), (u'-', 2552), (u'his', 2459), (u'it', 2209), (u'I', 2124), (u's', 1739), (u'is', 1695), (u'he', 1661), (u'with', 1659), (u'was', 1632), (u'as', 1620), (u'"', 1478), (u'all', 1462), (u'for', 1414), (u'this', 1280), (u'!', 1269), (u'at', 1231), (u'by', 1137), (u'but', 1113), (u'not', 1103), (u'--', 1070), (u'him', 1058), (u'from', 1052), (u'be', 1030), (u'on', 1005), (u'so', 918), (u'whale', 906), (u'one', 889), (u'you', 841), (u'had', 767), (u'have', 760), (u'there', 715), (u'But', 705), (u'or', 697), (u'were', 680), (u'now', 646), (u'which', 640), (u'?', 637), (u'me', 627), (u'like', 624)]

NLTKは3になってから結構いろいろ変更があるみたいなのでその都度調べながらやらないといけないようです。

2016-07-07

Pythonでエラー:UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-3: ordinal not in range(128)が出るときの対処法

最近、またコツコツと自然言語処理の勉強をしています。

PythonでNLTKを使っているといろんなところでこのエラーが出ますよね。

UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-3: ordinal not in range(128)

その度に、encode('utf-8')を使ってみたりunicode()を使ってみたりでその場しのぎをしてきましたけど、今回はどうしてもうまくいかなかった。

そこでオライリーの入門自然言語処理を読んでみるとばっちし対処法が書いてあった。


import codecs, sys

sys.stdout = codecs.getwriter('utf_8')(sys.stdout)
sys.stdin = codecs.getreader('utf_8')(sys.stdin)

最初にこれを追加してやると嘘のようにうまくいきました。

NLTKでいろいろやってて文字コードのエラーで困っている人はぜひ試してみて下さい。

入門 自然言語処理

オライリーの本はクオリティに差があるけどいい本は本当にいい。

nltkのnltk.clean_html()を使うと「NotImplementedError: To remove HTML markup, use BeautifulSoup's get_text() function」というエラーが出る場合の対処法

久しぶりにNLTKを使ってライバルサイトの調査をしようとしたら、nltk.clean()の行で以下のエラーが出た。

NotImplementedError: To remove HTML markup, use BeautifulSoup's get_text() function

調べてみるとNLTKのバージョン3以上からはnltk.clean_html()とnltk.clean_url()が使えなくなったらしい。

その代わりにBeautifulSoupのget_text()を使えということらしい。

ただ、BeautifulSoupのget_text()はJavaScriptのタグが除去できません。

だからJavaScriptのコードを除去するコードを自分で追加しないといけません。

探してみるとありました。

自分で以下のclean_htmlという関数を追加しました。

参考:Python nltk.clean_html not implemented - Stack Overflow


def clean_html(html):
    """
    Copied from NLTK package.
    Remove HTML markup from the given string.

    :param html: the HTML string to be cleaned
    :type html: str
    :rtype: str
    """

    # First we remove inline JavaScript/CSS:
    cleaned = re.sub(r"(?is)<(script|style).*?>.*?()", "", html.strip())
    # Then we remove html comments. This has to be done before removing regular
    # tags since comments can contain '>' characters.
    cleaned = re.sub(r"(?s)[\n]?", "", cleaned)
    # Next we can remove the remaining tags:
    cleaned = re.sub(r"(?s)<.*?>", " ", cleaned)
    # Finally, we deal with whitespace
    cleaned = re.sub(r" ", " ", cleaned)
    cleaned = re.sub(r"  ", " ", cleaned)
    cleaned = re.sub(r"  ", " ", cleaned)
return cleaned.strip()

参考にさせていただいたサイトのコメントの部分を見るとどうやら以前のclean_html関数の部分をそのまま持ってきたようですね。

もっと複雑なことをしてるのかと思ったけど、ほんの数行で処理していることにびっくり。

それにしてもめんどくさい。なんで無くなったんだろう。