Python

【入門】ディープラーニングとは?仕組みとPythonでの実装を見ていこう!

ウマたん
ウマたん
本記事では、ディープラーニングの仕組みやPythonでの実装方法について解説していきます。ディープラーニングってなんとなくブラックボックスなイメージがあるかもしれませんが、実はシンプルなアルゴリズムなんですよー!

こんにちは!

消費財メーカーでデジタルマーケ&データサイエンティスト的なお仕事をしているウマたん(@statistics1012)です。

最近はどっぷりディープラーニングに浸かっています。

ロボたん
ロボたん
ディープラーニングって良く聞くけどイマイチどういうモノなのか分かっていないんだよなー!
ウマたん
ウマたん
ディープラーニングという言葉自体はバズワードになっているんだけど、その実態についてはあまり知られていないんだよねー!

僕自身、前はディープラーニングについてそれほど詳しい知識を有しておらずアルゴリズムに関しても曖昧な理解でした。

ディープラーニングのアルゴリズムをブラックボックス的なモノだと考えている方も多いでしょう。

しかし!ディープラーニングの仕組み・考え方は非常にシンプルなのです。

この記事では入門と題していますが、ディープラーニングの基礎的な仕組みからPythonでの実装まで見ていきます。

ウマたん
ウマたん
Pythonの勉強は以下の記事をチェック!
【独学入門】初心者が3か月でPythonを習得できるようになる勉強法!当ブログ【スタビジ】の本記事では、Pythonを効率よく独学で習得する勉強法を具体的なコード付き実装例と合わせてまとめていきます。Pythonはできることが幅広いので自分のやりたいことを明確にして勉強法を選ぶことが大事です。...

ディープラーニングとは

まずはディープラーニングについて簡単に見ていきましょう!

ウマたん
ウマたん
動画でも10分ほどで分かりやすく解説しているのでぜひチェックしてみてください!

ロボたん
ロボたん
ディープラーニングって最近になってよく聞くようになったよなー!
ウマたん
ウマたん
実は、、、ディープラーニングらしきものはだいぶ昔からあったんだよー!

実は、ディープラーニングの原型は1940年代から存在していたと言われています。

ロボたん
ロボたん
え!?そんなに昔からあるの!?
ウマたん
ウマたん
そうなんだよー、最新の技術だと思われているんだけど既に理論自体はだいぶ昔から確立されていたんだ!

1940年~1950年にかけて人間の神経を模した仕組み「ニューラルネットワーク」が確立されました。

人間の神経が信号を伝播させていくようにある入力を次の層へと重み付けをして伝播させていき出力を求めます。

ロボたん
ロボたん
なんで今さら50年以上も前の手法が注目されてるの?
ウマたん
ウマたん
当時の状況では層を積み重ねていくことができなかったんだ!

この層を多層にしていくのがディープラーニングなのですが、当時のマシンパワーでは計算量が膨大過ぎて実現不可能でした。

計算負荷を軽減する誤差逆伝播法(バックプロパゲーション)などの計算手法の登場やマシンパワーの増強により現在に至ります。

そんな計算負荷の問題が解消され深層ニューラルネットワーク(ディープラーニング)が日の目を浴びたのは2006年。

このブレークスルーによって再びAIのブームが巻き起こり、第3次AIブームへと突入していくのです。

AIの歴史については以下の記事でまとめていますのでよければご覧ください!

人工知能(AI)とは?ビジネスに活かすためにはどうすればよいのか? こんにちは! ウマたん(@statistics1012)です。 大学院時代は統計科学を専攻しており、現在は消費財メー...

ディープラーニングの仕組み

さて、そんなディープラーニングですがどのような仕組みで成り立っているのでしょうか?

先ほど人間の脳を模した仕組みと述べましたが実際にどのようなカタチで信号が伝播していくのか、そしてその伝播をどのようにチューニングしているのか簡単に見ていきたいと思います。

ロボたん
ロボたん
結構難しそうだなー・・・
ウマたん
ウマたん
一見難しそうだけど、そんなことはないんだよー。単純な考え方が基になっているんだ!

ディープラーニングの基礎を学ぶ上では以下の書籍が非常に参考になります!

あまりにも有名ですが、是非目を通してみてください。こちらの記事でもこの書籍を参考にしていきます。

ディープラーニングの基本を理解する上で押さえておかなくはいけないのは以下の3点。それぞれについて見ていきます。

・パーセプトロン
・活性化関数
・損失関数と勾配法

パーセプトロン

パーセプトロンとは1957年にアメリカの研究者であるローゼンブラットによって考案されたアルゴリズムです。

パーセプトロンがニューラルネットワークに発展しそこから近年のディープラーニングへと繋がっているのです。

ニューラルネットワークそしてディープラーニングについて学ぶためには、まずはパーセプトロンについて押さえておく必要があります。

パーセプトロンは以下のようなイメージ。

入力\(x_1\)と\(x_2\)に対して重み\(w_1\)と\(w_2\)が掛け合わされ足されます。

そして、足しあわされた値がある閾値を超えれば\(y\)の出力値が変わるモデルです。

閾値を\({\theta}\)と置き数式で書くと以下のようなモデルになります。

\begin{eqnarray} y= \left\{ \begin{array}{l} 0   (w_1x_1+w_2x_2<=\theta) \\ 1   (w_1x_1+w_2x_2>\theta) \end{array} \right.\end{eqnarray}

この数式をグラフにすると以下のようになりステップ関数と呼びます。

このパーセプトロンに関して真理表を用いた例をPythonでの実装例を含めて「ゼロから作るDeep Leaning」で分かりやすく教えてくれるので興味のある人は是非読んでみてください!

活性化関数

パーセプトロンでは、ある閾値を超えた場合に1を出力し超えなければ0であるというステップ関数を用いていました。

これらのインプットからアウトプットに変換する関数を活性化関数と呼び、ディープラーニングを学ぶ上では非常に重要になります。

ディープラーニングでは、活性化関数に様々な関数を用います。

代表的な活性化関数について、それぞれどのような特徴があるのか見ていきましょう!

シグモイド関数

シグモイド関数は以下のロジスティック回帰分析に登場する関数であり出力を線形的に捉えることが可能です。以下のような関数になります。

$$ y= \frac{1}{1+exp(-x)} $$

シグモイド関数の意味は、ある入力に対する出力を0~1の範囲に抑えること。

グラフは以下のようになります。

ステップ関数では一定の閾値を超えないと計算結果の大小に限らず同じ値が出力されてしまいますが、シグモイド関数を用いれば微妙な大小を出力の段階で捉えることが可能です。

ロジスティック回帰分析と通常の判別分析の違いと同じですね。

シグモイド関数と似た関数で、Tangent関数があります。

Tangent関数はx,y=(0,0)であるのに対して、シグモイド関数はx,y=(0,0.5)であることが特徴です。

RELU(ランプ)関数

RELU関数は0より小さい場合は0を出力し、0より大きい場合はそのまま計算結果を出力するという特殊な関数です。

\begin{eqnarray} y= \left\{ \begin{array}{l} x   (x>0) \\ 0  (x<=0) \end{array} \right.\end{eqnarray}

単純なため計算速度が速いことと、マイナスの値をノイズと捉えたい場合は有用な活性化関数です。画像認識の場面ではマイナスはノイズになるのでRELU関数を用いられることが多いです。

出力層の活性化関数としては非常に貧弱なので、出力層では用いられることはほぼありません。

隠れ層の活性化関数として用いられます。

グラフは以下のようになります。

どの活性化関数を用いるかは状況によって違いますが、活性化関数によっては結果が大きく変わってくるので慎重に選ぶことが必要です。

損失関数と勾配法

ディープラーニングでは、基本的にパーセプトロンの考え方で層を積み重ね活性化関数を用いて出力を変化させます。

言ってしまえばそれだけです。

構造は分かりましたが、最適な重みを見つけるためにはどうすればよいでしょう?ここで登場するのが「損失関数と勾配法」という考え方です。

損失関数とはその名の通り損失を定義した関数。ここで言う損失とは何か。

ディープラーニングの層の最終出力と実測値の差

これが損失になります。

損失には二乗誤差やエントロピー誤差が使用されますが基本的には出力と実測値の差を示していると考えて問題ございません。

出力と実測値の差が0なら損失は0です。(ちなみに二乗誤差は回帰問題に、エントロピー誤差は分類問題に使用されます)

出力値を\(y_i\)、実測値を\(t_i\)とすると二乗誤差は以下のようにあらわされます。統計学・機械学習ではお馴染みの式ですね!

$$ \displaystyle \sum_{ i = 1 }^{ n } (y_i-t_i) $$

この時、\(t_i\)は定数であり、変数なのは(\(y_i\)。

どれだけ隠れ層があったとしても、(\(y_i\)は入力層からの入力と重み(\(w_i\)で表すことができます。つまり(\(y_i\)は(\(w_i\)の関数で表せるということ。

損失関数を最小限にとどめる(\(w_i\)を求めるには(\(y_i\)を(\(w_i\)で偏微分すれば良い!!高校数学の知識があれば分かると思います。

このようにしてディープラーニングの各層の重みが最適解に決まっていくのです。

この時、偏微分で得られた値をそのまま反映してしまうと局所最適になってしまうので、学習率を設けて徐々にパラメータ(\(w_i\)を更新していきます。

これを勾配法と呼ぶのです。

ちなみに偏微分は解析的に数値微分で解く方法もありますが複雑なネットワークだと計算負荷が膨大になるためそれを回避するために誤差逆伝播法が考案されており、現在のディープラーニングにはほぼ誤差逆伝播法が使用されています。

興味のある人は「ゼロから作るDeep Leaning」を読んでみると良いでしょう!

ディープラーニングをPythonで実装してみよう!

macとsurface

今まで見てきたディープラーニングを実際に0から実装してみることも可能ですが、Pythonには便利なライブラリが備わっていてライブラリを読み込むことで誰でも簡単にディープラーニングを実装することが可能です。

隠れ層の数や学習効率などパラメータを調整することは必要ですが、ディープラーニングのフォーマットが提供されておりそれを無料で自由に使用できるのは素晴らしい!

今回は定番のMnistという手書き文字のデータセットを用いて、Kerasというライブラリに入ったディープラーニングを使用して画像認識問題を解いていきます!

KerasはTensorFlowや、CNTK、Theanoなどの、より基本的な機械学習ライブラリを「バックエンド」として呼び出して使うようになっており、ディープラーニングのモデルを層を重ねるイメージで簡単に構築することができるようになっています。

Mnistは「Gradient-based learning applied to document recognition」で用いられたデータセットであり、現在でも多くの論文で用いられています。

Modified National Institute of Standards and Technologyの略であり、0~9の数字が手書き文字として格納されているデータセットです。

学習用に60000枚、検証用に10000枚のデータセットが格納されています。

まずは、必要なライブラリをインストールしていきましょう!

tensorflowなどのライブラリはあらかじめpip installしておいてくださいね!

続いてMnistのデータを学習データとテストデータに分けます。

そしてさらに学習データからパラメータチューニングのための検証データを取り出します。

この時画像データは、描画がしやすいように28×28の行列になっているのですが、学習するために1×784に直しましょう!さらに0~255のスケールを正規化しましょう!

続いてラベルをダミー変数化します。

ここでデータの成型が終了したので、ディープラーニングのネットワーク構築に入ります。

隠れ層では、RELU(ランプ)関数を用いて出力層ではソフトマックス関数を用いています。

Model.addを使うことで隠れ層をいくつも積み重ねることが可能です。

ネットワークの構築が終了した後は、最適な重みを見つけていきます。

AdamOptimizerは最近よく使われている最適化手法です。

Early stoppingとはもう精度が改善しないようなら学習を止めてしまう条件です。

これによってムダな学習を省くことが可能です。

最後のvalidation_dataで過学習が起こらないように検証を行っています。

最後にテストデータで予測を実行して実測値と予測値の正解率を求めます!

最終的な結果は・・・・96.96%!!

そこそこな精度をたたき出すことができました。パラメータをいじることで精度を99%まで伸ばしてみてください!

最後にまとめてコードを載せておきます。

ちなみに勾配ブースティング手法である、XgboostLightGBMCatboostでもMnistデータの分類をおこなっているので是非チェックしてみてください!

勾配ブースティング
勾配ブースティング手法をPythonで実装して比較していく!当サイト【スタビジ】の本記事では、勾配ブースティングの各手法をPythonで実装して徹底比較していきます!勾配ブースティングの代表手法「Xgboost」「Light gbm」「Catboost」で果たしてどのような違いがあるのでしょうか?...

おまけ:RNNをPythonで実装してみよう!

PC

おまけ的にPython実装をおこなっていきましょう!

通常のディープラーニングでは、時系列問題を上手く扱えません。

そこで登場するのがリカレントニューラルネットワーク(RNN)!

今までのディープラーニングでは、それぞれのインプットがそれぞれの中間層に与えられていましたが、RNNでは同一の中間層を用いて再帰的にインプットが行われます。

再帰的という部分がReccurentと言われるゆえんです。

こんな感じ。

rnnの概念

分かりづらいかも!

詳しくは以下の記事でまとめているのでチェックしてみてください!

RNNとは?Pythonでの実装方法と一緒に見ていこう!当サイト【スタビジ】の本記事では、ディープラーニングを時系列にも対応させたRNN(リカレントニューラルネットワーク)について解説していきます。RNNの仕組みや応用場面と一緒にPythonでの実装をしていきます。これからの応用が期待される領域なんですよー!...

ここでは、このRNNも簡単にPythonで実装できるんだよーってことを見ていきます!

使うデータセットはKaggleのホームページが落とせる航空会社の乗客数データ!

1949年から1960年までの月別乗客数がデータとして入っています。

149行2列のシンプルなデータセット

モデル構築は以下のサイトを参考にしています。

1変数の時系列データを基に過去のデータから未来の値を予測します。

この時、tflearnというライブラリを使ってRNN(正確にはLSTM)を実装していきます。tflearnはkerasと似たようなライブラリでディープラーニングの実装が感覚的に容易にできます。

実際にモデルを構築していきましょう!

最終的な評価はRMSE(Root Mean Square Error)で算出しています。

細かい実装ポイントについて見ていきましょう!

ここでは、データセットを時系列モデルに適した形に変形する関数と学習データ予測データに分ける関数を作っています。

ここが実際にRNN(LSTM)モデルを構築している部分。

ちなみに初回モデル構築は問題ないですが、再度パラメータを変えて処理を回そうとするとJupyter notebookではエラーをはいてしまうので、7行目に初期化するような記述を入れています。

これだけでRNNが実装できちゃうんです!簡単!

この時、RMSEは0.10079201となりました。それなりに良い予測ができてる!

ちなみに層を増やしてみると・・・

RMSEは0.16051404に悪化してしまいました・・・

簡易的なデータセットに複雑なモデルで当ててもあまり意味がなさそう。

ちなみに過学習を防ぐためにDropoutなどのパラメータで調節することも可能です!

ロボたん
ロボたん
こんなに簡単なの!?すごい!
ウマたん
ウマたん
ディープラーニングもだいぶ身近になったよねー!

ディープラーニング まとめ

ディープラーニングについて見てきましたが、非常にシンプルな仕組みでありかつPythonを使えば簡単に実装できることが理解いただけたでしょうか?

意外とちゃんと見ていくとシンプルなディープラーニングなのですが、効果は絶大!

簡単な例ですが画像認識を相当な精度で実現できたのはディープラーニングの素晴らしさをひしひしと感じますねー!

とは言え、まだまだここで紹介したのはディープラーニングの入門の入門です。

ディープラーニングの領域は研究が盛んで日々様々な手法が生み出されています。

この記事で何度も紹介してきましたが、以下の書籍がディープラーニングの理論を理解するにはうってつけなので興味のある人は是非読んでみてください!

ディープラーニングの勉強法に関しては以下の記事でまとめていますので、ぜひ参考にしてみてください!

【初心者向け】ディープラーニングの学習ロードマップまとめ当サイト【スタビジ】本記事では、ディープラーニングの学習方法について詳しくまとめていきます!ディープラーニングは難しいと思われがちですが、アルゴリズムは意外とシンプルで実装自体も非常に簡単なんです!Pythonでの実装もおこなっていきますよー!...
Pythonを初学者が最短で習得する勉強法

Pythonを使うと様々なことができます。しかしどんなことをやりたいかという明確な目的がないと勉強は捗りません。

Pythonを習得するためのロードマップをまとめましたのでぜひチェックしてみてくださいね!