NLTKでIOBタグ付けと頻出単語描画とストップワード除去とシノニムを探す
色々試しました。
Tokenize ~ Pos tagging ~ chunking ~ IOB tagging
import nltk sent = """iPhone is a line of smartphones designed and marketed by Apple Inc. The iPhone line of products use Apple's iOS mobile operating system software. The first-generation iPhone was released on June 29, 2007, and multiple new hardware iterations with new iOS releases have been released since."""
まず、Tokenizeはこう
tokens= nltk.word_tokenize(sent)
print(tokens)
実行結果
['iPhone', 'is', 'a', 'line', 'of', 'smartphones', 'designed', 'and', 'marketed', 'by', 'Apple', 'Inc', '.', 'The', 'iPhone', 'line', 'of', 'products', 'use', 'Apple', "'s", 'iOS', 'mobile', 'operating', 'system', 'software', '.', 'The', 'first-generation', 'iPhone', 'was', 'released', 'on', 'June', '29', ',', '2007', ',', 'and', 'multiple', 'new', 'hardware', 'iterations', 'with', 'new', 'iOS', 'releases', 'have', 'been', 'released', 'since', '.']
単語で分けるだけですね。英語なのでわかりやすくて良い。
次は品詞タグ付けです。
pos_tags = nltk.pos_tag(tokens)
print(pos_tags)
実行結果
[('iPhone', 'NN'), ('is', 'VBZ'), ('a', 'DT'), ('line', 'NN'), ('of', 'IN'), ('smartphones', 'NNS'), ('designed', 'VBN'), ('and', 'CC'), ('marketed', 'VBN'), ('by', 'IN'), ('Apple', 'NNP'), ('Inc', 'NNP'), ('.', '.'), ('The', 'DT'), ('iPhone', 'JJ'), ('line', 'NN'), ('of', 'IN'), ('products', 'NNS'), ('use', 'VBP'), ('Apple', 'NNP'), ("'s", 'POS'), ('iOS', 'NN'), ('mobile', 'NN'), ('operating', 'VBG'), ('system', 'NN'), ('software', 'NN'), ('.', '.'), ('The', 'DT'), ('first-generation', 'NN'), ('iPhone', 'NN'), ('was', 'VBD'), ('released', 'VBN'), ('on', 'IN'), ('June', 'NNP'), ('29', 'CD'), (',', ','), ('2007', 'CD'), (',', ','), ('and', 'CC'), ('multiple', 'JJ'), ('new', 'JJ'), ('hardware', 'NN'), ('iterations', 'NNS'), ('with', 'IN'), ('new', 'JJ'), ('iOS', 'NN'), ('releases', 'NNS'), ('have', 'VBP'), ('been', 'VBN'), ('released', 'VBN'), ('since', 'IN'), ('.', '.')]
はい。
そしてチャンキング
tree = nltk.ne_chunk(pos_tags)
print(tree)
実行結果
(S (GPE iPhone/NN) is/VBZ a/DT line/NN of/IN smartphones/NNS designed/VBN and/CC marketed/VBN by/IN (PERSON Apple/NNP Inc/NNP) ./. The/DT ・ ・ ・
ちょっとこれよくわからず。。
なんだろ。treeって描画用?
まあ、気にせずIOBタグ付けはこう
iob = nltk.tree2conlltags(tree)
print(iob)
実行結果
[('iPhone', 'NN', 'B-GPE'), ('is', 'VBZ', 'O'), ('a', 'DT', 'O'), ('line', 'NN', 'O'), ('of', 'IN', 'O'), ('smartphones', 'NNS', 'O'), ('designed', 'VBN', 'O'), ('and', 'CC', 'O'), ('marketed', 'VBN', 'O'), ('by', 'IN', 'O'), ('Apple', 'NNP', 'B-PERSON'), ('Inc', 'NNP', 'I-PERSON'), ('.', '.', 'O'), ('The', 'DT', 'O'), ('iPhone', 'JJ', 'B-ORGANIZATION'), ('line', 'NN', 'O'), ('of', 'IN', 'O'), ('products', 'NNS', 'O'), ('use', 'VBP', 'O'), ('Apple', 'NNP', 'B-PERSON'), ("'s", 'POS', 'O'), ('iOS', 'NN', 'B-ORGANIZATION'), ('mobile', 'NN', 'O'), ('operating', 'VBG', 'O'), ('system', 'NN', 'O'), ('software', 'NN', 'O'), ('.', '.', 'O'), ('The', 'DT', 'O'), ('first-generation', 'NN', 'O'), ('iPhone', 'NN', 'B-ORGANIZATION'), ('was', 'VBD', 'O'), ('released', 'VBN', 'O'), ('on', 'IN', 'O'), ('June', 'NNP', 'O'), ('29', 'CD', 'O'), (',', ',', 'O'), ('2007', 'CD', 'O'), (',', ',', 'O'), ('and', 'CC', 'O'), ('multiple', 'JJ', 'O'), ('new', 'JJ', 'O'), ('hardware', 'NN', 'O'), ('iterations', 'NNS', 'O'), ('with', 'IN', 'O'), ('new', 'JJ', 'O'), ('iOS', 'NN', 'B-ORGANIZATION'), ('releases', 'NNS', 'O'), ('have', 'VBP', 'O'), ('been', 'VBN', 'O'), ('released', 'VBN', 'O'), ('since', 'IN', 'O'), ('.', '.', 'O')]
めっちゃ簡単やんけ〜
英語ずるくない?
チャンキングとIOBタグ付けこれだけでできるのってすごくないですか?
日本語だったら品詞タグ付けまではMeCabでやって、チャンキングとかIOBタグ付け、、、どうすんの?目視?
頻出単語描画
他にも便利な関数がたくさんあったのでついでに試します。
文章は引き続き同じものを使います。
FreqDist
という関数を使うと計算できるっぽい。
freq = nltk.FreqDist(tokens)
print(freq.items())
実行結果
dict_items([('first-generation', 1), ('software', 1), ('June', 1), ('have', 1), ('been', 1), ('and', 2), ('is', 1), ('mobile', 1), ("'s", 1), ('new', 2), ('iPhone', 3), ('The', 2), ('.', 3), ('Apple', 2), ('released', 2), ('multiple', 1), ('marketed', 1), (',', 2), ('operating', 1), ('2007', 1), ('use', 1), ('29', 1), ('designed', 1), ('system', 1), ('iOS', 2), ('a', 1), ('line', 2), ('iterations', 1), ('was', 1), ('Inc', 1), ('on', 1), ('of', 2), ('products', 1), ('releases', 1), ('since', 1), ('hardware', 1), ('smartphones', 1), ('by', 1), ('with', 1)])
数字部分は各単語の登場回数です。
これをグラフで描画することができます。
freq.plot(20, cumulative=False)
実行結果
便利〜、何かに使えそう〜
ストップワードでクリーニング
上のグラフを見ると真ん中ぐらいに「of」があります。
こういう文章によく登場するけどあんま意味ない、みたいなやつは除去してあげる必要があります。
nltkには各言語のストップワードが用意されています。
from nltk.corpus import stopwords stopwords = stopwords.words('english') print(len(stopwords)) print(stopwords)
実行結果
179 ['i', 'me', 'my', 'myself', 'we', 'our', 'ours', 'ourselves', 'you', "you're", "you've", "you'll", "you'd", 'your', 'yours', 'yourself', 'yourselves', 'he', 'him', 'his', 'himself', 'she', "she's", 'her', 'hers', 'herself', 'it', "it's", 'its', 'itself', 'they', 'them', 'their', 'theirs', 'themselves', 'what', 'which', 'who', 'whom', 'this', 'that', "that'll", 'these', 'those', 'am', 'is', 'are', 'was', 'were', 'be', 'been', 'being', 'have', 'has', 'had', 'having', 'do', 'does', 'did', 'doing', 'a', 'an', 'the', 'and', 'but', 'if', 'or', 'because', 'as', 'until', 'while', 'of', 'at', 'by', 'for', 'with', 'about', 'against', 'between', 'into', 'through', 'during', 'before', 'after', 'above', 'below', 'to', 'from', 'up', 'down', 'in', 'out', 'on', 'off', 'over', 'under', 'again', 'further', 'then', 'once', 'here', 'there', 'when', 'where', 'why', 'how', 'all', 'any', 'both', 'each', 'few', 'more', 'most', 'other', 'some', 'such', 'no', 'nor', 'not', 'only', 'own', 'same', 'so', 'than', 'too', 'very', 's', 't', 'can', 'will', 'just', 'don', "don't", 'should', "should've", 'now', 'd', 'll', 'm', 'o', 're', 've', 'y', 'ain', 'aren', "aren't", 'couldn', "couldn't", 'didn', "didn't", 'doesn', "doesn't", 'hadn', "hadn't", 'hasn', "hasn't", 'haven', "haven't", 'isn', "isn't", 'ma', 'mightn', "mightn't", 'mustn', "mustn't", 'needn', "needn't", 'shan', "shan't", 'shouldn', "shouldn't", 'wasn', "wasn't", 'weren', "weren't", 'won', "won't", 'wouldn', "wouldn't"]
そして、これらを元の文章から取り除き、もう一度頻出単語をチェックしてみます。
clean_tokens = tokens[:] for token in tokens: if token in stopwords: clean_tokens.remove(token) clean_freq = nltk.FreqDist(clean_tokens) clean_freq.plot(20, cumulative=False)
真ん中ぐらいにあった「of」が無くなってますね。
シノニムを探す
シノニム(類義語)も辞書が用意されているらしい。
from nltk.corpus import wordnet syn = wordnet.synsets('Japan') print(syn[0].definition()) print(syn[0].examples())
実行結果
a string of more than 3,000 islands to the east of Asia extending 1,300 miles between the Sea of Japan and the western Pacific Ocean []
wordnet.synsets('Japan')
でシノニムを探す単語を指定します。
そして、syn[0].definition()
とするとwordnet
に登録されている定義を取得できます。
上ではJapanの定義を取得してますが、島3,000もないでしょ、おかしくね?って思ってググったら、
めっちゃあるやん、島
で、シノニムはこう
for syn in wordnet.synsets('Japan'): for lemma in syn.lemmas(): print(lemma.name())
実行結果
Japan Japanese_Islands Japanese_Archipelago Japan Nippon Nihon japan japan japan
ちゃんと「Nihon」とかもあるのがいいすね。
参考
参考はこの辺です。
Natural Language Toolkit — NLTK 3.2.5 documentation
便利機能系はこちらです。
他にも対義語を探すこと等もできるみたいです。