ろむめも

気になったこととか、調べたことをゆるくまとめます。主にプログラミング関連の話題が多いです。

身の程知らずの初心者がUdacityで機械学習を勉強した話 ①機械学習とは

以下に学習時のメモをまとめていきます。

Lesson 1 ようこそMachine Learning Nano Degree Program(MLND)へ

はじめに

機械学習は様々な分野で活躍しています。このコースでは実際にどういう領域に機械学習が応用出来るのか、そしてプロフェッショナルな人達はどういうアルゴリズムをどういうデータに当てはめて、どういうツールを使って実現しているのか、それらに関する主要な考え方を学んでいきます。それらを学ぶために、このコースでは数学、例えば統計学線形代数幾何学の内容も含みます。

機械学習(ML)とは

MLは様々なものを描写します。その延長線上には人工知能の実現があるともいえます。データを処理し、理解し、賢く応答する。そういう事に機械学習は活用できます。また別の言い方をすると、統計学のように、実際のデータに発展的なアルゴリズムを当てはめて、そのデータを理解し、比較し、評価し、まとめるようなものです。あるいは、アルゴリズムのようにデータを入力すると動き、出力を返します。機械学習は様々な分野におけるこれまでの業績の次世代的な複合の成果とも言えます。

これまでのシステムとの違い

これまでのシステムはその判断というものを直接的にコードに書いていました。例えば、顔を見てその人が誰かを判別する際には、眼鏡をかけているか、目や髪の色は何色か等、そういうことをコードに直接書いてそれが誰なのか判断してきました。MLでは違います。これらはただ画像データをモデルに流し込むことで実現されます。それらの識別に使う特徴的な情報はデータセットの形で引き渡され、そのデータセットによってモデルは学習します。そして、今ではコンピュータの信頼度は増しているので、そういったデータというものが共有化されているのです。そういった事情を踏まえても、MLは非常に便利なツールになってきています。

コースのアウトライン

まずは一般的なモデルビルディングとバリデーションについて学習します。
次に、教師あり学習、教師なし学習、強化学習について学習します。これらは異なったフィールドに適用され、それらをどう使うべきか学習します。
そして、それぞれのパートには実習フェーズがあります。これらを通じて、機械学習を体験してください。

Lesson 2 機械学習とは何か

導入

機械学習とはコンピュータを訓練し、所定のタスクを実行できるようにすることです。訓練にはデータを使います。
データから過去の経験をコンピュータに学ばせてそれを現在のデータに当てはめます。

決定木(Desision Tree)

例えばアプリのレコメンデーションシステムを考えます。ユーザーの性別、年齢、それからダウンロードしたアプリケーションのレコードがあった場合に未知のユーザーにはどのアプリを推薦するのが良いでしょうか。
それを考えるために与えられたデータを見てみましょう。今回のケースではアプリは年齢に関係がありました。即ち例えば20歳以下はAというアプリをダウンロードしていて、20歳以上はBというアプリをダウンロードしているように見えます。
こういった場合に決定木型のモデルが適用できます。例えば、データを入力した時に年齢を見ます。年齢が20歳以下であればA、20歳以下であればBというアプリをダウンロードするように提案するシステムを作ることが出来ます。
これはもちろん人間がコードすることなく、学習によって取得される特性として獲得されます。
決定木型のモデルを使えばこういったことが実現できます。

Naive baise

例えばe-mailのスパム検出を見てみましょう。過去のメールにタグをつけて、それがスパムかそうでないかラベルを付けることにします。
それらのメールの内容を確認して例えばスパムメールの中で富士山という文字列が入っているメールの数を数えます。同時に非スパムメールの中で富士山が含まれるメールの数を数えます。
例えばスパムメールで20通、非スパムメールで5通だとすると、富士山という文字が入っているメールがスパムである確率は80%となります。
なぜなら富士山が含まれるメールの総数25通に対して20通がスパムなので80%となります。
これを富士山という文字列だけでなく、様々な文字に対して行います。また他にも誤字が含まれているか、タイトルが適切でないか等も含めてトータルで判断する場合もあります。
これらの確率を掛け合わせて、そのメールがスパムであるか、そうでないかを判断します。

Gradient descent(勾配降下法)

学習に際して、この概念は重要です。これは最もエラーを最小化する方向に山を降りていくイメージのものです。最適解を探す際に、どの方向に降りるべきか決める為に用いる手法です。
エラーの山があって、その勾配を計算し、その分下に降りて、山を降りきるまで続けます。これはとても重要な概念なので覚えることをお勧めします。
山としてどういうエラーを定義するのか、そしてどのように山を降りるのか、またどこがゴールなのかを定義することが機械学習において重要になります。

Linear Regression(線形回帰)

データが線形である場合、その解析には線形回帰を使うことが出来ます。
回帰ではデータのすべての距離を最小化するような直線を引きます。これはデータの2つ以上の特徴が線形であることが前提です。線形というのはy=ax+bで表すことが出来るという事です。
このような前提が成り立つ場合、その直線を求めることができれば、任意の地点の値を片方のデータから算出することが出来ます。これが線形回帰の目的です。
この線形回帰を学習する場合、そのエラーは直線と各データポイントの距離を求め、それをすべてのデータポイントに関して和をとった値として定義されます。
このエラーを最小化することが線形回帰で最適な直線=最適解を求める方法になります。
この最適解を求めるのに先程のGradient descentを活用することができ、エラーが最小になるように直線の傾きや切片などの値を変えていきます。

Logistic Regression(ロジスティック回帰)

例えば入学試験の点数と入学後のGPAの値の組み合わせから、その学生が卒業できそうか、そうでないかを考えます。
この時、訓練用データはそれぞれの値と、卒業できたかそうでないかが与えられているものとします。
これらをうまく分類する、即ち、点数とGPAが与えられたときに卒業の可否を返すようなものを作ろうと考えます。
そのような考えに基づき、2つの変数の関係から卒業可否の境界を直線で表し、例えば新しいデータポイントがその直線の上側にいたら卒業でき、下側にいたら卒業できないというように分類するモデルをロジスティック回帰モデルと言います。
この時ほとんどの訓練用データはその分類に従っていますが、その全てがその分類に従っているわけではないという事に注意してください。

このモデルは訓練用データからどのように最適な分類直線を導き出しているのでしょうか?
まずはランダムな直線をデータの分布上に引きます。この時ラインの上側が合格、下側が不合格と勝手に決めます。この時訓練用のデータはその分類に従っているでしょうか?ランダムに引いた線なのでまだ得たい結果にはなっていません。そして、例えば間違えて分類してしまったデータ、つまり、正解は合格なのに不合格と判定してしまったり、その逆のデータの数を数えます。
次に、線形回帰と同じように例えばGradient descent等を使って、その間違いが少なくなるように直線を動かします。これを繰り返して、エラーが最も少なくなるような直線の式を導き出します。これが学習のプロセスです。
一方で実際にはデータの数を数えるのではなく、Log Loss関数をエラーの算出に用います。これは間違えて判定してしまったデータ点に対して大きなペナルティを与え、正しいものには小さいペナルティしか与えないようにするものです。そして、それをすべてのデータ点に対して和を取り、それをエラー値とします。これを最小化するのです。このペナルティは分類した直線から離れれば離れるほど大きな値となり、正しい分類に近づき、そして正しい分類になれば小さい値となるようにします。そうすると正しい分類が得られたときには、その和が最小化されているという事になり、そこがゴールとなります。このようにして正しい分類方法を学習させるのです。もちろん最小化させるにはGradient descentを使います。

Support Vector Machine(サポートベクトルマシーン)

SVMの場合はエラー関数が若干異なります。そのエラー値はX-Y軸のどちらかに平行な境界との距離で求められるのではなく、分類直線に垂直な形で求められます。もちろんこれは簡単な例であって実際には単なる直線ではなく、超平面上の直線という事になります。また、その直線から離れたデータ点は考慮に入れず、境界にある範囲以内のデータ点のみを使ってエラーを算出します。その範囲のことをマージンと呼びます。また、学習途中の境界線とマージン内の各データの距離のうち最も最小のものに着目します。SVMではこの最も小さい距離が最大になるように境界線を決めます。即ち、マージンの範囲内にあるデータ点の境界との距離のうち、最も最小のものが境界線を変更する過程において最大になるように境界線を決めるのです。別の観点から境界線を見ると、マージンの範囲内において境界はラベルに関わらずどの点からも一定の距離を保っているようになります。もちろん距離を最大化するのにはGradient Descentを使います。この方法をSVMと呼びます。サポートという名前が付いたのは、各点が境界線から一定の距離を保ち、かつどちらの領域からもその間を通っているように見えるので、各点が境界線を支えているように見えるからです。

Neural Network

例えばデータが線形分離できないとしましょう。その場合これまでの直線で分類する方法では対応しきれません。どうしますか?円を使いますか?2本の直線を使いますか?これらはおそらくどちらもうまく機能するでしょう。例えば2本の直線を使ってみる事としてみます。2本の直線はGradient descentを使ってLog Loss関数で求めることとします。これをNeural Networkと呼びます。なんでそう呼ぶのでしょうか?それぞれの直線に分類条件があり、そのどちらもYesの場合にAに分類し、それ以外の場合、即ちどちらかがNoの場合にはBと分類するように組み合わせるのです。もう少し細かく見てみます。このそれぞれの直線の分岐条件を一つのノードに置き換えます。例えば一本目の直線の判定がYesなのかNoなのかと分類します。次に別のノードで二本目の直線の判定がYesなのかNoなのかと分類します。今回の場合は、2つのノードへの入力は同じデータであることとします。最後にそれら2つのノードの出力を入力とした新しいノードを用意し、Yes/YesであればYes、それ以外はNoと返すようなものを用意します。これは例えば1,1で1を、それ以外のパターンで0を返すようなノードを用意すれば実現できます。最終的にこれらを結合してモデルを完成させます。これが今回求めたかったモデルであり、このようなノードを組み合わせて実現するモデルのことをNeural Networkと呼びます。もちろんノードを追加することもできますし、レイヤーを増やすこともできます。特にレイヤーを深くして言った場合にDeepNeuralNetworkと呼ばれます。

Kernel Method

同じようにデータが線形分離できない場合のことを考えます。例えばそれぞれのデータから別の特徴量(例えばr^2=x^2+y^2のr等)を算出したとします。その値を使ってデータを分離できないか?というのがKernel methodの基本的な方針です。その値を使って分類できる場合、その別の特徴量空間の分類平面をもとの空間に戻した形で表現できれば、それが分類直線になります。これをKernel Trick(カーネルトリック)と呼び、SVMで使われる手法です。

小まとめ

ロジスティック回帰は忍者みたいなものです。データをラベルに基づいて一直線に切り分けます。SVMは境界付近のデータを注意深く見て、その境界を適切に切り分けます。ただし通常一直線に、です。Neural Networkは複数の忍者が存在し、それぞれ異なった切り分け方を行い、最終的にその結果をマージするようなものです。Kernel Trickは別の考えに基づいていて、そのデータをどうやって切り分けたら良いか考え、別の次元に持ち込んでそのデータを切り分けます。
ところでXORはどうやって実現しましょうか?ちょっと考えてみてください。

K-means Clustering(非階層的手法)

例えば町にピザ屋を作るとします。近所には3つの顧客の集合がまとまってあって、その近辺に3件のピザ屋を効率よく建てたいです。どうしましょうか?まずはランダムな位置にピザ屋を配置します。すると顧客はどのお店を選ぶかと言えば、最も近くのお店を選ぶと思います。そのまとまりを一つのClusterとしましょう。これが最適なクラスタリングかと言われるとまだ甘いように見えます。もっと最適なクラスタリングが出来るとしたらどのような形が良いでしょうか。そうです。お店の位置を動かして、それぞれの顧客の位置からお店までの距離が最も小さくなるようにすればよいのです。どのように動かすかというと、とりあえずまとめた一つのクラスタの重心位置にお店を動かすのです。そしてもう一度最も近いお店の顧客でまとめ直してみると結果が変わり、より適切な位置にお店を配置することが出来ていることがわかります。このようなステップを繰り返して、最適なお店の位置を探す操作のことをK-means Clusteringと呼びます。K-means Clusteringはクラスタの数がわかっている場合にとても効果を発揮します。じゃあ、クラスタの数がわかっていない場合にどうしますか?

Hierarchical Clustering(階層的手法)

クラスタの数がわからない場合にはどうしましょうか。同じようにピザ屋の例で考えます。とりあえずまとめていきたいので、最も近い2つの顧客をグループとみなします。近い順にこのグループ化作業を行っていきます。途中で既にグループ化されたものと別の顧客がヒットしました。この場合は既に存在しているグループにその顧客を追加します。グループ同士であってもまとめてしまいます。最終的に顧客間の距離がある程度より大きくなったらそこでグループ化作業をストップします。これはどのぐらい離れていれば別のクラスタと見なすかというパラメータによって判断します。このアルゴリズムをHierarchical Clusteringと呼びます。この方法はクラスタの数は未知だが、クラスタ同士がどれぐらい離れているかという事はわかっているときに有効です。

まとめ

ここまでいろいろ学んできましたが、実際どのアルゴリズムを使えばよいのでしょうか?アルゴリズムの選択には実行時間や精度も含めた検討が必要になってきます。アルゴリズムを結合することもできるでしょうか。もちろんできます。この先のレッスンでは、実際のデータを使って、その分析をやってみましょう。

Project: Titanic Survival Exploration

タイタニックの生存者を予想するあれです。
machine-learning/projects/titanic_survival_exploration at master · romth777/machine-learning · GitHub
以下の1~4に関してはチュートリアル通りに実施したものです。5は自分で特徴量を考えてそれを実装しました。

  1. 最初にメトリクスとしてaccuracy_score関数を作りました。まずは生存or死亡が予想と一致しているかその割合を精度のメトリクスとしました。
  2. 最初の予測関数に全ての乗客が生き残らなかったという結果を返す関数を用意しました。これはデータの調査の為という意味合いが強いです。結果61.62%を得ることができました。
  3. 性別毎にデータを見てみます。これは用意された関数を使いました。生存、死亡の数を比較すると、男性はの死亡が多く、女性は生存が多い事がわかりました。そこで男性であれば死亡、女性であれば生存と予測する予測関数を作りました。結果として78.68%と良くなりました。
  4. 次に男性のデータを年齢別に眺めてみます。10歳以下の男の子のほとんどが生き残っていることがわかります。これをそのまま予測関数に適応し、女性は先程と同じで、男性は10歳以下であれば全て生存、それ以外は死亡と予測する予測関数をつくりました。結果は79.35%になりました。
  5. 最後に色々データを眺めて、自分で特徴量をつくりました。私は10歳以下の男の子のデータをさらに細分化してPclass(階級)およびSibSp(搭乗する乗客の兄弟および配偶者の数)に応じて結果を変えるように予測関数を修正しました。結果として80.70%を得ることが出来ました。なぜ10歳以下の男性に着目したかと言えば、他の年齢では男性で生存している人の数が少なかったからであり、今は全て死亡で予測している関係上、スコアに与えるインパクトが小さいと考えたからです。データを調査した結果SibSpが小さい値の場合に多くの生存者がいることがわかったので、それを追加しました。2017/10/7時点でKaggleだと700位ぐらいのスコアですね。
  6. [まとめ]今回は自分で決定木を実装しました。条件式を使ってデータを小さいグループに分けることが相当します。以下のリンクが参考として挙げられていました。確かに特徴量の値に応じてデータを分類していく様子が可視化されていました。

A visual introduction to machine learning

Lesson 5 Training Models

導入

まずモデルがどれぐらいうまくかについて学びます。それはメトリクスを学び、モデルがうまくいっているかいっていないか判断できるようにするという事です。次にメトリクスに基づいてどうやってモデルを良くするかです。そこではモデルを評価(Evaluate)し、検証(Validate)し、改善します。

概要

問題があったときにどうやって解決するか考えます。問題がどのぐらい深刻で何をどれぐらい直したらよいのか考えるためにはそれを測定するツールが必要です。

前提知識

  • Mean(平均値), Median(中央値), Mode(最頻値)
  • Inter Quartile Range(Q3-Q1の四分位値), Outliers(外れ値), Standard Deviation(標準偏差), Bessel's Correction(サンプルデータから母集団データの分散を予測するために分散計算の分母をn-1にする補正。データが正規分布であれば中央付近のデータをとってきてしまい、すそ野のデータが含まれない可能性が高いのでその影響を考慮にいれたもの)
  • Pandas/Numpy/Scikit Learn

Lesson 6 Testing Model

概念

Regression(回帰)は値を予測します。一つの値が与えられたときにもう一方の値をそのデータが属している母集団の分布から予測します。Classification(クラス分類)はラベルを予測します。一つの値が与えられたときにそのデータがどのクラスに属しているか、訓練用のデータから予測します。モデルが良いかどうかを確認するためにテストをします。テストでは過学習が発生していないか確認することができます。全てのデータを訓練用、テスト用に分割し、両方のデータセットでいい予測結果が出ることが望ましいです。テスト用データを訓練用データに使うべきではありません。

実装

  • train_test_split(X, y, test_size=0.2)を使ってデータを分割します。

Lesson 7 Evaluation Metrics

Confusion Matrix

Positive/Negativeはラベルデータで、True/Falseは予測結果が正しいかどうか。TP=True Positiveは実際Positiveだし予測結果もTrue。TN=True Negativeは実際Negativeだし予測結果もTrue。FP=False Positiveは実際はNegativeなんだけどPositiveと予想し予想結果がFalseのもの。FN=False Negativeは実際はPositiveなんだけどNegativeと予想し予想結果がFalseのもの。

Accuracy

Accuracyはモデルがどれぐらい良いか測るもの。どれぐらい正確に分類できたか。どれぐらい正しいか。全体のデータ数のうち、正しく予測できたものつまりTrueのものの割合であり、Accuracy=(TP+TF)/ALLとなる。accuracy_score(y_true, y_pred)で計算可能。ただしモデルがほとんどの場合の予測は正しいが、たまに間違えるようなケースで、その間違いを指標で表したいとするとデータ数が多くなった時に誤りの数が極めて少ないと指標には現れません。その場合はAccuracyを使うことは不適当です。

Precision

例えばスパムメールにおいてはFP(=実際はスパムでないがスパムとして破棄してしまうこと)は許容できないが、FN(=実際はスパムだがスパムではないと分類すること)は許容できる。このFPを見る指標としてPrecisionを使うことが出来る。Precision=TP/(TP+FP)。TPをTPとFP(=実際はNegativeだがPositiveと予測したもの)で割る。HighRecallモデル(=FPは許容できる)ではこの値は重要ではない。

Recall

例えば診断においてはFP(=実際は病気ではないが病気と診断すること)は許容できるが、FN(=実際は病気なのに病気ではないと診断すること)は許容できない。このFNの具合を見る指標としてRecallを使うことが出来る。Recall=TP/(TP+FN)。TPをTPとFN(=実際はPositiveだがNegativeと予測したもの)で割る。HighPrecisionモデル(=FNは許容できる)ではこの値は重要ではない。

F1 Score

PrecisionとRecallを一つのスコアで表すことを考えたのがこのF1スコア。F1 Score = 2 * Precision * Recall / (Precision + Recall)。普通に平均を取ってしまったらあまり特徴を表さない値になってしまうので、調和平均を取っている。これは低い値に近づくような平均の取り方になっていて、どちらかが低いとそれがわかるようになっている。

F-beta Score

F1 Scoreをもう少し一般化する為に、例えばF0.5 Score等を考えます。これはFbeta = (1+beta^2) * Precision * Recall / (beta^2 * Precision + Recall)で表されます。beta→0にするとこれはPrecisionになります。逆にbeta→∞にするとRecallになります。特にbeta=1の場合は調和平均です。このbetaの値は対象とする問題によってどちらが重要か考え、それに基づいて調整することが望ましいです。

ROC(Receiver Operating Characteristic)

データの境界線を引くときにTPとFPがすべてのデータに対してどのぐらいあるかを考えます。そしてデータの境界線を動かしていきます。両端では(TP ratio , FP ratio) = (1,1), (0,0)となります。完全に分類できた場合は(1,0)になります。また境界線を動かした時の値をプロットし、それが囲む領域の面積を考えると、ランダムモデルの時は0.5、完全なモデルの時は1、良いモデルの時はその間の値となります。つまり、その面積を1に近づけるようにするのが望ましく、それをメトリクスとしてモデルを調整するという方法もあります。

回帰モデルのメトリクス

回帰式からの距離の絶対値の平均を求める方法があります。mean_absolute_error(y, guess)です。実際これは良い方法ですが、値は微分可能でない場合もあり、あまり良くありません。そこでmean squared error=MSEを考えます。mean_squared_error(y, guess)です。他にもR2スコアというよく使われるものもあります。R2スコアは最も簡単なモデルとの比較によって算出されるものです。最も簡単なモデルとしてはデータの平均値で水平に分割し、その水平線からのMSEを算出するようなモデルです。この簡単なモデルからのMSEがもっと詳細にデータを表す検討中のモデルのMSEよりも大きくなるというのが考え方のベースです。なので、それをalpha = 検討中のモデルのMSE / 最も簡単なモデルのMSEという比の形で表すと、R2 = 1 - alphaとすることができます。即ち、悪いモデルでは最も簡単なモデルのMSEと同じになるのでalpha=1でありR2=0となります。反対に良いモデルでは簡単なモデルよりもはるかに小さいMSEになることが考えられ、alpha=0となり、R2=1となります。sklearnではr2_score(y_true, y_pred)です。

Lesson 8 Detecting Errors

Types of Errors

モデルを簡単にしすぎるとUnderfittingが発生し、モデルを複雑にしすぎるとOverfittingが発生しやすくなります。UnderfittingはHigh Biasによって発生します。本当は多項式なのに、直線でフィッティングしてしまうようなものです。このとき、Trainingデータでの結果が悪くなり、同時にTestデータの結果も悪くなる傾向にあります。OerfittingのエラーはHigh Varianceによって発生します。本当は二次関数なのにより高次の多項式で表現してしまうようなものです。この時、Trainingデータでの結果が非常に良くなるが、Testデータでの結果が悪くなる傾向にあります。良いモデルはTraining/Testどちらのデータでも良い結果を出すモデルです。

Model Complexity Graph

モデルの複雑度を変えていった時のTraining/Testエラーの推移をみます。どちらのエラーも高い場合、それはUnderfittingです。Trainingエラーの値は低いが、Testエラーの値が大きい場合、それはOverfittingです。その丁度良いところを選ぶのが良いモデルの選択です。ただし、テスト用データでトレーニングしてはいけません。そこでデータを3つに分割し、Cross Validation用のデータを更に分けます。これはどのモデルを使うか判定するのに使います。Testエラーの値の代わりにこの値の推移をモデルの複雑度に合わせて確認します。良い位置の探し方は先程と同じようにして両方が良い値のところを探します。

K-Fold Cross Validation

データを複数のデータセットに分けて、それぞれのデータセットのTraining用データとTest用データへの割り当てを組み替えて学習させるやり方を使う場合もあります。特にデータセットに分ける代わりにランダムにピックアップする方法でも実現できます。これはKFold(12, 3, shuffle=True)です。

Learning Curves

High Bias(=Underfitting)モデルの場合、TrainingエラーとCVエラーはどこかの漸近線に収束しますが、どちらも高い値になります。良いモデルの場合、どちらのエラーも小さい値に収束します。High Variance(=Overfitting)モデルの場合、その2つの値にはギャップがあります。これらの情報からモデルがどのような状態か推察することが可能です。

Lesson 9 Putting it all together

Grid Search

データをTraining/CV/Testingに分けてモデルの複雑度を変えていきます。例えばメトリクスとしてF1Scoreを採用します。ロジスティック回帰の場合、回帰式の次数、決定木の場合はモデルの深さ、SVMの場合はKernelの種類とγの値を変えることでモデルの複雑度を変えることが出来ます。これらをテーブルにしてそれぞれの場合のスコアを求める方法をGrid Searchと呼びます。

Summary

ここまでで問題に対してアルゴリズムを選んで、そしてそのアルゴリズムのパフォーマンスを評価する指標を見てきました。指標はAccuracy, Precision, Recall, F1 Score等がありました。そしてモデルの学習を見比べる基準としてModel Complexity GraphやLearning Curves等がありました。これらを使って個別のタスクを勉強していきます。

Practice: Naive bayes

Naive bayesを使ったSpam判定です。以下はGitHubのリンクですが、作業は反映していません。
machine-learning/Naive_Bayes_tutorial.ipynb at master · romth777/machine-learning · GitHub

  1. データの前処理
  • まずデータを見て、ラベルデータを分類します。ham=0, spam=1とします。
  • Bag of Words(BoW)コンセプトを適用し、文章を単語ごとに分割し、その単語の出現頻度を数えます。順番は関係ありません。これを一文毎に行います。それにはsklearnのcount vectorizerを使うと便利です。これは単語にIDを割り振って、そのID毎に出現数を数えます。ただし、大文字と小文字の区別はデフォルトでは行いません(parameter:lowercase)。また句読点や感嘆符も無視します(parameter:token_pattern)。更に良くある単語、例えばam, an, and等は無視することもできます(parameter:stop_words)。無視する単語はあらかじめ設定されています。これらはcount_vector=CountVectorizer()とした後に、count_vector.fit(documents)でcount_vector.transform(documents).toarray()です。count_vector.get_feature_names()でtokenを取得することもできます。
  • これを自分で実装するにはまず文章をすべて小文字にして、句読点、感嘆符を削除し、スペースを区切り文字として単語を分割し、出現回数をカウントします。カウントにはCounterを使うと良いです。
  • 他にも同法の方法としてTfidfVectorizerというものもあります。
  1. トレーニング
  • train_test_splitでデータを分割する
  • 分割したデータに対してCountVectorizerを適用する
  1. モデルの作成
  • 今回はmultinormal Naive Bayesを使う。これは入力の特徴量が不連続な値(例えば整数だけとか)の場合に有効です。一方でGaussianNBは連続な値で、かつ入力データがガウス分布の場合に有効です。model=MultinormalNB()でmodel.fit(training_data, y_train)、model.predict(testing_data)とします。
  1. 評価
  • Accuracy, Precision, Recall, F1値を算出します。ACC=0.99, Pre=0.97, Rec=0.94, F1=0.96となりました。比較的すべての値が高いので、良いモデルの作成が成功しているように見えます。AccはTP+TN、PrecisionはFP、RecallはFNの割合をそれぞれ示しています。1に近ければ間違いが少ないといえます。
  1. まとめ
  • Naive Bayes分類モデルの特徴は大きな数の特徴量を扱えることです。今回の場合は1000ぐらいの異なる単語がありました。また、意味をなさない特徴量があっても使えます。そして、単純です。このモデルは通常、データの分布が分かっている場合を除いてパラメータ調整の必要がほとんどありません。さらに、トレーニング、テスト用の処理時間も高速です。

Project Predicting Boston Housing Prices

このプロジェクトではボストンの住宅価格を予測するモデルを作りました。
machine-learning/boston_housing.ipynb at master · romth777/machine-learning · GitHub

  1. 前処理
  • 住宅価格について最小、最大、平均、中央、分散を算出
  • それぞれの特徴量が住宅価格にどのような影響を及ぼすか仮説を立てました
  1. モデル開発
  • メトリクスとしてR^2を採用。今回は回帰分析タスクになる。sklearnではr2_score(y_true, y_predict)
  • train_test_splitでデータを分ける。引数のrandom_stateは固定値にしておくとデータの再現性ができて良い。test_sizeは0.2とした。
  • 今回は決定木モデルを使ことにした。その場合のスコアについて考察。それぞれのスコアの振る舞いに応じてモデルがUnderfittingかOverfittingか適切か考察した。
  • 同様にModelComplexityカーブを算出した。このカーブからは両方が高く、その差が少ないところが良いモデルだといえる。
  1. モデルパフォーマンスの評価
  • GridSearchCVを使ってモデルのパラメータ毎のメトリクスを評価した。メトリクスは前述の通りR^2スコアを用いた。
  • 新しいサンプルデータを使って売値の予想を行った。ここでは似たような元データを引っ張ってきてその特徴量と新しいサンプルデータの特徴量が大体同じもので大体同じ売値になったから妥当だといえばよかったかもしれない。
  • モデルのロバスト性について評価を行った。似たようなデータセットを与えてその時にデータがどの程度ばらつくか評価した。
  • 他にも考えられる事として、1978のデータから今日のデータを予測できるか、特徴量は十分か、モデルのロバスト性は十分か、ボストン以外の場所で取得したデータをこのモデルに当てはめるとどうなるかについて考察した

以上
②教師あり学習に続く......