0

E資格_深層学習day3

75
0
$$$$

はじめに

 本レポートはラビットチャレンジ深層学習day3のレポートである

再帰的ニューラルネットワークの概念

再帰的ニューラルネットワーク(RNN)とは

 RNNとは、時系列データに対して有効なニューラルネットワークの一つ。従来のニューラルネットワークとは異なり、自己回帰的な構造を持ち、主に音声認識で使用される。

時系列データとは?

 時系列データとは、時間的順序を追って一定期間ごとに観察され、相互に統計的依存関係が認められるようなデータの系列 (例)音声データ、テキストデータ

演習

      import numpy as np
from common import functions
import matplotlib.pyplot as plt

# def d_tanh(x):



# データを用意
# 2進数の桁数
binary_dim = 8
# 最大値 + 1
largest_number = pow(2, binary_dim)
# largest_numberまで2進数を用意
binary = np.unpackbits(np.array([range(largest_number)],dtype=np.uint8).T,axis=1)

input_layer_size = 2
hidden_layer_size = 16
output_layer_size = 1

weight_init_std = 1
learning_rate = 0.1

iters_num = 10000
plot_interval = 100

# ウェイト初期化 (バイアスは簡単のため省略)
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


# He



# 勾配
W_in_grad = np.zeros_like(W_in)
W_out_grad = np.zeros_like(W_out)
W_grad = np.zeros_like(W)

u = np.zeros((hidden_layer_size, binary_dim + 1))
z = np.zeros((hidden_layer_size, binary_dim + 1))
y = np.zeros((output_layer_size, binary_dim))

delta_out = np.zeros((output_layer_size, binary_dim))
delta = np.zeros((hidden_layer_size, binary_dim + 1))

all_losses = []

for i in range(iters_num):
    
    # A, B初期化 (a + b = d)
    a_int = np.random.randint(largest_number/2)
    a_bin = binary[a_int] # binary encoding
    b_int = np.random.randint(largest_number/2)
    b_bin = binary[b_int] # binary encoding
    
    # 正解データ
    d_int = a_int + b_int
    d_bin = binary[d_int]
    
    # 出力バイナリ
    out_bin = np.zeros_like(d_bin)
    
    # 時系列全体の誤差
    all_loss = 0    
    
    # 時系列ループ
    for t in range(binary_dim):
        # 入力値
        X = np.array([a_bin[ - t - 1], b_bin[ - t - 1]]).reshape(1, -1)
        # 時刻tにおける正解データ
        dd = np.array([d_bin[binary_dim - t - 1]])
        
        u[:,t+1] = np.dot(X, W_in) + np.dot(z[:,t].reshape(1, -1), W)
        z[:,t+1] = functions.sigmoid(u[:,t+1])

        y[:,t] = functions.sigmoid(np.dot(z[:,t+1].reshape(1, -1), W_out))


        #誤差
        loss = functions.mean_squared_error(dd, y[:,t])
        
        delta_out[:,t] = functions.d_mean_squared_error(dd, y[:,t]) * functions.d_sigmoid(y[:,t])        
        
        all_loss += loss

        out_bin[binary_dim - t - 1] = np.round(y[:,t])
    
    
    for t in range(binary_dim)[::-1]:
        X = np.array([a_bin[-t-1],b_bin[-t-1]]).reshape(1, -1)        

        delta[:,t] = (np.dot(delta[:,t+1].T, W.T) + np.dot(delta_out[:,t].T, W_out.T)) * functions.d_sigmoid(u[:,t+1])

        # 勾配更新
        W_out_grad += np.dot(z[:,t+1].reshape(-1,1), delta_out[:,t].reshape(-1,1))
        W_grad += np.dot(z[:,t].reshape(-1,1), delta[:,t].reshape(1,-1))
        W_in_grad += np.dot(X.T, delta[:,t].reshape(1,-1))
    
    # 勾配適用
    W_in -= learning_rate * W_in_grad
    W_out -= learning_rate * W_out_grad
    W -= learning_rate * W_grad
    
    W_in_grad *= 0
    W_out_grad *= 0
    W_grad *= 0
    

    if(i % plot_interval == 0):
        all_losses.append(all_loss)        
        print("iters:" + str(i))
        print("Loss:" + str(all_loss))
        print("Pred:" + str(out_bin))
        print("True:" + str(d_bin))
        out_int = 0
        for index,x in enumerate(reversed(out_bin)):
            out_int += x * pow(2, index)
        print(str(a_int) + " + " + str(b_int) + " = " + str(out_int))
        print("------------")

lists = range(0, iters_num, plot_interval)
plt.plot(lists, all_losses, label="loss")
plt.show()
    

実行結果 実行結果

通時的誤差逆伝播法(BPTT)とは

 BPTTとは、誤差逆伝播法をRNNにおいて適応した学習アルゴリズムのこと。
BPTTの数学的記述 BPTTの数学的記述

確認テスト

Q. RNNのネットワークには大きくわけて3つの重みがある。1つは入力から現在の中間層を定義する際にかけられる重み、1つは中間層から出力を定義する際にかけられる重みである。残り1つの重みについて説明せよ。
A. 前の中間層から現在の中間層への重み

Q. (く)にあてはまるのはどれか。
A. (2)W.dot(np.concatenate([left, right]))

Q. 下図の$y_1$を数式を用いて表せ
image.png image.png
A. $z_1 = f(w_{in}x+wz_0+b)$
  $y_1 = g(w_{out}z_1+c)$

参考文献・参考サイト

 ゼロから作るDeepLearning2 5章 リカレントニューラルネットワーク
 G検定公式テキスト 第6章

LSTM

LSTMとは

 LSTM (Long Short-Term Memory)は、RNNの一種で、特に長期的な依存関係を扱うために設計されたニューラルネットワークのアーキテクチャ。LSTMにより時系列を遡れば遡ぼるほど勾配が消失していくというRNNの課題を解決することができる。

LSTMの構造

 LSTMには3つのゲートがある。
 忘却ゲート:現在の入力と前の状態を受け取り、どの情報を保持するかを決定するゲート
 入力ゲート:現在の入力と前の状態を受け取り、新しい情報をどの程度保持するかを決定するゲート
 出力ゲート:現在の入力と前の状態を受け取り、次の状態をどの程度出力するかを決定するゲート
LSTMの全体図 LSTMの全体図

実装

      # LSTMレイヤの実装
class LSTM:
    # 初期化メソッドの定義
    def __init__(self, Wx, Wh, b):
        self.params = [Wx, Wh, b] # パラメータ
        self.grads = [np.zeros_like(Wx), np.zeros_like(Wh), np.zeros_like(b)] # 勾配
        self.cache = None
    
    # 順伝播メソッドの定義
    def forward(self, x, h_prev, c_prev):
        # パラメータと変数の形状に関する値を取得
        Wx, Wh, b = self.params
        N, H = h_prev.shape
        
        # 結合したパラメータによる重み付き和の計算
        A = np.dot(x, Wx) + np.dot(h_prev, Wh) + b
        
        # 各ゲートの重み付き和を取得
        f = A[:, :H]      # forgetゲート
        g = A[:, H:2*H]   # 記憶セル
        i = A[:, 2*H:3*H] # inputゲート
        o = A[:, 3*H:]    # outputゲート
        
        # ゲート値に変換
        f = sigmoid(f)
        g = np.tanh(g)
        i = sigmoid(i)
        o = sigmoid(o)
        
        # 出力を計算
        c_next = f * c_prev + g * i  # 記憶セル
        h_next = o * np.tanh(c_next) # 出力データ
        
        # 逆伝播の計算用に変数を保存
        self.cache = (x, h_prev, c_prev, i, f, g, o, c_next)
        return h_next, c_next
    
    # 逆伝播メソッドの定義
    def backward(self, dh_next, dc_next):
        # 変数を取得
        Wx, Wh, b = self.params
        x, h_prev, c_prev, i, f, g, o, c_next = self.cache
        
        # 計算用に活性化記憶セルを計算
        tanh_c_next = np.tanh(c_next)
        
        # 現レイヤの記憶セルの勾配を計算
        ds = dc_next + (dh_next * o) * (1 - tanh_c_next ** 2)
        
        # 前レイヤの記憶セルの勾配を計算
        dc_prev = ds * f
        
        # 活性化後のゲートの勾配を計算
        di = ds * g
        df = ds * c_prev
        do = dh_next * tanh_c_next
        dg = ds * i
        
        # 活性化前のゲートの勾配を計算
        di *= i * (1 - i)
        df *= f * (1 - f)
        do *= o * (1 - o)
        dg *= (1 - g ** 2)
        
        # ゲートの勾配を結合
        dA = np.hstack((df, dg, di, do))
        
        # パラメータの勾配を計算
        dWh = np.dot(h_prev.T, dA)
        dWx = np.dot(x.T, dA)
        db = dA.sum(axis=0)
        
        # パラメータの勾配を格納
        self.grads[0][...] = dWx
        self.grads[1][...] = dWh
        self.grads[2][...] = db
        
        # 入力の勾配を計算
        dx = np.dot(dA, Wx.T)
        dh_prev = np.dot(dA, Wh.T)
        
        return dx, dh_prev, dc_prev
    

確認テスト

Q. シグモイド関数を微分したとき、入力値が0のときに最大値をとる。その値として正しいものを選択肢から選べ。
A. 0.25

Q. 以下の文章をLSTMに入力し空欄に当てはまる単語を予測したいとする。文中の「とても」という言葉は空欄の予測においてなくなっても影響を及ぼさないと考えられる。このような場合、どのゲートが作用すると考えられるか。
A. 忘却ゲート

Q. (け)にあてはまるのはどれか
A. (3)input_gatea+forget_gatec

参考文献・参考サイト

ゼロから作るDeepLearning2 6章 ゲート付きRNN

GRU

GRUとは

GRUとは、深層学習における一種の再帰型ニューラルネットワーク。LSTMと同様に、シーケンスデータに対するモデリングに適していて、パラメータが多く計算負荷が大きかったLSTMの課題点を解決するために作られた。GRUはパラメータ量がLSTMよりも少ないが、精度はLSTM同等かそれ以上になった。

GRUにはリセットゲート、更新ゲートの2つのゲートがある。

実装

      def gru(x, h, W_r, U_r, W_z, U_z, W, U):
  # ゲートを計算
  # ↓リセットゲート
  r = _sigmoid(x.dot(W_r.T) + h.dot(U_r.T)) 
  # ↓更新ゲート
  z = _sigmoid(x.dot(W_z.T) + h.dot(U_z.T)) 

  # 次の状態を計算
  h_bar = np.tanh(x.dot(W.T) + (r * h).dot(U.T)) 
  h_new = (1-z) * h + z * h_bar  
  return h_new
    

確認テスト

Q. LSTMとCECが抱える課題について、それぞれ簡潔に述べよ
A.
LSTM:パラメータ数が多く、計算量も多い
CEC:勾配が1で、単体では学習できない
Q. LSTMとGRUの違いを簡潔に述べよ
LSTM:パラメータ数が多く、計算量も多い。
GRU:パラメータを削減し計算負荷を減らしたが、同等またはそれ以上の精度が望める。

参考文献・参考サイト

 ゼロから作るDeepLearning2 付録C GRU
 【脱初心者】GRUの数式とあの図を攻略!超絶分かりやすい図解でステップ解説【E資格合格者のノート公開】  https://i-main.net/emmanote-ai-gru/

BiRNN

双方向RNN(BiRNN)とは?

 RNNを2つ組み合わせることで、未来から過去方向も含めて学習できるようにしたモデル。通常のRNNは過去から未来への一方向でしか学習をすることができないが、BiRNNによって未来の情報からの学習も可能になった。
 文章の推敲や機械翻訳に用いられている。

実装

      def bindirectional_rnn_net(xs, W_f, U_f, W_b, U_b, V):
  # W_f, U_f:入力から中間層、前の中間層から今の中間層の順方向の重み
  # W_b, U_b:W_f, U_fの逆方向
  # V:順方向、逆方向の中間層から出力層の重み
  xs_f = np.zeros_like(xs)
  xs_b = np.zeros_like(xs)

  for i, x in enumerate(xs):
    xs_f[i] = x
    xs_b[i] = x[::-1]

  hs_f = _rnn(xs_f, W_f, U_f)
  hs_b = _rnn(xs_b, W_b, U_b)
  hs = [np.concatenate([h_f, h_b[::-1]], axis=0)] for h_f, h_b in zip(hs_f, hs_b)
  ys = hs.dot(V.T)
  return ys
    

演習チャレンジ

A. (4)

参考文献・参考サイト

ゼロから作るDeepLearning2 8章 4-1 双方向RNN

Seq2Seq

Seq2Seqとは

 自然言語処理において、入力と出力の長さが異なるシーケンスを扱うためのモデル。エンコーダとデコーダという2つのニューラルネットワークをしようしている。

Encoder部分

 Encoder部分では、入力されたシーケンスデータを単語の埋め込み表現に変換し、RNNを使用してシーケンスを表す隠れ状態を生成する。隠れ状態は、最終的に固定長のベクトルに変換される。

Decoder部分

 Decoder部分では、エンコーダーが生成したベクトルを元に、出力となる文章を生成する。

HRED

 Seq2Seqモデルを拡張したニューラルネットワークモデル。HREDは、Seq2Seqのエンコーダーを階層的に拡張し、文書全体を階層的に表現することができる。文章を文単位や文書単位などのより細かい単位で表現することができ、より自然な文章生成が可能となっている。

VHRED

 HREDをベースにしたモデルであり、VAEを組み合わせることで、より自然な文章生成を実現するために開発されたニューラルネットワークモデルのこと。

VAE

 高次元データを低次元の潜在空間に写像し、そこでデータを生成する生成モデル。エンコーダーとデコーダーを使い、確率分布を学習して生成する。画像、音声、自然言語生成などに用いられる。

2022年に公開された画像生成系AIであるStable DiffusionもVAEが用いられている。

確認テスト

Q. Seq2SeqとHREDの違いを説明せよ
A. Seq2Seqが単一のエンコーダーとデコーダーで構成されるのに対し、HREDは複数の階層的なエンコーダーとデコーダーから構成される。

Q. HREDとVHREDの違いを説明せよ
A. HREDが階層的なエンコーダーとデコーダーから構成される一方、VHREDはそれに加えてVAEの概念を追加している。

Q. VAEに関する下記の説明文中の空欄に当てはまる言葉を答えよ。自己符号化器の潜在変数に__を導入したもの。
A. 確率分布

参考文献・参考サイト

ゼロから作るDeepLearning2 7章 RNN-Seq2Seq

seq2seqの実装と学習【ゼロつく2のノート(実装)】
https://www.anarchive-beta.com/entry/2021/03/29/150000
 
【世界一分かりやすい解説】Attentionを用いたseq2seqのメカニズム
https://tips-memo.com/translation-jayalmmar-attention

word2vec

word2vecとは

 単語の分散表現を生成するためのニューラルネットワークモデル。大規模なテキストコーパスから学習し、各単語をベクトル表現に変換する。
 word2vecにはcbowとskip-gramという2つのモデルがあり、cbowは文脈(周囲の単語)からターゲット単語を予測するモデルであり、skip-gramはターゲット単語から周囲の単語を予測するモデルである。

参考文献・参考サイト

G検定公式テキスト第2版 6章4節 1-4 単語埋め込み(word embedding)

Attention

Attentionとは

 入力された情報のうち、重要な情報に焦点を当てて処理するための仕組み。通常、Seq2SeqモデルやTransformerモデルなどの自然言語処理タスクで使用される。
 現在注目を浴びているchatGPTにもAttention機構が使用されている。

確認テスト

Q. RNNとword2vecの違いを説明せよ
A. RNNはシーケンスデータの処理に使用されるが、word2vecは単語の意味表現の学習に使用される。

Q. RNNとword2vecの違いを説明せよ
A. Seq2Seqは入力シーケンスから出力シーケンスを生成するためのモデルである一方、AttentionはSeq2Seqにおいて、より適切な情報に注目するための仕組みである。
 通常、Seq2SeqはRNNを使用して実装されるが、AttentionはRNNを使用しない。

参考文献・参考サイト

G検定公式テキスト第2版 6章4節 2-5 Attention

VQ-VAE

VQ-VAEとは

 VQ-VAEは、変分オートエンコーダーにベクトル量子化(Vector Quantizer)を組み合わせたニューラルネットワークの一種。データを圧縮し、潜在表現として得ることができる。
 従来のVAEでは潜在変数zを正規分布のベクトルになるような学習を行うが、VQ-VAEでは潜在変数を離散化した数値になるような学習を行う。
 VQ-VAEは、特に高次元データの圧縮や生成に有効で、より効率的な学習や高品質の生成が可能になる。

参考文献・参考サイト

VQ-VAEの理解( https://qiita.com/nishiha/items/44de5c46ebdfe615f6e8)
【論文解説+Tensorflowで実装】VQ-VAEを理解する( https://data-analytics.fun/2021/05/14/understanding-vq-vae/)

[フレームワーク演習]Seq2Seq

実装演習

      import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt

x = np.linspace(-3 * np.pi, 3 * np.pi, 100)
seq_in = np.sin(x)
seq_out = np.cos(x)

plt.plot(x, seq_in, label='$y=\sin x$')
plt.plot(x, seq_out, label='$y=\cos x$')
plt.legend()
plt.grid()
plt.show()
    

image.png image.png

      NUM_ENC_TOKENS = 1
NUM_DEC_TOKENS = 1
NUM_HIDDEN_PARAMS = 10
NUM_STEPS = 24

tf.keras.backend.clear_session()

e_input = tf.keras.layers.Input(shape=(NUM_STEPS, NUM_ENC_TOKENS), name='e_input')
_, e_state = tf.keras.layers.SimpleRNN(NUM_HIDDEN_PARAMS, return_state=True, name='e_rnn')(e_input)

d_input = tf.keras.layers.Input(shape=(NUM_STEPS, NUM_DEC_TOKENS), name='d_input')
d_rnn = tf.keras.layers.SimpleRNN(NUM_HIDDEN_PARAMS, return_sequences=True, return_state=True, name='d_rnn')
d_rnn_out, _ = d_rnn(d_input, initial_state=[e_state])

d_dense = tf.keras.layers.Dense(NUM_DEC_TOKENS, activation='linear', name='d_output')
d_output = d_dense(d_rnn_out)

model_train = tf.keras.models.Model(inputs=[e_input, d_input], outputs=d_output)
model_train.compile(optimizer='adam', loss='mean_squared_error')

model_train.summary()

n = len(x) - NUM_STEPS
ex = np.zeros((n, NUM_STEPS))
dx = np.zeros((n, NUM_STEPS))
dy = np.zeros((n, NUM_STEPS))

for i in range(0, n):
  ex[i] = seq_in[i:i + NUM_STEPS]
  dx[i, 1:] = seq_out[i:i + NUM_STEPS - 1]
  dy[i] = seq_out[i: i + NUM_STEPS]

ex = ex.reshape(n, NUM_STEPS, 1)
dx = dx.reshape(n, NUM_STEPS, 1)
dy = dy.reshape(n, NUM_STEPS, 1)

loss = history.history['loss']
plt.plot(np.arange(len(loss)), loss, label='loss')

loss = history.history['val_loss']
plt.plot(np.arange(len(loss)), loss, label='val_loss')

plt.grid()
plt.legend()
plt.show()
    

image.png image.png

      model_pred_e = tf.keras.models.Model(inputs=[e_input], outputs=[e_state])

pred_d_input = tf.keras.layers.Input(shape=(1, 1))
pred_d_state_in = tf.keras.layers.Input(shape=(NUM_HIDDEN_PARAMS))

pred_d_output, pred_d_state = d_rnn(pred_d_input, initial_state=[pred_d_state_in])
pred_d_output = d_dense(pred_d_output)


pred_d_model = tf.keras.Model(inputs=[pred_d_input, pred_d_state_in], outputs=[pred_d_output, pred_d_state])

def predict(input_data):
  state_value = model_pred_e.predict(input_data)
  _dy = np.zeros((1, 1, 1))
  
  output_data = []
  for i in range(0, NUM_STEPS):
    y_output, state_value = pred_d_model.predict([_dy, state_value])
    
    output_data.append(y_output[0, 0, 0])
    _dy[0, 0, 0] = y_output

  return output_data

init_points = [0, 24, 49, 74]

for i in init_points:
  _x = ex[i : i + 1]
  _y = predict(_x)
    
  if i == 0:
    plt.plot(x[i : i + NUM_STEPS], _y, color="red", label='output')
  else:
    plt.plot(x[i : i + NUM_STEPS], _y, color="red")

plt.plot(x, seq_out, color = 'blue', linestyle = "dashed", label = 'correct')
plt.grid()
plt.legend()
plt.show()  
    

image.png image.png

[フレームワーク演習]data augumentation

要点まとめ

 データ拡張(data augumentation)とは、既存のデータセットに手を加えることにより、新しいデータを生成することでデータセットを拡張する手法のこと。主に、画像データの回転、シフト、反転、切り抜き、色の変換などが行われる。データ拡張により、訓練データを増やすことができ、モデルの汎化性能の向上や過学習の防止などが期待される。

実装演習

      # 一部の処理でNumpyを使用して記述
import numpy as np
# データの水増し用APIを有するライブラリ
import tensorflow as tf
# 擬似乱数を生成するモジュール
import random
# 画像を表示するライブラリ
import matplotlib.pyplot as plt
# 画像をNotebook内に表示させるための指定
%matplotlib inline

#画像を表示するshow_images関数を定義する。
def show_images(images):
    """複数の画像を表示する"""
    n = 1
    while n ** 2 < len(images):
        n += 1
    for i, image in enumerate(images):
        plt.subplot(n, n, i + 1)
        plt.imshow(image)
        plt.axis('off')
    plt.show()

! mkdir sample_data
! wget -qnc --no-check-certificate -O ./sample_data/image_origin.jpg \
https://github.com/opencv/opencv/raw/master/samples/data/fruits.jpg

! mkdir sample_data
! wget -qnc --no-check-certificate -O ./sample_data/image_origin.jpg \
https://github.com/opencv/opencv/raw/master/samples/data/fruits.jpg

image = image_origin
show_images([image.numpy()])
    

image.png image.png

      #水平方向(左右)反転処理
image = image_origin
image = tf.image.random_flip_left_right(image, seed=123)

show_images([image.numpy()])
    

image.png image.png

参考文献

G検定公式テキスト第2版 6章1節 5 データ拡張

[フレームワーク演習]activate_functions

要点まとめ

 活性化関数(activation function)は、ニューラルネットワークにおいて、入力信号の総和を非線形に変換する関数のことを指す。活性化関数は、入力層、中間層、出力層において使用される。
 ニューラルネットワークの非線形性を担う重要な要素であり、活性化関数によって出力された値がしきい値を超えた場合に限り、信号を伝達することができる。

代表的な活性化関数

代表的な活性化関数には以下のものがある。

シグモイド関数
ReLU関数
Leaky ReLU関数
tanh関数
Softmax関数

実装

sigmoid

      def sigmoid(x):
    """forward
       
       sigmoid
       シグモイド関数
    """
    return 1.0 / (1.0 + np.exp(-x))

def d_sigmoid(x):
    """backward
       
       derivative of sigmoid
       シグモイド関数の導関数
    """
    dx = sigmoid(x) * (1.0 - sigmoid(x))
    return dx
    

tanh

      def tanh(x):
    """forward
       
       tanh
       双曲線正接関数
       (1)
    """
    return np.tanh(x)

# def tanh(x):
#     """forward
#        
#        tanh
#        双曲線正接関数
#        (2)
#     """
#     return np.sinh(x) / np.cosh(x)
#
# def tanh(x):
#     """forward
#        
#        tanh
#        双曲線正接関数
#        (3)
#     """
#     return (np.exp(x) - np.exp(-x)) / (np.exp(x) + np.exp(-x))
#
# def tanh(x):
#     """forward
#        
#        tanh
#        双曲線正接関数
#        (4)
#     """
#     return (np.exp(2.0*x) - 1.0) / (np.exp(2.0*x) + 1.0)
#
# def tanh(x):
#     """forward
#        
#        tanh
#        双曲線正接関数
#        (5)
#     """
#     return 2.0 * sigmoid(2.0*x) - 1.0

def d_tanh(x):
    """backward
       
       derivative of tanh
       双曲線正接関数の導関数
       (1)
    """
    dx = 1.0 / np.square(np.cosh(x))
    return dx

# def d_tanh(x):
#     """backward
#        
#        derivative of tanh
#        双曲線正接関数の導関数
#        (2)
#     """
#     dx = 4.0 / np.square(np.exp(x) + np.exp(-x))
#     return dx
    

ReLu

      def relu(x):
    """forward
       
       ReLU
       正規化線形関数
    """
    return np.maximum(0, x)

def d_relu(x):
    """backward
       
       derivative of ReLU
       正規化線形関数の導関数
    """
    dx = np.where(x > 0.0, 1.0, np.where(x < 0.0, 0.0, np.nan))
    return dx

# def d_relu(x):
#     """backward
#        
#        derivative of ReLU
#        正規化線形関数の導関数
#        (xが0.0のときの微分値を定義した劣微分)
#     """
#     dx = step_function(x)
#     return dx
    

Leaky ReLu

      alpha = 0.01

def lrelu(x):
    """forward
       
       Leaky ReLU
       漏洩正規化線形関数
    """
    return np.maximum(alpha*x, x)

def d_lrelu(x):
    """backward
       
       derivative of Leaky ReLU
       漏洩正規化線形関数の導関数
    """
    dx = np.where(x > 0.0, 1.0, np.where(x < 0.0, alpha, np.nan))
    return dx

# def d_lrelu(x):
#     """backward
#        
#        derivative of Leaky ReLU
#        漏洩正規化線形関数の導関数
#        (xが0.0のときの微分値を定義した劣微分)
#     """
#     dx = np.where(x > 0.0, 1.0, alpha)
#     return dx
    

参考文献

G検定公式テキスト第2版 5章4節 5 活性化関数

投稿日:2023331

この記事を高評価した人

高評価したユーザはいません

この記事に送られたバッジ

バッジはありません。

投稿者

コメント

他の人のコメント

コメントはありません。
読み込み中...
読み込み中