パス 1: 畳み込み層の順伝播を実装する
ミッションの詳細
このレベルのタスク: 畳み込み層の順伝播を実現します。
関連情報
このタスクを完了するには、以下を習得する必要があります。
- 全結合層の問題。
- 畳み込みとは何ですか?
- 畳み込み層とは何ですか。
この研修の内容については、書籍『ディープラーニング入門 Pythonによる理論と実装』の第7章を参照してください。
完全に接続された層の問題
前回のトレーニングでは、全結合層について学習しました。全結合層では、入力と出力の関係をより完全に抽出できるように、すべての入力ニューロンとすべての出力ニューロンがペアで接続されます。ただし、このアプローチにはいくつかの問題もあります。
まず、全結合層はデータ自体の構造や形状を無視するため、データの局所性を最大限に活用することができません。たとえば、画像は一般的に使用されるデータ形式であり、深層学習の分野で注目のトピックです。画像では、同じオブジェクトが連続した領域を占めることがよくありますが、このオブジェクトを認識することが目的の場合、対応する領域から特徴を抽出する方が明らかに合理的な選択です。完全に接続された層は全体像しか学習できませんが、これは良い方法ではありません。
一方で、完全接続層の計算およびストレージのオーバーヘッドは膨大です。画像を例に挙げます。224×224×3 の画像 (幅と高さは 224 ピクセル、RGB 3 つのカラー チャネルあり) の場合、チャネル数を 64 に変更したい場合、出力は 224×224 になります。 × 64 の特徴マップ。全結合層を使用すると、合計 224×224×3×224×224×64=483385147392 個のパラメータと乗算・加算演算が必要となり、これらのパラメータを格納するだけでも 1.7TB の容量が必要となり、明らかに耐えられません。また、後で紹介する 3×3 畳み込み層を使用する場合、必要なのは 64×3×3×3=1728 個のパラメーターと 224×224×64×3×3×3=86704128 個の乗算および加算演算だけであり、全体のストレージはまた、計算オーバーヘッドも大幅に減少しました。
畳み込み演算と畳み込み層
畳み込み演算は画像処理の分野で非常に一般的な演算であり、実際にはフィルタリングの一種です。H×W 入力画像の場合、コンボリューション演算により入力画像上で Kh × Kw コンボリューション カーネルがスライドされ、ウィンドウ内の入力画像の入力にコンボリューション カーネルの対応する要素が乗算されます。最終結果。以下の図は、畳み込み演算の手順を示しています。
図1 畳み込み演算
畳み込み演算のスライディング ウィンドウ法と出力特徴マップの形状を制御するために、ストライドとパッドの 2 つの概念も導入されています。入力が H×W の場合、畳み込みカーネルは Kh × Kw です。ステップ サイズ S、パディング P の畳み込み演算では、出力画像のサイズ Ho × Wo は次の式で計算できます。
Ho = (H−Kh + 2P)/S+1Wo = (W − Kw + 2P)/S+1
最も一般的に使用される畳み込み層構成の 1 つは、畳み込みカーネル サイズが 3×3、ストライドが 1、パディングが 1 であることです。このとき、入力および出力の特徴マップのサイズは同じです。畳み込み演算の詳細については、教科書の対応する章とこの記事を参照してください。
畳み込み層は、ニューラルネットワークに畳み込み演算を適用したネットワーク層です。上記の畳み込み演算に基づいて、畳み込み層ではチャネルの概念が導入され、各出力チャネルと各入力チャネルの間に一連の畳み込みパラメータが存在し、これらの畳み込みパラメータは畳み込みカーネルと呼ばれます。各出力チャネルは、すべての入力チャネルと対応する畳み込みパラメータの畳み込み演算の結果を合計することによって取得されます。以下の図は、畳み込み層がどのように計算されるかを示しています。
図2 畳み込み層の計算
畳み込み層は、畳み込みニューラル ネットワーク (CNN) の中核となる構成要素です。一般に、畳み込みニューラル ネットワークは、積み重ねられ結合された一連の畳み込み層で構成されます。コンピュータ ビジョン タスクでは、畳み込み層、プーリング層、バッチ正規化層、および活性化層のさまざまな組み合わせが使用され、強力なフィッティング能力を示します。今日、畳み込みニューラル ネットワークは、2 次元のコンピュータ ビジョン タスクを解決するための最も重要な方法となっており、3 次元のコンピュータ ビジョン タスクでも大きな役割を果たしています。
畳み込み層の実装
畳み込み層を実装する場合、行列計算の利便性を最大限に活用するために、通常、入力特徴マップはim2col
1 回の操作で大きな行列に変換され、この行列の各行が畳み込み時のウィンドウに対応します。このようにして、畳み込み演算は行列の乗算になります。具体的な分析については、教科書のセクション 7.4 の序論を参照してください。
トレーニングではクラスが事前に定義されておりConvolution
、このクラスのコンストラクターで、対応する Weight W
、bias b
、step size stride
、paddingを受け取りますpad
。重みW
は N×C×Kh × Kw numpy.ndarray
、オフセットb
は長さ M ですnumpy.ndarray
。ここで、N は出力チャネルの数、C は入力チャネルの数、Kh と Kw は畳み込みの次元です。カーネル。
この演習では、フォワード パス関数を実装する必要がありますforward()
。forward()
関数の入力はx
4 に等しい次元でnumpy.ndarray
、形状は (B、C、H、W) です。ここで、B はバッチ サイズです。まず第一に、 をx
操作する必要がim2col
あります。トレーニングではim2col
、入力特徴マップを (B×Ho×Wo、Kh×Kw×C) 行列に変換する操作が提供されています。各行は畳み込みウィンドウを表します。 。変換された特徴マップ行列は (B×Ho×Wo、Kh×Kw×C) であり、重み W は Co、C、Kh、Kw であるため、注目に値します。これを実装するときは、W を一度変形して Co、C×Kh×Kw にし、転置してから行列の乗算を実行する必要があります。
Fo ^ =im2col(F)×W^T
このとき、Fo ^ は(B×Ho ×Wo , Co )であり、このとき、1回の変形と転置操作で(B、Co、Ho、Wo)に変換できますFo 。
トレーニングによって提供されるim2col
関数の定義は次のとおりです。 im2col(input_data, filter_h, filter_w, stride=1, pad=0)
、対応するパラメーターの意味は次のとおりです。
input_data
: 入力特徴マップ;filter_h
およびfilter_w
: プーリング ウィンドウの高さと幅。stride
: プーリングステップサイズ。pad
: プールされたパディング。
プログラミング要件
プロンプトに従って、右側のエディターの Begin と End の間にコードを追加して、上記の畳み込み層の前方伝播を実現します。
試験指導
プラットフォームは、作成したコードをテストします。テスト方法は次のとおりです: プラットフォームは、入力、x
重みW
、およびバイアスをランダムに生成しb
、実装コードに従ってクラスのインスタンスを作成し、Convolution
このインスタンスを使用して順伝播計算を実行します。 、比較のために標準の回答と比較します。浮動小数点数の計算では、解答と標準解答との誤差が 10−5 を超えない限り、エラーが発生する可能性があるためです。
入力例:
x:
[[[[0.7 0.25 0.87 0.76]
[0.13 0.87 0.02 0.29]
[0.81 0.92 0.7 0.13]
[0.67 0.01 0.69 0.46]]
[[0.41 0.78 0.91 0.3 ]
[0.56 0.73 0.88 0.2 ]
[0.47 0.06 0.41 0.24]
[0.79 0.2 0.84 0.2 ]]]
[[[0.94 0.19 0.83 0.79]
[0.93 0.65 0.68 0.98]
[0.16 0.9 0.15 0.71]
[0.49 0.21 0.89 0.33]]
[[0.56 0.82 0.6 0.11]
[0.98 0.73 0.86 0.29]
[0.48 0.31 0.96 0.73]
[0.86 0.94 0.78 0.57]]]]
W:
[[[[ 0.73 0.61 0.31]
[-1.07 -1.13 -0.19]
[-0.24 0.9 -1.68]]
[[-0.59 -0.84 -0.37]
[-0.74 -0.83 -0.23]
[ 0.26 0.44 -0.42]]]
[[[-0.4 0.42 1.27]
[ 0.94 -0.58 1.41]
[-1.91 -1.18 1.93]]
[[-0.03 -1.14 0.72]
[-2.05 -0.45 -0.6 ]
[-0.84 0.1 -0. ]]]]
b:
[1.62 1.12]
stride: 1
pad: 1
対応する出力特徴マップは次のようになります。
[[[[-1.14 0.1 -1.35 -0.52]
[-0.08 -1.59 -0.81 0.93]
[ 0.59 -2.91 -0.92 0.28]
[ 0.51 0.7 0.52 -0.28]]
[[ 2. -0.53 -1.93 -1.6 ]
[ 3.15 -2.23 -1.62 -3.13]
[ 2.07 0.59 0.42 -1.93]
[ 1.29 1.66 0.27 -0.83]]]
[[[-0.26 -1.56 -1.55 0.36]
[-1.97 -1.57 -2.57 0.73]
[ 0.55 -1.75 -0.36 0.22]
[-0.04 -1.09 -1.43 -1.38]]
[[ 0.35 -0.79 -0.78 -3. ]
[ 2.82 -1.5 0.63 -2.71]
[ 2.43 -0.31 0.33 -4.35]
[ 1.08 0.88 -1.33 -0.7 ]]]]
上記の結果には丸め誤差がありますが、無視してかまいません。
実装コード:
numpyをnpとしてインポート
utilsインポートim2colから
クラス畳み込み:
def __init__(self、W、b、stride=1、pad=0):
あー」
畳み込み層の初期化
パラメータ:
- W: numpy.array、(C_out、C_in、K_h、K_w)
- b: numpy.array、(C_out)
- ストライド: int
- パッド: int
「」
self.W = W
self.b = b
self.stride = ストライド
self.pad = パッド
def forward(self, x):
あー」
畳み込み層の順伝播
パラメータ:
- x: numpy.array、(B、C、H、W)
戻る:
- y: numpy.array、(B、C'、H'、W')
H' = (H - Kh + 2P) / S + 1
W' = (W - Kw + 2P) / S + 1
「」
########## 始める ##########
FN、C、FH、FW = self.W.shape
N、C、H、W = x の形状
out_h = int(1 + (H + 2 * self.pad - FH) / self.stride)
out_w = int(1 + (W + 2 * self.pad - FW) / self.stride)
Col = im2col(x, FH, FW, self.stride, self.pad)
Col_w = self.W.reshape(FN, -1).T
out = np.dot(col,col_w) + self.b
out = out.reshape(N, out_h, out_w, -1).transpose(0, 3, 1, 2)
戻る
########## 終わり ##########
パス 2: プーリング層の順伝播を実装する
ミッションの詳細
このレベルのタスク: プーリング層の順方向伝播を実現します。
関連情報
このタスクを完了するには、以下を習得する必要があります。
- 受容野とダウンサンプリング;
- プーリング層の定義。
この研修の内容については、書籍『ディープラーニング入門 Pythonによる理論と実装』の第7章を参照してください。
受容野とダウンサンプリング
前回のトレーニングでは、畳み込み層について学習し、畳み込み層を使用して画像を処理する基本原理も理解しました。この演習では、さらに一歩進んで、畳み込みニューラル ネットワークにおける受容野とダウンサンプリングについて検討します。畳み込みニューラル ネットワークでは、特徴マップ内の各ピクセルは、畳み込み層のスタックを通じて入力画像内の特定の領域の影響を受けます。この領域の大きさを受容野と呼びます。受容野のサイズによって、ネットワークによって抽出される特徴の範囲が決まります。想像してみてください。ネットワーク モデルの受容野が非常に小さい場合、ネットワーク モデルがその受容野よりも大きなオブジェクトを認識するとどうやって期待できるでしょうか? したがって、画像分類、セマンティック セグメンテーション、物体検出などの多くの視覚タスクでは、受容野のサイズがネットワーク モデルのパフォーマンスに大きな影響を与えます。
畳み込み層の積み重ねにより、ネットワーク モデルの受容野は実際に増加しますが、この増加の速度は非常に遅いです。受容野の拡大をスピードアップするために、畳み込みステップ サイズを 2 に設定することで、特徴マップをダウンサンプリングできます。ダウンサンプリングにより、ネットワーク モデルの受容野を 2 倍に拡張できます。ただし、畳み込み計算は完全接続層よりもはるかに高速ですが、それでも大きな計算オーバーヘッドが発生します。それでは、ダウンサンプリングを達成して受容野を拡大する迅速な方法はあるのでしょうか? 答えはプーリング層です。
プーリング層
プーリング層は畳み込み層と同様に、入力特徴マップ上でウィンドウをスライドさせ、リダクション関数を通じてウィンドウ内の特徴値を計算して出力値を取得します。解像度関数として最大値を使用するプーリング層は最大プーリングと呼ばれ、解像度関数として平均値を使用するプーリング層は平均プーリングと呼ばれ、どちらも非常に一般的に使用されます。通常、プーリング層はウィンドウ サイズ Kh × Kw とストライドとパディングを設定します。プーリング層の一般的に使用される構成は、Kh = Kw = 2、ステップ サイズは 2、パディングは 0 です。このプーリング層により、特徴マップの長さと幅を半分に減らすことができます。次の図は、最大プーリングがどのように計算されるかを示しています。
図 1 最大プーリング
プーリング層では、入力特徴マップと出力特徴マップが 1 つずつ対応し、プーリング演算はチャネル間をまたぐことなく各チャネル内でのみ実行されるため、プーリング層の計算は非常に高速です。さらに、プーリング層はプーリング ウィンドウ内の特徴値を無差別に扱うため、畳み込み層が加重和を計算する方法よりも優れた平行移動と回転の不変性を提供できます。
プーリング層の実装
プーリング層の実装は畳み込み層の実装と似ており、行列計算の利便性を最大限に活用するために、通常、入力特徴マップは 1 回の操作で大きな行列に変換されます。この行列の各行はim2col
、プールウィンドウの 1 つ。このようにして、畳み込み演算は行ごとの最大値または平均値の演算になります。具体的な分析については、教科書のセクション 7.3 および 7.5 の導入部分を参照してください。
この演習では、最大プーリングを実装するだけで済みます。トレーニングではMaxPool
クラスが事前定義されており、このクラスのコンストラクターで、対応するプーリング ウィンドウ サイズpool_h
、pool_w
ストライドstride
、およびパディングを受け入れますpad
。
この演習では、フォワード パス関数を実装する必要がありますforward()
。forward()
関数の入力はx
4 に等しい次元でnumpy.ndarray
、形状は (B、C、H、W) です。ここで、B はバッチ サイズです。まず第一に、 をx
操作する必要がim2col
あります。トレーニングではim2col
、入力特徴マップを (B×Ho×Wo、Kh×Kw×C) 行列に変換する操作が提供されています。各行は畳み込みウィンドウを表します。 。
プログラミング要件
プロンプトに従って、右側のエディターの Begin と End の間にコードを追加して、上記の全結合層の前方伝播を実現します。
試験指導
プラットフォームは作成したコードをテストします。テスト方法は次のとおりです: プラットフォームは入力をランダムに生成しx
、実装コードに従ってクラスのインスタンスを作成しMaxPool
、このインスタンスを使用して順伝播計算を実行し、それを標準的な答え。浮動小数点数の計算では、解答と標準解答との誤差が 10−5 を超えない限り、エラーが発生する可能性があるためです。
入力例:
x:
[[[[0.7 0.25 0.87 0.76]
[0.13 0.87 0.02 0.29]
[0.81 0.92 0.7 0.13]
[0.67 0.01 0.69 0.46]]
[[0.41 0.78 0.91 0.3 ]
[0.56 0.73 0.88 0.2 ]
[0.47 0.06 0.41 0.24]
[0.79 0.2 0.84 0.2 ]]]
[[[0.94 0.19 0.83 0.79]
[0.93 0.65 0.68 0.98]
[0.16 0.9 0.15 0.71]
[0.49 0.21 0.89 0.33]]
[[0.56 0.82 0.6 0.11]
[0.98 0.73 0.86 0.29]
[0.48 0.31 0.96 0.73]
[0.86 0.94 0.78 0.57]]]]
pool_h: 2
pool_w: 2
stride: 2
pad: 0
対応する出力ニューロンは次のようになります。
[[[[0.7 0.87]
[0.92 0.7]]
[[0.78 0.91]
[0.79 0.84]]]
[[[0.94 0.98]
[0.49 0.89]]
[[0.98 0.86]
[0.94 0.96]]]]
ミッションを始めましょう。成功を祈っています!
実装コード:
numpyをnpとしてインポート
utilsインポートim2colから
クラスMaxPool:
def __init__(self、pool_h、pool_w、stride=1、pad=0):
あー」
プーリング層の初期化
パラメータ:
- プール_h: 整数
- プール_h: 整数
- ストライド: int
- パッド: int
「」
self.pool_h = プール_h
self.pool_w = プール_w
self.stride = ストライド
self.pad = パッド
def forward(self, x):
あー」
プーリング層の順伝播
パラメータ:
- x: numpy.array、(B、C、H、W)
戻る:
- y: numpy.array、(B、C、H'、W')
H' = (H - Kh + 2P) / S + 1
W' = (W - Kw + 2P) / S + 1
「」
########## 始める ##########
N、C、H、W = x の形状
out_h = int(1 + (H - self.pool_h) / self.stride)
out_w = int(1 + (W - self.pool_w) / self.stride)
Col = im2col(x, self.pool_h, self.pool_w, self.stride, self.pad)
Col = Col.reshape(-1, self.pool_h * self.pool_w)
out = np.max(col, axis=1)
out = out.reshape(N, out_h, out_w, C).transpose(0, 3, 1, 2)
戻る
########## 終わり ##########