尝试检查点Keras模型时出现'TypeError:Not JSON Serilizable'

时间:2019-08-27 17:59:56

标签: python keras deep-learning

我已经实现了一个残差网络,该残差网络由卷积层和随后的几个LSTM层组成,用于快照序列的二进制分类。为了使用此混合网络,我在循环层之前的层上广泛使用了TimeDistributed层包装。另外,我的输入数据以非常长的快照序列的形式出现。我通过重塑数据将那些长序列手动切成更小,更易于管理的序列。但是,当我尝试使用Keras ModelCheckpoint回调函数检查模型时,会得到以下堆栈跟踪:

8/8 [==============================] - 6s 728ms/step - loss: 0.6802 - acc: 0.1250 - val_loss: 2.2920 - val_acc: 0.5000

Epoch 00001: val_acc improved from -inf to 0.50000, saving model to epoch_01.h5
Traceback (most recent call last):
  File "SO_post.py", line 174, in <module>
    callbacks=callbacks_list)
  File "/usr/local/lib/python3.5/dist-packages/Keras-2.2.4-py3.5.egg/keras/engine/training.py", line 1178, in fit
    validation_freq=validation_freq)
  File "/usr/local/lib/python3.5/dist-packages/Keras-2.2.4-py3.5.egg/keras/engine/training_arrays.py", line 224, in fit_loop
    callbacks.on_epoch_end(epoch, epoch_logs)
  File "/usr/local/lib/python3.5/dist-packages/Keras-2.2.4-py3.5.egg/keras/callbacks.py", line 152, in on_epoch_end
    callback.on_epoch_end(epoch, logs)
  File "/usr/local/lib/python3.5/dist-packages/Keras-2.2.4-py3.5.egg/keras/callbacks.py", line 719, in on_epoch_end
    self.model.save(filepath, overwrite=True)
  File "/usr/local/lib/python3.5/dist-packages/Keras-2.2.4-py3.5.egg/keras/engine/network.py", line 1139, in save
    save_model(self, filepath, overwrite, include_optimizer)
  File "/usr/local/lib/python3.5/dist-packages/Keras-2.2.4-py3.5.egg/keras/engine/saving.py", line 415, in save_wrapper
    save_function(obj, filepath, overwrite, *args, **kwargs)
  File "/usr/local/lib/python3.5/dist-packages/Keras-2.2.4-py3.5.egg/keras/engine/saving.py", line 507, in save_model
    _serialize_model(model, h5dict, include_optimizer)
  File "/usr/local/lib/python3.5/dist-packages/Keras-2.2.4-py3.5.egg/keras/engine/saving.py", line 101, in _serialize_model
    model_config = json.dumps(model_config, default=get_json_type)
  File "/usr/lib/python3.5/json/__init__.py", line 237, in dumps
    **kw).encode(obj)
  File "/usr/lib/python3.5/json/encoder.py", line 198, in encode
    chunks = self.iterencode(o, _one_shot=True)
  File "/usr/lib/python3.5/json/encoder.py", line 256, in iterencode
    return _iterencode(o, 0)
  File "/usr/local/lib/python3.5/dist-packages/Keras-2.2.4-py3.5.egg/keras/engine/saving.py", line 91, in get_json_type
    raise TypeError('Not JSON Serializable: %s' % (obj,))
TypeError: Not JSON Serializable: 4

当我将t = 4更改为t = 8时,我得到了相同的踪迹,但是8不是JSON可序列化的,而不是4。这对我来说没有意义。

与该错误有关的大多数SO帖子已通过修复新维度的数据类型而得到解决。我检查了我能想到的每个地方的数据类型,它们都显示'int'作为数据类型。

我已尝试尽可能减少这种情况,这就是我所得到的。我很确定在“使用数据”部分中重塑数据时会以某种方式引入错误。谁能为我阐明一下?

SO_post.py

from keras.backend import clear_session
from keras.backend.tensorflow_backend import set_session
from keras.callbacks import ModelCheckpoint
from keras.layers import add, Activation, AveragePooling1D, BatchNormalization, Conv1D, Dense, Flatten, Input, LSTM, MaxPooling1D, ReLU, TimeDistributed
from keras.models import Model
from keras.optimizers import Adam
from keras.regularizers import l2
import numpy as np
import tensorflow as tf

# Define some parameters to use in the functions
batchsize=32
num_epochs = 50
GPU_mem_fraction = 0.5
adam_lr = 5e-3
checkpoint_freq = 1
N = 32
snapshot_len = 128
channels = 2
classes = 2

# ==============================================================================
#  Convenience functions
# ==============================================================================
def create_model(input_sh):

  clear_session()
  num_stacks = 2
  num_res_blocks = 2
  num_rec = 2
  rec_size = 128
  model = recurrent_resnet(input_sh, num_stacks, num_res_blocks, num_rec, rec_size)

  # Use an Adam optimizer to backpropagate error.
  adam = Adam(lr=adam_lr)
  model.compile(loss='categorical_crossentropy', optimizer=adam, metrics=['accuracy'])
  return model

def resnet_layer(inputs, num_filters=16, activation='relu', batchnorm=True, conv_first=True):

  conv = Conv1D(num_filters, kernel_size=3, strides=1, padding='same', \
                kernel_initializer='he_normal',
                kernel_regularizer=l2(1e-4))

  x = inputs
  if conv_first:
      x = TimeDistributed(conv, input_shape=x.shape[1:])(x)
      if batchnorm:
          x = TimeDistributed(BatchNormalization())(x)
      if activation is not None:
          x = TimeDistributed(Activation(activation))(x)
  else:
      if batchnorm:
          x = TimeDistributed(BatchNormalization(), input_shape=x.shape[1:])(x)
      if activation is not None:
          x = TimeDistributed(Activation(activation))(x)
      x = TimeDistributed(conv)(x)
  return x

def residual_block(x, num_filters, downsample=False):

  strides = 1
  y = resnet_layer(inputs=x,
                   num_filters=num_filters)
  y = resnet_layer(inputs=y,
                   num_filters=num_filters,
                   activation=None)

  if downsample:
      x = resnet_layer(inputs=x,
                       num_filters=num_filters,
                       activation=None,
                       batchnorm=False)

  x = add([x, y])

  x = TimeDistributed(Activation('relu'))(x)
  return x

def recurrent_resnet(input_shape, num_stacks=3, num_res_blocks=7,
                     num_recurrent=2, recurrent_size=256):

  num_filters = 16

  inputs = Input(shape=input_shape)
  my_x = resnet_layer(inputs=inputs)

  # Instantiate the stack of residual units
  for stack in range(num_stacks):
      for res_block in range(num_res_blocks):
        my_x = residual_block(my_x, \
                                  num_filters, \
                                  ((stack > 0) and (res_block == 0)))
      num_filters *= 2

  my_x = TimeDistributed(AveragePooling1D(pool_size=8))(my_x)
  my_y = TimeDistributed(Flatten())(my_x)

  # Add recurrent layers to keep some memory through time.
  for i in range(num_recurrent):
    # The last recurrent layer should just return the last output rather
    # than the whole time sequence.
    if (i == (num_recurrent - 1)):
      my_y = LSTM(recurrent_size, return_sequences=False)(my_y)
    else:
      my_y = LSTM(recurrent_size, return_sequences=True)(my_y)

  # Classify the output of the LSTM layers.
  outputs = Dense(2, activation='softmax', kernel_initializer='he_normal')(my_y)

  # Instantiate model.
  model = Model(inputs=inputs, outputs=outputs)
  return model

# ==============================================================================
#  Work with data
# ==============================================================================

# This mimics what I'm given in the data set (I can't change this).
orig_X_train = np.random.randn(N, snapshot_len, channels)
orig_X_test = np.random.randn(N, snapshot_len, channels)
orig_y_train = np.random.randint(0, 2, size=(N, classes))
orig_y_test = np.random.randint(0, 2, size=(N, classes))

# ----->  This next little bit seems to be the issue! <-----
# Re-shape inputs to create sequences of snapshots.
# Shape before:  (N, snapshot_len, channels)
# Shape after:   (N/t, t, snapshot_len, channels), in this case try t = 4
t = int(4)
X_train = np.reshape(orig_X_train, (int(orig_X_train.shape[0] / t), \
                     t, orig_X_train.shape[1], orig_X_train.shape[2]))
X_test = np.reshape(orig_X_test, (int(orig_X_test.shape[0] / t), t, \
                    orig_X_test.shape[1], orig_X_test.shape[2]))

# Reshape labels to have one per sequence.
# Shape before: (N, classes)
# Shape after:  (N/t, classes)
y_train = np.zeros((int(orig_y_train.shape[0]/t), orig_y_train.shape[1]))
y_test = np.zeros((int(orig_y_test.shape[0]/t), orig_y_test.shape[1]))
new_ind = 0
for i in range(len(orig_y_train)):
  if (i % t == 0):
    y_train[new_ind] = orig_y_train[i]
    new_ind += 1

new_ind = 0
for i in range(len(orig_y_test)):
  if (i % t == 0):
    y_test[new_ind] = orig_y_test[i]
    new_ind += 1

# ==============================================================================
#  Train the model
# ==============================================================================

config = tf.ConfigProto()
config.gpu_options.per_process_gpu_memory_fraction = GPU_mem_fraction
set_session(tf.Session(config=config))

model = create_model(X_train.shape[1:])

checkpoint_cb = ModelCheckpoint('epoch_{epoch:02d}.h5', \
                                monitor='val_acc', \
                                verbose=1, \
                                save_best_only=True, \
                                save_weights_only=False, \
                                period=checkpoint_freq)
callbacks_list = [checkpoint_cb]

history = model.fit(X_train, y_train, \
                    epochs=num_epochs, \
                    batch_size=batchsize, \
                    verbose=1, \
                    validation_data=(X_test, y_test), \
                    callbacks=callbacks_list)

0 个答案:

没有答案