Построение слоя пакетной нормализации - PullRequest
0 голосов
/ 21 января 2020

Я пытаюсь настроить слой BatchNormalization в C ++.

Код, который у меня есть, выглядит следующим образом:

mx::Symbol loadBatchNormalization(mx::Symbol previous, std::istream &file, const std::string &name, const Shape &inputShape, const Shape &outputShape, std::map<std::string, mx::NDArray> &args, bool tensorflow, bool debug)
{
    auto gammaShape_ = ReadShape(file);
    auto gamma_ = ReadFloats(file, sizeOf(gammaShape_));
    auto gammaShape = shape_(gammaShape_);
    mx::NDArray gamma { gamma_, gammaShape, ctx };

    auto betaShape_ = ReadShape(file);
    auto beta_ = ReadFloats(file, sizeOf(betaShape_));
    auto betaShape = shape_(betaShape_);
    mx::NDArray beta { beta_, betaShape, ctx };

    auto movingMeanShape_ = ReadShape(file);
    auto movingMean_ = ReadFloats(file, sizeOf(movingMeanShape_));
    auto movingMeanShape = shape_(movingMeanShape_);
    mx::NDArray movingMean { movingMean_, movingMeanShape, ctx };

    auto movingVarianceShape_ = ReadShape(file);
    auto movingVariance_ = ReadFloats(file, sizeOf(movingVarianceShape_));
    auto movingVarianceShape = shape_(movingVarianceShape_);
    mx::NDArray movingVariance { movingVariance_, movingVarianceShape, ctx };

    mx::Symbol gammaSymbol(name + "_gamma");
    mx::Symbol betaSymbol(name + "_beta");
    mx::Symbol movingMeanSymbol(name + "_movingMean");
    mx::Symbol movingVarianceSymbol(name + "_movingVariance");

    double eps = 0.001;
    mx_float momentum = 0.9; // should never be used?
    bool fix_gamma = false;
    bool use_global_stats = false;
    bool output_mean_var = false;
    int axis = 1;
    bool cudnn_off = false;

    mx::Symbol layer = mx::BatchNorm(
        name,
        previous,
        gammaSymbol,
        betaSymbol,
        movingMeanSymbol,
        movingVarianceSymbol,
        eps,
        momentum,
        fix_gamma,
        use_global_stats,
        output_mean_var,
        axis,
        cudnn_off
    );

    args[name + "_gamma"] = gamma;
    args[name + "_beta"] = beta;
    args[name + "_movingMean"] = movingMean;
    args[name + "_movingVariance"] = movingVariance;

    return layer;
}

В двух словах, сделайте гамму, бета, movingMean и movingVariance и создайте BatchNorm, используя эти символы.

Но. Слой BatchNorm выводит нули. Что заставляет меня думать, что мне нужно делать что-то еще.

Может ли кто-нибудь подсказать мне, как построить слой BatchNorm с ранее обученными весами?

1 Ответ

0 голосов
/ 23 января 2020

По состоянию на 23 января 2020 г. M xnet Кажется, что Batchnorm работает неправильно, если он построен с использованием гамма, бета, movingMean и movingVariance из обученной сети keras m xnet.

Посмотрите на Исходный код keras для их пакета прогнозирования.

возможное решение - что-то вроде:

mx::Symbol generateBatchNormalization (const std::string &name, mx::Symbol &inputSymbol_, mx::Symbol &gammaSymbol, mx::Symbol &betaSymbol, mx::Symbol &movingMeanSymbol, mx::Symbol &movingVarianceSymbol)
{
    //  auto normalization = (inputSymbol - movingMeanSymbol) / mx::sqrt(movingVarianceSymbol + eps) * gammaSymbol + betaSymbol;

    auto inputSymbol = mx::SwapAxis(inputSymbol_, 1, 3);
    auto n0 = mx::broadcast_sub(inputSymbol, movingMeanSymbol);
    double epsilon = 0.0001;
    auto n1 = mx::sqrt(movingVarianceSymbol + epsilon);
    auto n2 = mx::broadcast_div(n0, n1);
    auto n3 = mx::broadcast_mul(n2, gammaSymbol);
    auto n4 = mx::broadcast_add(n3, betaSymbol);

    auto normalization = mx::SwapAxis(n4, 1, 3);
    return normalization;
}
...