ニューラルネットワークの活性化層、tanhExpの層を追加しよう[c++ Arrayfire]
六花です。
以下のサイトを参考にしてArrayfireでの実装をしました。
活性化関数一覧 (2020)
https://qiita.com/kuroitu/items/73cd401afd463a78115a#tanhexp%E9%96%A2%E6%95%B0
§環境
windows 10
Microsoft Visual Studio Community 2022 (64 ビット) Version 17.3.4
ArrayFire v3.8.2
struct tanhExp_layer : public Layer
{
const af::array& x;
af::array& y;
af::array& dx;
const af::array& dy;
tanhExp_layer(const af::array& x, af::array& y, af::array& dx, const af::array& dy)
: x(x)
, y(y)
, dx(dx)
, dy(dy)
{
}
inline void forward()
{
y = x * af::tanh(af::exp(x));
y.eval();
}
inline void backward()
{
dy.eval();
const af::array x_exp = af::exp(x);
const af::array tanh_exp = af::tanh(x_exp);
dx += dy * (tanh_exp - x * x_exp * (tanh_exp * tanh_exp - (var_t)1));
}
};
その他のコードは前回とほぼ同じです。(ニューラルネットワークの層を抽象化しよう[Arrayfire])
「ReLU_layer」を指定していたところを「tanhExp_layer」に変更するだけで活性化層の変更は終了です。
std::vector<std::shared_ptr<Layer>> layer; // 処理層
layer.push_back(std::make_shared<FC_layer>(data.at(0), data.at(1), grad.at(0), grad.at(1)));
layer.push_back(std::make_shared<tanhExp_layer>(data.at(1), data.at(2), grad.at(1), grad.at(2)));
layer.push_back(std::make_shared<FC_layer>(data.at(2), data.at(3), grad.at(2), grad.at(3)));
そして実行結果が以下の通り。
ArrayFire v3.8.2 (CUDA, 64-bit Windows, build 5752f2dc) Platform: CUDA Runtime 11.4, Driver: 11070 [0] NVIDIA GeForce RTX 3080, 10240 MB, CUDA Compute 8.6 -1- NVIDIA GeForce GTX 1080 Ti, 11264 MB, CUDA Compute 6.1 -------- 1.28746 0.000931946 = 0 1.28839 1.28746 2.57585 0.000361801 = 0 ------- epoch : 1 diff : 0.0442849 norm : 0.664314 epoch : 101 diff : 0.0056465 norm : 0.0803502 epoch : 201 diff : 0.00370682 norm : 0.0587545 epoch : 301 diff : 0.00240572 norm : 0.0339859 epoch : 401 diff : 0.00282481 norm : 0.0426597 epoch : 501 diff : 0.00192247 norm : 0.0310125 epoch : 601 diff : 0.00217782 norm : 0.0291756 epoch : 701 diff : 0.00192898 norm : 0.0303572 epoch : 801 diff : 0.00171179 norm : 0.0239474 epoch : 901 diff : 0.00169059 norm : 0.0232014 epoch : 1001 diff : 0.0017036 norm : 0.0240447 epoch : 1101 diff : 0.00142472 norm : 0.0208765 epoch : 1201 diff : 0.00141479 norm : 0.0200511 epoch : 1301 diff : 0.00159284 norm : 0.0233243 epoch : 1401 diff : 0.0015683 norm : 0.0232986 epoch : 1501 diff : 0.00137678 norm : 0.0193596 epoch : 1601 diff : 0.00126273 norm : 0.0171523 epoch : 1701 diff : 0.00132578 norm : 0.0196574 epoch : 1801 diff : 0.00112736 norm : 0.0162941
前回より1epoch当たりの速度が少し遅くなりましたが、収束の度合はこちらの方が早かったです。