2015年9月2日水曜日

機械学習を使った、twitterのクレーム検知、通報システム


機械学習とその分類アルゴリズムにニューラルネットワークを利用したディープラーニングを使い、米国の携帯会社4社を対象としたクレーム検知、担当者への自動通知システムを作成した。
米国携帯会社用として作成したが、いろいろな分野でも応用が効くだろう。
※IBM Bluemix Challenge 2015"Attention Informer"という名称で応募していたアプリケーションである。


◆ UI


designed by 西大輝



◆ アプリ概要
twitterでの苦情を検知し適切な担当へ通知することを目的とする。

アプリの動きは大きく2つ。
twitterタイムラインから
● 肯定的発言、否定的発言を抽出・・・
さらに、同音異義語があっても意図するものだけを選択・・・
● クレーム内容から連絡先を自動判別・・・


簡易的に図示するとこのようになる。
twitter → positive tweets
        → negative tweets → 各担当部署
                     


①から③の部分でIBMのBluemix上にあるwatsonサービス群を利用している。
(Insights for Twitter)
①異常の検知
Negative tweetとPositive tweetを分類させる。
異常な状態は、Negative tweetの比率が対象期間全ツイートの10%を超えた場合とした。

(Natural Language Classifier(NLC))
※アプリを動作させる前に当然学習させておく必要がある。
その手段は下段"◆ コード補足"を参照のこと。

②同音異義語の判別
例えば、sprintと検索した時、それが携帯会社に関連したツイートとは限らない。
Natural Language Classifierを用いて携帯会社のtweetを自動判別させる。
  o:I wanna an Apple iPhone sold in sprint.
  x:I need to work on my sprint finish.

③通知先の判別
本アプリでは、通知先として"基地局監視部署"と"サーバ監視部署"を想定して実装した。
  基地局:Can't call any Sprint customers right now for some reason.
  サーバ:Sprint server down? There is no valid DNS server so !?

通知手段としてtwilioを利用したがメールでもなんでもよいだろう。


◆ コード
https://github.com/alpha-netzilla/attention-informer

一部、NLCの操作面について補足しておく。
APIはすべてREST経由で操作できる。
利用する言語に依らないようにcurlでのコード例を記載しておく。
※本アプリの実コードはRuby on Railsのフレームワークを使っている

○ 学習データの用意
以下の形式のcsvセットを用意する必要がある。

文章, 分類したいインテント

ここでは、ある文章が、cellphoneについて語っているのか、そうではないのかをインテント付けしている。

I'll buy new cell phone?, cellphone
Sprint network improved!!, cellphone
Do show your sprint", others
He made a sprint for escape, others
〜snip〜

以下説明のため、ここでは上記をファイル名"file=train.csv"で保存したとする。

どの程度、どういった文章を学習させればよいのかについて公式マニュアルには明確な言及がなかった。
学習後に独自に性能評価をする必要があるだろう。


○ 学習
$ url="https://gateway.watsonplatform.net/natural-language-classifier/api"

$ curl -u  ${username}:${password} \
-F training_data=@${file} \
-F training_metadata="{\"language\":\"en\",\"name\":\"claim\"}" \
"${url}/v1/classifiers"
en部分をjaにすると、日本語にも対応する。

正常に登録できれば分類器のid(classifier_id)を確認できる。
$ curl -u ${username}:${password} ${url}/v1/classifiers| jq .


○ ステータス確認
学習が終わるまでに数分かかる。
ステータスの変化で進捗を判断できる。

$ curl -u ${username}:${password} ${url}/v1/classifiers | jq .
"status": "Training" ⇒ "Available"


○ 問合わせ(POST)
適当な文章を作り、その内容がどのようにカテゴライズされるかを確認する。
学習時の言語設定をenにしている想定である。jaにしていれば日本語での質問も対応する。
$ question="I want to buy an iPhone"

$ curl -X POST -u ${username}:${password}\
-H "Content-Type:application/json" \
-d "{\"text\":\"${question}\"}" \
"${url}/v1/classifiers/${classifier_id}/classify" | jq .
{
  ~snip~
  "classes": [
    {
      "class_name": "cellphone",
      "confidence": 0.9165256889739971
    },
    {
      "class_name": "other",
      "confidence": 0.08347431102600286
    }
  ]
}

cellphoneについて言及している確率が91%になっている。


○ 分類器の削除
$ curl -X DELETE -u ${username}:${password} "${url}/${classifier_id}"



◆ NLCの選択動機
少し脱線するが、watsonサービスのNLCを本アプリを実装する上で選択した理由を書いておく。今回の対象データは自然言語という非構造化データであり、機械学習の分類系の実装であるNLCであれば対応できると判断したためである。

機械学習の基礎を確認しておこう。

● 機械学習の流れ
(教師データあり)
1.
教師データ     →     特徴ベクトル     →     予測モデル
         特徴生成               学習
            

2.
未知データ     →     特徴ベクトル     →     予測
                   予測モデル
         特徴生成               予測



● 機械学習のアルゴリズムに与える特徴ベクトルの生成
(特徴抽出)
・Word2Vec NLCが利用?
・TF-IDF
・CountVectorizer

(特徴変換)
・Tokenizer
・StopWordsRemover
・n-gram
・StringIndexer
・Binarizer、Bucketizer、QuantileDiscretizer
・PCA
・PolynomialExpansion
・OneHotEncoder
・Normalizer、StandardScaler、MinMaxScaler

(特徴選択)
・VectorSlicer
・RFormula
・ChiSSelector


● 機械学習で実現可能なこと
(教師データあり)
・分類(質的変数の予測) NLCが得意
・回帰(量的変数の予測)

(教師データなし)
・クラスタリング(類似データのグルーピング)
・次元削減(データの本質的特徴の作成)
・強化学習(特定環境下の行動最適化)
・レコメンデーション(価値があると思われるコンテンツを個別提示)


● 機械学習のアルゴリズム
(教師データあり)
・分類
      - ディープラーニング(複数回層での非線形分類) NLCの実装
            ※ニューラルネットワーク技術の総称
      - 多層パーセプトロン(複数回層での非線形分類)
      - SVM(カーネル空間への特徴変換からの分類)
      - ロジスティック回帰(重回帰の分類版)
      - 判別分析(グループの境界線探索)
      - 単純ベイズ分類(確率分類)
      - 決定木(人間の意思決定に近い分類)
      - ランダムフォレスト(複数決定木のマージ)

・回帰
      - 線形回帰
      - 重回帰
      - リッジ回帰
      - Isotonic回帰
      - 生存回帰
      - 決定木
      - ランダムフォレスト

(教師データなし)
・クラスタリング
      - K-means
      - 混合ガウスモデル
      - PIC: Power Iteration Clustering
      - LDA: Latent Dirichlet Allocation
      - クラスタ分析
      - 自己組織化マップ

・次元削減
     - 主成分分析
     - カーネル主成分分析
     - NMF

・強化学習
    - DQN

・レコメンデーション
    - 強調フィルタリング
    - アソシエーション分析


● 機械学習の予測モデルの評価
(教師データあり)
・分類
      - ROC曲線の曲線下面積(AUC)  ※後で詳細解説

・回帰
      - 二乗平均誤差(MSE: Mean Square Error)
      - 二乗平均平方根誤差(RMSE: Root Mean Square Error)

(教師データなし)
明確な回答がないため、満足度、売上、利益、になるだろうか。



◆ 分類器の性能評価
学習させたNLCはどの程度の性能なのであろうか?
交差検定(cross-validation)あたりを使い、性能の評価をしていくことになるのだろうが、何を持って良し悪しを決めればいいのだろうか。
正解率を見れば良いのだろうか。
しかし、正解率という精度の計測だけでは分類器の評価は十分にできない。

Accuracy(精度)     = 正解数 / データ数
Error Rate(誤差率) = 1 - Accuracy 

例えば1万人のうち100人がかかる(陽性となる)病気をすべて陰性と判断すると精度はほぼ100%になる。


分類器の評価方法を考える前に、基本知識を抑えておきたい。

混同行列(Confusion Matrix)
+----------+-------------+
|          |     予測     |
|          +------+------+
|          | 陽性  | 陰性 |
+----+-----+------+------+
| 事 | 陽性 |  TP  |  FN  |
|    +-----+-----+-------+
| 実 | 陰性 |  FP  |  TN  |
+----+-------------------+

TP(新陽性): True Positive
FN(偽陰性): False Negative
FP(偽陽性): False Positive
TN(新陰性): True Negative

・Precision(適合率)
  TP / (TP + FP)
  陽性と予測したもの(分母は予測陽性)の正解率


TPR(真陽性率)、Recall(再現率)ヒット率
  TP / (TP + FN)
  陽性のうち(分母は事実陽性)正しく予測できた率


・FPR(偽陽性率、誤報率)
  FP / (FP + TN)
  陰性のうち(母数は事実陰性)誤って陽性と予測した率

・F-measure(F値)
  2 * (Precision * Recall) / (Precision + Recall)
  精度と再現率の調和平均
                   



先の1万人中100人が病気であることを見逃す例だとこうなるわけである。
+----------+-------------+
|          |     予測     |
|          +------+------+
|          | 陽性 | 陰性  |
+----+-----+------+------+
| 事 | 陽性 |   0  | 100  |
|    +-----+-----+-------+
| 実 | 陰性 |   0  | 9900 |
+----+-------------------+

精度    = 0.99
適合率  = 0
再現率  = 0
F値    = 0

精度だけでは評価ができないことが理解できただろう。

そこで、こういった場合の評価には次の手法が使われる。
ROC曲線: Receiver Operator Characteristic
分類器の一般的な振る舞いを評価できる。
パラメータを変化させ、偽陽性率と真陽性率をプロットした曲線である。

今回は利用しないが以下も使うことがある。
Precision-recall curve(P/R): 適合率-再現率曲線
陽性(Positive)が陰性(Negative)のサンプル数より興味がある、またはかなり少ない場合、例としては、情報検索、不正行為検出の場合などに使う。

両曲線のX軸、Y軸の定義を記しておく。
+--------------------------+
|     |  X軸   |    Y軸     |
+-----+--------+-----------+
| ROC |  FPR   |   TPR     |
+-----+--------+-----------+
| P/R | Recall | Precision |
+--------------------------+


また、ROC曲線を描いた後は、曲線下面積(AUC: Area Under Curve)を算出する。
0から1までの値をとり、完全な分類が可能なときの面積は1で、ランダムな分類の場合は0.5になる。

以上の予備知識があれば計算とグラフは描画できるだろう。
手計算で式を作っていく必要はない。
scipy、matplotlib(pythonのライブラリである。他にも多数ある)あたりを利用すればすぐに対応できる。
ROCを書くには事実と予測値を用意し、ライブラリの関数を呼び出すだけでよい。

事実値  [1.0, 1.0  1.0, 0.0, 0.0, 0.0]
予測値  [0.7, 0.2, 0.6, 0,2, 0,5, 0.8]

ここで少し疑問が湧くかもしれない。
ROCのX軸とY軸にはFPRとTPRが必要だった。
それぞれの定義を思い返そう。

TPR: 陽性のうち(分母は事実陽性)正しく予測できた率
FPR: 陰性のうち(分母は事実陰性)誤って陽性と予測した率

予測値がどの閾値(カットオフポイント)を上回ればまたは下回れば予測が正しい、または間違っていると言えるだろうか。
閾値しだいでTPR、FPRも変わってくる。
が、それでよい。ROC曲線はその閾値をいろいろと変えることでFPR、TPRのX、Y点をプロットしたものである。


(参考)
ROCの理解が進むだろう。
https://oku.edu.mie-u.ac.jp/~okumura/stat/ROC.html
http://qiita.com/kenmatsu4/items/550b38f4fa31e9af6f4f

scikitライブラリの使い方がわかる。
https://datamize.wordpress.com/2015/01/24/how-to-plot-a-roc-curve-in-scikit-learn/



0 件のコメント:

コメントを投稿