Nieznany regulator: L2 w tensorflowjs

Sep 25 2020

Wytrenowałem model w Pythonie przy użyciu modelu

reg = 0.000001
model = Sequential()
model.add(Dense(24, activation='tanh', name='input_dense', input_shape=input_shape))
model.add(GRU(24, activation='tanh', recurrent_activation='sigmoid', return_sequences=True, kernel_regularizer=regularizers.l2(reg), recurrent_regularizer=regularizers.l2(reg), reset_after=False))
model.add(Flatten())
model.add(Dense(2, activation='softmax'))

Ale kiedy przekonwertowałem ten model za pomocą „tensorflowjs_converter --input_format keras” i załadowałem do przeglądarki, pojawia się błąd

Nieobsłużone odrzucenie (błąd): Nieznany regulator: L2. Może to wynikać z jednej z następujących przyczyn:

  1. Regulator jest zdefiniowany w Pythonie, w takim przypadku należy go przeportować do TensorFlow.js lub kodu JavaScript.
  2. Niestandardowy regulator jest zdefiniowany w JavaScript, ale nie jest poprawnie zarejestrowany za pomocą tf.serialization.registerClass ().

Zawartość pliku model.json to

{
 "format": "layers-model",
 "generatedBy": "keras v2.4.0",
 "convertedBy": "TensorFlow.js Converter v2.3.0",
 "modelTopology": {
  "keras_version": "2.4.0",
  "backend": "tensorflow",
  "model_config": {
   "class_name": "Sequential",
   "config": {
    "name": "sequential",
    "layers": [
     {
      "class_name": "InputLayer",
      "config": {
       "batch_input_shape": [null, 22, 13],
       "dtype": "float32",
       "sparse": false,
       "ragged": false,
       "name": "input_dense_input"
      }
     },
     {
      "class_name": "Dense",
      "config": {
       "name": "input_dense",
       "trainable": true,
       "batch_input_shape": [null, 22, 13],
       "dtype": "float32",
       "units": 24,
       "activation": "tanh",
       "use_bias": true,
       "kernel_initializer": {
        "class_name": "GlorotUniform",
        "config": { "seed": null }
       },
       "bias_initializer": { "class_name": "Zeros", "config": {} },
       "kernel_regularizer": null,
       "bias_regularizer": null,
       "activity_regularizer": null,
       "kernel_constraint": null,
       "bias_constraint": null
      }
     },
     {
      "class_name": "GRU",
      "config": {
       "name": "gru",
       "trainable": true,
       "dtype": "float32",
       "return_sequences": true,
       "return_state": false,
       "go_backwards": false,
       "stateful": false,
       "unroll": false,
       "time_major": false,
       "units": 24,
       "activation": "tanh",
       "recurrent_activation": "sigmoid",
       "use_bias": true,
       "kernel_initializer": {
        "class_name": "GlorotUniform",
        "config": { "seed": null }
       },
       "recurrent_initializer": {
        "class_name": "Orthogonal",
        "config": { "gain": 1.0, "seed": null }
       },
       "bias_initializer": { "class_name": "Zeros", "config": {} },
       "kernel_regularizer": {
        "class_name": "L2",
        "config": { "l2": 9.999999974752427e-7 }
       },
       "recurrent_regularizer": {
        "class_name": "L2",
        "config": { "l2": 9.999999974752427e-7 }
       },
       "bias_regularizer": null,
       "activity_regularizer": null,
       "kernel_constraint": null,
       "recurrent_constraint": null,
       "bias_constraint": null,
       "dropout": 0.0,
       "recurrent_dropout": 0.0,
       "implementation": 2,
       "reset_after": false
      }
     },
     {
      "class_name": "Flatten",
      "config": {
       "name": "flatten",
       "trainable": true,
       "dtype": "float32",
       "data_format": "channels_last"
      }
     },
     {
      "class_name": "Dense",
      "config": {
       "name": "dense",
       "trainable": true,
       "dtype": "float32",
       "units": 2,
       "activation": "softmax",
       "use_bias": true,
       "kernel_initializer": {
        "class_name": "GlorotUniform",
        "config": { "seed": null }
       },
       "bias_initializer": { "class_name": "Zeros", "config": {} },
       "kernel_regularizer": null,
       "bias_regularizer": null,
       "activity_regularizer": null,
       "kernel_constraint": null,
       "bias_constraint": null
      }
     }
    ]
   }
  },
  "training_config": {
   "loss": "categorical_crossentropy",
   "metrics": ["accuracy"],
   "weighted_metrics": null,
   "loss_weights": null,
   "optimizer_config": {
    "class_name": "Nadam",
    "config": {
     "name": "Nadam",
     "learning_rate": 0.0020000000949949026,
     "decay": 0.004000000189989805,
     "beta_1": 0.8999999761581421,
     "beta_2": 0.9990000128746033,
     "epsilon": 1e-7
    }
   }
  }
 },
 "weightsManifest": [
  {
   "paths": ["group1-shard1of1.bin"],
   "weights": [
    { "name": "dense/kernel", "shape": [528, 2], "dtype": "float32" },
    { "name": "dense/bias", "shape": [2], "dtype": "float32" },
    { "name": "gru/gru_cell/kernel", "shape": [24, 72], "dtype": "float32" },
    {
     "name": "gru/gru_cell/recurrent_kernel",
     "shape": [24, 72],
     "dtype": "float32"
    },
    { "name": "gru/gru_cell/bias", "shape": [72], "dtype": "float32" },
    { "name": "input_dense/kernel", "shape": [13, 24], "dtype": "float32" },
    { "name": "input_dense/bias", "shape": [24], "dtype": "float32" }
   ]
  }
 ]
}

Odpowiedzi

2 edkeveked Sep 25 2020 at 21:03

opcja 1

Nie ma zajęć L1i L2; to tylko interfejsy (więcej tutaj )

Istnieje klasa, L1L2która pobierze konfigurację i zwróci właściwy regulator. Możesz ręcznie zastąpić wszystkie wystąpienia L2do L1L2.

Opcja 2

Zarejestruj klasę L2

class L2 {

    static className = 'L2';

    constructor(config) {
       return tf.regularizers.l1l2(config)
    }
}
tf.serialization.registerClass(L2);

// now load the model