22 |
Pongと強化学習 (78) |
このコードにReLUを組み込むにはどうするのかを聞いてみます。
ReLU(Rectified Linear Unit)関数は、一般的にニューラルネットワークの活性化関数として使用されます。ReLU関数は入力が0以下の場合は0を出力し、入力が0より大きい場合はその入力をそのまま出力します。ハードウェア(特にBSVでの実装)においてReLUを組み込む場合、各計算ステップの後にこの単純な条件チェックを適用することになります。
以下の例では、畳み込み計算の結果に対してReLUを適用する方法を示します。ここでは、畳み込み演算の結果を格納する前にReLU関数を適用しています。
package ConvolutionFSMwithReLU;
import StmtFSM::*;
interface Conv2D_IF;
method Action start();
method ActionValue#(Bit#(8)) getResult(Int#(32) x, Int#(32) y);
endinterface
module mkConvolutionFSMwithReLU#(parameter Int#(32) width = 84,
parameter Int#(32) height = 84,
parameter Int#(32) kWidth = 8,
parameter Int#(32) kHeight = 8)(Conv2D_IF);
// ここで入力行列、カーネル行列、出力行列を定義
Reg#(Bit#(8)) inputMatrix[0:width-1][0:height-1];
Reg#(Bit#(8)) kernelMatrix[0:kWidth-1][0:kHeight-1];
Reg#(Bit#(8)) resultMatrix[0:width-kWidth][0:height-kHeight];
Reg#(Bool) startFlag <- mkReg(False);
// ReLU関数の定義
function Bit#(8) ReLU(Bit#(32) x);
return (x > 0) ? truncate(x) : 0;
endfunction
// 畳み込み計算のFSM
Stmt main = seq
// x, y のループ
for (x <= 0; x < width - kWidth + 1; x <= x + 1) seq
for (y <= 0; y < height - kHeight + 1; y <= y + 1) seq
// 畳み込み計算
action
Bit#(32) sum = 0;
for (Int#(32) dx = 0; dx < kWidth; dx = dx + 1) begin
for (Int#(32) dy = 0; dy < kHeight; dy = dy + 1) begin
sum = sum + (inputMatrix[x+dx][y+dy] * kernelMatrix[dx][dy]);
end
end
resultMatrix[x][y] = ReLU(sum); // 結果にReLUを適用して格納
endaction
endseq
endseq
endseq;
mkAutoFSM(main);
method Action start();
startFlag <= True;
endmethod
method ActionValue#(Bit#(8)) getResult(Int#(32) x, Int#(32) y);
return resultMatrix[x][y];
endmethod
endmodule
endpackage
この例では、ReLU
関数を定義し、畳み込み計算の結果に適用してから結果をresultMatrix
に格納しています。この方法により、畳み込み後の特徴マップに非線形性を導入し、ニューラルネットワークの表現力を高めることができます。ただし、ReLU
関数の出力ビット幅に注意が必要です。ここでは出力をBit#(8)
にトランケートしていますが、実際のアプリケーションに応じて適切なビット幅を選択する必要があります。