#<科目> 深層学習
目次
[深層学習: Day1 NN ]
(https://qiita.com/matsukura04583/items/6317c57bc21de646da8e)
[深層学習: Day2 CNN ]
(https://qiita.com/matsukura04583/items/29f0dcc3ddeca4bf69a2)
[深層学習: Day3 RNN]
(https://qiita.com/matsukura04583/items/9b77a238da4441e0f973)
[深層学習: Day4 強化学習・Tensor Flow]
(https://qiita.com/matsukura04583/items/50806b750c8d77f2305d)
##深層学習: Day3 CNN (講義の要約)
深層学習全体像の復習–学習概念
####最新のCNN
•AlexNet
AlexNetとは2012年に開かれた画像認識コンペティション2位に大差をつけて優勝したモデルである。AlexNetの登場で、ディープラーニングが大きく注目を集めた。
モデルの構造
5層の畳み込み層およびプーリング層など、それに続く3層の全結合層から構成される
##再帰型ニューラルネットワークについて
###Section1)再帰型ニューラルネットワークの概念
- 1-1RNN全体像
u[:,t+1] = np.dot(X, W_in) + np.dot(z[:,t].reshape(1, -1), W)
z[:,t+1] = functions.sigmoid(u[:,t+1])
np.dot(z[:,t+1].reshape(1, -1), W_out)
y[:,t] = functions.sigmoid(np.dot(z[:,t+1].reshape(1, -1), W_out))np.dot(z[:,t+1].reshape(1, -1), W_out)
- 1-2BPTT
-
1-2-1BPTTとは誤差逆伝播法の復習
-
1-2-2BPTTの数学的記述
-
上からコードに紐付けると
- np.dot(X.T,delta[:,t].reshape(1,-1))
- np.dot(z[:,t+1].reshape(-1,1),delta_out[:,t].reshape(-1,1))
- 3)np.dot(z[:,t].reshape(-1,1), delta[:,t].reshape(1,-1))
- (bとcは)simple RNNコードでは簡略化のため省略
- (bとcは)simple RNNコードでは簡略化のため省略
-
$u^t=W_{(in)}x^t+Wz^{t-1}+b$
(コード) u[:,t+1] = np.dot(X, W_in) + np.dot(z[:,t].reshape(1, -1), W) -
$z^t=f(W_{(in)}x^t+Wz^{t-1}+b)$
(コード) z[:,t+1] = functions.sigmoid(u[:,t+1]) -
$v^t=W_{(out)}z^t+c$
+(コード) y[:,t] = functions.sigmoid(np.dot(z[:,t+1].reshape(1, -1), W_out)) -
パラメータの更新式
-
1-2-3BPTTの全体図
-
###Section2) LSTM
全体像(前回の流れと課題全体像のビジョン)
####LTSM全体図
-
2-1CEC
-
勾配消失および勾配爆発の解決方法として、勾配が、1であれば解決できる。
課題入力データについて、時間依存度に関係なく重みが一律である。$\Rightarrow$ニューラルネットワークの学習特性が無いということ。
入力層→隠れ層への重み入力重み衝突。隠れ層→出力層への重み出力重み衝突。 -
2-2入力ゲートと出力ゲート
- 入力・出力ゲートの役割とは?$\Rightarrow$入力・出力ゲートを追加することで、それぞれのゲートへの入力値の重みを、重み行列W,Uで可変可能とする。$\Rightarrow$CECの課題を解決。
-
2-3忘却ゲート
- LSTMブロックの課題から忘却ゲートが誕生
- 課題過去の情報が要らなくなった場合、削除することはできず、保管され続ける。LSTMの現状CECは、過去の情報が全て保管されている。解決策過去の情報が要らなくなった場合、そのタイミングで情報を忘却する機能が必要。$\Rightarrow$忘却ゲートの誕生
-
2-4覗き穴結合
CECの保存の過去の情報を、任意のタイミングで他のノードに伝播させたり、あるいは任意のタイミングで忘却させたいニーズに対応するために誕生した仕組み。CEC自身の値は、ゲート制御に影響を与えていない。覗き穴結合とは?$\Rightarrow$CEC自身の値に、重み行列を介して伝播可能にした構造。
###Section3) GRU
GRU全体図
-
(背景)LSTMでは、パラメータ数が多く、計算負荷が高くなる問題があった。$\Rightarrow$GRU誕生
-
GRUとは?$\Rightarrow$従来のLSTMでは、パラメータが多数存在していたため、計算負荷が大きかった。しかし、GRUでは、そのパラメータを大幅に削減し、精度は同等またはそれ以上が望める様になった構造。
-
メリット$\Rightarrow$計算負荷が低い。
###Section4)双方向RNN
##RNNでの自然言語処理
###Section5)Seq2Seq
####Seq2Seq全体像
Seq2seqの具体的な用途とは?$\Rightarrow$機械対話や、機械翻訳などに使用されている。
Seq2seqとは?$\Rightarrow$Encoder-Decoderモデルの一種を指します。
-
5-1Encoder RNN
-
ユーザーがインプットしたテキストデータを、単語等のトークンに区切って渡す構造
-
Taking :文章を単語等のトークン毎に分割し、トークンごとのIDに分割する。
Embedding :IDから、そのトークンを表す分散表現ベクトルに変換。
Encoder RNN:ベクトルを順番にRNNに入力していく。 -
Encoder RNN処理手順
- vec1をRNNに入力し、hidden stateを出力。このhiddenstateと次の入力vec2をまたRNNに入力してきたhidden stateを出力という流れを繰り返す。
- 最後のvecを入れたときのhiddenstateをfinalstateとしてとっておく。このfinalstateがthoughtvectorと呼ばれ、入力した文の意味を表すベクトルとなる
-
-
5-2Decoder RNN
- システムがアウトプットデータを、単語等のトークンごとに生成する構造。
- Decoder RNNの処理
- 1)Decoder RNN: Encoder RNN のfinal state (thought vector) から、各token の生成確率を出力していきますfinal state をDecoder RNN のinitial state ととして設定し、Embedding を入力。
- 2)Sampling:生成確率にもとづいてtoken をランダムに選びます。
- 3)Embedding:2で選ばれたtoken をEmbedding してDecoder RNN への次の入力とします。
- 4)Detokenize:1 -3 を繰り返し、2で得られたtoken を文字列に直します。
-
5-3HRED
- Seq2seqの課題 一問一答しかできない。問に対して文脈も何もなく、ただ応答が行われる続ける。これを解決するためにHREDが誕生。
- HREDとは?過去n-1 個の発話から次の発話を生成する。システム:インコかわいいよね。ユーザー:うんシステム:インコかわいいのわかる。Seq2seqでは、会話の文脈無視で、応答がなされたが、HREDでは、前の単語の流れに即して応答されるため、より人間らしい文章が生成される。
-
5-4VHRED
- VHREDとは?$\Rightarrow$HREDに、VAE(バエと呼ばれている)の潜在変数の概念を追加したもの。
- HREDの課題を、VAEの潜在変数の概念を追加することで解決した構造。
-
5-5VAE
-
5-5-1オートエンコーダ―
- オートエンコーダとは?$\Rightarrow$教師なし学習の一つ。そのため学習時の入力データは訓練データのみで教師データは利用しない。
- オートエンコーダ具体例MNISTの場合、28x28の数字の画像を入れて、同じ画像を出力するニューラルネットワークということになります。
- オートエンコーダ構造
- 構造図
- オートエンコーダ構造説明$\Rightarrow$入力データから潜在変数zに変換するニューラルネットワークをEncoder逆に潜在変数zをインプットとして元画像を復元するニューラルネットワークをDecoder。
-
メリット$\Rightarrow$次元削減が行えること
※zの次元が入力データより小さい場合、次元削減とみなすことができる。
-
5-5-2VAE
###Section6)Word2vec
- 学習データからボキャブラリを作成
Ex) I want to eat apples. I like apples.{apples,eat,I,like,to,want}※わかりやすく7語のボキャブラリを作成したら本来は、辞書の単語数だけできあがる。 - メリット
- 大規模データの分散表現の学習が、現実的な計算速度とメモリ量で実現可能にした。
- ✗:ボキャブラリ×ボキャブラリだけの重み行列が誕生。
- ○:ボキャブラリ×任意の単語ベクトル次元で重み行列が誕生
- 大規模データの分散表現の学習が、現実的な計算速度とメモリ量で実現可能にした。
###Section7)AttentionMechanism
-
課題:seq2seq の問題は長い文章への対応が難しいです。seq2seq では、2単語でも、100単語でも、固定次元ベクトルの中に入力しなければならない
-
解決策:文章が長くなるほどそのシーケンスの内部表現の次元も大きくなっていく、仕組みが必要になります。
+「入力と出力のどの単語が関連しているのか」の関連度を学習する仕組み -
Attention Mechanism具体例$\Rigtharrow$※「a」については、そもそも関連度が低く、「I」については「私」との関連度が高い.
##確認テスト
【P11】確認テスト
サイズ5×5の入力画像を、サイズ3×3のフィルタで畳み込んだ時の出力画像のサイズを答えよ。なおストライドは2、パディングは1とする。
⇒【考察】 答え 3✖️3
入力サイズ高さ(H),入力サイズ幅(W)
Output Hight(OH)
Output Width(OW)
Filler Hight(FH)
Filler Width(FW)
ストライド(S)
パンディング(P)
【P12】連鎖律の原理を使い、dz/dxを求めよ。
z = t^2,t=x+y
⇒【考察】
次のような計算にて求める事ができる。
\frac{dz}{dx}=\frac{dz}{dy}\frac{dy}{dx}
,t=x+y
z = t^2なのでtで微分すると \frac{dz}{dt}=2t
t=x+yなのでxで微分すると \frac{dt}{dx}=1
\frac{dz}{dx}=2t・1=2t=2(x+y)
OH =\frac{H+2P-FH}{S}+1 =\frac{5+2・1-3}{2}+1=3
OH =\frac{W+2P-FW}{S}+1 =\frac{5+2・1-3}{2}+1=3
決まった計算方法なので、公式として覚えておこう。
【P23】確認テスト
RNNのネットワークには大きくわけて3つの重みがある。1つは入力から現在の中間層を定義する際にかけられる重み、1つは中間層から出力を定義する際にかけられる重みである。残り1つの重みについて説明せよ。
⇒【考察】
答えは、中間層から次の中間層へ渡される重み。
【P37】連鎖律の原理を使い、dz/dxを求めよ。
z = t^2,t=x+y
⇒【考察】
次のような計算にて求める事ができる。
\frac{dz}{dx}=\frac{dz}{dy}\frac{dy}{dx}
,t=x+y
z = t^2なのでtで微分すると \frac{dz}{dt}=2t
t=x+yなのでxで微分すると \frac{dt}{dx}=1
\frac{dz}{dx}=2t・1=2t=2(x+y)
【P46】確認テスト
下図のy1をx・s0・s1・win・w・woutを用いて数式で表せ。※バイアスは任意の文字で定義せよ。※また中間層の出力にシグモイド関数g(x)を作用させよ。
Z_1=sigmoid(S_0W+x_1W_{(in)}+b)
出力層もシグモイドを使う
y_1=sigmoid(Z_1W_{(out)}+c)
書物によって記号の書き方が違うので、本質を知る。
【P54】コード演習問題
⇒【考察】答えは(2)
【解説】RNNでは中間層出力h_{t}が過去の中間層出力h_{t-1},.., h_{1}に依存する。RNNにおいて損失関数を重みWやUに関して偏微分するときは、それを考慮する必要があり、dh_{t}/dh_{t-1} = Uであることに注意すると、過去に遡るたびにUが掛けられる。つまり、delta_t= delta_t.dot(U)となる。
【P63】シグモイド関数を微分した時、入力値が0の時に最大値をとる。その値として正しいものを選択肢から選べ。(1)0.15(2)0.25(3)0.35(4)0.45
⇒【考察】
sigumoidの微分
(sigmoid)'=(1-sigmoid)(sigmoid)
sigmoid関数は0.5で最大となるので、
(sigmoid)'=(1-0.5)(0.5)=0.25 となる
⇒【考察】
正解:1【解説】勾配のノルムがしきい値より大きいときは、勾配のノルムをしきい値に正規化するので、クリッピングした勾配は、勾配×(しきい値/勾配のノルム)と計算される。つまり、gradient * rateである。
勾配に対して敷居値がかけあわされて正規化されているだけなので理解しやい。
【P79】確認テスト
以下の文章をLSTMに入力し空欄に当てはまる単語を予測したいとする。文中の「とても」という言葉は空欄の予測においてなくなっても影響を及ぼさないと考えられる。このような場合、どのゲートが作用すると考えられるか。「映画おもしろかったね。ところで、とてもお腹が空いたから何か____。」
⇒【考察】
正解:忘却ゲート。
忘却ゲートの役割は,直前の影響をどの程度考慮するかを定めることに利用される。
⇒【考察】
正解:3【解説】新しいセルの状態は、計算されたセルへの入力と1ステップ前のセルの状態に入力ゲート、忘却ゲートを掛けて足し合わせたものと表現される。つまり、input_gate* a + forget_gate* cである。
【P89】確認テスト
LSTMとCECが抱える課題について、それぞれ簡潔に述べよ。
⇒【考察】
LSTMとCECが抱える課題。
LSTMでは、パラメータ数が多く、計算負荷が高い問題があった。
CECでは、学習という概念がなく、重みも利用されていない。保存の過去の情報を、任意のタイミングで他のノードに伝播させたり、あるいは任意のタイミングで忘却させたいニーズに応えられない。
【P93】確認テスト
LSTMとGRUの違いを簡潔に述べよ。
⇒【考察】
LSTMでは、パラメータ数が多く、計算負荷が高い問題があったが、GRUではパラメータも削減され、処理も高速となった。
ただし、全てがGRUがまさっている訳ではなく、場合によって比較選択してゆくのが良い。
【P96】演習チャレンジ
⇒【考察】 正解:4【解説】双方向RNNでは、順方向と逆方向に伝播したときの中間層表現をあわせたものが特徴量となるので、np.concatenate([h_f, h_b[::-1]], axis=1)である。 (参考)[np.concatenate構文は、こちらで学習](https://www.sejuku.net/blog/67869)【P111】演習チャレンジ
⇒【考察】
正解:1【解説】単語wはone-hotベクトルであり、それを単語埋め込みにより別の特徴量に変換する。これは埋め込み行列Eを用いて、E.dot(w)と書ける。
wはOneーhotベクトルでできている。
(参考)自然言語処理とon-hotの関係は、こちらで学習
文書が大きい時には、on-hotデータも大きくなり、処理が間に合わない場合もありうる課題あり。
【P120】確認テスト
seq2seqとHRED、HREDとVHREDの違いを簡潔に述べよ。
⇒【考察】
seq2seqは一問一答しかできなかったが、HREDはその課題を解決するためにできたもの。HREDとVHREDの違いは、HREDが同じような回答しができない課題があり、その課題を解決し、表現を変えながら回答できるのがVHREDである。
【P129】確認テスト
VAEに関する下記の説明文中の空欄に当てはまる言葉を答えよ。自己符号化器の潜在変数に____を導入したもの
⇒【考察】答えは、潜在変数に『確率変数』を導入したもの。
【P138】確認テスト
RNNとword2vec、seq2seqとAttentionの違いを簡潔に述べよ。
⇒【考察】
RNNは、ボキャブラリー数✖️ボキャブラリー数の重みの行列を生成する必要があったが、word2vecは、ボキャブラリー数✖️任意の単語ベクトル数の重みの行列で作る事ができる。
seq2seqとAttentionでは、seq2seq同じ質問に同じ回答しか出せないが、Attentionでは重要度・関連度が活用でき、バリエーションをもつ回答を返せるようになる。繰り返し学習により精度向上に繋がる回答を出せるようになる。
【ビデオDN60】演習チャレンジ
⇒【考察】答えは(2)。
表現ベクトルで表し、レフトとライトで隣接した表現ベクトルに対して重みをつけて計算してゆく。
##演習
###DN42_ソース演習①
[try] weight_init_stdやlearning_rate, hidden_layer_sizeを変更してみよう
weight_init_std 1→10
learning_rate 0.1→0.01
hidden_layer_size 16→32
かなり学習が悪くなった。
[try] 重みの初期化方法を変更してみよう
Xavier, Heのどちらも変えて実施してみる。
(ソース変更箇所)
########### 変更箇所 ##############
# ウェイト初期化 (バイアスは簡単のため省略)
#W_in = weight_init_std * np.random.randn(input_layer_size, hidden_layer_size)
#W_out = weight_init_std * np.random.randn(hidden_layer_size, output_layer_size)
#W = weight_init_std * np.random.randn(hidden_layer_size, hidden_layer_size)
# Xavierを使ってウェイト初期化
W_in = np.random.randn(input_layer_size, hidden_layer_size) / (np.sqrt(input_layer_size))
W_out = np.random.randn(hidden_layer_size, output_layer_size) / (np.sqrt(hidden_layer_size))
W = np.random.randn(hidden_layer_size, hidden_layer_size) / (np.sqrt(hidden_layer_size))
# Heを使ってウェイト初期化
# W_in = np.random.randn(input_layer_size, hidden_layer_size) / (np.sqrt(input_layer_size)) * np.sqrt(2)
# W_out = np.random.randn(hidden_layer_size, output_layer_size) / (np.sqrt(hidden_layer_size)) * np.sqrt(2)
# W = np.random.randn(hidden_layer_size, hidden_layer_size) / (np.sqrt(hidden_layer_size)) * np.sqrt(2)
#####################################
Xavierを使った結果
HEを使った結果
ほぼ近しい結果となった。
[try] 中間層の活性化関数を変更してみよう
ReLU(勾配爆発を確認しよう)
# z[:,t+1] = functions.sigmoid(u[:,t+1])
z[:,t+1] = functions.relu(u[:,t+1])
# z[:,t+1] = functions.np.tanh(u[:,t+1])
tanh(numpyにtanhが用意されている。導関数をd_tanhとして作成しよう)
def d_tanh(x):
return np.tanh(x)
# z[:,t+1] = functions.sigmoid(u[:,t+1])
# z[:,t+1] = functions.relu(u[:,t+1])
z[:,t+1] = d_tanh(u[:,t+1])