about MeCab (3) 品詞IDの指定

品詞を品詞名で出力するのではなく、品詞IDを指定してそれを出力することが出来る
http://mecab.sourceforge.net/posid.html

定義した品詞IDは出力時に%hを指定することで参照される

% mecab -F"%m\t%h\n" -E"EOS\n"

品詞IDの定義

pos-id.defを編集する。
形式

マッチパターン  ID

マッチパターンの記述

*: すべての文字列にマッチ
(AB|CD|EF): AB もしくは CD もしくは EF にマッチ
AB: 文字列 AB のみに完全マッチ

pos-id を変更したら, 辞書をリコンパイルする必要があります.

/usr/local/libexec/mecab/mecab-dict-index

定義例

単純な例

名詞 1
動詞 2
形容詞 3
副詞 4
助詞 5
接続詞 6
助動詞 7
連体詞 8
感動詞 9
* 10
ちょっと複雑な例

名詞 1
(助詞|助動詞) 2
(副詞|形容詞|連体詞) 3

* 4

もっと複雑な例

その他,間投,*,* 0
フィラー,*,*,* 1
感動詞,*,*,* 2
記号,アルファベット,*,* 3
記号,一般,*,* 4
記号,括弧開,*,* 5
記号,括弧閉,*,* 6
記号,句点,*,* 7
記号,空白,*,* 8
記号,読点,*,* 9
形容詞,自立,*,* 10
形容詞,接尾,*,* 11
形容詞,非自立,*,* 12
助詞,格助詞,一般,* 13
助詞,格助詞,引用,* 14
助詞,格助詞,連語,* 15
助詞,係助詞,*,* 16
助詞,終助詞,*,* 17
助詞,接続助詞,*,* 18
助詞,特殊,*,* 19

定義例をもっと

about Mecab (2) 出力フォーマットの定義とその指定方法

ユーザによる出力フォーマットの定義とその指定方法

http://mecab.sourceforge.net/format.html

node
一つの形態素を出力,デフォルトは空文字
unk
一つの未知語形態素を出力、デフォルトはnodeと同一フォーマット
bos
形態素解析の結果に先立って出力、デフォルトは空文字
eos
形態素解析の結果のあとに出力,デフォルトは"EOS\n"

これらをもとに指定する。パラメータ詳細は後述。

指定方法

on commandline

mecab --node-format=STR --bos-format=STR --eos-format --unk-format=STR

mecabrcファイルに記述する方法
任意の文字列KEYを使って以下のように定義

node-format-KEY = STR
unk-format-KEY = STR
eos-format-KEY = STR
bos-format-KEY = STR

コマンドラインから呼び出すには

mecab -Okey 

on python

import MeCab
m = MeCab.Tagger("Okey")
出力フォーマットのパラメータ
%s 形態素の種類(0:通常、1:未知語, 2:文頭、 3:文末)
%S 入力文
%L 入力文の長さ
%m 形態素の表層文字列
%M 形態素の空白文字を含む表層文字列
%h 素性の内部ID
%% %そのもの
%c 単語生起コスト
%H 素性(品詞、活用、読み)などをCSVで表現したもの
%t 文字種id
%P 周辺確率
%pi 形態素に付与されるユニークなID
%pS 形態素が空白文字列で始まる場合,その空白文字列を表示 %pS%mと%Mは同一
%ps 開始位置
%pe 集良一
%pC 一つ前の形態素との連接コスト
%pw %cと同じ
%pc 連接コスト+単語生起コスト (文頭から累積)
%pn 連接コスト+単語生起コスト(その形態素単独 = %pw+%pC)
%pb 最適パスの場合*, それ以外は''
%pP 周辺確率
%pA blpha, forward log確率
%pB beta, backward log確率
%pl 形態素の表層文字としての長さ, strlen(%m)と同じ
%pL 空白文字列を含む形態素の表層文字列としての長さ,strlen(%M)と同じ
%phl 左文脈id
%phr 右文脈id
%f[N] csvで表記された素性のN番目の要素
%f[N1, N2, N3,...] N1, N2, N3番目の素性を","をデリミタとして表示
%Fc[N1, N2, N3,...] N1, N2, N3番目の素性を"C"をデリミタとして表示 ただし、要素が空の場合は以降表示が省略 ex) %F-[N1, N2]
\s ' '半角スペース

# ChaSen
node-format-chasen = %m\t%f[7]\t%f[6]\t%F-[0,1,2,3]\t%f[4]\t %f]5],\n
#; 表層文字列 f[7] f[6] F[0]-F[1]-F[2]-F[3] f[4]f[5]
unk-format-chasen = %m\t%m\t%F-[0,1,2,3]\t\t\n
eos-format-chasen = EOS\n
# 表層文字列 表層文字列F[0]-F[1]-F[2]-F[3]

f[n] ?csvファイルはどれだろう?

MeCab説明書きの写経 (1)

さて、取得したテキストの解析にあたって、MeCab/CaboChaで実際にどういうことが出来るのかしらということで、MeCabとCaboChaの説明書きを写経 & まとめてみた

まずはMeCabから。

MeCabオープンソース形態素解析エンジン.パラメータの推定に Conditional Random Fields (CRF) を用いている、とか。CRF++を用いて、辞書スコアなどの学習ができる?とかなんとかはこれから読む。
形態素解析

形態素解析とは、自然言語で書かれた文を形態素(Morpheme, おおまかにいえば、言語で意味を持つ最小単位)の列に分割し、それぞれの品詞を判別する作業を指す。

wikipedia 形態素解析

形態素解析に手を出してみた

第一歩目は,twitterから取得したテキストをMeCabを使って形態素に分割すること。

import twitter
import MeCab

id = 'xxxxx'
pass = 'xxxxx'

api = twitter.Api(id, pass)
posts = api.GetFriendsTimeline(count=200)

mecabによりテキストを形態素に分解し,その結果をparseddataのタプルに保存する

entry = posts[0].text.encode('utf-8')

m = MeCab.Tagger("Ochasen")
parsed = m.parseToNode(entry)

parseddata = []
while parsed.next:
    if len(n.surface)>0:
        parseddata.append((parsed.surface.decode("utf-8"), (parsed.feature.decode("utf-8").rsplit(',')), parsed.cost))
    parsed = parsed.next

結果

BOS/EOS,*,*,*,*,*,*,*,* 0

テレ朝 名詞 固有名詞 組織 * * * テレ朝 テレアサ テレアサ 4144
野球 名詞 一般 * * * * 野球 ヤキュウ ヤキュー 1990
ニュース 名詞 一般 * * * * ニュース ニュース ニュース 5521
始まっ 動詞 自立 * * 五段・ラ行 連用タ接続 始まる ハジマッ ハジマッ 12662
助動詞 * * * 特殊・タ 基本形 11722

タプルの第一要素が分割した表層文字列、第二要素が解析結果…ここはそれぞれが何か良くまだわかってない&表示方法は「m = MeCab.Tagger("Ochasen")」で指定かな,ってことでマニュアル読む。第三要素が、その要素の「コスト」となっております。とりあえず、解析ができることはわかった。

あとで

def getLDRWeatherHacks():
    url = 'http://weather.livedoor.com/forecast/webservice/rest/v1'

    parameters['day']  = 'today'
    parameters['city'] = '01'
    postdata = urllib.urlencode(parameters)

    weatherxml = urllib.urlopen(url, postdata).read()

    tree = etree.fromstring(weatherxml)
    wtokens['forecastday'] = [tree.xpath('//forecastday')[0].text]
    wtokens['day']         = [tree.xpath('//day')[0].text]
    wtokens['telop']       = [tree.xpath('//telop')[0].text]
    wtokens['temperature'] = [tree.xpath('//temperature/max/celsius')[0].text, tree.xpath('//temperature/min/celsius')[0].text]
    wtokens['area']        = [tree.xpath('//location@area')[0]]
    wtokens['pref']        = [tree.xpath('//location@pref')[0]]
    wtokens['city']        = [tree.xpath('//location@city')[0]]
    wtokens['title']       = [tree.xpath('//title')[0].text]

    return wtokens

def getLDRWHdict():
    pdict[u'道北'] = {
    'areacode':'1a',
    'citylist':{
    u'稚内':'1',
    u'旭川':'2',
    u'留萌':'3',
    },
    }

    #  ### pref
    pdict[u'道央'] = {
    'areacode':'1b',
    'citylist':{
    u'札幌':'4',
    u'岩見沢':'5',
    u'倶知安':'6',
    },
    }

    #  ### pref
    pdict[u'道東'] = {
    'areacode':'1c',
    'citylist':{
    u'網走':'7',
    u'北見':'8',
    u'紋別':'9',
    u'根室':'10',
    u'釧路':'11',
    u'帯広':'12',
    },
    }

    #  ### pref
    pdict[u'道南'] = {
    'areacode':'1d',
    'citylist':{
    u'室蘭':'13',
    u'浦河':'14',
    u'函館':'15',
    u'江差':'16',
    },
    }

    return pdict


def getforecastpoint(entry):
    weatherdict = getLDRWHdict()
    forecastpoint = {'cityindx':[], 'cityname':[], 'areaname':[], 'areacode':[]}


    for area in weatherdict.keys():
        for city in weatherdict[area]['citylist'].keys():
            if entry.find(city) != -1:
##                forecastpoint['cityindx'] = weatherdict[area]['citylist'][city]
##                forecastpoint['cityname'] = city
##                forecastpoint['areaname'] = area
##                forecastpoint['areacode'] = weatherdict[area]['areacode']
                forecastpoint['cityindx'].append(weatherdict[area]['citylist'][city])
                forecastpoint['cityname'].append(city)
                forecastpoint['areaname'].append(area)
                forecastpoint['areacode'].append(weatherdict[area]['areacode'])

    return forecastpoint

def getforecastday(entry):
    daydict['today']=[u'今日', u'きょう']

    day = 'today'
    indx = [entry.find(x) for x in daydict[day] if entry.find(x) != -1]
    if len(indx):
          daycandidate.append(day)