スパムメールフィルターの開発にチャレンジ!
cha_kabu
運営の皆様、新しいコンペの開催ありがとうございます。自然言語処理に挑戦したことが無いのでコンペに参加しながら勉強したいと思います。
上述の通り自然言語処理は初めてですが、ネット上の情報を寄せ集めてひとまず自分の中でBaselintと呼べるものができたので、今朝までの私と同じような「自然言語処理って何からすれば良いの?」という方の参考になれば幸いです。
また、付け焼刃の知識ですので、間違った知識やよろしくない処理が含まれていると思います。不慣れな方は信じすぎず、詳しい方はコメントで教えて頂けると大変幸いです。
Baseline作成に当たり、以下のサイトを参考にしました。特にkaggleの方はまだまだ読み切っていませんが、当コンペでも役立つ情報が多そうです。
[Kaggle:SMS Spam Collection Dataset](https://www.kaggle.com/uciml/sms-spam-collection-dataset/notebooks)[Qiita:機械学習 〜 迷惑メール分類(ナイーブベイズ分類器) 〜](https://qiita.com/fujin/items/50fe0e0227ef8457a473)
import re import string import matplotlib.pyplot as plt import nltk import numpy as np import pandas as pd import scipy.stats as stats import seaborn as sns from bs4 import BeautifulSoup from imblearn.under_sampling import RandomUnderSampler from nltk.corpus import stopwords from sklearn.feature_extraction.text import CountVectorizer from sklearn.metrics import f1_score from sklearn.naive_bayes import MultinomialNB from wordcloud import STOPWORDS, WordCloud
df = pd.read_csv("train_data.csv") test = pd.read_csv("test_data.csv")
df.head()
stopwordsとは、日本語で言えば「は」、「です」など、英語で言えば「a」、「is」などの出現頻度が高いにも関わらず特別な意味を持たない単語のことで、こういった単語を削除することで認識精度を向上させます。nltkライブラリに基本的なものは格納されていますが、こちらは要するに単なるlistなので、自分でstopwordsを追加することもできます。以下では、string.punctuationで取得できる記号と、rawデータを見て無駄そうだった"Subject"も加えています。
string.punctuation
以下の処理の際、私の環境(Anaconda上のjupyter notebook)ですとpip installできていたと思ってもエラーが起きました。Anacondaでうまく動かないときは以下もご参照ください。https://stackoverflow.com/questions/48385829/how-to-install-stop-words-package-for-anaconda
stop = set(stopwords.words("english")) # string.punctuation = ['!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~'] punctuation = list(string.punctuation) # 手動で追加 org_stop = ["Subject"] # stopwordsの定義更新 add_stop = punctuation + org_stop stop.update(add_stop)
stopwordsの削除の他、URLの削除などを行います。
# htmlの分割 def strip_html(text): soup = BeautifulSoup(text, "html.parser") return soup.get_text() # []で囲まれた文章の削除(脚注、linkなど) def remove_between_square_brackets(text): return re.sub('\[[^]]*\]', '', text) # URLの削除 def remove_between_square_brackets(text): return re.sub(r'http\S+', '', text) # stopwordsの削除 def remove_stopwords(text): final_text = [] for i in text.split(): if i.strip().lower() not in stop: if i.strip().isalpha(): final_text.append(i.strip()) return " ".join(final_text) # ↑の関数をまとめて適用する関数 def denoise_text(text): text = strip_html(text) text = remove_between_square_brackets(text) text = remove_stopwords(text) return text # ↑の関数の適用 df['contents']=df['contents'].apply(denoise_text)
sns.countplot(df["y"])
<matplotlib.axes._subplots.AxesSubplot at 0x24f2f8ba4c8>
ほとんどが非スパムで、非常に不均衡なデータです
WordColudは「実装したことは無いけど見たことはある」人も多いのではないでしょうか。出現頻度が高い単語ほど大きく、そうでない単語ほど小さく表示し、直感的にどういった単語が多い文章か分かる様になってます。
# 非spam plt.figure(figsize=(20,20)) wc = WordCloud(max_words = 2000, width = 1600, height = 800, stopwords = STOPWORDS).generate(" ".join(df[df.y == 0].contents)) plt.imshow(wc, interpolation="bilinear")
<matplotlib.image.AxesImage at 0x24f2fd08508>