毎日テキストマイニング

180日間、毎日テキストマイニングをするブログです

2018/7/17【25日目】Pythonでn-gramを実装していく

今日は自然言語処理のテキストに良く出てくるn-gramについて実装していきたいと思います。

n-gramとは

大学受験の時に、『英単語ピーナッツほど美味しいものはない』という単語帳がありましたが、「形容詞+名詞」や「動詞+名詞」をひたすらノートに書いていくというものでした。まさにあれがn-gramというものらしいです。

例をあげると「know」と「how」だけですと、「知る」と「どのように」という意味ですが、「know how」になると「やり方」になるように、2つ以上の単語で置き換えができない組み合わせをコロケーションというらしいです。

n-gramはこれらのコロケーションを見つけるために、2文字ずつ(バイグラム)、3文字ずつ(スリーグラム)、4文字ずつ(フォーグラム)といったぐらいに言葉を集めることだそうです。

物は試しにとりあえず実装していきます。

実装

とりあえず、ライブラリでpython-ngramというのがあり、一番簡単そうなので、まずはこれを使ってみます。

github.com

tweet = "SHOWROOM「こみの部屋」ありがとうございました〜??チームKについてたくさんお話できたかな!舞台、プロレスと今年も一緒に夏を過ごしそうです??? https://t.co/qxc047jzLg"

import ngram
index = ngram.NGram(N=2)

for two_gram in index.ngrams(index.pad(tweet)):
    print(two_gram)

実行結果

$S
SH
HO
OW
WR
RO
OO
OM
M「
「こ
こみ
みの
の部
(省略)

それぽいのができました。ただ、これだとKnow howというようなコロケーションは一生作れなさそうですね。 できれば単語ごとに分けていきたいような気がします。

ちょっと調べてみましたが、いいライブラリがなさそうなので自分で実装してみます。 まずは単語にばらして配列に代入。

import MeCab

tagger = MeCab.Tagger ("")

kaisekiyou = tweet.split('¥n')
string = ' '.join(kaisekiyou)
mecab = tagger.parse(string)
kaigyou = mecab.splitlines()

word = []

for tango_list in kaigyou:
    tab = tango_list.split('\t')
    words = tab[0]
    word.append(words)
print(word)

実行結果。

['SHOWROOM', '「', 'こみの部屋', '」', 'ありがとう', 'ござい', 'まし', 'た', '〜', '??', 'チームK', 'について', 'たくさん', 'お話', 'でき', 'た', 'か', 'な', '!', '舞台', '、', 'プロレス', 'と', '今年', 'も', '一緒', 'に', '夏', 'を', '過ごし', 'そう', 'です', '???', 'https', '://', 't', '.', 'co', '/', 'qxc', '047', 'jzLg', 'EOS']

とりあえず単語ごとに配列に代入しました。 これを1個ずつスライドして新しい配列にすれば良さそうです。 配列に2つずつ追加するには、数字でfor文を回して、2つずつappedすれば良さそうです。

bigram_list = []
for i in range(len(word)-1):
    bigram_list.append((word[i], word[i+1]))

実行結果

[('SHOWROOM', '「'), ('「', 'こみの部屋'), ('こみの部屋', '」'), ('」', 'ありがとう'), ('ありがとう', 'ござい'), ('ござい', 'まし'), ('まし', 'た'), ('た', '〜'), ('〜', '??'), ('??', 'チームK'), ('チームK', 'について'), ('について', 'たくさん'), ('たくさん', 'お話'), ('お話', 'でき'), ('でき', 'た'), ('た', 'か'), ('か', 'な'), ('な', '!'), ('!', '舞台'), ('舞台', '、'), ('、', 'プロレス'), ('プロレス', 'と'), ('と', '今年'), ('今年', 'も'), ('も', '一緒'), ('一緒', 'に'), ('に', '夏'), ('夏', 'を'), ('を', '過ごし'), ('過ごし', 'そう'), ('そう', 'です'), ('です', '???'), ('???', 'https'), ('https', '://'), ('://', 't'), ('t', '.'), ('.', 'co'), ('co', '/'), ('/', 'qxc'), ('qxc', '047'), ('047', 'jzLg'), ('jzLg', 'EOS')]

お、良さそうにできています。 明日はこれを使って何か分析ぽいことをしたいと思います。

ちなみに3グラムの時はこんな感じですね。

three_list = []
for i in range(len(word)-2):
    three_list.append((word[i], word[i+1], word[i+2]))

今日の結果

本日のAKBメンバーによる呟きは45件でした。 久しぶりに画像を作ってみます。

f:id:rimt:20180718220440p:plain

{'あおい': 13, '楽しい': 11, '嬉しい': 8, '暑い': 5, 'すごい': 3, '可愛い': 2, '優しい': 2, '凄い': 2, '面白い': 2, '少ない': 1, '黒い': 1, 'ない': 1, 'すっごい': 1, '暖かい': 1, 'うれしい': 1, 'たのしい': 1, '大きい': 1})

'公演': 27, '今日': 17, 'さん': 16, 'あおい': 13, '楽しい': 11, '嬉しい': 8, '暑い': 5, '笑': 5, '皆さん': 5, 'ん': 5, 'みんな': 4, '出演': 4, '福岡': 4, '日': 4, '私': 4, 'みなさん': 4, 'たくさん': 4, 'ちゃん': 4,

'公演': 27, 'する': 27, '今日': 17, 'さん': 16, 'あおい': 13, '楽しい': 11, '嬉しい': 8, 'なる': 6, '暑い': 5, '笑': 5, '皆さん': 5, 'ん': 5, 'せる': 5, '頑張る': 5, 'くださる': 5, 'ゆう': 5,

こんな感じでした。

今日勉強したこと