// // Initializer.cpp // MNN // // Created by MNN on 2019/11/28. // Copyright © 2018, Alibaba Group Holding Limited // #include "Initializer.hpp" #include #include #include #include "Distributions.hpp" #include "RandomGenerator.hpp" namespace MNN { namespace Express { Express::VARP Initializer::createConstVar(Express::INTS dim, Express::Dimensionformat format) { auto res = Express::_Input(dim, format, halide_type_of()); this->onExecute(res); res.fix(Express::VARP::CONSTANT); return res; } class ConstantInitializer : public Initializer { public: ConstantInitializer(float value) : mConstant(value) { } virtual void onExecute(Express::VARP p) override { const int count = p->getInfo()->size; MNN_ASSERT(count > 0); auto ptr = p->writeMap(); for (int i = 0; i < count; i++) { ptr[i] = mConstant; } } private: float mConstant; }; Initializer* Initializer::constValue(float value) { return new ConstantInitializer(value); } class UniformInitializer : public Initializer { public: UniformInitializer(float min = 0, float max = 1) { mMin = min; mMax = max; } virtual void onExecute(Express::VARP p) override { const int count = p->getInfo()->size; MNN_ASSERT(count > 0); Distributions::uniform(count, mMin, mMax, p->writeMap(), RandomGenerator::generator()); } private: float mMin; float mMax; }; Initializer* Initializer::uniform(float minValue, float maxValue) { return new UniformInitializer(minValue, maxValue); } class XavierInitializer : public Initializer { public: XavierInitializer(VarianceNorm norm = FANIN) { mNorm = norm; } virtual void onExecute(Express::VARP p) override { const int count = p->getInfo()->size; MNN_ASSERT(count > 0); const std::vector dims = p->getInfo()->dim; // referenced from Caffe // https://github.com/BVLC/caffe/blob/master/include/caffe/filler.hpp int fanIn = count / dims[0]; int fanOut = dims.size() > 1 ? count / dims[1] : count; float n = fanIn; // default: FANIN if (mNorm == VarianceNorm::AVERAGE) { n = (fanIn + fanOut) / 2.0f; } else if (mNorm == VarianceNorm::FANOUT) { n = fanOut; } float scale = sqrtf(3.0f / n); Distributions::uniform(count, -scale, scale, p->writeMap(), RandomGenerator::generator()); } private: VarianceNorm mNorm; }; Initializer* Initializer::xavier(VarianceNorm norm) { return new XavierInitializer(norm); } class GaussianInitializer : public Initializer { public: GaussianInitializer(float mean = 0, float std = 1) { mMean = mean; mStd = std; } virtual void onExecute(Express::VARP p) override { const int count = p->getInfo()->size; MNN_ASSERT(count > 0); Distributions::gaussian(count, mMean, mStd, p->writeMap(), RandomGenerator::generator()); } private: float mMean; float mStd; }; Initializer* Initializer::gauss(float mean, float std) { return new GaussianInitializer(mean, std); } class MSRAInitializer : public Initializer { public: MSRAInitializer(VarianceNorm norm = FANIN) { mNorm = norm; } virtual void onExecute(Express::VARP p) override { const int count = p->getInfo()->size; MNN_ASSERT(count > 0); const std::vector dims = p->getInfo()->dim; // referenced from Caffe // https://github.com/BVLC/caffe/blob/master/include/caffe/filler.hpp int fanIn = count / dims[0]; int fanOut = dims.size() > 1 ? count / dims[1] : count; float n = fanIn; // default: FANIN if (mNorm == VarianceNorm::AVERAGE) { n = (fanIn + fanOut) / 2.0f; } else if (mNorm == VarianceNorm::FANOUT) { n = fanOut; } float std = sqrtf(2.0f / n); Distributions::gaussian(count, 0.0f, std, p->writeMap(), RandomGenerator::generator()); } private: VarianceNorm mNorm; }; Initializer* Initializer::MSRA(VarianceNorm norm) { return new MSRAInitializer(norm); } class BilinearInitializer : public Initializer { public: BilinearInitializer() = default; virtual void onExecute(Express::VARP p) override { const int count = p->getInfo()->size; MNN_ASSERT(count > 0); const std::vector dims = p->getInfo()->dim; MNN_ASSERT(dims.size() == 4); MNN_ASSERT(dims[2] == dims[3]); // NCHW, H == W // referenced from Caffe // https://github.com/BVLC/caffe/blob/master/include/caffe/filler.hpp int f = ceilf(dims[3] / 2.0f); float c = (dims[3] - 1) / (2.0f * f); auto ptr = p->writeMap(); for (int i = 0; i < count; i++) { float x = i % dims[3]; float y = (i / dims[3]) % dims[2]; ptr[i] = (1 - std::fabs(x / f - c)) * (1 - std::fabs(y / f - c)); } } }; Initializer* Initializer::bilinear() { return new BilinearInitializer(); } class PositiveUnitball : public Initializer { public: PositiveUnitball() = default; virtual void onExecute(Express::VARP p) override { const int count = p->getInfo()->size; MNN_ASSERT(count > 0); const std::vector dims = p->getInfo()->dim; auto ptr = p->writeMap(); Distributions::uniform(count, 0, 1, ptr, RandomGenerator::generator()); int dim = count / dims[0]; for (int i = 0; i < dims[0]; i++) { float sum = 0; for (int j = 0; j < dim; j++) { sum += ptr[i * dim + j]; } for (int j = 0; j < dim; j++) { ptr[i * dim + j] = ptr[i * dim + j] / sum; } } } }; Initializer* Initializer::positiveUnitball() { return new PositiveUnitball(); } } // namespace Express } // namespace MNN