FANCOMI Ad-Tech Blog

株式会社ファンコミュニケーションズ nend・新規事業のエンジニア・技術ブログ

「そのアプリ、広告あるんですか?」2値分類

こんにちは。ピザが大好きg_takahashiです。イタリアではマフィアに襲われて5万円盗まれました。
前回はデータの可視化をしましたが、今回は2値分類に取り組みます。

目的

次の画像をご覧ください。
f:id:fan_g_takahashi:20180309092805p:plain
お分かりいただけただろうか。iTunesストアにあるアプリには広告があるかどうかが記載されていないです。GooglePlayStoreで販売されている Deemo には「広告を含む・アプリ内購入あり」という欄があるのに対して、iTunesストアで販売されている y_kawasaki さんのアプリにはそういった情報が書いていない。
これをデータを使って判定することが今回の目的です。
目標正解率は90%です。

手法

今回は広告あるなしの2値分類をしていきます。データ収集にはRubyを使い、解析にはPythonを使いました。機械学習にはscikit-learnとgensimを使いました。

データ概要

タイプ1: Google Playのカテゴリ毎のページをクロールして、レビュー部分のみスクレイプする。
タイプ2: タイプ1 + カテゴリの種類
取得したアプリ数は合計3403個。内訳は58%が広告を含む、42%が広告を含まない。

データ加工

形態素解析、TF-IDF、辞書作成、Bag-of-Wordsの順番で、自然言語から数値へ加工しました。一つのレビューが整数が入ったlistになるイメージです。

コーパスの作成は、現代語に強いmecab-ipadic-neologdを利用して、形態素解析を行い、TF-IDFの値が0.8以上のもののみを抜き出しました。メモリ容量の制約があり、制約を超えると分類機の学習の段階でカーネルがダウンしてしまうため、ダウンしないギリギリ数値がTF-IDFでは0.8でした。このときの特徴量は4800程です。

しかし、データの形式をlistからpandasのDataFrameに変更することでメモリ使用量が大幅にダウンすることが分かり、そもそも特徴量の制約はあまり考える必要がなかったということが分かりました。これは次回の改善点として、そのまま解析に移ります。

分類器と結果

各データ、各分類機での結果は以下のようになりました。

データタイプ1

auc 正解率(1SD)
ベイジアンフィルタ 0.65 70.0%(±0.14%)
ロジスティック回帰 0.60 67.9%(±0.37%)
SVM 0.58 68.5%(±0.17%)

データタイプ2

auc 正解率(1SD)
ベイジアンフィルタ 0.68 68.4%(±1.48%)
ロジスティック回帰 0.65 69.1%(±2.23%)
SVM 0.68 68.3%(±1.78%)

ベイジアンフィルタは多項分布を仮定したモデルの方が当てはまりが良かったです。5分割の交差検定は1分程度で終わります。
ロジスティック回帰は最適化にSGDを使い、正則化項にはL2を使いました。交差検定には1.5時間かかります。L1と比較したのですがL2のほうが当てはまりが良かったです。L1では従属変数のパラメータが0になることが多く、意味のない変数を排除できるといったことを考えると、TF-IDFの処理がその代わりを務めたためと考えられます。また、最適化の手法はsag,sagaとも比較してもSGDのほうが正解率、経過時間ともに良く、使いやすかったです。SVMでもL2を正則化項としました。


タイプ2のほうがaucが高く、カテゴリを特徴量として使うことは有意であるとわかります。各用語の説明はfan_k_arimuraさんのブログに素晴らしくまとまっています。
tech-blog.fancs.com

おまけ

自然言語処理を調べていたらWord2Vec、Doc2Vecに興味が湧き、2値分類に応用できないかを実験してみました。レビューの内容が広告の有無で変化するならdoc2vecが広告を持つレビューを判断してくれるのではないか、という発想です。作業の流れは、形態素解析 => Doc2Vec => K-Means です。
Doc2Vecによって、300次元にしたあとで、K-Meansによって2つのクラスターに分けます。PCAによって次元削減してグラフを作ると以下のようになります。

f:id:fan_g_takahashi:20180312113428p:plain

広告あり 広告なし
K-Meansによるクラスタ1
K-Meansによるクラスタ2 黄土色 水色

この図を見てみるとX軸の-0.3あたりでK-Meansによる分割がされていることがわかりますが、分割された集合の中には、広告ありなしに関わらず含まれているためこの手法は優れていないことがわかりました。実際に、正解率は54.0%でした。残念。


感想

・目標正解率には20%も足りなく、よろしくない結果になりました。力不足で残念です。

・Google Playストア用のスクレイプに大きく時間を掛けてしまいました。しかし、githubを覗いてみると、他の多数の方が既にそれらを作っていて、これを使えばよかったなと反省しています。車輪の再発明というやつをやってしまいました。

・pandasすごい。

・AdaBoostを使ってのモデルの改善、tf-idfの調整など多数の改善点が見つかり、調整を続けていきたいと思います。

・勉強することが多くエキサイティングな時間を過ごせました。プレゼンをする機会もいただいて、人として成長したと思います。ありがとうございました。今後はよりtech-drivenに頑張ります。