keras自定义层加载数据

keras custom layer to load data

我正在按照 this 教程使用自定义图层进行预处理。

def pre_process(file_path):
    # loading file from disk and transforming into [90,13,1] 

class PreProcessBlock(layers.Layer):
    def __init__(self):
        super(PreProcessBlock,self).__init__()
    
    def call(self, inputs):
        return pre_process(inputs.numpy())
    
    def compute_output_shape(self, input_shape):
        return input_shape
preprocess = tf.keras.Sequential([
            PreProcessBlock()
])
model = keras.Sequential(
     [
      preprocess,
      
      layers.Dense(256, activation = "relu"),
      layers.Dropout(.5), 
      layers.Dense(len(LABELS))]

我将我的数据集创建为

files = ['file1,'file2`]
labels = [0,1]
def get_data_set(files, labels, is_training=False):
    dataset = tf.data.Dataset.from_tensor_slices((files, labels))

    if is_training:
        dataset = dataset.shuffle(SHUFFLE_BUFFER_SIZE, reshuffle_each_iteration = True)
    dataset = dataset.batch(BATCH_SIZE)
    dataset = dataset.prefetch(AUTOTUNE)
    return dataset
train_dataset = get_data_set(files, labels, is_training=True)
val_dataset = get_data_set(files, labels)

模型拟合失败并出现错误

model.fit(train_dataset, epochs=1, verbose=1,validation_data=val_dataset)

错误

AttributeError: in user code:

    /opt/conda/lib/python3.7/site-packages/tensorflow/python/keras/engine/training.py:806 train_function  *
        return step_function(self, iterator)
    <ipython-input-158-3f6d9dd39f2f>:6 call  *
        return pre_process(inputs.numpy())

    AttributeError: 'Tensor' object has no attribute 'numpy'

我的问题

这是实现模型管道的有效方式吗?

层的结构以及将所有预处理层组织到一个顺序层中非常棒。您不应该分层加载任何学习示例(它不是模型的一部分,并且会降低可移植性)。

两个问题:

您没有 numpy() 方法,因为 。我建议坚持使用静态图,不要尝试将 keras 图中的任何内容转换为 numpy,除非绝对必要——性能问题。大多数张量运算都可以使用 tf.

完成

您的自定义预处理层应继承自 tensorflow.keras.layers.experimental.preprocessing.PreprocessingLayer(来自 tf.keras.layers.experimental.preprocessing 的所有层直接或通过 CombinerPreprocessingLayer 从同一包继承)。 PreprocessingLayer class 的源代码中没有太多内容,但所有内容都很重要:

  1. PreprocessingLayeradapt 方法提供接口:
    adapt(self, data, reset_state=True)。请参阅“纯”keras docs 为什么以及何时需要它。

  2. PreprocessingLayer class 有标志 _must_restore_from_config = True 我们从 Layer 文档中读到:

When loading from a SavedModel, Layers typically can be revived into a generic Layer wrapper. Sometimes, however, layers may implement methods that go beyond this wrapper, as in the case of PreprocessingLayers' adapt method. When this is the case, layer implementers can override must_restore_from_config to return True; layers with this property must be restored into their actual objects (and will fail if the object is not available to the restoration code).

让我们以Resizing层代码为例(为了便于阅读,省略了注释):

class Resizing(PreprocessingLayer):
  def __init__(self,
               height,
               width,
               interpolation='bilinear',
               name=None,
               **kwargs):
    self.target_height = height
    self.target_width = width
    self.interpolation = interpolation
    self._interpolation_method = get_interpolation(interpolation)
    self.input_spec = InputSpec(ndim=4)
    super(Resizing, self).__init__(name=name, **kwargs)
    base_preprocessing_layer._kpl_gauge.get_cell('V2').set('Resizing')

  def call(self, inputs):
    outputs = image_ops.resize_images_v2(
        images=inputs,
        size=[self.target_height, self.target_width],
        method=self._interpolation_method)
    return outputs

  def compute_output_shape(self, input_shape):
    input_shape = tensor_shape.TensorShape(input_shape).as_list()
    return tensor_shape.TensorShape(
        [input_shape[0], self.target_height, self.target_width, input_shape[3]])

  def get_config(self):
    config = {
        'height': self.target_height,
        'width': self.target_width,
        'interpolation': self.interpolation,
    }
    base_config = super(Resizing, self).get_config()
    return dict(list(base_config.items()) + list(config.items()))

这是一个非常通用的图层。它可以将图像调整到一定的宽度和高度。然而,预处理层的要点是将整个端到端管道保存在一个模型中。因此,在 你的 管道中,你将具有特定的宽度和高度,并且你不想在进行推理时使用适当的参数实例化层而烦恼 - 它应该与训练中的相同(适用任何预处理方法,真的)。所以在 get_config() 方法中,除了基本的配置外,高度和宽度都被保存了,以后在重新建模时可以很容易地读取。请注意,该层不会覆盖 adapt 方法,因为它对数据是不变的。