このシリーズではE資格対策として、書籍「ゼロから作るDeep Learning」を参考に学習に役立つ情報をまとめています。
<参考書籍>
Affineレイヤ
アフィン変換(線形変換とバイアスの追加)を実行するAffineクラスを定義しています。アフィン変換は、ニューラルネットワークの線形変換部分で用いられます。
# Affineクラスを定義します
class Affine:
# インスタンス化時に重みWとバイアスbを初期化します
def __init__(self, W, b):
self.W = W
self.b = b
# 入力x、元のxの形状、勾配dW、勾配dbを初期化します
self.x = None
self.original_x_shape = None
self.dW = None
self.db = None
# 順伝播を実行するforwardメソッドを定義します
def forward(self, x):
# 入力xの形状を記憶します
self.original_x_shape = x.shape
# 入力xを2次元にリシェイプします(バッチサイズ、特徴量数)
x = x.reshape(x.shape[0], -1)
# リシェイプしたxをインスタンス変数に格納します
self.x = x
# 順伝播の計算を実行し、出力を返します
out = np.dot(self.x, self.W) + self.b
return out
# 逆伝播を実行するbackwardメソッドを定義します
def backward(self, dout):
# 逆伝播の計算を実行し、dxを求めます
dx = np.dot(dout, self.W.T)
# 重みの勾配dWを求めます
self.dW = np.dot(self.x.T, dout)
# バイアスの勾配dbを求めます
self.db = np.sum(dout, axis=0)
# dxを元のxの形状にリシェイプし、返します
dx = dx.reshape(*self.original_x_shape)
return dx
__init__(self, W, b)
: イニシャライザ。重み行列 W とバイアスベクトル b を受け取り、インスタンス変数に保存します。また、入力データ、重み・バイアスパラメータの微分、元の入力データの形状を保存するためのインスタンス変数も定義しています。forward(self, x)
: 順伝播を行うメソッド。入力データ x を受け取り、アフィン変換を実行して出力を返します。テンソル対応のため、入力データの形状を保存し、2次元配列に変換しています。backward(self, dout)
: 逆伝播を行うメソッド。出力データの誤差(勾配) dout を受け取り、重み W とバイアス b の勾配(dW, db)を計算します。また、入力データ x に対する勾配 dx も計算し、元の形状に戻して返します。
この Affine
クラスは、ニューラルネットワークの学習や予測時にアフィン変換を行う際に使用されます。順伝播(forward
)では、入力データ x を重み行列 W とのドット積を計算し、バイアスベクトル b を加算します。逆伝播(backward
)では、パラメータ W と b の勾配を計算し、入力データ x に対する勾配を求めます。
実装例
この Affine
クラスを使って簡単な順伝播(forward)と逆伝播(backward)の例を示します。numpyをインポートして、簡単なデータと重み、バイアスを作成して実行します。
import numpy as np
# 入力データ
x = np.array([[1.0, 0.5], [-0.4, 0.3]])
# 重み行列 W とバイアスベクトル b
W = np.array([[0.1, 0.3, 0.5], [0.2, 0.4, 0.6]])
b = np.array([0.1, 0.2, 0.3])
# Affine クラスのインスタンス化
affine = Affine(W, b)
# 順伝播
out = affine.forward(x)
print("Forward output:")
print(out)
# 出力の勾配(例として適当な値を使用)
dout = np.array([[1.0, 0.5, -0.2], [0.4, -0.1, 0.2]])
# 逆伝播
dx = affine.backward(dout)
print("Backward dx:")
print(dx)
print("Backward dW:")
print(affine.dW)
print("Backward db:")
print(affine.db)
実行結果:
Forward output:
[[0.3 0.7 1.1 ]
[0.12 0.2 0.28]]
Backward dx:
[[0.15 0.28]
[0.11 0.16]]
Backward dW:
[[ 0.84 0.54 -0.28]
[ 0.62 0.22 -0.04]]
Backward db:
[1.4 0.4 0. ]
Softmax-with-Lossレイヤ
ソフトマックス関数と交差エントロピー誤差を組み合わせて損失値を計算し、勾配を求めるための逆伝播を実行します。
# SoftmaxWithLoss クラス: ソフトマックス関数と損失関数(交差エントロピー誤差)を組み合わせたクラス
class SoftmaxWithLoss:
# コンストラクタ
def __init__(self):
self.loss = None # 損失値
self.y = None # ソフトマックス関数の出力
self.t = None # 教師データ(正解ラベル)
# 順伝播メソッド
def forward(self, x, t):
self.t = t # 教師データをセット
self.y = softmax(x) # ソフトマックス関数で計算
self.loss = cross_entropy_error(self.y, self.t) # 交差エントロピー誤差で損失を計算
return self.loss # 損失値を返す
# 逆伝播メソッド
def backward(self, dout=1):
batch_size = self.t.shape[0] # バッチサイズを取得
# 教師データがone-hot-vectorの場合
if self.t.size == self.y.size:
dx = (self.y - self.t) / batch_size
else:
dx = self.y.copy()
dx[np.arange(batch_size), self.t] -= 1
dx = dx / batch_size
return dx # 勾配を返す
ニューラルネットワークで多クラス分類問題を解く際に使用される、ソフトマックス関数と交差エントロピー誤差を組み合わせた損失レイヤーであるSoftmaxWithLoss
クラスを実装しています。このクラスは、順伝播によって損失値を計算し、逆伝播によって勾配を求めます。
__init__
メソッド:- コンストラクタで、損失値、ソフトマックス関数の出力、教師データをそれぞれ初期化しています。
f
orward
メソッド:- 順伝播を行います。このメソッドは、入力データ
x
と教師データt
を引数に取ります。 softmax
関数を使用して、入力データx
を確率分布に変換し、self.y
に格納します。cross_entropy_error
関数を使用して、ソフトマックス関数の出力self.y
と教師データself.t
の交差エントロピー誤差を計算し、self.loss
に格納します。- 損失値
self.loss
を返します。
- 順伝播を行います。このメソッドは、入力データ
b
ackward
メソッド:- 逆伝播を行います。このメソッドは、
dout
(デフォルトは1)を引数に取ります。 - バッチサイズを取得します。
- 教師データがone-hotベクトルの場合、ソフトマックス関数の出力
self.y
と教師データself.t
の差を計算し、バッチサイズで割ります。これにより、入力データx
に対する損失の勾配dx
を求めます。 - 教師データがone-hotベクトルでない場合、ソフトマックス関数の出力
self.y
のコピーを作成し、教師データself.t
のインデックスに該当する要素を1減らします。その後、バッチサイズで割ります。これにより、入力データx
に対する損失の勾配dx
を求めます。 - 勾配
dx
を返します。
- 逆伝播を行います。このメソッドは、
このSoftmaxWithLoss
クラスは、ニューラルネットワークの最後の層として使用され、訓練時に損失値を計算し、勾配を求めるために使用されます。損失値は、ネットワークの訓練がうまく進んでいるかどうかを評価するために使われ、最小化することが目標です。勾配は、ネットワークのパラメータを更新する際に使用される重要な情報で、損失を最小化する方向へパラメータを調整するために使われます。
SoftmaxWithLoss
クラスは、一般的なニューラルネットワークの実装において、訓練の最適化プロセスに不可欠な役割を果たします。多クラス分類問題を解く際、ソフトマックス関数は、ネットワークの出力を確率分布に変換し、交差エントロピー誤差は、その確率分布と教師データとの間の誤差を計算します。この誤差が小さくなるようにネットワークのパラメータを調整することで、訓練データに対する予測精度が向上し、汎化性能が高まることが期待されます。
まとめ
最後までご覧いただきありがとうございました。