2026.03.06 23:46
バックプロパゲーションもなんとか書けた
・Chromeに脆弱性があったとかでアップデート
・いつものことながら自動ではうまくアップデートしてくれないので、.debパッケージをダウンロードしてsudo apt installでインストール。最後になんかエラーっぽいメッセージは出たけど、Chrome再起動したら「バージョン 145.0.7632.159(公式ビルド) (64 ビット)」となっていたので、たぶん良いのだろう。
・ということで、CNNの続きでバックプロパゲーションを書く。
・行数にすればわずか数行の演算なのだけど、やりたいことをどう書いたら良いのかという感じ。ウェイトやバイアスはまだ良いけど、入力に戻す誤差成分を算出するのはちょっと面倒だった。
・行列の形でいうと、バックプロパゲーションのときに後段から戻ってくる誤差データは[バッチサイズ、出力チャンネル数(フィルタ数)、Yサイズ、Xサイズ]な4次元配列データ。バッチサイズというのは、一度に複数の画像データをまとめて処理するときの画像の枚数。フィルタはたとえば3x3といった小さい領域に対する重みデータで、これが元画像から切り出した同じサイズ(3x3)のデータと積和演算されているわけだ。
・元画像側がカラー画像だと1つの画像がRGBの3枚で形成されている。これが入力チャンネル。
・で、ごちゃごちゃしたけど、1つのニューロンは
・入力:9つ(3x3)の画素データがチャンネル数分
フィルタ(3x3の重みデータ)がチャンネル数分
バイアス値がチャンネル数分
・出力:画素の各位置と対応するフィルタの値を掛けて全部足す、さらにバイアス値も足す
ということをやっていて、これが平面にズラーッと並んだものがあり、更にこれがフィルタ数分あるという感じ。
・重み(フィルタ)
weight[output_ch_num, input_ch_num, fil_xsize, fil_ysize]
・誤差データ
err_in[Bach_Size, output_ch_num, xsize, ysize]
ということで、こいつらの積和ってことなので、まずは掛け算するために次元を揃える。err_in側は1点ずつ(ニューロン1個分ずつ)切り出すので、i,jをy方向、x方向のスキャンとして、
weight_reshape = weight.reshape(1,output_ch_num, input_ch_num, fil_xsize, fil_ysize)
err_reshape = err_in[:,:,i:i+1,j:j+1].reshape(batch_size,output_ch_num,1,1,1)
で、あとは出力チャンネル数方向で積和をとってやる(複数のフィルタをかけたものを通したものからそれぞれ入力に誤差分が戻って合流する感じ)
np.sum(weight_reshape*err_reshape, axis=1)
入力データは[batch_size, input_ch_num, input_xsize, input_ysize]みたいな感じで4次元。ここからフィルタサイズ分切り出したところに足せば良いんだから、
d_input[:,:,i:i+fil_xsize, j:j+fil_ysize] = np.sum(weight_reshape*err_reshape, axis=1)
何ていう感じ。わずか数行だけど、ここにたどり着くのは少々しんどかったよと。
・他の部分もまとめてなんとかバックプロパゲーションは書けた(と思う)
・一応Gemini君は「完璧」と言ってくれたけど、本当にちゃんと動くのかな?
この記事へのコメント
コメントを書く