[Layer] Remove Output Layer
authorjijoong.moon <jijoong.moon@samsung.com>
Wed, 6 May 2020 03:21:03 +0000 (12:21 +0900)
committerJijoong Moon <jijoong.moon@samsung.com>
Wed, 6 May 2020 11:09:01 +0000 (20:09 +0900)
Output Layer Can be replaced by Fully Connected Layer.
No need to be exist.

**Self evaluation:**
1. Build test:  [X]Passed [ ]Failed [ ]Skipped
2. Run test:  [X]Passed [ ]Failed [ ]Skipped

Signed-off-by: jijoong.moon <jijoong.moon@samsung.com>
15 files changed:
Applications/Classification/jni/main.cpp
Applications/Classification/res/Classification.ini
Applications/Classification/res/Classification_func.ini
Applications/LogisticRegression/jni/main.cpp
Applications/LogisticRegression/res/LogisticRegression.ini
Applications/ReinforcementLearning/DeepQ/jni/DeepQ.ini
Applications/ReinforcementLearning/DeepQ/jni/main.cpp
Applications/Training/jni/main.cpp
Applications/Training/res/Training.ini
nntrainer/include/layers.h
nntrainer/include/neuralnet.h
nntrainer/src/layers.cpp
nntrainer/src/neuralnet.cpp
test/include/nntrainer_test_util.h
test/unittest/unittest_nntrainer_internal.cpp

index 7d62e15..267ddb7 100644 (file)
@@ -443,7 +443,7 @@ int main(int argc, char *argv[]) {
     featureVector.resize(feature_size);
     getFeature(img, featureVector);
     nntrainer::Tensor X = nntrainer::Tensor({featureVector});
-    cout << NN.forwarding(X).apply(stepFunction) << endl;
+    cout << NN.forwarding(X, status).apply(stepFunction) << endl;
   }
   /**
    * @brief     Finalize NN
index 3b4e800..1bf3734 100644 (file)
@@ -33,15 +33,13 @@ LabelData="label.dat"
 # Layer Section : Name
 [inputlayer]
 Type = input
-Id = 0                 # Layer Id
 HiddenSize = 62720             # Input Layer Dimension
 Bias_zero = true       # Zero Bias
 Normalization = true
 Activation = sigmoid   # activation : sigmoid, tanh
 
 [outputlayer]
-Type = output
-Id = 1
+Type = fully_connected
 HiddenSize = 10                # Output Layer Dimension ( = Weight Width )
 Bias_zero = true
 Activation = softmax   # activation : sigmoid, softmax
index b2bb55a..90f0e46 100644 (file)
@@ -22,15 +22,13 @@ epsilon = 1e-7      # epsilon for adam
 # Layer Section : Name
 [inputlayer]
 Type = input
-Id = 0                 # Layer Id
 HiddenSize = 62720             # Input Layer Dimension
 Bias_zero = true       # Zero Bias
 Normalization = true
 Activation = sigmoid   # activation : sigmoid, tanh
 
 [outputlayer]
-Type = output
-Id = 1
+Type = fully_connected
 HiddenSize = 10                # Output Layer Dimension ( = Weight Width )
 Bias_zero = true
 Activation = softmax   # activation : sigmoid, softmax
index da59fc3..081bd48 100644 (file)
@@ -134,11 +134,12 @@ int main(int argc, char *argv[]) {
      * @brief     forward propagation
      */
     int cn = 0;
+    int status = 0;
     for (unsigned int j = 0; j < inputVector.size(); ++j) {
       std::vector<std::vector<float>> in, label;
       in.push_back(inputVector[j]);
       label.push_back(outputVector[j]);
-      if (NN.forwarding(nntrainer::Tensor(in))
+      if (NN.forwarding(nntrainer::Tensor(in), status)
             .apply(stepFunction)
             .getValue(0, 0, 0) == label[0][0])
         cn++;
index fc96ffe..3ce7f7a 100644 (file)
@@ -16,14 +16,12 @@ epsilon = 1e-5
 # Layer Section : Name
 [inputlayer]
 Type = input
-Id = 0                 # Layer Id
 HiddenSize = 2
 Bias_zero = true       # Zero Bias
 Activation = sigmoid
 
 [outputlayer]
-Type = output
-Id = 1
+Type = fully_connected
 HiddenSize = 1
 Bias_zero = true
-Activation = sigmoid
\ No newline at end of file
+Activation = sigmoid
index 99ffe9a..5263f2c 100644 (file)
@@ -21,28 +21,24 @@ epsilon = 1e-8              # epsilon for adam
 # Layer Section : Name
 [inputlayer]
 Type = input
-Id = 0                 # Layer Id
 HiddenSize = 4         # Input Layer Dimension
 Bias_zero = true       # Zero Bias
 Activation = tanh      # activation : sigmoid, tanh
 
 [fc1layer]
 Type = fully_connected
-Id = 1
 HiddenSize = 50                # Hidden Layer Dimension ( = Weight Width )
 Bias_zero = true
 Activation = tanh      # activation : sigmoid, tanh
 
 [fc2layer]
 Type = fully_connected
-Id = 2
 HiddenSize = 50
 Bias_zero = true
 Activation = tanh      # activation : sigmoid, tanh
 
 [outputlayer]
-Type = output
-Id = 3
+Type = fully_connected
 HiddenSize = 2         # Output Layer Dimension ( = Weight Width )
 Bias_zero = true
-Activation = sigmoid   # activation : sigmoid, tanh
\ No newline at end of file
+Activation = sigmoid   # activation : sigmoid, tanh
index a0124f8..6fc3365 100644 (file)
@@ -260,6 +260,7 @@ int main(int argc, char **argv) {
   std::deque<Experience> expQ;
 
   PTR env;
+  int status = 0;
 
   /**
    * @brief     Initialize Environment
@@ -322,7 +323,8 @@ int main(int argc, char **argv) {
         /**
          * @brief     get action with input State with mainNet
          */
-        nntrainer::Tensor test = mainNet.forwarding(nntrainer::Tensor({input}));
+        nntrainer::Tensor test =
+          mainNet.forwarding(nntrainer::Tensor({input}), status);
         std::vector<float> temp = test.mat2vec();
         action.push_back(argmax(temp));
 
@@ -412,13 +414,14 @@ int main(int argc, char **argv) {
         /**
          * @brief     run forward propagation with mainNet
          */
-        nntrainer::Tensor Q = mainNet.forwarding(nntrainer::Tensor(inbatch));
+        nntrainer::Tensor Q =
+          mainNet.forwarding(nntrainer::Tensor(inbatch), status);
 
         /**
          * @brief     run forward propagation with targetNet
          */
         nntrainer::Tensor NQ =
-          targetNet.forwarding(nntrainer::Tensor(next_inbatch));
+          targetNet.forwarding(nntrainer::Tensor(next_inbatch), status);
         std::vector<float> nqa = NQ.mat2vec();
 
         /**
index f383ce1..8dd379d 100644 (file)
@@ -237,7 +237,7 @@ int main(int argc, char *argv[]) {
   srand(time(NULL));
   std::string ini_file = data_path + "ini.bin";
   std::vector<std::vector<float>> inputVector, outputVector;
-
+  int status = 0;
   /**
    * @brief     Extract Feature
    */
@@ -279,7 +279,7 @@ int main(int argc, char *argv[]) {
     featureVector.resize(128);
     getFeature(img, featureVector);
     nntrainer::Tensor X = nntrainer::Tensor({featureVector});
-    cout << NN.forwarding(X).apply(stepFunction) << endl;
+    cout << NN.forwarding(X, status).apply(stepFunction) << endl;
   }
 
   /**
index 0a819da..9d6c4eb 100644 (file)
@@ -19,21 +19,18 @@ minibatch = 1               # mini batch size
 # Layer Section : Name
 [inputlayer]
 Type = input
-Id = 0                 # Layer Id
 HiddenSize = 128       # Input Layer Dimension
 Bias_zero = true       # Zero Bias
 Activation = sigmoid
 
 [fc1layer]
 Type = fully_connected
-Id = 1
 HiddenSize = 20                # Hidden Layer Dimension ( = Weight Width )
 Bias_zero = true
 Activation = sigmoid
 
 [outputlayer]
-Type = output
-Id = 3
+Type = fully_connected
 HiddenSize = 3         # Output Layer Dimension ( = Weight Width )
 Bias_zero = true
 Activation = sigmoid
index a3dd5e8..7e2e96e 100644 (file)
@@ -58,16 +58,9 @@ typedef enum {
  * @brief     Enumeration of layer type
  *            0. Input Layer type
  *            1. Fully Connected Layer type
- *            2. Output Layer type
- *            3. Unknown
+ *            2. Unknown
  */
-typedef enum {
-  LAYER_IN,
-  LAYER_FC,
-  LAYER_OUT,
-  LAYER_BN,
-  LAYER_UNKNOWN
-} LayerType;
+typedef enum { LAYER_IN, LAYER_FC, LAYER_BN, LAYER_UNKNOWN } LayerType;
 
 /**
  * @brief     Enumeration of Weight Initialization Type
@@ -105,14 +98,14 @@ public:
    * @param[in] in Input Tensor taken by upper layer
    * @retval    Output Tensor
    */
-  virtual Tensor forwarding(Tensor in) = 0;
+  virtual Tensor forwarding(Tensor in, int &status) = 0;
 
   /**
    * @brief     Forward Propation of neural Network
    * @param[in] in Input Tensor taken by upper layer
    * @retval    Output Tensor
    */
-  virtual Tensor forwarding(Tensor in, Tensor output) = 0;
+  virtual Tensor forwarding(Tensor in, Tensor output, int &status) = 0;
 
   /**
    * @brief     Back Propation of neural Network
@@ -128,13 +121,13 @@ public:
    * @param[in] b batch
    * @param[in] h Height
    * @param[in] w Width
-   * @param[in] id index of this layer
+   * @param[in] last last layer
    * @param[in] init_zero Bias initialization with zero
    * @param[in] wini Weight Initialization Scheme
    * @retval #ML_ERROR_NONE Successful.
    * @retval #ML_ERROR_INVALID_PARAMETER invalid parameter.
    */
-  virtual int initialize(int b, int h, int w, int id, bool init_zero,
+  virtual int initialize(int b, int h, int w, bool last, bool init_zero,
                          WeightIniType wini) = 0;
 
   /**
@@ -181,6 +174,7 @@ public:
 
   int checkValidation();
 
+protected:
   /**
    * @brief     Input Tensor
    */
@@ -193,9 +187,9 @@ public:
   Tensor hidden;
 
   /**
-   * @brief     Layer index
+   * @brief     last layer
    */
-  unsigned int index;
+  bool last_layer;
 
   /**
    * @brief     batch size of Weight Data
@@ -283,7 +277,7 @@ public:
    * @param[in] in input Tensor from lower layer.
    * @retval    return Input Tensor
    */
-  Tensor forwarding(Tensor in);
+  Tensor forwarding(Tensor in, int &status);
 
   /**
    * @brief     foward propagation : return Input Tensor
@@ -292,7 +286,9 @@ public:
    * @param[in] output label Tensor.
    * @retval    return Input Tensor
    */
-  Tensor forwarding(Tensor in, Tensor output) { return forwarding(in); };
+  Tensor forwarding(Tensor in, Tensor output, int &status) {
+    return forwarding(in, status);
+  };
 
   /**
    * @brief     Set Optimizer
@@ -307,13 +303,13 @@ public:
    * @param[in] b batch size
    * @param[in] h height
    * @param[in] w width
-   * @param[in] id index of this layer
+   * @param[in] last last layer
    * @param[in] init_zero boolean to set Bias zero
    * @param[in] wini Weight Initialization Scheme
    * @retval #ML_ERROR_NONE Successful.
    * @retval #ML_ERROR_INVALID_PARAMETER invalid parameter.
    */
-  int initialize(int b, int h, int w, int id, bool init_zero,
+  int initialize(int b, int h, int w, bool last, bool init_zero,
                  WeightIniType wini);
 
   /**
@@ -348,7 +344,7 @@ public:
   /**
    * @brief     Constructor of Fully Connected Layer
    */
-  FullyConnectedLayer(){};
+  FullyConnectedLayer() : loss(0.0), cost(COST_UNKNOWN){};
 
   /**
    * @brief     Destructor of Fully Connected Layer
@@ -372,7 +368,7 @@ public:
    * @param[in] in Input Tensor from upper layer
    * @retval    Activation(W x input + B)
    */
-  Tensor forwarding(Tensor in);
+  Tensor forwarding(Tensor in, int &status);
 
   /**
    * @brief     foward propagation : return Input Tensor
@@ -381,7 +377,7 @@ public:
    * @param[in] output label Tensor.
    * @retval    Activation(W x input + B)
    */
-  Tensor forwarding(Tensor in, Tensor output) { return forwarding(in); };
+  Tensor forwarding(Tensor in, Tensor output, int &status);
 
   /**
    * @brief     back propagation
@@ -403,86 +399,14 @@ public:
    * @param[in] b batch size
    * @param[in] h height
    * @param[in] w width
-   * @param[in] id layer index
-   * @param[in] init_zero boolean to set Bias zero
-   * @param[in] wini Weight Initialization Scheme
-   * @retval #ML_ERROR_NONE Successful.
-   * @retval #ML_ERROR_INVALID_PARAMETER invalid parameter.
-   */
-  int initialize(int b, int h, int w, int id, bool init_zero,
-                 WeightIniType wini);
-
-private:
-  Tensor weight;
-  Tensor bias;
-};
-
-/**
- * @class   OutputLayer
- * @brief   OutputLayer (has Cost Function & Weight, Bias)
- */
-class OutputLayer : public Layer {
-public:
-  /**
-   * @brief     Constructor of OutputLayer
-   */
-  OutputLayer() : loss(0.0), cost(COST_UNKNOWN){};
-
-  /**
-   * @brief     Destructor of OutputLayer
-   */
-  ~OutputLayer(){};
-
-  /**
-   * @brief     Read Weight & Bias Data from file
-   * @param[in] file input stream file
-   */
-  void read(std::ifstream &file);
-
-  /**
-   * @brief     Save Weight & Bias Data to file
-   * @param[in] file output stream file
-   */
-  void save(std::ofstream &flle);
-
-  /**
-   * @brief     forward propagation with input
-   * @param[in] in Input Tensor from upper layer
-   * @retval    Activation(W x input + B)
-   */
-  Tensor forwarding(Tensor in);
-
-  /**
-   * @brief     forward propagation with input and set loss
-   * @param[in] in Input Tensor from upper layer
-   * @param[in] output Label Tensor
-   * @retval    Activation(W x input + B)
-   */
-  Tensor forwarding(Tensor in, Tensor output);
-
-  /**
-   * @brief     back propagation
-   *            Calculate dJdB & dJdW & Update W & B
-   * @param[in] input Input Tensor from lower layer
-   * @param[in] iteration Number of Epoch for ADAM
-   * @retval    dJdB x W Tensor
-   */
-  Tensor backwarding(Tensor label, int iteration);
-
-  /**
-   * @brief     initialize layer
-   * @param[in] b batch size
-   * @param[in] h height
-   * @param[in] w width
-   * @param[in] id layer index
+   * @param[in] last last layer
    * @param[in] init_zero boolean to set Bias zero
    * @param[in] wini Weight Initialization Scheme
    * @retval #ML_ERROR_NONE Successful.
    * @retval #ML_ERROR_INVALID_PARAMETER invalid parameter.
    */
-  int initialize(int b, int w, int h, int id, bool init_zero,
+  int initialize(int b, int h, int w, bool last, bool init_zero,
                  WeightIniType wini);
-
   /**
    * @brief     get Loss value
    */
@@ -496,12 +420,6 @@ public:
    */
   int setCost(CostType c);
 
-  /**
-   * @brief     copy layer
-   * @param[in] l layer to copy
-   */
-  void copy(Layer *l);
-
 private:
   Tensor weight;
   Tensor bias;
@@ -542,7 +460,7 @@ public:
    * @param[in] in Input Tensor from upper layer
    * @retval    Activation(W x input + B)
    */
-  Tensor forwarding(Tensor in);
+  Tensor forwarding(Tensor in, int &status);
 
   /**
    * @brief     foward propagation : return Input Tensor
@@ -551,7 +469,9 @@ public:
    * @param[in] output label Tensor.
    * @retval    Activation(W x input + B)
    */
-  Tensor forwarding(Tensor in, Tensor output) { return forwarding(in); };
+  Tensor forwarding(Tensor in, Tensor output, int &status) {
+    return forwarding(in, status);
+  };
 
   /**
    * @brief     back propagation
@@ -581,13 +501,13 @@ public:
    * @param[in] b batch size
    * @param[in] h height
    * @param[in] w width
-   * @param[in] id layer index
+   * @param[in] last last layer
    * @param[in] init_zero boolean to set Bias zero
    * @param[in] wini Weight Initialization Scheme
    * @retval #ML_ERROR_NONE Successful.
    * @retval #ML_ERROR_INVALID_PARAMETER invalid parameter.
    */
-  int initialize(int b, int h, int w, int id, bool init_zero,
+  int initialize(int b, int h, int w, bool last, bool init_zero,
                  WeightIniType wini);
 
 private:
index 6c4ecd9..ae85b0f 100644 (file)
@@ -123,7 +123,7 @@ public:
    * @param[in] input Input Tensor X
    * @retval    Output Tensor Y
    */
-  Tensor forwarding(Tensor input);
+  Tensor forwarding(Tensor input, int &status);
 
   /**
    * @brief     forward propagation
@@ -131,7 +131,7 @@ public:
    * @param[in] label Input Tensor Y2
    * @retval    Output Tensor Y
    */
-  Tensor forwarding(Tensor input, Tensor output);
+  Tensor forwarding(Tensor input, Tensor output, int &status);
 
   /**
    * @brief     back propagation to update W & B
@@ -139,7 +139,7 @@ public:
    * @param[in] expectedOutput Lable Tensor Y
    * @param[in] iteration Epoch Number for ADAM
    */
-  void backwarding(Tensor input, Tensor expected_output, int iteration);
+  int backwarding(Tensor input, Tensor expected_output, int iteration);
 
   /**
    * @brief     save W & B into file
index 03960a8..0cf600e 100644 (file)
@@ -101,7 +101,7 @@ static Tensor weightInitialization(unsigned int width, unsigned int height,
 Layer::Layer() {
   type = LAYER_UNKNOWN;
   activation_type = ACT_UNKNOWN;
-  index = 0;
+  last_layer = false;
   batch = 0;
   width = 0;
   height = 0;
@@ -172,21 +172,21 @@ int InputLayer::setOptimizer(Optimizer &opt) {
 void InputLayer::copy(Layer *l) {
   InputLayer *from = static_cast<InputLayer *>(l);
   this->opt = from->opt;
-  this->index = from->index;
+  this->last_layer = from->last_layer;
   this->height = from->height;
   this->width = from->width;
   this->input.copy(from->input);
   this->hidden.copy(from->hidden);
 }
 
-Tensor InputLayer::forwarding(Tensor in) {
+Tensor InputLayer::forwarding(Tensor in, int &status) {
   input = in;
   if (normalization)
     input = input.normalization();
   return input;
 }
 
-int InputLayer::initialize(int b, int h, int w, int id, bool init_zero,
+int InputLayer::initialize(int b, int h, int w, bool last, bool init_zero,
                            WeightIniType wini) {
   int status = ML_ERROR_NONE;
   if (b <= 0 || h <= 0 || w <= 0) {
@@ -197,13 +197,13 @@ int InputLayer::initialize(int b, int h, int w, int id, bool init_zero,
   this->batch = b;
   this->width = w;
   this->height = h;
-  this->index = 0;
+  this->last_layer = last;
   this->bn_fallow = false;
   return status;
 }
 
-int FullyConnectedLayer::initialize(int b, int h, int w, int id, bool init_zero,
-                                    WeightIniType wini) {
+int FullyConnectedLayer::initialize(int b, int h, int w, bool last,
+                                    bool init_zero, WeightIniType wini) {
   int status = ML_ERROR_NONE;
   if (b <= 0 || h <= 0 || w <= 0) {
     ml_loge("Error: Dimension must be greater than 0");
@@ -213,7 +213,7 @@ int FullyConnectedLayer::initialize(int b, int h, int w, int id, bool init_zero,
   this->batch = b;
   this->width = w;
   this->height = h;
-  this->index = id;
+  this->last_layer = last;
   this->init_zero = init_zero;
   this->bn_fallow = false;
 
@@ -231,81 +231,7 @@ int FullyConnectedLayer::initialize(int b, int h, int w, int id, bool init_zero,
   return status;
 }
 
-Tensor FullyConnectedLayer::forwarding(Tensor in) {
-  input = in;
-  hidden = input.dot(weight).add(bias);
-
-  if (this->bn_fallow)
-    return hidden;
-
-  return hidden.apply(activation);
-  ;
-}
-
-void FullyConnectedLayer::read(std::ifstream &file) {
-  weight.read(file);
-  bias.read(file);
-}
-
-void FullyConnectedLayer::save(std::ofstream &file) {
-  weight.save(file);
-  bias.save(file);
-}
-
-void FullyConnectedLayer::copy(Layer *l) {
-  FullyConnectedLayer *from = static_cast<FullyConnectedLayer *>(l);
-  this->opt = from->opt;
-  this->index = from->index;
-  this->height = from->height;
-  this->width = from->width;
-  this->input.copy(from->input);
-  this->hidden.copy(from->hidden);
-  this->weight.copy(from->weight);
-  this->bias.copy(from->bias);
-}
-
-Tensor FullyConnectedLayer::backwarding(Tensor derivative, int iteration) {
-  Tensor djdb;
-
-  djdb = derivative.multiply(hidden.apply(activation_prime));
-
-  Tensor ret = djdb.dot(weight.transpose());
-
-  Tensor djdw = input.transpose().dot(djdb);
-
-  opt.calculate(djdw, djdb, weight, bias, iteration, this->init_zero);
-
-  return ret;
-}
-
-int OutputLayer::initialize(int b, int h, int w, int id, bool init_zero,
-                            WeightIniType wini) {
-  int status = ML_ERROR_NONE;
-  if (b <= 0 || h <= 0 || w <= 0) {
-    ml_loge("Error: Dimension must be greater than 0");
-    return ML_ERROR_INVALID_PARAMETER;
-  }
-
-  this->batch = b;
-  this->width = w;
-  this->height = h;
-  this->index = id;
-  this->init_zero = init_zero;
-
-  bias = Tensor(1, w);
-  this->bn_fallow = false;
-
-  weight = weightInitialization(w, h, wini, status);
-
-  if (init_zero) {
-    bias.setZero();
-  } else {
-    bias = bias.apply(random);
-  }
-  return status;
-}
-
-int OutputLayer::setCost(CostType c) {
+int FullyConnectedLayer::setCost(CostType c) {
   int status = ML_ERROR_NONE;
   if (c == COST_UNKNOWN) {
     ml_loge("Error: Unknown cost fucntion");
@@ -315,9 +241,13 @@ int OutputLayer::setCost(CostType c) {
   return status;
 }
 
-Tensor OutputLayer::forwarding(Tensor in) {
+Tensor FullyConnectedLayer::forwarding(Tensor in, int &status) {
   input = in;
   hidden = input.dot(weight).add(bias);
+
+  if (this->bn_fallow)
+    return hidden;
+
   if (activation_type == ACT_SOFTMAX) {
     return hidden.apply(softmax);
   } else {
@@ -325,7 +255,11 @@ Tensor OutputLayer::forwarding(Tensor in) {
   }
 }
 
-Tensor OutputLayer::forwarding(Tensor in, Tensor output) {
+Tensor FullyConnectedLayer::forwarding(Tensor in, Tensor output, int &status) {
+  if (!this->last_layer) {
+    ml_loge("Error: Cannot update cost. This is not last layer of network");
+    status = ML_ERROR_INVALID_PARAMETER;
+  }
   input = in;
   hidden = input.dot(weight).add(bias);
   Tensor y2 = output;
@@ -385,20 +319,20 @@ Tensor OutputLayer::forwarding(Tensor in, Tensor output) {
   return y;
 }
 
-void OutputLayer::read(std::ifstream &file) {
+void FullyConnectedLayer::read(std::ifstream &file) {
   weight.read(file);
   bias.read(file);
 }
 
-void OutputLayer::save(std::ofstream &file) {
+void FullyConnectedLayer::save(std::ofstream &file) {
   weight.save(file);
   bias.save(file);
 }
 
-void OutputLayer::copy(Layer *l) {
-  OutputLayer *from = static_cast<OutputLayer *>(l);
+void FullyConnectedLayer::copy(Layer *l) {
+  FullyConnectedLayer *from = static_cast<FullyConnectedLayer *>(l);
   this->opt = from->opt;
-  this->index = from->index;
+  this->last_layer = from->last_layer;
   this->height = from->height;
   this->width = from->width;
   this->input.copy(from->input);
@@ -408,87 +342,90 @@ void OutputLayer::copy(Layer *l) {
   this->loss = from->loss;
 }
 
-Tensor OutputLayer::backwarding(Tensor label, int iteration) {
+Tensor FullyConnectedLayer::backwarding(Tensor derivative, int iteration) {
+  Tensor djdb;
   float loss_sum = 0.0;
-  Tensor y2 = label;
+  Tensor y2 = derivative;
   Tensor y;
-  if (activation_type == ACT_SOFTMAX)
-    y = hidden.apply(softmax);
-  else
-    y = hidden.apply(activation);
-
-  Tensor ret;
-  Tensor djdb;
-
-  float ll = opt.getLearningRate();
-  if (opt.getDecaySteps() != -1) {
-    ll = ll * pow(opt.getDecayRate(), (iteration / opt.getDecaySteps()));
-  }
-
-  switch (cost) {
-  case COST_MSR: {
-    Tensor sub = y2.subtract(y);
-    Tensor l = (sub.multiply(sub)).sum().multiply(0.5);
-    std::vector<float> t = l.mat2vec();
-    for (int i = 0; i < l.getBatch(); i++) {
-      loss_sum += t[i];
-    }
-
-    loss = loss_sum / (float)l.getBatch();
-    if (opt.getWeightDecayType() == WeightDecayType::l2norm) {
-      loss += opt.getWeightDecayLambda() * 0.5 * (weight.l2norm());
-    }
-    if (activation_type == ACT_SOFTMAX) {
-      djdb = y.subtract(y2).multiply(y.apply(softmaxPrime));
-    } else {
-      djdb = y.subtract(y2).multiply(hidden.apply(activation_prime));
-    }
-  } break;
-  case COST_ENTROPY: {
-    Tensor l;
-    if (activation_type == ACT_SIGMOID) {
-      djdb = y.subtract(y2).multiply(1.0 / y.getWidth());
-      l = (y2.multiply(y.apply(logFloat))
-             .add((y2.multiply(-1.0).add(1.0))
-                    .multiply((y.multiply(-1.0).add(1.0)).apply(logFloat))))
-            .multiply(-1.0 / (y2.getWidth()))
-            .sum();
-    } else if (activation_type == ACT_SOFTMAX) {
-      djdb = y.subtract(y2).multiply(1.0 / y.getWidth());
-      l =
-        (y2.multiply(y.apply(logFloat))).multiply(-1.0 / (y2.getWidth())).sum();
-    } else {
-      ml_loge("Only support sigmoid & softmax for cross entropy loss");
-      exit(0);
-    }
 
-    std::vector<float> t = l.mat2vec();
-
-    for (int i = 0; i < l.getBatch(); i++) {
-      loss_sum += t[i];
+  if (!last_layer) {
+    djdb = derivative.multiply(hidden.apply(activation_prime));
+  } else {
+    if (activation_type == ACT_SOFTMAX)
+      y = hidden.apply(softmax);
+    else
+      y = hidden.apply(activation);
+    float ll = opt.getLearningRate();
+    if (opt.getDecaySteps() != -1) {
+      ll = ll * pow(opt.getDecayRate(), (iteration / opt.getDecaySteps()));
     }
-    loss = loss_sum / (float)l.getBatch();
 
-    if (opt.getWeightDecayType() == WeightDecayType::l2norm) {
-      loss += opt.getWeightDecayLambda() * 0.5 * (weight.l2norm());
+    switch (cost) {
+    case COST_MSR: {
+      Tensor sub = y2.subtract(y);
+      Tensor l = (sub.multiply(sub)).sum().multiply(0.5);
+      std::vector<float> t = l.mat2vec();
+      for (int i = 0; i < l.getBatch(); i++) {
+        loss_sum += t[i];
+      }
+
+      loss = loss_sum / (float)l.getBatch();
+      if (opt.getWeightDecayType() == WeightDecayType::l2norm) {
+        loss += opt.getWeightDecayLambda() * 0.5 * (weight.l2norm());
+      }
+      if (activation_type == ACT_SOFTMAX) {
+        djdb = y.subtract(y2).multiply(y.apply(softmaxPrime));
+      } else {
+        djdb = y.subtract(y2).multiply(hidden.apply(activation_prime));
+      }
+    } break;
+    case COST_ENTROPY: {
+      Tensor l;
+      if (activation_type == ACT_SIGMOID) {
+        djdb = y.subtract(y2).multiply(1.0 / y.getWidth());
+        l = (y2.multiply(y.apply(logFloat))
+               .add((y2.multiply(-1.0).add(1.0))
+                      .multiply((y.multiply(-1.0).add(1.0)).apply(logFloat))))
+              .multiply(-1.0 / (y2.getWidth()))
+              .sum();
+      } else if (activation_type == ACT_SOFTMAX) {
+        djdb = y.subtract(y2).multiply(1.0 / y.getWidth());
+        l = (y2.multiply(y.apply(logFloat)))
+              .multiply(-1.0 / (y2.getWidth()))
+              .sum();
+      } else {
+        ml_loge("Only support sigmoid & softmax for cross entropy loss");
+        exit(0);
+      }
+
+      std::vector<float> t = l.mat2vec();
+
+      for (int i = 0; i < l.getBatch(); i++) {
+        loss_sum += t[i];
+      }
+      loss = loss_sum / (float)l.getBatch();
+
+      if (opt.getWeightDecayType() == WeightDecayType::l2norm) {
+        loss += opt.getWeightDecayLambda() * 0.5 * (weight.l2norm());
+      }
+
+    } break;
+    case COST_UNKNOWN:
+    default:
+      break;
     }
-
-  } break;
-  case COST_UNKNOWN:
-  default:
-    break;
   }
 
-  Tensor djdw = input.transpose().dot(djdb);
+  Tensor ret = djdb.dot(weight.transpose());
 
-  ret = djdb.dot(weight.transpose());
+  Tensor djdw = input.transpose().dot(djdb);
 
   opt.calculate(djdw, djdb, weight, bias, iteration, this->init_zero);
 
   return ret;
 }
 
-int BatchNormalizationLayer::initialize(int b, int h, int w, int id,
+int BatchNormalizationLayer::initialize(int b, int h, int w, bool last,
                                         bool init_zero, WeightIniType wini) {
   int status = ML_ERROR_NONE;
   if (b <= 0 || h <= 0 || w <= 0) {
@@ -499,7 +436,7 @@ int BatchNormalizationLayer::initialize(int b, int h, int w, int id,
   this->batch = b;
   this->width = w;
   this->height = h;
-  this->index = id;
+  this->last_layer = last;
   this->init_zero = init_zero;
 
   this->gamma = Tensor(batch, w);
@@ -517,7 +454,7 @@ int BatchNormalizationLayer::setOptimizer(Optimizer &opt) {
   return this->opt.initialize(height, width, false);
 }
 
-Tensor BatchNormalizationLayer::forwarding(Tensor in) {
+Tensor BatchNormalizationLayer::forwarding(Tensor in, int &status) {
   Tensor temp;
 
   hidden = in;
@@ -587,7 +524,7 @@ void BatchNormalizationLayer::save(std::ofstream &file) {
 void BatchNormalizationLayer::copy(Layer *l) {
   BatchNormalizationLayer *from = static_cast<BatchNormalizationLayer *>(l);
   this->opt = from->opt;
-  this->index = from->index;
+  this->last_layer = from->last_layer;
   this->height = from->height;
   this->width = from->width;
   this->input.copy(from->input);
index 807e9e7..8fb8ab2 100644 (file)
@@ -143,12 +143,11 @@ unsigned int parseType(std::string ll, InputType t) {
    * @brief     Layer Type String from configure file
    *            "input"  : Input Layer Object
    *            "fully_conntected" : Fully Connected Layer Object
-   *            "output" : Output Layer Object
    *            "batch_normalization" : Batch Normalization Layer Object
    *            "unknown" : Batch Normalization Layer Object
    */
-  std::array<std::string, 5> layer_string = {
-    "input", "fully_connected", "output", "batch_normalization", "unknown"};
+  std::array<std::string, 4> layer_string = {"input", "fully_connected",
+                                             "batch_normalization", "unknown"};
 
   /**
    * @brief     Weight Initialization Type String from configure file
@@ -278,7 +277,6 @@ int NeuralNetwork::setConfig(std::string config) {
 
 int NeuralNetwork::init() {
   int status = ML_ERROR_NONE;
-  int id;
   bool b_zero;
   std::string l_type;
   LayerType t;
@@ -372,7 +370,6 @@ int NeuralNetwork::init() {
     break;
     case LAYER_IN:
     case LAYER_FC:
-    case LAYER_OUT:
     default:
       h_size =
         iniparser_getint(ini, (layers_name[i] + ":HiddenSize").c_str(), 0);
@@ -422,20 +419,23 @@ int NeuralNetwork::init() {
     iniparser_getint(ini, "DataSet:BufferSize", batch_size));
 
   for (unsigned int i = 0; i < layers_name.size(); i++) {
+    bool last = false;
     l_type =
       iniparser_getstring(ini, (layers_name[i] + ":Type").c_str(), unknown);
     t = (LayerType)parseType(l_type, TOKEN_LAYER);
-    id = iniparser_getint(ini, (layers_name[i] + ":Id").c_str(), 0);
+    if (i == (layers_name.size() - 1)) {
+      last = true;
+    }
     b_zero =
       iniparser_getboolean(ini, (layers_name[i] + ":Bias_zero").c_str(), true);
     std::stringstream ss;
-    ml_logi("%d : %s %d %d", id, l_type.c_str(), hidden_size[i], b_zero);
+    ml_logi("%d : %s %d %d", i, l_type.c_str(), hidden_size[i], b_zero);
 
     switch (t) {
     case LAYER_IN: {
       InputLayer *input_layer = new (InputLayer);
       input_layer->setType(t);
-      status = input_layer->initialize(batch_size, 1, hidden_size[i], id,
+      status = input_layer->initialize(batch_size, 1, hidden_size[i], last,
                                        b_zero, weight_ini);
       NN_RETURN_STATUS();
 
@@ -456,13 +456,15 @@ int NeuralNetwork::init() {
     case LAYER_FC: {
       FullyConnectedLayer *fc_layer = new (FullyConnectedLayer);
       fc_layer->setType(t);
+      status = fc_layer->setCost(cost);
+      NN_RETURN_STATUS();
       if (i == 0) {
         ml_loge("Error: Fully Connected Layer should be after "
                 "InputLayer.");
         return ML_ERROR_INVALID_PARAMETER;
       }
       status = fc_layer->initialize(batch_size, hidden_size[i - 1],
-                                    hidden_size[i], id, b_zero, weight_ini);
+                                    hidden_size[i], last, b_zero, weight_ini);
       NN_RETURN_STATUS();
       status = fc_layer->setOptimizer(opt);
       NN_RETURN_STATUS();
@@ -473,33 +475,12 @@ int NeuralNetwork::init() {
       NN_RETURN_STATUS();
       layers.push_back(fc_layer);
     } break;
-    case LAYER_OUT: {
-      OutputLayer *output_layer = new (OutputLayer);
-      output_layer->setType(t);
-      status = output_layer->setCost(cost);
-      NN_RETURN_STATUS();
-      if (i == 0) {
-        ml_loge("Error: Output layer shouldn't be first layer of network");
-        return ML_ERROR_INVALID_PARAMETER;
-      }
-      status = output_layer->initialize(batch_size, hidden_size[i - 1],
-                                        hidden_size[i], id, b_zero, weight_ini);
-      NN_RETURN_STATUS();
-      status = output_layer->setOptimizer(opt);
-      NN_RETURN_STATUS();
-      status = output_layer->setActivation((ActiType)parseType(
-        iniparser_getstring(ini, (layers_name[i] + ":Activation").c_str(),
-                            unknown),
-        TOKEN_ACTI));
-      NN_RETURN_STATUS();
-      layers.push_back(output_layer);
-    } break;
     case LAYER_BN: {
       BatchNormalizationLayer *bn_layer = new (BatchNormalizationLayer);
       bn_layer->setType(t);
       status = bn_layer->setOptimizer(opt);
       NN_RETURN_STATUS();
-      status = bn_layer->initialize(batch_size, 1, hidden_size[i], id, b_zero,
+      status = bn_layer->initialize(batch_size, 1, hidden_size[i], last, b_zero,
                                     weight_ini);
       NN_RETURN_STATUS();
       layers.push_back(bn_layer);
@@ -545,10 +526,10 @@ void NeuralNetwork::finalize() {
 /**
  * @brief     forward propagation using layers object which has layer
  */
-Tensor NeuralNetwork::forwarding(Tensor input) {
+Tensor NeuralNetwork::forwarding(Tensor input, int &status) {
   Tensor X = input;
   for (unsigned int i = 0; i < layers.size(); i++) {
-    X = layers[i]->forwarding(X);
+    X = layers[i]->forwarding(X, status);
   }
   return X;
 }
@@ -556,11 +537,11 @@ Tensor NeuralNetwork::forwarding(Tensor input) {
 /**
  * @brief     forward propagation using layers object which has layer
  */
-Tensor NeuralNetwork::forwarding(Tensor input, Tensor output) {
+Tensor NeuralNetwork::forwarding(Tensor input, Tensor output, int &status) {
   Tensor X = input;
   Tensor Y2 = output;
   for (unsigned int i = 0; i < layers.size(); i++) {
-    X = layers[i]->forwarding(X, Y2);
+    X = layers[i]->forwarding(X, Y2, status);
   }
   return X;
 }
@@ -570,19 +551,22 @@ Tensor NeuralNetwork::forwarding(Tensor input, Tensor output) {
  *            Call backwarding function of layer in reverse order
  *            No need to call at first Input Layer (No data to be updated)
  */
-void NeuralNetwork::backwarding(Tensor input, Tensor expected_output,
-                                int iteration) {
+int NeuralNetwork::backwarding(Tensor input, Tensor expected_output,
+                               int iteration) {
+  int status = ML_ERROR_NONE;
   Tensor Y2 = expected_output;
   Tensor X = input;
-  Tensor Y = forwarding(X);
+  Tensor Y = forwarding(X, status);
 
   for (unsigned int i = layers.size() - 1; i > 0; i--) {
     Y2 = layers[i]->backwarding(Y2, iteration);
   }
+  return status;
 }
 
 float NeuralNetwork::getLoss() {
-  OutputLayer *out = static_cast<OutputLayer *>((layers[layers.size() - 1]));
+  FullyConnectedLayer *out =
+    static_cast<FullyConnectedLayer *>((layers[layers.size() - 1]));
   return out->getLoss();
 }
 
@@ -712,7 +696,7 @@ int NeuralNetwork::train() {
           for (int i = 0; i < batch_size; ++i) {
             nntrainer::Tensor X = nntrainer::Tensor({in[i]});
             nntrainer::Tensor Y2 = nntrainer::Tensor({label[i]});
-            nntrainer::Tensor Y = forwarding(X, Y2);
+            nntrainer::Tensor Y = forwarding(X, Y2, status);
             if (Y.argmax() == Y2.argmax())
               right++;
             valloss += getLoss();
index 98e6e5d..4e64cbb 100644 (file)
@@ -77,8 +77,6 @@ const std::string config_str = "[Network]"
                                "\n"
                                "Type = input"
                                "\n"
-                               "Id = 0"
-                               "\n"
                                "HiddenSize = 62720"
                                "\n"
                                "Bias_zero = true"
@@ -89,9 +87,7 @@ const std::string config_str = "[Network]"
                                "\n"
                                "[outputlayer]"
                                "\n"
-                               "Type = output"
-                               "\n"
-                               "Id = 1"
+                               "Type = fully_connected"
                                "\n"
                                "HiddenSize = 10"
                                "\n"
index cc50789..676336b 100644 (file)
@@ -336,7 +336,8 @@ TEST(nntrainer_Optimizer, setOptParam_01_p) {
 TEST(nntrainer_InputLayer, initialize_01_p) {
   int status = ML_ERROR_NONE;
   nntrainer::InputLayer layer;
-  status = layer.initialize(1, 1, 1, 0, true, nntrainer::WEIGHT_XAVIER_NORMAL);
+  status =
+    layer.initialize(1, 1, 1, false, true, nntrainer::WEIGHT_XAVIER_NORMAL);
   EXPECT_EQ(status, ML_ERROR_NONE);
 }
 
@@ -346,7 +347,8 @@ TEST(nntrainer_InputLayer, initialize_01_p) {
 TEST(nntrainer_InputLayer, initialize_02_n) {
   int status = ML_ERROR_NONE;
   nntrainer::InputLayer layer;
-  status = layer.initialize(1, 0, 1, 0, true, nntrainer::WEIGHT_XAVIER_NORMAL);
+  status =
+    layer.initialize(1, 0, 1, false, true, nntrainer::WEIGHT_XAVIER_NORMAL);
   EXPECT_EQ(status, ML_ERROR_INVALID_PARAMETER);
 }
 
@@ -356,7 +358,8 @@ TEST(nntrainer_InputLayer, initialize_02_n) {
 TEST(nntrainer_InputLayer, setOptimizer_01_p) {
   int status = ML_ERROR_NONE;
   nntrainer::InputLayer layer;
-  status = layer.initialize(1, 1, 1, 0, true, nntrainer::WEIGHT_XAVIER_NORMAL);
+  status =
+    layer.initialize(1, 1, 1, false, true, nntrainer::WEIGHT_XAVIER_NORMAL);
   nntrainer::Optimizer op;
   nntrainer::OptType t = nntrainer::OptType::adam;
   nntrainer::OptParam p;
@@ -400,7 +403,8 @@ TEST(nntrainer_InputLayer, setActivation_02_n) {
 TEST(nntrainer_FullyConnectedLayer, initialize_01_p) {
   int status = ML_ERROR_NONE;
   nntrainer::FullyConnectedLayer layer;
-  status = layer.initialize(1, 1, 1, 0, true, nntrainer::WEIGHT_XAVIER_NORMAL);
+  status =
+    layer.initialize(1, 1, 1, false, true, nntrainer::WEIGHT_XAVIER_NORMAL);
   EXPECT_EQ(status, ML_ERROR_NONE);
 }
 
@@ -410,7 +414,8 @@ TEST(nntrainer_FullyConnectedLayer, initialize_01_p) {
 TEST(nntrainer_FullyConnectedLayer, initialize_02_n) {
   int status = ML_ERROR_NONE;
   nntrainer::FullyConnectedLayer layer;
-  status = layer.initialize(1, 0, 1, 0, true, nntrainer::WEIGHT_XAVIER_NORMAL);
+  status =
+    layer.initialize(1, 0, 1, false, true, nntrainer::WEIGHT_XAVIER_NORMAL);
   EXPECT_EQ(status, ML_ERROR_INVALID_PARAMETER);
 }
 
@@ -420,91 +425,75 @@ TEST(nntrainer_FullyConnectedLayer, initialize_02_n) {
 TEST(nntrainer_FullyConnectedLayer, initialize_03_n) {
   int status = ML_ERROR_NONE;
   nntrainer::FullyConnectedLayer layer;
-  status = layer.initialize(1, 1, 1, 0, true, nntrainer::WEIGHT_UNKNOWN);
-  EXPECT_EQ(status, ML_ERROR_NONE);
-}
-
-/**
- * @brief Fully Connected Layer
- */
-TEST(nntrainer_FullyConnectedLayer, setOptimizer_01_p) {
-  int status = ML_ERROR_NONE;
-  nntrainer::FullyConnectedLayer layer;
-  status = layer.initialize(1, 1, 1, 0, true, nntrainer::WEIGHT_XAVIER_NORMAL);
-  nntrainer::Optimizer op;
-  nntrainer::OptType t = nntrainer::OptType::adam;
-  nntrainer::OptParam p;
-  status = op.setType(t);
-  EXPECT_EQ(status, ML_ERROR_NONE);
-  p.learning_rate = 0.001;
-  p.beta1 = 0.9;
-  p.beta2 = 0.9999;
-  p.epsilon = 1e-7;
-  p.weight_decay.type = nntrainer::WeightDecayType::l2norm;
-  p.weight_decay.lambda = 0.001;
-  status = op.setOptParam(p);
-  EXPECT_EQ(status, ML_ERROR_NONE);
-  status = layer.setOptimizer(op);
+  status = layer.initialize(1, 1, 1, false, true, nntrainer::WEIGHT_UNKNOWN);
   EXPECT_EQ(status, ML_ERROR_NONE);
 }
 
 /**
- * @brief Fully Connected Layer
+ * @brief FullyConnected Layer
  */
-TEST(nntrainer_FullyConnectedLayer, setActivation_01_p) {
+TEST(nntrainer_FullyConnectedLayer, initialize_04_p) {
   int status = ML_ERROR_NONE;
   nntrainer::FullyConnectedLayer layer;
-  status = layer.setActivation(nntrainer::ACT_TANH);
+  status =
+    layer.initialize(1, 1, 1, true, true, nntrainer::WEIGHT_XAVIER_NORMAL);
   EXPECT_EQ(status, ML_ERROR_NONE);
 }
 
 /**
- * @brief Fully Connected Layer
+ * @brief FullyConnected Layer
  */
-TEST(nntrainer_FullyConnectedLayer, setActivation_02_n) {
+TEST(nntrainer_FullyConnectedLayer, initialize_05_n) {
   int status = ML_ERROR_NONE;
   nntrainer::FullyConnectedLayer layer;
-  status = layer.setActivation(nntrainer::ACT_UNKNOWN);
+  status =
+    layer.initialize(1, 0, 1, true, true, nntrainer::WEIGHT_XAVIER_NORMAL);
   EXPECT_EQ(status, ML_ERROR_INVALID_PARAMETER);
 }
 
 /**
- * @brief Output Layer
+ * @brief FullyConnected Layer
  */
-TEST(nntrainer_OutputLayer, initialize_01_p) {
+TEST(nntrainer_FullyConnectedLayer, initialize_06_n) {
   int status = ML_ERROR_NONE;
-  nntrainer::OutputLayer layer;
-  status = layer.initialize(1, 1, 1, 0, true, nntrainer::WEIGHT_XAVIER_NORMAL);
+  nntrainer::FullyConnectedLayer layer;
+  status = layer.initialize(1, 1, 1, true, true, nntrainer::WEIGHT_UNKNOWN);
   EXPECT_EQ(status, ML_ERROR_NONE);
 }
 
 /**
- * @brief Output Layer
- */
-TEST(nntrainer_OutputLayer, initialize_02_n) {
-  int status = ML_ERROR_NONE;
-  nntrainer::OutputLayer layer;
-  status = layer.initialize(1, 0, 1, 0, true, nntrainer::WEIGHT_XAVIER_NORMAL);
-  EXPECT_EQ(status, ML_ERROR_INVALID_PARAMETER);
-}
-
-/**
- * @brief Output Layer
+ * @brief Fully Connected Layer
  */
-TEST(nntrainer_OutputLayer, initialize_03_n) {
+TEST(nntrainer_FullyConnectedLayer, setOptimizer_01_p) {
   int status = ML_ERROR_NONE;
-  nntrainer::OutputLayer layer;
-  status = layer.initialize(1, 1, 1, 0, true, nntrainer::WEIGHT_UNKNOWN);
+  nntrainer::FullyConnectedLayer layer;
+  status =
+    layer.initialize(1, 1, 1, false, true, nntrainer::WEIGHT_XAVIER_NORMAL);
+  nntrainer::Optimizer op;
+  nntrainer::OptType t = nntrainer::OptType::adam;
+  nntrainer::OptParam p;
+  status = op.setType(t);
+  EXPECT_EQ(status, ML_ERROR_NONE);
+  p.learning_rate = 0.001;
+  p.beta1 = 0.9;
+  p.beta2 = 0.9999;
+  p.epsilon = 1e-7;
+  p.weight_decay.type = nntrainer::WeightDecayType::l2norm;
+  p.weight_decay.lambda = 0.001;
+  status = op.setOptParam(p);
+  EXPECT_EQ(status, ML_ERROR_NONE);
+  status = layer.setOptimizer(op);
   EXPECT_EQ(status, ML_ERROR_NONE);
 }
 
 /**
- * @brief Output Layer
+ * @brief FullyConnected Layer
  */
-TEST(nntrainer_OutputLayer, setOptimizer_01_p) {
+TEST(nntrainer_FullyConnectedLayer, setOptimizer_02_p) {
   int status = ML_ERROR_NONE;
-  nntrainer::OutputLayer layer;
-  status = layer.initialize(1, 1, 1, 0, true, nntrainer::WEIGHT_XAVIER_NORMAL);
+  nntrainer::FullyConnectedLayer layer;
+  status =
+    layer.initialize(1, 1, 1, true, true, nntrainer::WEIGHT_XAVIER_NORMAL);
   nntrainer::Optimizer op;
   nntrainer::OptType t = nntrainer::OptType::adam;
   nntrainer::OptParam p;
@@ -523,41 +512,41 @@ TEST(nntrainer_OutputLayer, setOptimizer_01_p) {
 }
 
 /**
- * @brief Output Layer
+ * @brief Fully Connected Layer
  */
-TEST(nntrainer_OutputLayer, setActivation_01_p) {
+TEST(nntrainer_FullyConnectedLayer, setActivation_01_p) {
   int status = ML_ERROR_NONE;
-  nntrainer::OutputLayer layer;
-  status = layer.setActivation(nntrainer::ACT_SIGMOID);
+  nntrainer::FullyConnectedLayer layer;
+  status = layer.setActivation(nntrainer::ACT_TANH);
   EXPECT_EQ(status, ML_ERROR_NONE);
 }
 
 /**
- * @brief Output Layer
+ * @brief Fully Connected Layer
  */
-TEST(nntrainer_OutputLayer, setActivation_02_n) {
+TEST(nntrainer_FullyConnectedLayer, setActivation_02_n) {
   int status = ML_ERROR_NONE;
-  nntrainer::OutputLayer layer;
+  nntrainer::FullyConnectedLayer layer;
   status = layer.setActivation(nntrainer::ACT_UNKNOWN);
   EXPECT_EQ(status, ML_ERROR_INVALID_PARAMETER);
 }
 
 /**
- * @brief Output Layer
+ * @brief FullyConnected Layer
  */
-TEST(nntrainer_OutputLayer, setCost_01_p) {
+TEST(nntrainer_FullyConnectedLayer, setCost_01_p) {
   int status = ML_ERROR_NONE;
-  nntrainer::OutputLayer layer;
+  nntrainer::FullyConnectedLayer layer;
   status = layer.setCost(nntrainer::COST_ENTROPY);
   EXPECT_EQ(status, ML_ERROR_NONE);
 }
 
 /**
- * @brief Output Layer
+ * @brief FullyConnected Layer
  */
-TEST(nntrainer_OutputLayer, setCost_02_n) {
+TEST(nntrainer_FullyConnectedLayer, setCost_02_n) {
   int status = ML_ERROR_NONE;
-  nntrainer::OutputLayer layer;
+  nntrainer::FullyConnectedLayer layer;
   status = layer.setCost(nntrainer::COST_UNKNOWN);
   EXPECT_EQ(status, ML_ERROR_INVALID_PARAMETER);
 }
@@ -568,7 +557,8 @@ TEST(nntrainer_OutputLayer, setCost_02_n) {
 TEST(nntrainer_BatchNormalizationLayer, initialize_01_p) {
   int status = ML_ERROR_NONE;
   nntrainer::BatchNormalizationLayer layer;
-  status = layer.initialize(1, 1, 1, 0, true, nntrainer::WEIGHT_XAVIER_NORMAL);
+  status =
+    layer.initialize(1, 1, 1, false, true, nntrainer::WEIGHT_XAVIER_NORMAL);
   EXPECT_EQ(status, ML_ERROR_NONE);
 }
 
@@ -578,7 +568,8 @@ TEST(nntrainer_BatchNormalizationLayer, initialize_01_p) {
 TEST(nntrainer_BatchNormalizationLayer, initialize_02_n) {
   int status = ML_ERROR_NONE;
   nntrainer::BatchNormalizationLayer layer;
-  status = layer.initialize(1, 0, 1, 0, true, nntrainer::WEIGHT_XAVIER_NORMAL);
+  status =
+    layer.initialize(1, 0, 1, false, true, nntrainer::WEIGHT_XAVIER_NORMAL);
   EXPECT_EQ(status, ML_ERROR_INVALID_PARAMETER);
 }