Skip to content

Latest commit

 

History

History
282 lines (183 loc) · 14.2 KB

File metadata and controls

282 lines (183 loc) · 14.2 KB

Article Classifier

Image

概要説明

Article Classifier は、フォームに入力された記事 URL から HTML を取得し、記事のカテゴリを判定し、画面に出力するアプリケーションである。

アプリケーション概要

アプリケーション画面の中央にあるフォームに、https://gunosy.com/ から選んだ記事 URL を入力する。
Analyze ボタンを押すと、記事のカテゴリを反映し、画面に出力する。
Correct Form

記事 URL ではない URL を入力すると、例外処理が働く。
以下の画像のように、"Please submit a gunosy article"とエラー文が出る。
Incorrect Form

分類器精度の概要

記事のカテゴリを判定する際に二種類の分類器を使用することが可能である。一つはナイーブベイズを用いた分類器、もう一つはロジスティック回帰を用いた分類器である。   また、いずれの分類器に対しても、訓練データとテストデータの比は 8:2 で学習を行なっている。
それぞれの分類器の適合率(precision)、再現率(recall)、F 値(f1-score)、テストに使われたデータ数(support)を以下に示す。   また、特定のデータセットに対して過学習を起こしていないことを示すため、交差検定による値も以下に記している。

ナイーブベイズを用いた分類器

category precision recall f1-score support
IT・科学 0.79 0.94 0.86 541
おもしろ 0.75 0.15 0.25 101
エンタメ 0.97 0.94 0.96 4039
グルメ 0.87 0.95 0.91 611
コラム 0.81 0.87 0.83 1155
スポーツ 0.97 0.96 0.97 827
国内 0.87 0.82 0.84 671
海外 0.84 0.86 0.85 336
avg / total 0.91 0.91 0.91 8281

また、五分割交差検証により得られた値は

scores: [ 0.91063881 0.90882744 0.90725758 0.91038647 0.90736715]

で、平均値は

average value: 0.908895489763

であり、交差検証においては平均で約90.9%の精度を出した。

ロジスティック回帰を用いた分類器

category precision recall f1-score support
IT・科学 0.90 0.95 0.92 541
おもしろ 0.80 0.69 0.74 101
エンタメ 0.98 0.98 0.98 4039
グルメ 0.93 0.96 0.94 611
コラム 0.91 0.89 0.90 1155
スポーツ 0.98 0.98 0.98 827
国内 0.90 0.87 0.88 671
海外 0.88 0.91 0.89 336
avg / total 0.95 0.95 0.95 8281

また、五分割交差検証により得られた値は

scores: [ 0.94046613 0.9364811 0.94119068 0.93538647 0.93913043]

で、平均値は

average value: 0.938530962853

であり、交差検証においては平均で約93.9%の精度を出した。

環境構築

実行環境は以下の通りです。
Mac OS X: Sierra 10.12.2
Python: 3.6.1

ターミナルにて、

$ brew update
$ brew install python3
$ pip install virtualenv
$ virtualenv --python=/usr/local/bin/python3 --no-site-packages env
$ source env/bin/activate

と入力して、仮想環境を起動する。

次に、

$ brew install mecab
$ brew install mecab-ipadic
$ git clone --depth 1 git@github.com:neologd/mecab-ipadic-neologd.git
$ ./mecab-ipadic-neologd/bin/install-mecab-ipadic-neologd -y -n

と入力して、MeCab の辞書として使用する mecab-ipadic-neologd をインストールする。

更に

$ git clone git@github.com:ajingu/gunosy.git
$ cd gunosy
$ pip install -r requirements.txt

と入力し、必要な python パッケージを仮想環境にインストールする。

最後に、.bash_profile に環境変数を描き込む必要がある。   今回は、データベースのパスワード等を隠蔽するために、.bash_profile に環境変数を追加し、os モジュールを使ってプログラム中で環境変数を読み込んでいる。

$ cd ~
$ vim .bash_profile

で.bash_profile を開き、テキスト内に

export GUNOSY_HOST="****"
export GUNOSY_USERNAME="****"
export GUNOSY_PASSWORD="****"
export GUNOSY_DATABASE_NAME="****"
export GUNOSY_TABLE_NAME="****"

と入力し、環境変数を追加する。

それぞれの変数の対応は以下の通りである。各々が使うデータベースを考慮して、ふさわしい値を設定する必要がある。

環境変数
GUNOSY_HOST ホスト名
GUNOSY_USERNAME ユーザー名
GUNOSY_PASSWORD パスワード
GUNOSY_DATABASE_NAME データベース名
GUNOSY_TABLE_NAME テーブル名

動作させるための方法

Step1: ナイーブベイズ分類器を使ったウェブアプリの作成

※当レポジトリにはデフォルトで学習済みデータが入っているので、最初から$ python manage.py runserverと入力しても動く。

1.データ収集の際に、以前に収集したデータを消したい場合、gunosychallenge レポジトリにて

$ python manage.py initialize

というコマンドを打つことで、該当テーブルの全ての行を消去し、データベースを初期化することができる。

2.scrapy を用いたデータを収集を行う際、gunosychallenge レポジトリにて

$ python manage.py scrapy crawl gunosy

というコマンドを打って行う。データ収集の完了には約 70 分かかり、40000 記事前後のデータを取得する。

3.ナイーブベイズ分類器の学習は、gunosychallenge レポジトリにて

$ python manage.py make_clf nb

というコマンドを打って行う。学習には約 8 分かかる。

4.ウェブアプリを起動する際には、gunosychallenge レポジトリにて

$ python manage.py runserver

というコマンドを打つ。

ローカルサーバーで立ち上げるため、http://127.0.0.1:8000/ にアクセスすると、該当するウェブアプリが起動している。
上記の「概要説明」でも説明したが、中央のフォームに https://gunosy.com/ から選んだ記事 URL を入力し「Analyze」ボタンを押すと、記事のカテゴリを「エンタメ」、「スポーツ」、「おもしろ」、「国内」、「海外」、「コラム」、「IT・科学」、「グルメ」の中から推測し、画面に出力する。

Step2: 分類器の精度向上

1.ロジスティック回帰を用いた分類器の学習は、gunosychallenge レポジトリにて

$ python manage.py make_clf logistic

というコマンドを打って行う。学習には約 10 分かかる。

2.ウェブアプリの立ち上げと記事 URL の入力・カテゴリの推測は、Step1 と全く同じ方法で行う。

appendix: テスト  

アプリケーションのテストを行うことが可能である。

Scrapy のテスト

gunosy レポジトリにて   $ python gunosynews/scrapy_test.py
と入力すると、クローラーのテストを行うことができる。

ウェブアプリのテスト

gunosychallenge レポジトリにて   $ python manage.py test
と入力すると、ウェブアプリのテストを行うことができる。

工夫

1. データ収集に関して

・可能な限り多くの記事の取得
該当箇所 : gunosy.py
学習・テストの際になるべく多くの記事を使うために、https://gunosy.com/tags から記事を収集した。
タグは現時点で 1~2500 の 2500 個存在し、それぞれのタグが「エンタメ」、「スポーツ」、「おもしろ」、「国内」、「海外」、「コラム」、「IT・科学」、「グルメ」の 8 つのカテゴリに割り振られている。   しかし、タグの中には、カテゴリに割り振られていないものやタグだけ存在して記事が存在しないものもある。そのようなイレギュラーなタグは無視する実装を行なった。

・pipelines.py に Mysql を設定
該当箇所 : pipelines.py
pipelines.py に、django アプリと紐付けた Mysql を設定することで、データ収集からデータベースへのアップロードまでの流れがスムーズに行われるようにした。

2. 分類器の学習に関して

2-1. 分類器全般に関して

2-1-1. mecab-ipadic-neologd の使用

該当箇所 : preprocess.py
日本語の形態素解析器 MeCab を使って形態素解析を行ったが、その際に辞書として mecab-ipadic-neologd を使用した。   これによって、人物名や地名などの固有名詞が多いニュース記事から、より適切な特徴語を抽出することができている。また、特徴語は名詞と形容詞に限定し、話の文脈との関連性がより高い言葉を抽出した。   また、構築環境によって辞書の位置を指定するパスが変わるため、データを前加工する際に最初に辞書のパスを検索するように実装した。

2-1-2. ストップワードの設定

該当箇所 : preprocess.py
日本語のストップワードを集めたslothlib をプログラム中で読み込む実装を行い、ストップワードを設定した。

2-1-3. 分類器のシリアライズ

該当箇所 : NaiveBayes.py, Logistic.py
分類器の学習の際に、学習した分類器を dill ライブラリを使ってシリアライズしている。   そのため、ウェブアプリで記事 URL を入力した際、すでに作った分類器を読み込むだけで新記事の解析が可能になるため、記事のカテゴリ判別にかかる時間を大幅に短縮した。

2-2. ナイーブベイズ分類器に関して

該当箇所 : NaiveBayes.py

2-2-1. ラプラススムージングの実装

ナイーブベイズ法における「ゼロ頻度問題」(あるカテゴリに学習時に含まれなかった単語がテスト文書に含まれていると、そのカテゴリである確率が 0 になってしまう問題)を回避するため、ラプラススムージングを実装した。

2-3. ロジスティック回帰を用いた分類器に関して

該当箇所 : Logistic.py

2-3-1. ロジスティック回帰の使用  

ナイーブベイズ法では、それぞれの単語の現れる事象は互いに独立であると前提して、単語の条件付き確率を掛け合わせている。これだと先ほどあげた「ゼロ頻度問題」のために、学習時に存在しなかった単語に結果を左右されやすい。   そのため、学習時に存在する単語のみに着目して計算を行う(学習時に存在しなかった特徴語に関しては、ロジスティック関数への入力は 0 となり実質的に影響を与えない)モデルであり、カテゴリ判別に広く使われるロジスティック回帰モデルを今回は使用した。

2-3-2. TfidfVectorizer の設定  

単語ごとの TF-IDF を計算して、それぞれの単語に対して適切な重み付けを行なった。

2-3-3. LogisticRegression モデルにおける class_weight の設定

それぞれのカテゴリーのサンプル数に大幅な違いがある事が原因で、ナイーブベイズ分類器の時には「おもしろ」カテゴリーの再現率が0.15と大変低い数値になっている。これは「おもしろ」カテゴリーのサンプル数が他カテゴリーに比べて非常に少ないことが理由で、実際には「おもしろ」カテゴリーである記事が他カテゴリーであると推測される場合が多くなるため、偽陰性が高くなっていると考えられる。   このようなサンプル数によるカテゴリー判別の偏りを軽減するために、LogisticRegression モデルの重み付けパラメータである class_weight を"balanced"に設定し、各カテゴリーでの特徴語の重みをサンプル数に反比例させる事で、「おもしろ」カテゴリーの再現率を 50 ポイント以上改善する事ができた。   なお、データをアンダーサンプリングしてそれぞれのカテゴリのデータ数をそろえる方法も考慮したが、その場合データ数が全部で約 4000 となってサンプル数が激減し、精度が急激に下がるので、今回は class_weight を設定する手法をとった。

2-3-4. GridSearch の使用

LogisticRegression モデルの正則化のパラメータである C の値を最適化するために、GridSearch を使用した。

3. ウェブアプリに関して

3-1. 例外処理

該当箇所 : views.py
https://gunosy.com/ の記事 URL ではない URL を入力すると、HTML 構造を把握できず、ウェブアプリの画面ではなく、django のエラー画面が出力されてしまう。   そのため、あらかじめ例外処理を書いておき、不適当な URL が入力された場合には、ウェブアプリの画面にエラー文を出力するように設定した。

4. その他

4-1. データベースのパスワードの隠蔽

該当箇所 : settings.py(gunosychallenge ディレクトリ), database.py, pipelines.py   ~/.bash_profile に環境変数を設定することで、Mysql のパスワードの公開を避けた。