1919
2020#pragma once
2121
22+ #include < algorithm>
23+ #include < cmath>
2224#include < cstddef>
2325#include < random>
2426#include < thread>
@@ -44,15 +46,15 @@ class BasicFFN {
4446 inline static FP epsilon = 1e-6 ; // untuk mencegah dead neuron ketika menggunakan ReLU
4547 bool xavier = false ;
4648 FP eta = 1e-2 ;
49+ std::random_device rd;
50+ std::mt19937 gen;
4751 // FP = Floating Point @param FP1 current eta/learning rate @param FP2 grad
4852 FP (*adaptive_eta_func)(FP, FP);
4953
5054 // setiap layer punya distribusi yang berbeda
5155 template <size_t inSize, size_t outSize>
5256 void init_layer (FP k, FP (&w)[inSize][outSize], FP (&b)[outSize]) {
53- // setup random
54- std::random_device rd;
55- std::mt19937 gen (rd ());
57+ // setup normal distribution
5658 std::normal_distribution<FP> dis (0 , std::sqrt (k));
5759
5860 for (size_t i = 0 ; i < outSize; ++i) {
@@ -65,6 +67,8 @@ class BasicFFN {
6567 * sedangkan xavier init make k = input + output;
6668 */
6769 void init_wb () {
70+ // setup random number generator
71+ gen.seed (rd ());
6872 FP k0 = inputSize, k1 = hidden1Size, k2 = hidden2Size;
6973 if (xavier) {
7074 k0 += hidden1Size;
@@ -111,16 +115,16 @@ class BasicFFN {
111115 FP eta) {
112116 // update bobot dan bias berdasarkan delta in
113117 for (size_t i = 0 ; i < inSize; ++i) {
114- for (size_t j = 0 ; j < outSize; ++j) w[j][i] -= eta * deltaIn[inSize ] * dataIn[i];
115- b[i] -= eta * deltaIn[inSize ];
118+ for (size_t j = 0 ; j < outSize; ++j) w[j][i] -= eta * deltaIn[i ] * dataIn[i];
119+ b[i] -= eta * deltaIn[i ];
116120 }
117121
118122 if (!deltaOut) return ;
119123 // update delta Out jika disediakan
120124 for (size_t i = 0 ; i < outSize; ++i) {
121- for (size_t j = 0 ; j < inSize; ++j) deltaOut[i] += w[i][j] * deltaIn[j];
125+ for (size_t j = 0 ; j < inSize; ++j) (* deltaOut) [i] += w[i][j] * deltaIn[j];
122126 // aturan rantai
123- if (actFuncDeriv) deltaOut[i] *= actFuncDeriv (dataIn[i]);
127+ if (actFuncDeriv) (* deltaOut) [i] *= actFuncDeriv (dataIn[i]);
124128 }
125129 }
126130
@@ -137,6 +141,12 @@ class BasicFFN {
137141 @note array will be lost after class is destroyed
138142 */
139143 FP (&forward (FP (&data)[inputSize]))[outputSize] {
144+ // zeroing data layer agar tidak menumpuk
145+ std::fill (toHid1, toHid1 + hidden1Size, 0 );
146+ std::fill (toHid2, toHid2 + hidden2Size, 0 );
147+ std::fill (out, out + outputSize, 0 );
148+
149+ // lambda switch for mathing activation function
140150 auto actFuncFromType = [](ACTIVATION_TYPE act_t ) {
141151 switch (act_t ) {
142152 case ACTIVATION_TYPE::RELU: return ReLU;
@@ -176,6 +186,12 @@ class BasicFFN {
176186 */
177187 void backward (FP (&inputData)[inputSize], FP (&targetData)[outputSize]) {
178188 forward (inputData);
189+ // zeroing delta layer agar tidak menumpuk
190+ std::fill (dOut, dOut + outputSize, 0 );
191+ std::fill (dHid2, dHid2 + hidden2Size, 0 );
192+ std::fill (dHid1, dHid1 + hidden1Size, 0 );
193+
194+ // lambda switch for mathing activation function derivative
179195 auto actFuncDerivFromType = [](ACTIVATION_TYPE act_t ) {
180196 switch (act_t ) {
181197 case ACTIVATION_TYPE::RELU: return ReLU_deriv;
@@ -197,10 +213,10 @@ class BasicFFN {
197213 // calculate dOut first for update through backward_layer template function
198214 for (size_t i = 0 ; i < outputSize; ++i) dOut[i] = lossDerivFunc (out[i], targetData[i]) * actFuncDeriv (out[i]);
199215
200- backward_layer<outputSize, hidden2Size>(wHid2, bHid2, dOut, dHid2, actFuncDeriv, eta);
201- backward_layer<hidden2Size, hidden1Size>(wHid1, bHid1, dHid2, dHid1, actFuncDeriv, eta);
202- backward_layer<hidden1Size, inputSize>(wIn, bIn, dHid1, 0 , 0 , eta);
216+ backward_layer<outputSize, hidden2Size>(wHid2, bHid2, out, dOut, & dHid2, actFuncDeriv, eta);
217+ backward_layer<hidden2Size, hidden1Size>(wHid1, bHid1, toHid2, dHid2, & dHid1, actFuncDeriv, eta);
218+ backward_layer<hidden1Size, inputSize>(wIn, bIn, toHid1, dHid1, 0 , 0 , eta);
203219 }
204220};
205221
206- } // namespace NN
222+ } // namespace NN
0 commit comments