じぶんメモ

プログラミングのメモ、日常のメモとか。

【ゼロから作るDeep Learning】要点まとめ 第7章

7章 - 畳み込みニューラルネットワーク

CNN(Convolutional Neural Network)は、畳み込み層、プーリング層からなる学習方法
基本的にはconv→relu→conv→relu→...→pool→conv→relu→conv→relu→...→pool→affine→softmaxの流れ
conv→relu or conv→relu→poolが隠れ層になるイメージ。

このサイトがとてもわかり易い。
http://postd.cc/how-do-convolutional-neural-networks-work/

畳み込み層

  • 畳み込み層は、用意された入力データ(画像データなど)をフィルタ(重み)を使って畳み込む
  • 入力データ(縦×横×チャネル→RGB画像なら3チャネル)に対して、フィルタを少しずつづらしながら行列演算をしていく。
  • 入力データのチャネル数とフィルタのチャネル数は合わせておく必要がある。 例) 入力データxは(32,32,3)、フィルタwは(5,5,3)
  • 入力データxは(32,32,3)、フィルタwは(5,5,3)を1幅ずつスライドさせていくと、出力される値は(28,28,1)のデータになる。
  • フィルタの数が増えれば(4次元配列)、出力されるデータのチャネル数も同じ数だけ増える。
  • 例) 入力データx(32,32,3)、フィルタw(10,5,5,3)(10はフィルタの数)を畳み込むと出力される値は(28,28,10)のデータになる。
  • 入力データxを行列に変換 × フィルタwを行列に変換 + バイアス →reluに突っ込む → 再度4次元データに変換して次の隠れ層へ送る。
  • ストライド == スライド幅
  • パディング == スライドした時にはみ出る箇所のデータを0として扱う

プーリング層

  • 縦横の幅を決めてその範囲内での最大値を取る(maxプーリング)プーリングを行う層。
  • 大きな画像を、重要な情報は残しつつ縮小する利点がある。
  • maxプーリングの他にもaverageプーリングがある。

【ゼロから作るDeep Learning】要点まとめ 第6章

6章 - 学習に関するテクニック

勾配法の種類

  • 勾配法の種類はSGD, Momentum, AdaGrad, Adamがある。(AdaGrad,Adamが学習スピードが早い)

重みパラメータと活性化関数での出力値

  • 重みパラメータの初期値は小さくすることで過学習を防げるが、0にすると各層での誤差逆伝播法の出力が均等になってしまうので避けること。
  • 重みパラメータの初期値はランダムである必要がある。
  • 各隠れ層のアクティベーション(活性化関数で出力された値)が、0と1に傾くと勾配損失が発生し、層を深くする意味がなくなってしまう。
  • アクティベーションを分散させるには重みパラメータのスケール(標準偏差)にHeの定数、Xavierの定数を適用させる。
  • 活性化関数が線形(sigmoid, tanh等)の場合はXavierの定数、ReLUの場合はHeの定数が適している。
  • 強制的にアクティベーションの分布を制御するには活性化関数の前にBatch Normalization(正規化)をする。
  • 正規化をしない場合、適切なスケールを設定しないといつまでたってもしっかりと学習されない。
  • 正規化を使用すると重みの初期値にロバストする。(初期値に依存しない)

過学習

  • 特定の訓練データにだけ適応しすぎてしまい、訓練データに含まれないデータにはうまく対応できない状態。
  • 訓練データが少なかったり、パラメータが大量で表現力の高いモデル(隠れ層のノードが多い)場合に発生しやすい。
  • 過学習を避けるためには重みパラメータを抑制するためにWeigt Decay(荷重減衰)または、Dropoutを使用する。
  • Weight Decayは損失関数に対して重みの1.2ノルムを加算する。(ただしハイパーパラメータの設定が必要)
  • Dropoutはニューロンをランダムに消去しながら学習を行う。
  • ハイパーパラメータを適正な値に設定するには検証データを使用する。
  • テストデータをもとにしてハイパーパラメータを設定するのはNG。テストデータのみに適したハイパーパラメータになってしまうため。
  • 検証データを用意する最も簡単な方法は訓練データの20%を分離して使用すること。
  • 最適なハイパーパラメータを求めるには、ハイパーパラメータの範囲を定め、その範囲の中からランダムにサンプリングし、認識精度の評価を行う。それを数回繰り返して最適な値を狭めていく。

【ゼロから作るDeep Learning】要点まとめ 第4章, 第5章

4章 - ニューラルネットワークの精度を高めるためには

損失関数

勾配法

  • 微分  = ある関数でのパラメータの変化の様子
  • 偏微分 = 引数が複数ある関数での1つの引数の微分のことを示す
  • 勾配  = 偏微分をベクトル(一次元配列)で示したもの。勾配が示す方向は、各場所において関数の値を最も減らす方向
  • 損失関数の結果を最小にするには、勾配法(学習率を使って決められたステップ数、重みパラメータの初期値から勾配を引いて更新していく。)を使用する。
  • 上記のような学習を最急降下法SGD)という
  • 勾配法で使用する学習率はハイパーパラメータといい、唯一人間が与える必要があるもの(重みパラメータは勾配法を使用して自動的に更新される想定)

5章 - 誤差逆伝播

順伝播(Affine)で解いた結果から、逆の方向から各隠れ層の微分を求めることで、 重みパラメータの勾配を高速に求めることができる。

誤差逆伝播法を使用するには以下の組み合わせが必要。 - 分類問題では出力層でソフトマックス関数、損失関数に交差エントロピー誤差を使用する。 - 回帰問題では出力層で恒等関数、損失関数に二乗和誤差を使用する。

【ゼロから作るDeep Learning】要点まとめ 第3章ニューラルネットワーク

最近オライリー社から出版されている「ゼロから作るDeep Learning」を読み始めた。
数学の知識がない僕には結構難しかったので、備忘録として要点をまとめていこうと思う。
1,2章に関してはpythonの話や、ANDゲート等の基本情報的な内容が多いので、ここでは省略する。

3章 - ニューラルネットワークについて

Affine空間

  • 入力値xと重みパラメータ、バイアスを使って行列の計算をする。 例)x1, x2、一層目の隠れ層が3つのノードからなるとき。 入力値が2つで出力が3つを求められるので、重みは3×2の配列で必要。
x1w11 + x2w12 + b = a1
x1w21 + x2w22 + b = a2
x1w31 + x2w32 + b = a3

↑のような行列の計算をAffineという。

  • 一層目に出力された値を活性化関数を使って更に計算する(シグモイド関数、RELU)
  • 最終層への出力時は、活性化関数に、恒等関数(回帰問題)、ソフトマックス関数(分類問題)を使用する。

活性化関数

Affineの結果から次のノードに渡すべき値を出力する関数。

  • シグモイド関数
  • RELU(出力の値が0以上ならそのまま値を、0未満なら0を出力する)

出力層の活性化関数

  • ソフトマックス関数: 出力される値の合計が1になるため、確率を求めることができる。分類問題に使用される。基本的にAffineの結果が一番大きい値を使用するので、学習フェーズ以外では使用されない。
  • 恒等関数: 入力された値をそのまま返却する。回帰問題に使用される。

出力層のノードの個数

期待する候補の数だけ必要。 例えば与えられた数値が何なのかを判定する場合は0~9のうちのどれかということになるので、 出力層は10個になる。

バッチ処理

画像のような二次元配列のデータを使う場合に、纏めて複数のデータをニューラルネットワークに投入して結果を得る方法のこと。

例) 10個の画像データ。1データが28 * 28の784ピクセル隠れ層は2つ、それぞれ50, 100のノードを保つ場合。

x  = 100 × 784
w1 = 784 × 50(隠れ層1への重み付け)
w2 = 50  × 100(隠れ層2への重み付け)
w3 = 100 × 10(出力層への重み付け)

railsでポリモーフィック関連でインターフェースっぽく振る舞わせる

railsにもインターフェースはないのかな?と思い調べてみると、
ポリモーフィック関連というものを使うそうです。
例として、Article、Eventという二つのモデルを用意し、
その両方ともにCommentモデルをhas_manyの関係で保持させたいとします。

テーブル定義

  • articlesテーブル
idID
titleタイトル
body本文
created_at作成日時
updated_at更新日時


  • eventsテーブル
idID
titleタイトル
body内容
created_at作成日時
updated_at更新日時


  • commentsテーブル
idID
commentable_id関連元レコードID
commentable_type関連元レコード種別
name発言者名
body内容
created_at作成日時
updated_at更新日時

commentable_id は、どのレコードに対するコメントなのか、
commentable_type は、commentable_idに対してどのテーブルへの関連なのかを示します。

モデル定義

class Article < ApplicationRecord
  has_many :comments, as: :commentable
end
class Event < ApplicationRecord
  has_many :comments, as: :commentable
end
class Comment < ApplicationRecord
  belongs_to :commentable, polymorphic: true, inverse_of: :comments
end

has_manyに as: :commentable とすることで、ポリモーフィック関連でのアソシエーションを生成します。
commentモデル側では belongs_to :commentable, polymorphic: true とすることで、
article、eventのどちらのモデルからも参照される・することを定義しています。

インターフェース部分を別ファイルに切り出すと、以下のような感じ

class Article < ApplicationRecord
  include Commentable
end
class Event < ApplicationRecord
  include Commentable
end
module Commentable
  extend ActiveSupport::Concern

  included do
    has_many :comments, as: :commentable
  end
end
class Comment < ApplicationRecord
  belongs_to :commentable, polymorphic: true, inverse_of: :comments
end

has_manyな関連テーブルのレコードのカラムでソート

チャットとかchat(チャットルーム) has_many chat_messages(チャットのメッセージ)みたいなテーブル構造になると思うが、 この時、チャットルームをメッセージが来た順に並び変えたいとかあると思う。 メッセージの投稿日時がmaxのもので比較してソートする必要があるが、書き方がわからなかったので調べた。

テーブル構造はこんな感じ

chatsテーブル

idID
created_at作成日時
updated_at更新日時

chat_messagesテーブル

idID
chat_idチャットID
message本文
created_at作成日時
updated_at更新日時
select chats.*, max_created_at from chats
left outer join (
  select max(chat_messages.created_at) max_created_at , chat_id
  from chat_messages
  group by chat_id
) cm on chats.id = cm.chat_id
order by max_created_at desc;

Sweet Alertで簡単に綺麗なアラート画面を作る

普通にjavascriptでalert()を使うと味気ないアラートウィンドウしか出ないが、sweet alertを使うと簡単に綺麗なアラート画面を出せる。
jQuery依存でなくプレーンなjavascriptで使用できる。

導入

  • npmでも公式サイトでjsとcssを落とすでもOK。

  • 落としてきたら必要なcssとjsをインクルードしておく。

<link rel="stylesheet" type="text/css" href="dist/sweetalert.css">
<link rel="stylesheet" type="text/css" href="themes/twitter.css">
  • あとはjavascriptでswal()と呼び出すだけで綺麗なアラートが出る。
swal({
  title: "データを消しますか?",
  text: "消されたデータは元に戻すことができません。",
  type: "warning",
  showCancelButton: true,
  confirmButtonColor: "#DD6B55",
  confirmButtonText: "OK",
  cancelButtonText: "キャンセル",
  closeOnConfirm: false
},
function(){
  swal("削除しました!", "データは正常に削除されました。", "success");
});

細かい使い方は公式を参照。

SweetAlert