今回はストップワードかどうかを判定するコードを書きました。さらに、実際どのような単語が多く出現しているのかも見てみました。
言語処理100本ノック #071
71. ストップワード
英語のストップワードのリスト(ストップリスト)を適当に作成せよ.さらに,引数に与えられた単語(文字列)がストップリストに含まれている場合は真,それ以外は偽を返す関数を実装せよ.さらに,その関数に対するテストを記述せよ.
単語の数が多いほど時間がかかるので、今回なら肯定的な文にも否定的な文にも共通して現れるような単語は除いたほうが効率的に分析ができる。このように省く単語を「ストップワード」という。
準備
適当に作成するのもなんかアレかなと思って、既存のやつを利用することにした。 参考 👉 NLTK’s list of english stopwords · GitHub
NLTK (Natural Language Toolkit) をインストール
$ pip install nltk ... Successfully installed nltk-3.4.5
ストップワードを使うためには、最初だけダウンロードする必要がある。
>>> import nltk >>> nltk.download('stopwords') [nltk_data] Downloading package stopwords to /Users/🕶/nltk_data... [nltk_data] Unzipping corpora/stopwords.zip. True
あとはインポートして、english を指定。
>>> from nltk.corpus import stopwords >>> stopwords.words(‘english’) [‘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”]
ストップワードのリストが手に入った。
解答
# knock_071.py import sys import nltk # nltk.download('stopwords') from nltk.corpus import stopwords def stop_evaluator(word): if word in stopwords.words('english'): return True else: return False def show_stopwords(): print(stopwords.words('english')) if __name__ == '__main__': if len(sys.argv) < 2: show_stopwords() else: for w in sys.argv[1:]: print(w, '->', stop_evaluator(w))
テスト出力
$ python knock_071.py hello , my name is piijey hello -> False , -> False my -> True name -> False is -> True piijey -> False
頻出単語を調べる
rt-polarity.pos と rt-polarity.neg それぞれにある単語の頻度50位までと、総合頻度50位までの頻度分布を作った。
コード
zip(*c.most_common(50))
の *
は、行列の転置。
頻度を調べるのに Python の Collections Counter を使った。参考 👉 PythonのCounterでリストの各要素の出現個数をカウント | note.nkmk.me
# knock_071_2.py import codecs import collections import matplotlib.pyplot as plt POSFILE = './rt-polaritydata/rt-polaritydata/rt-polarity.pos' NEGFILE = './rt-polaritydata/rt-polaritydata/rt-polarity.neg' FIG1 = './knock_071_2_posneg.png' def word_list(file): with codecs.open(file, 'r', 'utf-8', 'ignore') as fr: out_list = [] for line in fr: for word in line[:-1].split(' '): out_list.append(word) return out_list def count_freq(wlist): c = collections.Counter(wlist) values, counts = zip(*c.most_common(50)) return values, counts def plot_bar(values, counts, title): plt.bar(values, counts) plt.xticks(rotation=70, fontsize=8) plt.yticks(fontsize=8) plt.title(title) def plot_commons(file1, file2): plt.figure(figsize=(10, 8)) plt.subplot(3, 1, 1) values, counts = count_freq(word_list(file1)) plot_bar(values, counts, file1.split('/')[-1]) plt.subplot(3, 1, 2) values, counts = count_freq(word_list(file2)) plot_bar(values, counts, file2.split('/')[-1]) plt.subplot(3, 1, 3) values, counts = count_freq(word_list(file1)+word_list(file2)) plot_bar(values, counts, file1.split('/')[-1]+' and '+file2.split('/')[-1]) plt.subplots_adjust(wspace=0.4, hspace=0.6) plt.savefig(FIG1) if __name__ == '__main__': plot_commons(POSFILE, NEGFILE)
頻度分布
ざっと見ると、NLTK のストップワードリストに、記号(.
など)と今回固有の頻出単語 movie
と film
を加えて使った方が良いかなと思った。