Help us understand the problem. What is going on with this article?

AIエンジニアを目指してみる(※執筆中)

はじめに

最近はいたるところでAIというワードをよく耳にします。AIスピーカーを始め、AIを搭載した家電もよく見かけます。でも、実はAIってよくわかってないし、機械学習やディープラーニングなんて更にわからないです。なので、ここらでAIについてしっかり学んでみたいと思います。そして、せっかくなのでAIエンジニアを目指します。

この記事では、AIについての学習の過程やポイントを残していきたいと思います。少しでもみなさんの参考になれば幸いです。

この記事の対象者

・これからディープラーニングの学習を始める方

学習計画

  1. AIの概要を理解する
  2. JDLA「G検定」に合格する(2019/3/14、見事合格!!
  3. 機械学習を斜め読みする(ニューラルネットワークに絞る)
  4. Deep Learningを身につける
  5. 実際にAIで何か実装してみる
  6. JDLA「E資格」に合格する

※学習計画立案の参考サイト
【保存版・初心者向け】僕が本気でオススメするPythonと機械学習の良書12選
【保存版・初心者向け】独学でAIエンジニアになりたい人向けのオススメの勉強方法
人工知能(AI)を独学で学ぶ方法をステップ別に紹介します

学習用環境の構築(Windows10/VirtualBox/Ubuntu/Docker)

AIはライブラリが豊富なPythonで構築するのが一般的なのだそうですが、私はWindows10しか持っていないので、VirtualBoxでLinuxの仮想環境を構築してみます。当初はVagrant/Dockerも一緒に入れる予定でしたが、試しに全部入れたら訳がわからなくなったので、まずは最小構成とし、理解してから次に進みます。最小構成(VirtualBox+Ubuntu)のインストール手順はこちらを参考にしています。

1. AIの概要を理解する

概要理解の為、まずは以下の書籍を読み進め、ポイントを抜粋してみました。AIの歴史や現状、各用語の説明があるので、学習の初めに読むと良いです。
2.jpg

概要を流し読みしたい方はこちら

:triangular_flag_on_post:序章「広がる人工知能 ― 人工知能は人類を滅ぼすか」
・将棋など「人間 vs 人工知能」の戦いが繰り広げられている
・IBMが開発した人工知能「ワトソン」の活躍が広がっている
・Pepperには「感情エンジン」という人工知能が搭載されていて、悲しい時は励まし嬉しい時は一緒に喜んでくれる
・検索エンジンやネット広告分野でも人工知能は使われている
・金融市場の取引の90%以上はコンピュータによるものだという報告もある
・世界ではグーグル/フェイスブック/バイドゥ/IBMの投資が盛ん
・日本ではドワンゴ/プリファードインフラストラクチャーの投資が盛ん
・定型的な業務の人間は職を失う方向
・人類にとっての脅威は「シンギュラリティ(技術的特異点)」という概念で語られる
 ⇒人工知能が賢くなって自身より賢い人工知能を作れるようになる瞬間
 ⇒2045年という主張がある
 ⇒ビルゲイツなど人工知能に否定的な人も多い
:triangular_flag_on_post:1章「人工知能とは何か ― 専門家と世間の認識のズレ」
・本当の意味での(人間のように考える)AIは、まだ完成していない
・しかし人間の知的活動の一面を真似る技術をAIと呼ぶこともあり、これはできてる
・人間の脳は電気回路と同じ仕組みなので、AIが完成しないわけがない
 ⇒人工知能とは、これを目指す研究分野である
 ⇒しかし高名な科学者の中にも、この考えを否定している人がいる
・人工知能研究者の多くは、知能を「構成論的(作ってなんぼ)」(⇔分析的)に解明している
・人工知能とロボットの違いは、ロボットの脳が人工知能
・人工知能(の研究分野)は長い歴史の中で、様々な副産物を生んできた
 ⇒音声認識、文字認識、自然言語処理、ゲーム、検索エンジン
 ⇒これらはかつて人工知能と呼ばれていたが、実用化され一つの分野を構成すると、そう呼ばれなくなる
・世の中で人工知能と呼ばれるものは、次のレベル1~4に分類できそう
 - <レベル1> 単純な制御プログラムを「人工知能」と称している(主に家電の類)
 - <レベル2> 古典的な人工知能(将棋、ルンバ、質問に答える系)
 - <レベル3> 機械学習を取り入れた人工知能(検索エンジンなど)
 - <レベル4> ディープラーニングを取り入れた人工知能
:triangular_flag_on_post:2章「推論と探索の時代 ― 第1次AIブーム」
・第1次AIブームは1950年代後半~1960年代。「トイ・プロブレム(おもちゃの問題)」は解けても、複雑な現実の問題は解けないことが明らかになり、ブームが去った
・主に行われたのは「推論」と「探索」の研究。「探索」とは、以下のような迷路のスタート/ゴール/分岐/行き止まりをノードと捉え、コンピュータが解きやすい形式に読み替える
map.png
・探索木の進め方は主に2つあり、「深さ優先探索」と「幅優先探索」。「幅優先」は最短経路が必ず見つかるが、途中の経路を全て記憶する必要がある。「深さ優先」は必ずしも最短経路がすぐ見つからないが、メモリはいらない
・これが発展するとチェスや将棋になるが、相手がいることで組合せが膨大に。とてもじゃないが全組合せを調べていられないので、「盤面を評価するスコア」という概念を作り、スコアがよくなるように次の指し手を探索する設計。スコアとは例えば、自分の王将が王手なら-10、相手の王将が王手なら+10、王将の周囲8マスに相手の飛車がいれば-8、、、といった具合である
・そして、第1次AIブームは終わる。。。
:triangular_flag_on_post:3章「知識を入れると賢くなる ― 第2次AIブーム」
・第2次AIブームを支えたのは「知識」である
・「知識」を使った人工知能の大本命が「エキスパートシステム」である
・「エキスパートシステム」とは、ある専門分野の知識を取り込み、推論を行うことで、その分野のエキスパートのように振る舞うプログラムを指す
・「エキスパートシステム」の課題
 ⇒「知識」は専門家からヒアリングして取り出さないといけない
 ⇒「知識」やルールが増えると、お互い矛盾してることもあり、適切な維持管理が必要
 ⇒ 曖昧な知識の定義が難しい
・人間が持つ「一般常識」を、コンピュータが処理しやすい形にする必要があり、その為の基本的な研究が「知識表現」の研究である
・「知識」の表現(記述)方法が難しいことが判明し、記述すること自体の研究が行われるようになり、それが「オントロジー研究」につながった
・「オントロジー」は人工知能用語では「概念化の明示的な仕様」と定義される。つまり、プログラミングするには仕様書があるべきだ、という考え方である
・「オントロジー」の一つの例として、「is-a関係」と「part-of関係」によって知識を記述する
・「A is-a B」で「B is-a C」なら、「A is-a C」は成立する(推移律)。しかし、「A part-of B」で「B part-of C」だからといって、「A part-of C」は必ずしも成立しない。例えば、「足 part-of 山田太郎」で「山田太郎 part-of 鈴木商事」の場合など
・知識の記述が難しいことがわかってきたので、2つの流派ができた
 ⇒ヘビーウェイト・オンコロジー、ライトウェイト・オンコロジー
 ⇒ライトは、まぁ大体でいいじゃん!ってノリ
・ライトの究極形の1つがIBMが開発した「ワトソン」である
・機械翻訳はとても難易度が高い技術である。「He saw a women in the garden with a telescope.」
 ⇒上記文章の解釈は文法的には一意に定まらず、一般常識が必要
 ⇒庭の中にいるのは、彼?彼女?という点
・フレーム問題
 ⇒あるタスクを実行するのに、「関係ある知識だけを取り出してそれを使う」という作業がいかに難しいか、ということ
・シンボルグラウンディング問題
 ⇒シンボル(文字列、言葉)を、それが意味するものと結びつけるのが難しい
・そして、第2次AIブームは終わる。。。
:triangular_flag_on_post:4章「機械学習の静かな広がり ― 第3次AIブーム①」
・インターネットや検索エンジンをベースに、「機械学習」「自然言語処理」が発展、その結果「統計的自然言語処理」と呼ばれる領域が急速に発展した
 ⇒翻訳を考える際、文法構造や意味構造を考えず、単に機械的に訳される確率の高いものをあてはめていけばいい、という考え方
・グーグルは統計的自然言語処理の権化のような企業である
・そもそも学習とは「分ける」ことである
・機械学習は、コンピュータが大量のデータを処理しながらこの「分け方」を自動的に習得する
・機械学習は大きく「教師あり学習」と「教師なし学習」に分けられる
・教師あり学習は「入力」と「正しい出力(分け方)」がセット
・教師なし学習は「入力」のみで、データに内在する構造をつかむために用いる
・代表的な分類のしかたは以下の5つ
 ①最近傍法:一番近いデータのカテゴリが当てはまる確率が高いのでは?
 ②ナイーブベイズ法:確立に関する定義「ベイズの定理」を使用し、データの特徴ごとにどのカテゴリに当てはめるのかを足し合わせていく
 ③決定木:ある属性がある値に入っているかどうかで線引きをする
 ④サポートベクトルマシン:マージンを最大にするように分ける
 ⑤ニューラルネットワーク:人間の脳神経回路をマネする
neural.jpg
 ⇒手書きの「3」をインプットとする(28px × 28px)
 ⇒入力層は28×28=784あり、それぞれ重みづけを行う
 ⇒出力層は0~9=10あり、一番該当する確率の高い数値(0~9)を出力する
 ⇒入力と出力が異なっていれば、入力層(と隠れ層の間)の重みづけ、出力層(と隠れ層の間)の重みづけを調整する
 ⇒上記を繰り返して認識の精度を上げていく(誤差逆伝搬)
・ただ、機械学習の弱点が「特徴量設計」である。例えば、年収を予測する問題では「住所」「年齢」「職業」はヒントになるが、「身長」はイマイチである。これらが特徴量であり、コンピュータが「どんな特徴量を使うべきか」は判断できない
・ここまでの問題は結局、同じ一つのことを指している。すなわち「世界からどの特徴に注目して情報を取り出すべきか」に関して、コンピュータは人間の手を借りなければならなかった
:triangular_flag_on_post:5章「静寂を破るディープラーニング ― 第3次AIブーム②」
・「ディープラーニング」は多階層のニューラルネットワークである
・ディープラーニングでは「自己符号化器(情報圧縮器)」を用いる
・自己符号化器では、入力をそのまま答えとする。更に、隠れ層を圧縮し少ない情報で正答を導くよう促す。例えば、全都道府県の天気を当てる事を考える。
 特徴表現①:北海道、岩手、宮城、、、山形のみ
  ⇒北日本の天気しか当てられなさそう
 特徴表現②:北海道、岩手、新潟、東京、大阪、、、沖縄
  ⇒割と効率的に正解できそう
 特徴表現③:全国、北海道、東北、関東、日本海側、太平洋側、沖縄
  ⇒3つの特徴表現の中では一番良い
・1層目の隠れ層を、2層目の入力層(及び正答)とする。これを繰り返す。抽出度がどんどん増し、高次の特徴量が生成される
・「教師あり学習」的な方法による「教師なし学習」で特徴量を作り、最後に何か分類させたいときは「教師あり学習」になる
・ノイズを加え、ぐらつかない「特徴量」に磨き上げる
・ドロップアウトといって、隠れ層のいくつかのニューロンを欠落させることで、ある特徴量に依存しない特徴量が作り上げられる
:triangular_flag_on_post:6章「人工知能は人間を超えるか ― ディープラーニングの先にあるもの」
:triangular_flag_on_post:終章「変わりゆく世界 ― 産業・社会への影響と戦略」
・この分野の今後の発展と、社会の変化の予測など(詳細割愛)

更なる理解の為、以下の書籍を読み進めG検定の合格を目指します。内容のおよそ半分は書籍「人工知能は人間を超えるか」と重複する印象ですが、知識を体系化する助けになりお薦めです。
7.jpg

概要を流し読みしたい方はこちら

:triangular_flag_on_post:1章~3章、5章
※書籍「人工知能は人間を超えるか」と重複するので割愛
:triangular_flag_on_post:7章~9章
※研究や活用事例、法律等の紹介なので割愛
:triangular_flag_on_post:4章「機械学習の具体的手法」
<教師あり学習>
・与えられたデータ(入力)を元に、そのデータがどんなパターン(出力)になるのかを識別・予測する
 例1)過去の売上から、将来の売上を予測(回帰問題)
 例2)与えられた動物の画像が、何の動物かを識別したい(分類問題)
手法 概要
線形回帰 データ(の分布)の最も当てはまる直線を考える
ロジスティック回帰 シグモイド(ソフトマックス)関数にて、与えられたデータを2種類(3種類以上)に分類
ランダムフォレスト 入力からランダムに特徴量を選び、複数の決定木を作成し、多数決する
ブースティング 一部のデータを繰り返し抽出し、複数のモデルを学習させる
サポートベクターマシン 各データ点との距離が最大となるような境界線を求める
ニューラルネットワーク 人間の脳の構造を模したアルゴリズム

<教師なし学習>
・教師あり学習の出力データが無いケース
 例1)売上データから、顧客層を認識
 例2)入力データの各項目間にある関係性を把握したい

手法 概要
k-means 入力からグループ構造を見つけ出し、k個のグループに振り分ける
主成分分析 入力データの特徴量間の相関を分析し、データ構造をつかむ

・手法の評価方法

評価方法 概要
正解率 全データ中、どれだけ予測が当たったかの割合
適合率 予測が正の中で、実際に正であったものの割合
再現率 実際に正の中で、正と予測できたものの割合
F値 適合率と再現率の調和平均

:triangular_flag_on_post:6章「ディープラーニングの手法」
・ディープラーニングの課題として、誤差逆伝搬の際に勾配が消失する。その最大の原因がシグモイド関数の微分(の最大値)である
・出力層ではシグモイド関数またはソフトマックス関数を用いる必要がある。しかし、隠れ層では任意の実数を非線形に変換できる関数なら何でもよい

活性化関数 概要
tanh -1から1の範囲(シグモイド関数は0から1)
ReLU y=max(0,x)
Leaky ReLU x<0において、わずかな傾きを持っている

kansu.png

・機械学習が目指しているのは「予測値と実測値の誤差をなくす」。これは数学的には微分につながる。それぞれの層の重みで誤差関数を微分した値がゼロになるような重みを求めればいい。しかし、ニューラルネットワークで解く問題は多次元で簡単ではないので、いきなり解を求めるのではなく「探索」するアプローチになる。ここで用いられるのが「勾配降下法」

x^{(k+1)} = x^{(k)} - af'(x^{(k)})

 kは「エポック」で、これまでに何回繰り返し計算を行ったか
 aは「学習率」で、勾配に沿って一度にどれだけ降りていくか
・ニューラルネットワークの「学習」とは、勾配降下法を用いて繰り返し計算を行うこと
kobai.png
・勾配降下法の問題として「局所最適解」か見抜けない。本当は「大域最適解」にたどり着きたい
・いい感じのタイミングで、学習率を大きくしたり小さくする必要がある
・「モーメンタム」と呼ばれる手法は物理の慣性の考え方を適用したもの。最適化の進行方向に学習を加速させることで、学習の停滞を防げるらしい
・他の問題として、「オーバーフィッティング」がある。対応テクニックの一つに「ドロップアウト」がある。「ドロップアウト」はランダムにニューロンを除外し学習する(アンサンブル学習をしていることになる)
・学習が進むとオーバーフィッティングは避けられないので、「early stopping」という手法で学習を早めに打ち切る
・ここまで「学習の途中の工夫を記載してきたが、そもそも「学習の始め」を工夫することはできないか

手法 概要
正規化 データ全体を調整する
標準化 特徴量を標準正規分布に従うよう変換(0~1の範囲)
白色化 各特徴量を無相関化する

・上記は機械学習では効果的だが、ディープニューラルネットワークでは効果が薄くなりがち。伝搬の際に何かしらの活性化関数がかかると、分布が徐々に崩れていく。そこで考えられたのが「重みの初期値を工夫する」。シグモイド関数には「Xavier」の初期値、ReLU関数には「He」の初期値
・重みの初期値などまどろっこしいのじゃなくて、直接的な方法を取りたい。各層に伝わってきたデータを、その層でまた正規化したい。これを「バッチ正規化」が実現した

・「CNN」は画像処理分野で用いられるニューラルネットワークである
・大元のアプローチは、人間が持つ視覚野の神経細胞の2つを模すというもの。
 ⇒単純型細胞(S細胞):画像の濃淡パターンを検出
 ⇒複雑型細胞(C細胞):物体が移動しても同一とみなす
・最初に組み込んだモデルが福島邦彦考案の「ネオコグニトロン」。S細胞層とC細胞層を交互に複数組み合わせた構造で、まさにニューラルネットワーク
・次に考案されたのが「LeNet」で、畳み込み層とプーリング層が交互に複数
・畳み込みとは、フィルタを用いて画像から特徴を抽出する処理のこと
cnn1.png
・CNNではそれぞれのフィルタをどういった値にすればいいかを学習していく。これにより「位置のズレ」に強いモデルができる
・プーリングとは、画像サイズを決められたルールに従って小さくする。
cnn2.png
 プーリングは畳み込みとは異なり、学習すべきパラメータは存在しない
・畳み込みもプーリングも出力は画像のままなので、「全結合層」で出力を1次元にする。これは隠れ層&出力層に該当する。ただ最近は全結合層を用いず、「1つの特徴マップに1つのクラスを対応させる」ことで分類を行う「Global Average Pooling」が主流
・現実世界の物体を認識するには、以下の課題もある
 ⇒同じ物体でも角度が異なると見え方が異なる
 ⇒同じ物体でも拡大縮小によって見え方が異なる
 ⇒同じ物体でも光の当たり方によって見え方が異なる
・その為、上記を網羅した膨大な量のデータを準備する必要が出てくる。
 これを「データ拡張(データの水増し)」と呼ぶ
・以下、これまで考案されてきたCNNモデル

モデル 概要
AlexNet 2012年にILSVRCで圧勝
VGG CNNをディープに
GoogLeNet Inceptionモジュールというブロックを構成
ResNet Skip connection「層を飛び越えた結合」

・「RNN」は時系列データ処理分野で用いられるニューラルネットワークである。RNNでは隠れ層に時間情報を持ち、(現在の)隠れ層の入力として、入力層 +(過去の)隠れ層が対象となるのが特徴である
・RNNの問題として、通常のNN同様、勾配消失問題がある。また、時系列固有の問題として、「今の時点では関係ないけど、将来の時点では関係ある」という入力が与えられた際、重みは大きくすべきだけど小さくすべきであるという矛盾を抱えることになる。これは「入力(出力)重み衝突」と呼ばれる
・「入力(出力)重み衝突」の対策として「LSTM」が考案された。LSTMは大まかに以下の2つの機構で構成されている
 ⇒セル(CEC):誤差を内部にとどまらせる
 ⇒ゲート:必要な情報を必要なタイミングで保持・消却させる
lstm.png
・LSTMを簡略化した手法として「GRU」がある
・以下、LSTMの発展形である

モデル 概要
Bidirectional RNN LSTMを2つ組合せ、未来だけでなく過去方向も学習可
RNN Encoder-Decoder 出力も時系列で予測したい場合
Attention 「時間の重み(どの時点がどれだけ影響あるか)」を組み込んだ

・「強化学習」は一連の行動系列の結果としての報酬を最大とするように学習する。例えば、ロボットの歩行制御では「歩けた距離」を報酬として与えると、機械は歩行距離を最大化すべく自ら行動を変え、歩行距離が延びるよう学習する
・これまでは「認識」「識別」タスクを記載してきたが、「生成」タスクにも応用され始めている。元データから新たなデータを生成するモデルを「生成モデル」と呼び、ディープラーニングを取り入れた生成モデルを「深層生成モデル」と言う。画像分野でよい成果を残している深層生成モデルが、以下の2つ

モデル 概要
変分オートエンコーダ(VAE) 入力を何かしらの分布に基づいて生成されたものとし、その分布を表現するよう学習する
敵対的生成ネットワーク(GAN) ジェネレータはディスクリミネータが間違えるような偽物画像を作るよう学習し、ディスクリミネータは偽物を見抜けるよう学習する。これら2種類のネットワークを闘わせることで、最終的には本物と見分けがつかないような偽物を実現する

その他、G検定対策としては以下の問題集に取り組みました。
G.jpg

更に更に、検定当日に以下のサイトの模擬試験に取り組みました。実際の検定と似た問題が掲載されており、とても助けられました!(2019/3/14、見事合格!!
Study-AI

2. 機械学習を斜め読みする(ニューラルネットワークに絞る)

以下の書籍を読み進めます。Pythonとsikit-learnに焦点を絞った入門書です。
syoseki3.jpg

概要を流し読みしたい方はこちら

:triangular_flag_on_post:1章「はじめに」
・Pythonはデータのロード、可視化、統計、自然言語処理、画像処理などのライブラリが用意されており、機械学習と相性がよい
・scikit-learnはオープンソースプロジェクトであり、常に開発と改良が続けられており、最先端の機械学習アルゴリズムが用意されている。また、NumPyとSciPyの2つのPythonパッケージに依存している
・グラフ描画など行うには、matplotlibやIPython、Jupyter Notebookも便利である。下記のパッケージ済みディストリビューションを使うと簡単。
 ⇒Anaconda、Enthought Canopy、Python(x,y)
ツール 概要
Jupyter Notebook ブラウザ上でコードを実行する為の環境
NumPy Pythonで科学技術計算をする際の基本的なツールの1つ。scikit-learnは2次元NumPy配列で入力を受け取る
SciPy Pythonで科学技術計算を行う為の関数を集めたもの。scikit-learnはSciPyの関数群を利用している
matplotlib Pythonの科学技術計算向けのグラフ描画ライブラリ
pandas データを変換・解析するライブラリ。RのDataFrameを模して作られた

・k-最近傍法のよるアヤメの分類のサンプルあり
 ※大筋は書籍「Raspberry Piではじめる機械学習」と重複するので割愛
:triangular_flag_on_post:2章「教師あり学習」
※scikit-learnにもニューラルネットワークに関する機能が準備されてるが、僅かである。
 本書でもTensor-FlowやKeras等のライブラリを推奨している。

あわせて、以下の書籍も読み進めてみました。内容は、scikit-learnによるサポートベクターマシン、ニューラルネットワークと、keras/Teanoによるディープラーニングの実践が主なテーマでした。実際の物作りを通して知識を習得したい人にお薦めです。
syoseki.png
この書籍から派生して、勉強がてら顔認証の仕組みを作ってみました。

3. Deep Learningを身につける

以下の書籍を読み進めます。ディープラーニングの学習書籍では有名で、ニューラルネットワークの仕組みをTensorflowなどのフレームワークを使わず「ゼロ(Python)」から学べます。後半ではCNNの実装もあります。
4.jpg

概要を流し読みしたい方はこちら

:triangular_flag_on_post:1章「Python入門」
・Pythonの高いパフォーマンス性に加えて、NumPyやSciPyといった数値計算や統計処理を行う優れたライブラリなどにより、Pythonはデータサイエンスの分野で確固としたポジションを占めている。
・Pythonには2系と3系の2つのバージョンが存在し、互換性はない。
・Anacondaはデータ分析に重点を置いたディストリビューションで、NumPyやMatplotlibなどのデータ分析に有用なライブラリが含まれている
・Pythonは「動的型付き言語」に分類される(変数の型が状況に応じて決定)
・リスト(配列)が使える。スライシングという便利な記法があり、リストのサブ(部分)リストにアクセスできる。
a = [1,2,3,4,99]
a[0:2] # ⇒ [1,2]  インデックスの0番目から2番目(より前)を取得
a[1:] # ⇒ [2,3,4,99]  インデックスの1番目から最後までを取得
a[:3] # ⇒ [1,2,3]  最初からインデックスの3番目(より前)を取得
a[:-1] # ⇒ [1,2,3,4]  最初から最後の要素の1つ前までを取得
a[:-2] # ⇒ [1,2,3]  最初から最後の要素の2つ前までを取得

・ディクショナリは、キー値と値をペアにしてデータを格納する

me = {'height':180} # ディクショナリを作成
me['height'] # ⇒ 180  要素にアクセス
me['weight'] # = 70  新しい要素を追加
print(me) # ⇒ {'height:180, 'weight':70}

・Pythonでは空白文字が重要な意味を持つ(タブ文字も可能だが空白文字を推奨)
 以下はif文の例

if hungry:
    print("I'm hungry")
else:
    print("I'm not hungry")
    print("I'm sleepy")

・NumPyは標準のPythonには含まれていない「外部」ライブラリで、配列や行列を扱うのに便利なメソッドが多く用意されている
・配列同士の計算は「要素ごと」で、配列とスカラ値や、形状の異なる配列同士の計算を行う機能はブロードキャストという
・Pythonなどの動的言語は、C/C++などの静的言語(コンパイル型言語)に比べて処理が遅い。NumPyも主な処理はC/C++で実装されている
・Matplotlibはグラフ描画のためのライブラリ
・flatternは、画像をNumPy配列として1次元で格納する
・reshapteは、flatternされた1次元配列を基の形状に再変形する

:triangular_flag_on_post:2章「パーセプトロン」
・パーセプトロンはニューラルネットワーク(ディープラーニング)の起源となるアルゴリズム
・パーセプトロンは複数の信号を入力として受け取り、1つの信号を出力する
・以下は2入力のパーセプトロン。wはweight(重み)の頭文字、〇はニューロンやノードと呼ぶ
1.png
・論理回路のANDやNAND,ORは、パーセプトロンでイメージがつきやすい。ANDをPythonで実装すると以下のようになる

def AND(x1, x2):
    w1, w2, theta = 0.5, 0.5, 0.7 # 値の組合せは色々ある!
    tmp = x1*w1 + x2*w2
    if tmp <= theta:
        return 0
    elif tmp > theta:
        return 1

・重みとバイアスを導入する。重みは入力信号への重要度をコントロールする。バイアスは発火のしやすさを調整する

def AND(x1, x2):
    x = np.array([x1, x2]) # 入力
    w = np.array([0.5, 0.5]) # 重み
    b = -0.7 # バイアス
    tmp = np.sum(x*w) + b
    if tmp <= 0:
        return 0
    else:
        return 1

・実は、これまでの(単純)パーセプトロンでは、XORは実現できない。ANDやNAND、ORを視覚的に考えると、「線形分離可能」であることがわかる。しかし、XORはどう頑張っても線形分離はできない
2.png
・ただ、XORはこれまでのゲート(AND,NAND,OR)の組合せで表現できる!
3.png
・もちろんPythonでも実装できる

def XOR(x1, x2):
    s1 = NAND(x1, x2)
    s2 = OR(x1, x2)
    y = AND(s1, s2)
    return y

・これをパーセプトロンで表現すると以下のようになる。すなわち多層パーセプトロンである
4.jpg
・多層パーセプトロンでは、足し算を行う加算器や、2進数を10進数に変換するエンコーダ、実のところ(理論上は)コンピュータ自体も表現することができる!

:triangular_flag_on_post:3章「ニューラルネットワーク」
・パーセプトロンとニューラルネットワークの主な違いは、活性化関数だけである。パーセプトロンでは活性化関数としてステップ関数が使われているが、他の関数にすることでニューラルネットワークの世界へと進むことができる
・ステップ関数をPythonで実装すると以下になる

def step_function(x): # xはNumPy配列を想定
    y = x > 0 # yはBooleanの配列
    return y.astype(np.int) # np.int型に変換

5.png

・シグモイド関数をPythonで実装すると以下になる

def sigmoid(x): # xはNumPy配列を想定
    return 1 / (1 + np.exp(-x)) # NumPyのブロードキャスト機能で正しく計算される

6.png
・ステップ関数もシグモイド関数の共通点は、どんな値でも0から1の間に押し込める
・ステップ関数もシグモイド関数も非線形関数であり、多層にすることの恩恵を受けるためには活性化関数には非線形関数を使う必要がある(線形関数を用いた計算は隠れ層の無いネットワークで表現可能)
・ReLU関数をPythonで実装すると以下になる

def relu(x):
    return np.maximum(0, x) # 0とxで大きい方を返す

7.png

・行列同士の積は以下の通り。pythonでは要素数によらず「np.dot(A,B)」
tensor.png
・全3層のニューラルネットワークをPythonで実装すると以下(順方向のみ、一部抜粋)

def init_network():
    network = {}
    network['W1'] = np.array([[0.1, 0.3, 0.5], [0.2, 0.4, 0.6]])
    network['b1'] = np.array([0.1, 0.2, 0.3])
    network['W2'] = np.array([[0.1, 0.4], [0.2, 0.5], [0.3, 0.6]])
    network['b2'] = np.array([0.1, 0.2])
    network['W3'] = np.array([[0.1, 0.3], [0.2, 0.4]])
    network['b3'] = np.array([0.1, 0.2])
    return network

def forward(network, x):
    W1, W2, W3 = network['W1'], network['W2'], network['W3']
    b1, b2, b3 = network['b1'], network['b2'], network['b3']

    a1 = np.dot(x, W1) + b1
    z1 = sigmoid(a1)
    a2 = np.dot(z1, W2) + b2
    z2 = sigmoid(a2)
    a3 = np.dot(z2, W3) + b3
    y = identity_function(a3) # 最後は入力をそのまま出力する「恒等関数」を使用
    return y

・ポイントは、「ニューラルネットワークの計算は行列の計算としてまとめて行える」ということ
・出力層について、分類と回帰で活性化関数を変更する必要がある。回帰では恒等関数を、分類ではソフトマックス関数を使う。ソフトマックス関数をPythonで実装すると以下になる

def softmax(a):
    c = np.max(a) # 入力の最大値
    exp_a = np.exp(a - c) # オーバーフロー対策
    sum_exp_a = np.sum(exp_a)
    y = exp_a / sum_exp_a
    return y

9.png
・ソフトマックス関数の出力は0.0から1.0の間の実数で、出力の総和は1になる。つまり、出力を「確率」として解釈することができる
・出力層で利用する活性化関数は、以下の通り

問題の種類 活性化関数
回帰問題 恒等関数
2クラス分類問題 シグモイド関数
多クラス分類問題 ソフトマックス関数

・pickleは、プログラムの実行中のオブジェクトをファイルとして保存する機能。MNISTなど大量データを何度も読み込む必要がある時など、即座に復元することが可能

:triangular_flag_on_post:4章「ニューラルネットワークの学習」
・機械学習はデータが命
・機械学習では、人の介入を極力避け、集まられたデータから答えを見つけようと試み、更にニューラルネットワークやディープラーニングは、従来の機械学習以上に人の介入を遠ざけることができるという重要な性質を持つ
・画像から規則性を見つける際、コンピュータビジョンの分野では有名なSIFT/SURF/HOGなどの特徴量を用いて、機械学習で使われる識別器-SVM/KNN-で学習させる。この特徴量は人が設計したもの
・ニューラルネットワークは画像をそのまま学習する。すなわち、どんな問題でも手法を変えずそのまま解けるのが利点である
・ディープラーニングを含めた機械学習では、訓練データとテストデータの2つのデータに分け、学習や実験を行うのが一般的。なぜなら、汎化能力を正しく評価したい為
・ニューラルネットワークで最適な重みパラメータを探索する際の指標として「損失関数」があり、一般には2乗和誤差や交差エントロピー誤差などが用いられる
 ⇒2乗和誤差:出力と正解ラベルの差を2乗したものの和
 ⇒交差エントロピー誤差:実質、正解ラベルが1に対応する出力の自然対数
・損失関数ではなく認識精度を指標にしてしまうと、パラメータの微分がほとんどの場所で0になってしまい、ふさわしくない
・ミニバッチ学習とは、データの中から一部を選び、全体の近似として利用
・勾配法とは、勾配の情報を使って進む方向を決める
・微分とは、ある瞬間の変化の量を表したもの
・すべての変数の偏微分をベクトルとしてまとめたものを勾配という(イメージは以下)
grad.png
・勾配が示す方向は、各場所において関数の値を最も減らす方向である
・学習率のように人間が設定する必要のあるパラメータをハイパーパラメータという
・ニューラルネットワークの学習の手順は、以下の通り

ステップ 概要 詳細
1 ミニバッチ 訓練データからランダムに一部を選択
2 勾配の算出 ミニバッチの損失関数減の為、各重みパラメータの勾配を求める
3 パラメータの更新 重みパラメータを勾配方向に微笑量だけ更新
4 繰り返し ステップ1~3を繰り返す

・使用するデータがミニバッチでランダムに選択していることから、確率的勾配降下法と呼ぶ
・エポック(epoch)は単位で、1エポックとは学習において訓練データをすべて使い切ったときの回数に対応する。例えば、10000個の訓練データに対して100個のミニバッチで学習する場合、確率的勾配降下法を100回繰り返したら、全ての訓練データを使ったことになり、100回=1エポックとなる

:triangular_flag_on_post:5章「誤差逆伝搬法」
・100円のリンゴを消費税10%の状態で2個買うとする。リンゴの値段が値上がりした時に、最終的な支払金額にどのように影響するか知りたい場合、「リンゴの値段に関する支払金額の微分」を求めることに相当する
・誤差逆伝搬で「局所的な微分」を逆方向に伝達する原理は、連鎖律によるもの
・まず合成関数とは、複数の関数によって構成される関数のこと
・その合成関数の微分は、構成するそれぞれの関数の微分の積によって表せる。これを連鎖律の原理と言う
jun.png
・加算ノードは、入力信号を次のノードへそのまま出力する
wa.png
・乗算ノードは、入力信号に、順伝搬時の入力信号を"ひっくり返した値"を乗算する
seki.png
・先のリンゴの例では、逆伝搬は以下の通り
ap.png

:triangular_flag_on_post:6章「学習に関するテクニック」
・ニューラルネットワークの学習の目的は、損失関数の値をできるだけ小さくするパラメータの発見
・これまで学んだ手法としてSGD(確率的勾配降下法)があるが、関数によっては不適切な手法となる。
 以下は、勾配を見つける様子を視覚化したもの
sgd.png
・モーメンタムは「運動量」という意味で、物理に関係がある
mo.png
・学習係数が小さいと学習に時間がかかるが、大きいと発散して正しい学習が行えない。有効なテクニックとして、学習係数の減衰という方法がある。これは、学習が進むにつれて学習係数を小さくする方法。これを発展させたのがAdaGrad
ada.png
・モーメンタムとAdaGradを融合する、これがAdamという手法のベースとなるアイデア
adam.png
・ただ結局、すべての問題で優れた手法というのは(今のところ)ないので、色々試すこと
・重みの初期値としてどのような値を設定するかで、学習の成否が分かれることがよくある
・基本的に、重みの値を小さくすることで、過学習が起きにくくなる。かと言って、全て0に設定するのはNG。正確には、重みを均一にしてはいけない。なぜなら、誤差逆伝搬法において、全ての重みの値が均一に更新されてしまう為
・隠れ層のアクティベーション(活性化関数後の出力データ)の分布を観察することで多くの知見が得られる。0と1に偏ったデータ分布では、逆伝搬で勾配消失が起きる。一部の値に偏ったデータ分布では、複数のニューロンがほとんど同じ値を出力することに相当し、意味がない
・Xavierの初期値は、一般的なディープラーニングフレームワークで標準的に用いられる。sigmoid関数/tanh関数と相性が良い
・ReLU関数に特化した初期値として、「Heの初期値」を用いる
・各層のアクティベーションの分布が適度な広がりを持つよう「強制的」に調整する、そのようなアイデアをベースとする手法をBatch Normalizationと呼ぶ。利点は以下
 ⇒学習を早く進行させる(学習係数を大きくすることができる)
 ⇒初期値にそれほど依存しない
 ⇒過学習を抑制する(Dropoutなどの必要性を減らす)
・Batch Normはミニバッチごとに正規化を行う。具体的には、データの分布が平均0、分散1になるよう正規化する
・Bath Normのタイミングは各層の活性化関数の前か後
・過学習とは、訓練データだけに適応しすぎてしまい、訓練データに含まれない他のデータにはうまく対応できない状態
・Weight decayは過学習の抑制に用いられる手法で、学習の過程において大きな重みを持つことに対してペナルティを課すことで、過学習を抑制しようというもの
・モデルが複雑になるとWeight decayだけでは対応が困難になる。そこでDropoutという手法が用いられる
・Dropoutは、学習時に隠れ層のニューロンをランダムに消去する
・機械学習ではアンサンブル学習というものがあり、複数のモデルを個別に学習させ、推論時に平均するというもの。Dropoutは毎回異なるモデルを学習させていると解釈できる。アンサンブル学習と同じ効果を(疑似的に)一つのネットワークで実現している
・ニューラルネットワークには、パラメータとハイパーパラメータが登場する。
 パラメータ:重みやバイアスで、DLが自動的に学習
 ハイパーパラメータ:ニューロン数やバッチサイズ、学習係数やWeight decayなどで、人間が設定
・訓練データ、テストデータのほかに、検証データを用意して評価すべき。なぜなら、テストデータを使ってハイパーパラメータを調整するとすれば、ハイパーパラメータの値はテストデータに対して過学習を起こすことになる
・ハイパーパラメータの最適化を行う上で重要なポイントは、ハイパーパラメータの「良い値」が存在する範囲を徐々に絞りこんでいく、ということ(当たり前っちゃ当たり前)

:triangular_flag_on_post:7章「畳み込みニューラルネットワーク」
・一般的なニューラルネットワークでは、Affine/ReLUを繰り返し最後にAffine/Softmaxなど。これに対しCNNは、Conv/ReLU/Poolingを繰り返し、Conv/ReLU、Affine/ReLU、Affine/Softmaxなどになる。後半はどちらも似てる
・全結合層(Affine)の問題点として、データの形状が無視されてしまうこと。例えば入力に画像を使う場合、縦・横・チャンネルの3次元の形状が1次元に均されてしまう。3次元の形状には大切な空間的情報が含まれているはずだが生かせない!
・一方、畳み込み層は形状を維持する。ちなみにCNNでは入出力データを特徴マップと呼ぶことがある
・畳み込み層で行う処理は「畳み込み演算」である
cnna.png
・バイアスは、フィルター(カーネル)適用後のすべての要素に加算される
・畳み込み層の処理を行う前に、入力データの周囲に固定のデータを埋め込むことがある。これをパディングという。パディングによって、フィルターをかけてもデータサイズが小さくならない
cnnb.png
・入力が3次元の場合、チャンネル毎の特徴マップに対してそれぞれフィルターをかけ、それらの結果を加算して一つの出力を得る
・プーリングは、縦・横方向の空間を小さくする演算である。微小な位置変化に対してロバストである
cnnc.png
・3,4次元の入力データを使った実装は、馬鹿正直にやると複雑になるが、im2colという関数を使うことでシンプルになる。im2colは3,4次元データを2次元に変換してくれる
・CNNの可視化を試みると、8層のCNNで、1層目はエッジやブロブに反応、3層目はテクスチャ、5層目は物体のパーツ、最後の全結合層では物体のクラス(犬や車など)に反応する。このように、最初の層は単純なエッジに反応し、続いてテクスチャ、そしてより複雑な物体のパーツへと反応するように変化する

:triangular_flag_on_post:8章「ディープラーニング」
・これまで学んだ手法以外で、更に認識精度を高める手法として、Data Augmentationがある。入力画像に対して、回転や縦横方向の移動など微小な変化を与えたり、一部を切り出すcrop処理や左右を反転させるflip処理などによって、画像枚数を増やすことを行う
・高速化の観点では、多くのディープラーニングのフレームワークではGPUをサポートしている。また、複数GPUや複数マシンによる分散学習もサポートされ始めている

以下の書籍は、上述の「ゼロから作るDeep Learning」の第二弾です。第一弾ではCNNを実装しましたが、こちらの書籍ではRNNを実装します。
ze2.png
※鋭意学習中!!

概要を流し読みしたい方はこちら

:triangular_flag_on_post:1章「ニューラルネットワークの復習」
※前作のダイジェストにつき割愛

:triangular_flag_on_post:2章「自然言語と単語の分散表現」
・自然言語処理とは「私たちの言葉をコンピュータに理解させるための技術(分野)」を指す
・私たちの言葉は文字で構成され、意味の最小単位は「単語」である為、「単語の意味」をコンピュータに理解させるのが重要と言えそう
・「シソーラス」とは類似辞書であり「同じ意味の単語(同義語)」や「意味の似た単語(類義語)」が同じグループに分類されている。例えばcarの同義語には、automobileやmotorcarなどが存在する。また、単語間で上位/下位、全体/部分など、より細かい関連性が定義されている場合がある
・自然言語処理の分野で最も有名なシソーラスは「WordNet」で、プリンストン大学で1985年に開発がスタートした伝統あるシソーラスである
・シソーラスの問題点は以下
 ⇒時代の変化に対応するのが困難
 ⇒人の作業コストが高い
 ⇒単語の細かなニュアンスを表現できない
・カウントベースの手法において、「コーパス(corpus)」を利用する。コーパスとは簡単に言うと大量のテキストデータで、自然言語処理の研究やアプリケーションのために目的をもって収集されたテキストデータ。カウントベースの手法の目標は、人の知識が詰まったコーパスから、自動的に、効率よく、そのエッセンスを抽出すること
・コーパスには例えば、WikipediaやGoogle News、シェイクスピアや夏目漱石などの作品群も用いられる
・単語の分散表現とは、単語を固定長のベクトルで表現する
・単語をベクトルで表す研究はこれまで数多く行われてきたが、重要な手法のほとんど全てが、ある一つのシンプルなアイデアに基づいている。そのアイデアとは「単語の意味は、周囲の単語によって形成される」というもので「分布仮説」と呼ばれる
・「コンテキスト」とは、その単語の周囲に存在する単語を指す
・すべての単語に対して共起する単語をまとめたテーブルを「共起行列」と呼ぶ
共起行列.png
・ベクトル間の類似度を計測するのに「コサイン類似度」がよく用いられる。直感的には「2つのベクトルがどれだけ同じ方向を向いているか」を表し、完全に同じなら1を、完全に逆向きだと-1になる
・単語の出現頻度だけを見ると、「the」などが高頻度な為、例えば「car」が「drive」より「the」に強い関連性を持ってしまうことになる。そのような問題を解決する為に「相互情報量(PMI)」と呼ばれる指標が使われる
・PMIには一つ問題があり、2つの単語で共起する回数が0回だと-∞になるので、実践上では「正の相互情報量(Positive PMI=PPMI)」が使われる
・PPMI行列にも大きな問題があり、コーパスの語彙数が増えるにつれて、各単語のベクトルの次元数も増えるという問題。例えばコーパスに含まれる語彙数が10万に達すれば、そのベクトルの次元数も10万になる。また、その要素の多くが0(重要度が低い)である!
・「次元削減」は例えば2次元のデータ点を、データの広がりを考慮して一つの座標軸で表すよう新たな軸を導入する。このとき各データは新しい軸への射影された値によって表される
・次元削減を行う方法として「特異値分解(SVD)」がある。SVDは任意の行列を3つの行列の積へと分解する(X=USV)
SVD.png
・本格的だけど大きすぎないコーパス「Penn Treebank(PTB)」データセットは、word2vecの発明者であるTomas Mikolov氏のWebページで用意されている

:triangular_flag_on_post:3章「word2vec」
・カウントベースの手法は、大規模なコーパスを扱う場合に発生する。例えば、語彙数を100万としたばあい、カウントベースの手法では、100万×100万の巨大な行列を作ることになり、そのような行列にSVDを行うのは現実的ではない
・推論ベースの手法では、たとえばニューラルネットワークを用いる場合はミニバッチで学習するのが一般的。すなわち、一度に少量の学習サンプルを見ながら重みを繰り返し更新する。よって、語彙数が大きいコーパスにおいてSVDなどの計算量が膨大で処理が難しい場合でも、ニューラルネットワークの学習は複数マシン/複数GPUの利用による並列計算も可能であり、全体の学習も高速化できる
・推論ベースの手法では何らかのモデルが登場し、ニューラルネットワークが使われる。モデルはコンテキスト情報を入力として受け取り、各単語の出現する確率を出力する
・ニューラルネットワークで「you」や「say」などの単語を処理するため、固定長ベクトルに変換する必要がある。そのための方法の一つは、単語を「one-hot表現(またはone-hotベクトル)」へ変換すること
・word2vecで使用されるニューラルネットワークは2つあり、「continuous bag-of-words(CBOW)」と「skip-gram」である
・「CBOW」は、コンテキストからターゲットを推測することを目的としたニューラルネットワークである(ターゲットは中央の単語、その周囲の単語がコンテキスト)
cbow.png

de.png

概要を流し読みしたい方はこちら

caf.png

概要を流し読みしたい方はこちら

py.png

概要を流し読みしたい方はこちら

4. 実際に人工知能を実装してみる

4.1. 作品

Raspberry PiカメラでDeepLearningによるリアルタイム顔認証

4.2. 環境構築

Ubuntu16.04にCaffeをインストールする
Ubuntu16.04にCaffe2をインストールする

4.3. 調査

Sony Neural Network Consoleで学習の途中出力結果を確認する

※Linuxコマンドメモ

### rootのパスワード変更 ###
$ sudo passwd root
### オーナーの一括変更 ###
$ chown -R user[:group] 対象ディレクトリ
### 権限の一括変更 ###
$ find 対象ディレクトリ -type d -exec chmod 755 {} \;
$ find 対象ディレクトリ -type f -exec chmod 644 {} \;
### swapの作成&反映 ###
$ dd if=/dev/zero of=/swap bs=1M count=1024
$ mkswap /swap
$ swapon /swap
Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away