オートエンコーダー(AE)とクラスタリングの実装

4、8、16次元の任意の特徴を持つベクトルのデータセットを作ります。それらをオートエンコーダーで2次元ベクトルに変換して、クラスタリングすることを目的とします。ラベリングはわかっているので、最後にこれらを並べて描画して、精度を確認します。

 

オートエンコーダー(AE)とは自分自身を教師データとしてニューラルネットワークを学習することで、特徴を抽出する手法のことです。今回はこれで次元圧縮を行います。

 

AEとChainerについては以下の本を参考にしました。

shop.ohmsha.co.jp

 

 

1:学習するデータを作る

2:オートエンコーダーで学習して2次元ベクトルにする

3:クラスタリングする

4:ラベリングと比較して、精度を確認する

 

この流れで説明します。

 

作成したプログラムは全てgithubに上げてあります。

github.com

 

 

          1:学習するデータを作る

 

1から10の数字がランダムに入った8、16次元ベクトルを作ります。8次元ベクトルは2つずつ、16次元ベクトルは4つずつ、マイナスにします。こうすることで、それぞれ4クラスずつ、データを作ります。

 data_create.pyです。

 

          2:オートエンコーダーで学習して2次元ベクトルにする

 

train3.pyでは8次元ベクトルをオートエンコーダーで2次元ベクトルに変換して、ラベリングはわかっているので、クラスごとに色付けて、グラフに描画しました。

train4.pyでは16次元ベクトルを2次元です。後は同様です。

train5.pyでは16次元ベクトルを6次元にして、その6次元ベクトルを、2次元にします。後は同様です。

train3.py、train4.py、train5.pyです。 

描画結果は4で示します。

 

          3:クラスタリングする

 

ラベリングはわかっていないものとしてtrain5.pyで変換された2次元ベクトルにクラスタリングを行います。 

 

クラスタリングするために、sklearnをインポートします。

使うアルゴリズムはkmeansです。この手法はあらかじめクラスタ数がわかっている必要があります。最初にクラスタ数分の中心点をランダムに設定します。その中心点から各点の距離を考えて、それぞれの点をクラスタに分類します。その後、それぞれのクラスタの重心を求め、その位置で中心点を更新します。これを繰り返します。これがkmeansです。

 

機械学習の手法については別記事でまとめてあります。

person.hatenablog.jp

 

scikitlearnでkmeansを使う方法について、以下の記事を参考にしました。

 

1: scikit-learn でクラスタ分析 (K-means 法) – Python でデータサイエンス

2: paiza.hatenablog.com

 

作成したプログラムはcluster.py です。

最後はクラスタごとに色を付けて、グラフに描画しています。

 

 

          4:ラベリングと比較して精度を確認する

 

 

f:id:wada0421514:20180406211505p:plain

 

8次元ベクトルをAEで2次元に変換したやつです。左がラベリングで、右がクラスタリングの結果です。クラスタリングがほとんどうまくいっていることがわかります。(train3.py)

 

 

f:id:wada0421514:20180406211914p:plain

 

16次元ベクトルをAEで2次元に変換したやつです。左がラベリングで、右がクラスタリングの結果です。クラスタリングがかなりうまくいっていることがわかります。(train4.py)

 

f:id:wada0421514:20180406212437p:plain

 

16次元ベクトルをAEで6次元に変換して、それを2次元に変換したやつです。左がラベリングで、右がクラスタリングの結果です。色とマーカーが対応してないです。すいません。AEによるデータ圧縮があんまりうまくいっていない感じです。直感的に、間に6次元を挟んであげることで、特徴をとらえやすくなるかと考えましたが、ダメでした。(train5.py)

 

 以上、AEとクラスタリングでした。AEは思った以上に圧縮がうまくいっていたので良かったです。クラスタリングをするのにsklearnを使いましたが、思った以上に使いやすく、驚きました。

 

アドバイス、改善点、質問があればお願いします。

ChainerでCNN使って画像分類2-学習、精度確認-

犬が画像に写っているかどうか判定することを目的とします。ChainerでCNNを使います。やっていることは、以前書いたTensorflowの記事と同じです。

 

person.hatenablog.jp

 

 

ChainerでCNN使って画像分類1-データ用意-から続きます。

 

person.hatenablog.jp

 

1では、用意した画像を配列に変換して、訓練データ、テストデータをファイルに保存しました。

2では学習を行い、精度を確認します。

 

作成したプログラムは全てgithubに上げてあります。

github.com

 

 

2:学習、精度確認

 

ファイルに保存された訓練データとテストデータを読み込んで、学習します。Chainerお決まりの書き方があるのでそれに従いました。 クラスMyModelの部分です。

 

精度は6、7割くらいです。かなり悪いです。層が浅い、工夫なし、学習短めですので仕方ないと思います。前回同様、実際に体験することを目的としているので良いです。暇があったら精度向上に取り組もうと思います。

 

Chainerはシンプルで使いやすいです。Tensorflowに比べて、エラーも見やすいです。エラーは次元に関わるものが多かったです。加えて、注意点についてです。

 

注意点

・(28,28,3)ではなく、(3,28,28)にする必要があること

・インプットはバッチ形式

・ソフトマックスクロスエントロピー誤差はクラス番号ラベル

 

こんな感じです。アドバイス、改善点があればお願いします。

 

 

ChainerでCNN使って画像分類1-データ用意-

以前、TensorflowでCNN使って、犬の画像分類をやりました。それと同じことをChainerで実装しました。

 

person.hatenablog.jp

 

作成したプログラムは全てgithubに上げてあります。

github.com

 

家で飼っている犬の写真が1000枚程たまったので、ネットから集めた画像1000枚と合わせて2000枚を学習データとします。

犬が画像に移っているかどうかを判定することを目標とします。

 

ChainerはTensorflowより、使いやすかったです。

 

以下の本を参考にしました。

shop.ohmsha.co.jp

 

この本は、numpy、基礎的なChainer利用、Trainer、NN、CNN、word2vec、RNN、LSTMなどを取り上げています。Python2ですが、コードも数式も扱っているので、オススメです。

 

以下の2ステップで行います。

 

1:データ用意

2:学習、精度確認

 

 

1:データ用意

 

person.hatenablog.jp

 

上の記事とやっていることはだいたい同じです。画像を集めたり、整えたりするところは割愛するので、上の記事を見てください。

 

(28,28)の犬のjpg画像901枚をファイルlattteに、(28,28)の適当なjpg画像1101枚をファイルotherに用意できたところから始めます。

 

gazo2vec.pyの関数jpg_2_tensorはファイルのjpg画像を読み込んで、クラスごとに配列として保存します。

vec2train.pyの関数tensor_2_allはクラスごとに保存された配列データを訓練データ、テストデータに分けて保存します。

 

これらの関数をtrain_data_hozon.pyから使って、訓練データ、テストデータをファイルに保存しました。tensorflowでは(28,28,3)でしたが、chainerでは(3,28,28)にする必要があるので、それもここでやりました。

 

損失関数にソフトマックスクロスエントロピー誤差関数を使うので、label_cov.pyで、one-hotラベルを、クラス番号ラベルに変換して、ファイルに保存します。

 

これで、(3,28,28)の訓練データ、テストデータとクラス番号ラベルの訓練教師データ、テスト教師データをファイルに保存できました。学習の準備は完了です。

 

ChainerでCNN使って画像分類2-学習、精度確認-に続きます。

person.hatenablog.jp

 

機械学習の手法、チートシートの解説

 

f:id:wada0421514:20180317101035p:plain

 

いわゆる古典的な機械学習についてあまり勉強したことがなかったので、足掛かりとして、アルゴリズムチートシートの理解から勉強を始めることにしました。このあと、kaggleに取り組みたいと考えています。

 

上記の機械学習アルゴリズムチートシートについて解説します。数式、コードは出てきません。直感的な理解を意識したので、間違っている可能性も結構あります。

 

主に以下の記事を参考にしました。

qiita.com

 

 

以下のリンクはscikit-learn公式による詳しい説明です。

http://scikit-learn: machine learning in Python — scikit-learn 0.19.1 documentation

 

 

説明の順番

 

1:クラス分類

2:クラスタリング

3:回帰

4:次元圧縮

5:その他の有名な手法

 

 

          1:[クラス分類(classification)]、教師あり学習 

f:id:wada0421514:20180317102110p:plain

 

/SGD(Stochastic Gradient Descent)classifier

確率的勾配降下法と言います。データを識別平面で分けることを考えます。識別平面の係数を学習します。データを一つずつ学習するので確率的と言います。識別結果と教師データから損失関数を算出して、それを減少させるようにパラメータを更新します。損失関数のパラメータの勾配を求めて、それをパラメータから引いて、パラメータを更新するということを行います。だから、勾配降下法です。

 

/LinearSVC

SVMによる線形な(linear)Classificationという意味です。SVM(Support Vector Machine)を使って線形な識別平面を求めてクラス分類します。SVMとは識別平面と、各クラスの最も近いデータの距離を最大化することでパラメータを得る方法です。

 

/(kernel)SVC
順番が飛びますが先にSVCについて説明します。SVCとだけ言うと、基本的に、kernelSVCのことを指します。これは、高次元空間にデータを写像して、SVMする手法です。カーネルによって、高次元空間に明示的に訪れることなく、必要な計算が可能になります。

home.hiroshima-u.ac.jp

 

enakai00.hatenablog.com

 

qiita.com

 

/カーネル近似(kernel approximation)

kernelSVCはデータ数が多いと計算コストが高すぎて使えません。それを乱数による近似で解決する手法です。細かい部分はよくわかりませんでした。

 

/K近傍法(K Neighbors Classifier)

識別したいデータから、近くにあるK点を選んで、その中で一番数が多いクラスに分類する手法です。

 

/Ensemble Classification、ランダムフォレスト

 ここでは、一番よくあるアンサンブル学習としてランダムフォレストを説明します。
ランダムフォレストは決定木を使います。決定木はYESかNOで質問に答えて枝分かれすることを繰り返して分類します。ジニ不純度やエントロピーで誤差を測ってパラメータを調整します。各決定木は全データnからそれぞれ異なるデータmを用いて学習します。そうしてできた複数の決定木の多数決でクラス分類する手法です。

mathwords.net

 


/ナイーブベイズ(Naive Bayes)

ニュース記事などのクラス分類に用いられる方法です。ナイーブとは各単語を独立であると仮定することを意味します。内閣というワードが含まれる記事は政治クラス、野球だったらスポーツクラスに分類される確率が高いです。クラス1の学習データよりクラス2の学習データにゲームという単語の出現回数が多かったら、テストデータでゲームという単語を含む記事はクラス1よりクラス2に分類される可能性が高いだろうということです。これを全部の単語に対して行います。こういった考え方を使ってベイズ推定する方法です。

ベイズ推定とは、最尤法に加えてベイズの定理をもとに事前確率も考慮して確率分布のパラメータを求める方法です。

www.anlyznews.com

 

 
        2:[クラスタリング]、教師なし学習 

f:id:wada0421514:20180317104225p:plain

 

/KMeans
予めクラスタ数がわかっている必要があります。アルゴリズムに基づいて、適当にクラスタ数分の中心点を生成します。各データを、最も近い中心点のクラスに分類します。分類した各クラスの重心を求めて、中心点とします。中心点が動かなくなるまで、クラス分類、中心点求める、を繰り返します。


/スペクトルクラスタリング
予めクラスタ数がわかっている必要があります。データのつながりを考えて、グラフで表現します。このグラフを行列で表現します。こうしてできたグラフ行列をスペクトル分解と呼ばれる固有値分解のようなことをして、グラフ行列の固有値ベクトルを求めます。この固有値ベクトルを結合してできた固有値ベクトル行列をKMeansでクラスタリングします。


/GMM
予めクラスタ数がわかっている必要があります。KMeansと同じことをガウス分布で行います。これらの手法をEMアルゴリズムと言います。クラスタ数分の分布を適当に決めます。最も所属する確率の高い分布に各データを分類します。各分類されたデータを生成する確率の最も高い分布を求めます。分類、分布生成を変化がなくなるまで繰り返します。分布の推定には最尤法を使います。

最尤法とは、観測されたデータの確率の積(尤度)を最大化して、データを説明する確率分布のパラメータを求める方法です。

uncorrelated.hatenablog.com

 

 

/MeanShift
予めクラスタ数がわからなくてもよいです。クラスタ数を指定せずにKMeansを行う方法です。既定の距離より近くなったクラスタは合体して1つにします。


/VBGMM
変分ベイズとGMMを合わせたような方法です。クラスタ数はベイズ推定で求めます。分布の推定にはベイズ推定を使います。

 

 

        3:[回帰](regression) 

f:id:wada0421514:20180317105350p:plain

 

/SGD Regressor

分類のsgdとやっていることは同じです。誤差の指標となる損失関数の減少を目指します。損失関数のパラメータの勾配によって、パラメータを更新します。


/Lasso

損失関数にL1ノルムを加えて、パラメータを学習する方法です。パラメータはスパースになりやすいです。

ノルムについて説明します。特定の点からある点までの距離を表すのがノルムです。L2ノルムは各データのノルムを2乗した値の和です。L1ノルムは各データのノルムの絶対値の和です。

blue-intelligence.cocolog-nifty.com

 

/Ridge

損失関数にL2ノルムを加えて、パラメータを学習する方法です。

 

/ElasticNet

損失関数にL1ノルムとL2ノルムを加えて、パラメータを学習する方法です。それぞれに係数をかけて影響を調節します。

 

/linearSVR

SVMで線形に回帰します。回帰直線とデータの誤差の最小化でパラメータを学習します。特徴は一定距離まで誤差を考慮しないことです。

 

/SVR

カーネルを利用して高次元空間にデータを写像してSVMで回帰します。

 

/Ensemble Regressors
分類と同様にランダムフォレストがよく使われます。ランダムフォレストで、分類と同じことを回帰でします。

 

 

        4:[次元圧縮]

f:id:wada0421514:20180317111935p:plain

 

/PCA
主成分分析と言います。分散が大きい方向を見つけて、その方向に新しい
軸を設定する方法です。この時、固有値分解を使います。

bdm.change-jp.com

 

/kernelPCA
カーネルを使って非線形変換してから、PCAを使う方法です。

 

/Spectral Embedding
スペクトラルクラスタリングとしていることは同じです。データのつながりを意識して、グラフ行列を作り、これを固有値分解して、固有値ベクトルを得ることで、次元を圧縮します。


/Isomap
3次元空間上のデータを考えるとき、そのデータがとある平面上(多様体)に分布していたとすると、そのデータは2次元で表すことができます。これと同じ事をn次元で行います。

www.slideshare.net

 

/LLE
多様体の考え方を使うのは、Isomapと同じです。それに加えて、拘束条件が加わるみたいです。

 

 

        5:[その他の有名な手法]

 

1:K-fold cross validatio
データをk個のグループに分けます。k-1個のグループのデータでパラメータを推定して、残りの1つで検証します。これをk回繰り返す方法です。

 

2:XGBoost

まず、GB(Gradient Descent)について説明します。GBとは複数の弱学習器を使ってアンサンブル学習するときにパラメータの更新に勾配降下法を使う手法です。ブースティングは弱学習器を1つずつ順番に構築することを意味します。

smrmkt.hatenablog.jp

 
上記のGBとランダムフォレストを組み合わせた手法です。弱学習器として
決定木を用いるということです。

qiita.com

またXGBoostではGBではなくて後述のNewtonBoostingを使うこともあるそうです。

NewtonBoostingとは勾配降下法ではなく、ニュートン法を用いて学習する手法です。
        ニュートン法は、接線による近似を繰り返す方法です。

qiita.com

 

3:グリッドサーチ
ハイパーパラメータを最適化する方法です。
組み合わせを全部試してみて、一番良いハイパーパラメータを決定します。

 

以上です。機械学習の手法について何となくわかりました。

アドバイス、改善点があればお願いします。

 

 

 

深層学習のブレークスルーと流行

 

深層学習の流行の始まりがわからなかったので、いろいろ調べました。

その結果わかったことをまとめます。かなり雑かもしれないです。間違っている可能性もあります。ぼくの勝手な解釈も入ります。

 

 

昔から、ニューラルネットワークの開発は色々行われていた。層を深くすれば精度が上がりそうであることがわかった。しかし、勾配消失問題のせいで深くできない。だめだ。ニューラルネットワーク下火になる。

 

2006年にトロント大学のヒントン先生がDeep Belief Networkを発表した。これを使った事前学習で、勾配消失問題が回避できるらしい。ニューラルネットワーク、深層学習に注目が集まった。

 

2012年にヒントン先生の教え子、Alexさんが中心となって作ったAlexNetがILSVRC2012でその他の古典的手法に大きく差をつけて優勝した。AlexNetはLeCunさんの研究論文をもとに作られたCNNである。LeCunさんのその研究は福島さんのネオコグニトロンをルーツに持つらしい。この歴史的優勝によって、深層学習研究に火が付いた。

 

こんな感じです。

 

実際、2013年以降のILSVRCは2012年の結果を受けて、上位チームのほとんどがCNNだったらしい。この例からも、ニューラルネットワークの流行り具合が明らかです。

 

 

わかりにくいですが、2012年のAlexNetにヒントン先生のDBNによる事前学習は行われていません。もともと、CNNは事前学習を必要としないからです。この辺がわかりにくかったです。2006年と2012年は直接は繋がってないです。

 

 

リバストのブログ Deep Learningの概要

 

こちらの記事を主に参考にしました。後、深層学習の青本も参考にしました。以上です。

 

改善点、アドバイスがあればお願いします。

 

2017年4月、大学一年始めから、2018年2月、大学1年終わりまでの振り返り

 

11ヵ月間でやったことをまとめます。現在は2018年2月13日です。

下記の記事と一部、重複します。

 

person.hatenablog.jp

 

以下の4つの期間に分けます。

 

1:2017年4月から2017年8月(大学一年春学期)

2:2017年9月から2017年10月(夏休み)

3:2017年11月から2018年1月(大学一年秋学期)

4:2018年2月(春休み)

 

 

1:大学一年春学期:

 

大学の勉強に結構時間を使いました。

 

2:夏休み:

 

Pythonの勉強をして、deeplearningの本を読んで、tensorflowを試しました。

 

3:大学一年秋学期:

 

秋学期前半で、別記事にある、CNNの実装を行いました。並行して、深層学習の本も読みました。一度、ニューラルネットワーク系の勉強会に参加しました。春学期同様、大学の勉強に結構時間を使いました。

 

4:春休み:

 

いくつか目標を設定しました。達成できるように頑張りたいです。

 

 

アドバイス、改善点があればお願いします。

chainerでsin関数の非線形回帰

名前の通りです。chainerを使って、ニューラルネットワークによるy=sin(x)の非線形回帰を行います。

 

作成したプログラムは全てgithubに上げてあります。

github.com

 

qiita.com

 

こちらのリンクを参考にしました。というより、ほぼそのままとなっています。備忘録的に自分のブログにまとめさせていただきました。自分が必要な部分だけやったので、こちらのリンクより内容は軽くなっています。

 

説明はコメントアウトでします。 

Mychain.pyでパラメーターと伝播の仕方をクラスとして用意します。

practice.pyで学習データの用意と、学習を行います。

 

誤差関数の更新の様子は以下のようになりました。

 

f:id:wada0421514:20171208103652p:plain

 

以上です。

 

qiita.com

 

上のリンクを参考にしました。再度、貼っておきます。

 

chainerでsin関数の非線形回帰をしました。

chainerはTensorflowと比較して、使いやすかったですし、かかった時間も短く感じました。理由として、tensorflowはセッションなどの概念が複雑であるので、まず慣れるの時間がかかったこと、エラーが起こりやすく、かつ、検出しにくかったことが挙げられると思います。pythonで初めてニューラルネットワークを利用する場合は、個人的にchainerをお勧めします。

 

アドバイス、改善点がある場合はお願いします。