Browse Source

implement instancenorm

tags/20180314
nihuini 8 years ago
parent
commit
5f4ac776d1
3 changed files with 134 additions and 0 deletions
  1. +1
    -0
      src/CMakeLists.txt
  2. +88
    -0
      src/layer/instancenorm.cpp
  3. +45
    -0
      src/layer/instancenorm.h

+ 1
- 0
src/CMakeLists.txt View File

@@ -141,6 +141,7 @@ ncnn_add_layer(DetectionOutput)
ncnn_add_layer(Interp)
ncnn_add_layer(DeconvolutionDepthWise)
ncnn_add_layer(ShuffleChannel)
ncnn_add_layer(InstanceNorm)

add_library(ncnn STATIC ${ncnn_SRCS})



+ 88
- 0
src/layer/instancenorm.cpp View File

@@ -0,0 +1,88 @@
// Tencent is pleased to support the open source community by making ncnn available.
//
// Copyright (C) 2017 THL A29 Limited, a Tencent company. All rights reserved.
//
// Licensed under the BSD 3-Clause License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at
//
// https://opensource.org/licenses/BSD-3-Clause
//
// Unless required by applicable law or agreed to in writing, software distributed
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License.

#include "instancenorm.h"
#include <math.h>

namespace ncnn {

DEFINE_LAYER_CREATOR(InstanceNorm)

InstanceNorm::InstanceNorm()
{
one_blob_only = true;
support_inplace = true;
}

int InstanceNorm::load_param(const ParamDict& pd)
{
channels = pd.get(0, 0);
eps = pd.get(1, 0.001f);

return 0;
}

int InstanceNorm::load_model(const ModelBin& mb)
{
gamma_data = mb.load(channels, 1);
if (gamma_data.empty())
return -100;

beta_data = mb.load(channels, 1);
if (beta_data.empty())
return -100;

return 0;
}

int InstanceNorm::forward_inplace(Mat& bottom_top_blob) const
{
// x = (x - mean) / (sqrt(var) + eps) * gamma + beta

int w = bottom_top_blob.w;
int h = bottom_top_blob.h;
int size = w * h;

#pragma omp parallel for
for (int q=0; q<channels; q++)
{
float* ptr = bottom_top_blob.channel(q);

// mean and var
float sum = 0.f;
float sqsum = 0.f;
for (int i=0; i<size; i++)
{
sum += ptr[i];
sqsum += ptr[i] * ptr[i];
}
float mean = sum / size;
float var = sqsum / size - mean * mean;

float gamma = gamma_data[q];
float beta = beta_data[q];

float a = gamma / (sqrt(var) + eps);
float b = - mean * a + beta;

for (int i=0; i<size; i++)
{
ptr[i] = ptr[i] * a + b;
}
}

return 0;
}

} // namespace ncnn

+ 45
- 0
src/layer/instancenorm.h View File

@@ -0,0 +1,45 @@
// Tencent is pleased to support the open source community by making ncnn available.
//
// Copyright (C) 2017 THL A29 Limited, a Tencent company. All rights reserved.
//
// Licensed under the BSD 3-Clause License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at
//
// https://opensource.org/licenses/BSD-3-Clause
//
// Unless required by applicable law or agreed to in writing, software distributed
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License.

#ifndef LAYER_INSTANCENORM_H
#define LAYER_INSTANCENORM_H

#include "layer.h"

namespace ncnn {

class InstanceNorm : public Layer
{
public:
InstanceNorm();

virtual int load_param(const ParamDict& pd);

virtual int load_model(const ModelBin& mb);

virtual int forward_inplace(Mat& bottom_top_blob) const;

public:
// param
int channels;
float eps;

// model
Mat gamma_data;
Mat beta_data;
};

} // namespace ncnn

#endif // LAYER_INSTANCENORM_H

Loading…
Cancel
Save