TensorFlow. js: «Ошибка: веса не заданы» при загрузке преобразованной модели со слоями BatchNormalization - PullRequest
1 голос
/ 08 апреля 2020

Я портирую на TF. js модель, переоборудованную из Keras с ее предварительно тренированными весами. Я следовал инструкциям документации и сохранил веса из локального пути.

Когда я инициализирую свою модель, загружая файл .json с узлом tf js 1.7.1, я получаю следующую ошибку:

(node:39703) UnhandledPromiseRejectionWarning: Error: 152 of 197 weights are not set: conv1_1/3x3_s1/bn/gamma,conv1_1/3x3_s1/bn/beta,conv1_1/3x3_s1/bn/moving_mean,conv1_1/3x3_s1/bn/moving_variance,conv2_a_1x1_reduce/bn/gamma,conv2_a_1x1_reduce/bn/beta,conv2_a_1x1_reduce/bn/moving_mean,conv2_a_1x1_reduce/bn/moving_variance,conv2_a_3x3/bn/gamma,conv2_a_3x3/bn/beta,conv2_a_3x3/bn/moving_mean,conv2_a_3x3/bn/moving_variance,conv2_a_1x1_increase/bn/gamma,conv2_a_1x1_increase/bn/beta,conv2_a_1x1_increase/bn/moving_mean,conv2_a_1x1_increase/bn/moving_variance,conv2_a_1x1_proj/bn/gamma,conv2_a_1x1_proj/bn/beta,conv2_a_1x1_proj/bn/moving_mean,conv2_a_1x1_proj/bn/moving_variance,conv2_b_1x1_reduce/bn/gamma,conv2_b_1x1_reduce/bn/beta,conv2_b_1x1_reduce/bn/moving_mean,conv2_b_1x1_reduce/bn/moving_variance,conv2_b_3x3/bn/gamma,conv2_b_3x3/bn/beta,conv2_b_3x3/bn/moving_mean,conv2_b_3x3/bn/moving_variance,conv2_b_1x1_increase/bn/gamma,conv2_b_1x1_increase/bn/beta,conv2_b_1x1_increase/bn/moving_mean,conv2_b_1x1_increase/bn/moving_variance,conv3_a_1x1_reduce/bn/gamma,conv3_a_1x1_reduce/bn/beta,conv3_a_1x1_reduce/bn/moving_mean,conv3_a_1x1_reduce/bn/moving_variance,conv3_a_3x3/bn/gamma,conv3_a_3x3/bn/beta,conv3_a_3x3/bn/moving_mean,conv3_a_3x3/bn/moving_variance,conv3_a_1x1_increase/bn/gamma,conv3_a_1x1_increase/bn/beta,conv3_a_1x1_increase/bn/moving_mean,conv3_a_1x1_increase/bn/moving_variance,conv3_a_1x1_proj/bn/gamma,conv3_a_1x1_proj/bn/beta,conv3_a_1x1_proj/bn/moving_mean,conv3_a_1x1_proj/bn/moving_variance,conv3_b_1x1_reduce/bn/gamma,conv3_b_1x1_reduce/bn/beta,conv3_b_1x1_reduce/bn/moving_mean,conv3_b_1x1_reduce/bn/moving_variance,conv3_b_3x3/bn/gamma,conv3_b_3x3/bn/beta,conv3_b_3x3/bn/moving_mean,conv3_b_3x3/bn/moving_variance,conv3_b_1x1_increase/bn/gamma,conv3_b_1x1_increase/bn/beta,conv3_b_1x1_increase/bn/moving_mean,conv3_b_1x1_increase/bn/moving_variance,conv3_c_1x1_reduce/bn/gamma,conv3_c_1x1_reduce/bn/beta,conv3_c_1x1_reduce/bn/moving_mean,conv3_c_1x1_reduce/bn/moving_variance,conv3_c_3x3/bn/gamma,conv3_c_3x3/bn/beta,conv3_c_3x3/bn/moving_mean,conv3_c_3x3/bn/moving_variance,conv3_c_1x1_increase/bn/gamma,conv3_c_1x1_increase/bn/beta,conv3_c_1x1_increase/bn/moving_mean,conv3_c_1x1_increase/bn/moving_variance,conv4_a_1x1_reduce/bn/gamma,conv4_a_1x1_reduce/bn/beta,conv4_a_1x1_reduce/bn/moving_mean,conv4_a_1x1_reduce/bn/moving_variance,conv4_a_3x3/bn/gamma,conv4_a_3x3/bn/beta,conv4_a_3x3/bn/moving_mean,conv4_a_3x3/bn/moving_variance,conv4_a_1x1_increase/bn/gamma,conv4_a_1x1_increase/bn/beta,conv4_a_1x1_increase/bn/moving_mean,conv4_a_1x1_increase/bn/moving_variance,conv4_a_1x1_proj/bn/gamma,conv4_a_1x1_proj/bn/beta,conv4_a_1x1_proj/bn/moving_mean,conv4_a_1x1_proj/bn/moving_variance,conv4_b_1x1_reduce/bn/gamma,conv4_b_1x1_reduce/bn/beta,conv4_b_1x1_reduce/bn/moving_mean,conv4_b_1x1_reduce/bn/moving_variance,conv4_b_3x3/bn/gamma,conv4_b_3x3/bn/beta,conv4_b_3x3/bn/moving_mean,conv4_b_3x3/bn/moving_variance,conv4_b_1x1_increase/bn/gamma,conv4_b_1x1_increase/bn/beta,conv4_b_1x1_increase/bn/moving_mean,conv4_b_1x1_increase/bn/moving_variance,conv4_c_1x1_reduce/bn/gamma,conv4_c_1x1_reduce/bn/beta,conv4_c_1x1_reduce/bn/moving_mean,conv4_c_1x1_reduce/bn/moving_variance,conv4_c_3x3/bn/gamma,conv4_c_3x3/bn/beta,conv4_c_3x3/bn/moving_mean,conv4_c_3x3/bn/moving_variance,conv4_c_1x1_increase/bn/gamma,conv4_c_1x1_increase/bn/beta,conv4_c_1x1_increase/bn/moving_mean,conv4_c_1x1_increase/bn/moving_variance,conv5_a_1x1_reduce/bn/gamma,conv5_a_1x1_reduce/bn/beta,conv5_a_1x1_reduce/bn/moving_mean,conv5_a_1x1_reduce/bn/moving_variance,conv5_a_3x3/bn/gamma,conv5_a_3x3/bn/beta,conv5_a_3x3/bn/moving_mean,conv5_a_3x3/bn/moving_variance,conv5_a_1x1_increase/bn/gamma,conv5_a_1x1_increase/bn/beta,conv5_a_1x1_increase/bn/moving_mean,conv5_a_1x1_increase/bn/moving_variance,conv5_a_1x1_proj/bn/gamma,conv5_a_1x1_proj/bn/beta,conv5_a_1x1_proj/bn/moving_mean,conv5_a_1x1_proj/bn/moving_variance,conv5_b_1x1_reduce/bn/gamma,conv5_b_1x1_reduce/bn/beta,conv5_b_1x1_reduce/bn/moving_mean,conv5_b_1x1_reduce/bn/moving_variance,conv5_b_3x3/bn/gamma,conv5_b_3x3/bn/beta,conv5_b_3x3/bn/moving_mean,conv5_b_3x3/bn/moving_variance,conv5_b_1x1_increase/bn/gamma,conv5_b_1x1_increase/bn/beta,conv5_b_1x1_increase/bn/moving_mean,conv5_b_1x1_increase/bn/moving_variance,conv5_c_1x1_reduce/bn/gamma,conv5_c_1x1_reduce/bn/beta,conv5_c_1x1_reduce/bn/moving_mean,conv5_c_1x1_reduce/bn/moving_variance,conv5_c_3x3/bn/gamma,conv5_c_3x3/bn/beta,conv5_c_3x3/bn/moving_mean,conv5_c_3x3/bn/moving_variance,conv5_c_1x1_increase/bn/gamma,conv5_c_1x1_increase/bn/beta,conv5_c_1x1_increase/bn/moving_mean,conv5_c_1x1_increase/bn/moving_variance
    at new ValueError (./AudioReco/node_modules/@tensorflow/tfjs-layers/dist/errors.js:68:28)
    at LayersModel.Container.loadWeights (./AudioReco/node_modules/@tensorflow/tfjs-layers/dist/engine/container.js:569:23)
    at ./AudioReco/node_modules/@tensorflow/tfjs-layers/dist/models.js:303:27
    at step (./AudioReco/node_modules/@tensorflow/tfjs-layers/dist/models.js:54:23)
    at Object.next (./AudioReco/node_modules/@tensorflow/tfjs-layers/dist/models.js:35:53)
    at fulfilled (./AudioReco/node_modules/@tensorflow/tfjs-layers/dist/models.js:26:58)

Я понимаю, что это как-то связано со всеми слоями нормализации партии, которые использует модель, но как правильно восстановить гаммы, бета-версии, перемещение Среднее и скользящее среднее для каждого из них?


Модель взята из работы Wei X ie из VoxCeleb . Первоначальные веса модели можно найти на его Google Drive , а преобразованные значения в формате .json можно найти по этой ссылке .

Выполнен код :

модель. js

const tf = require('@tensorflow/tfjs-node')

class VGGVox_Model {
    constructor() {
        this.model;
    }

    async init() {
        // Loading the custom layers
        require('./layers/VladPooling');
        require('./layers/Lambda');

        this.model = await tf.loadLayersModel('file://resources/model/model.json', false);
        this.model.summary();
    }
}

(async function main() {
  const myModel = new VGGVox_Model();
  myModel.init();
})();

VladPooling. js

const tf = require('../node_modules/@tensorflow/tfjs-node')

class VladPooling extends tf.layers.Layer {
    constructor(config) {
        super(config);
        this.kCenters = config.kCenters;
        this.gCenters = config.gCenters;
        this.mode = config.mode;
    }


    compute_output_shape(input_shape) {
        return (input_shape[0][0], this.kCenters * input_shape[0][input_shape[0].length - 1])
    }

    build(input_shape) {
        this.cluster = this.addWeight(
            'centers',
            [ this.kCenters + this.gCenters, input_shape[0][input_shape[0].length - 1] ],
            'float32',
            'orthogonal');
        this.built = true;
    }


    call(inputs, kwargs) {
        return tf.tidy(() => {
            console.log('call')
        });
    }


    getConfig() {
        const baseConfig = super.getConfig();
        const config = {
            kCenters: this.kCenters,
            gCenters: this.gCenters,
            mode: this.mode
        };
        Object.assign(config, baseConfig);
        return config;
    }


    static get className() {
        return 'VladPooling';
    }
}
tf.serialization.registerClass(VladPooling);
exports.vlad_pooling = VladPooling;

Лямбда. js

const tf = require('../node_modules/@tensorflow/tfjs-node')

class Lambda extends tf.layers.Layer {
    constructor(config) {
        super(config);
        if (config.name === undefined) {
            config.name = ((+new Date) * Math.random()).toString(36); //random name from timestamp in case name hasn't been set
        }
        this.name = config.name;
        this.lambdaFunction = config.function;
    }

    call(input) {
        return tf.tidy(() => {
            let result = null;
            eval(this.lambdaFunction);
            return result;
        });
    }

    computeOutputShape(inputShape) {
        return inputShape;
    }

    getConfig() {
        const config = super.getConfig();
        Object.assign(config, {
            lambdaFunction: this.lambdaFunction
        });
        return config;
    }

    static get className() {
        return 'Lambda';
    }
}
tf.serialization.registerClass(Lambda);

Что касается двух пользовательских слоев (Vlad Pooling и Lambda), я также добавил их в папку Google Drive. Код лямбда-слоя был взят здесь . Я еще не включил call () в Vlad Pooling, так как не мог проверить выходные данные (модель не загружается). В любом случае, они требуются, потому что загрузка модели не будет работать без них.

1 Ответ

0 голосов
/ 09 апреля 2020

Рассматривая метод call VladPoolingLayer in python и js, метод js не полностью реализует VLadPoolingLayer модели python. call - метод, при котором происходит фактическое вычисление слоя. Следовательно, он должен возвращать тензор, форма которого совпадает с формой, возвращаемой computeOutputShape (опечатка для VladPoolingLayer).

Написанный лямбда-слой был скопирован из сообщения здесь . Существует разница в способе написания лямбда-слоя по сравнению с обычным лямбда-слоем в python. Таким образом, этот лямбда-слой не может быть использован, как здесь для модели. Лямбда-слой VGG-Speaker-Recognition выполняет нормализацию l2. Таким образом, слой можно записать следующим образом:

class lambdaLayer extends tf.layers.Layer {
  constructor(config) {
    super(config)
  }

  call(input) {
    return tf.layers.layerNormalization({axis: 1}).apply(input);
  }

  static get className() {
    return 'lambdaLayer';
  }

tf.serialization.registerClass(lambdaLayer);
...