ニューラルネットワークの活性化層、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当たりの速度が少し遅くなりましたが、収束の度合はこちらの方が早かったです。

おすすめ

1件の返信

  1. Shirley より:

    This article really informative, I have learnt so much from it.

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です