Как использовать генератор наборов данных, который выводит dict для оценки или прогнозирования? - PullRequest
1 голос
/ 18 марта 2020

У меня большой массив данных, состоящий из изображений и связанных скалярных данных. Изображения довольно большие, поэтому я не могу разместить весь свой тренировочный набор в памяти на моей машине.

Из-за этого я переместил свой код на использование наборов данных и генераторов наборов данных.

Потому что моя модель использует как данные изображения, так и скалярные данные, и модель сначала обрабатывает их отдельно перед объединением, мне пришлось написать функцию генератора, которая выдает словарь.

for i in range(len(name)):
  image =tf.cast(images[i],tf.float32)
  scalar=tf.cast(scalars[i],tf.float32)
  value = {'img':image,'data':scalar}
  localstate=tf.cast(state[i],tf.bool)
  #print("yielding with state: ",localstate," with shape ",tf.shape(localstate),flush=True)
  if (train):
    yield value,localstate
  else:
    yield value

позже в моем коде, когда придет время чтобы соответствовать моей модели, вот как это выглядит.

train_dataset = tf.data.Dataset.from_generator(functools.partial(pickleGen, phase=names[phase],band=band,chunks=trainchunks)
  ,({'img':tf.float32,'data':tf.float32}, tf.bool)
  ,output_shapes=({'img':(1523,312,8,),'data':(439,)},[])
  ).batch(batchsize)
inputImg = tf.keras.Input(shape=(1523,312,8),name='img')
inputVec = tf.keras.Input(shape=(439),name='data')
x = tf.keras.layers.Conv2D(32,(3,3), activation='relu')(inputImg)
x = tf.keras.layers.MaxPooling2D((2,2))(x)
x = tf.keras.layers.Conv2D(64,(3,3), activation='relu')(x)
x = tf.keras.layers.MaxPooling2D((2,2))(x)
x = tf.keras.layers.Conv2D(256,(3,3), activation='relu')(x)
x = tf.keras.layers.MaxPooling2D((2,2))(x)
x = tf.keras.layers.Flatten()(x)
x = tf.keras.layers.Dense(512, activation=tf.nn.relu)(x)
x = tf.keras.layers.Dropout(rate=.2)(x)
x = tf.keras.layers.Dense(128, activation=tf.nn.relu)(x)
x = tf.keras.Model(inputs=inputImg,outputs=x)
y = tf.keras.layers.Flatten()(inputVec)
y = tf.keras.layers.Dense(512, activation=tf.nn.relu)(y)
y = tf.keras.layers.Dropout(rate=.2)(y)
y = tf.keras.layers.Dense(128, activation=tf.nn.relu)(y)
y = tf.keras.Model(inputs=inputVec,outputs=y)
combo = tf.keras.layers.concatenate([x.output,y.output],axis=1)
z = tf.keras.layers.Dense(256, activation=tf.nn.relu)(combo)
z = tf.keras.layers.Dropout(rate=.2)(z)
z = tf.keras.layers.Dense(64, activation=tf.nn.relu)(z)
z = tf.keras.layers.Dense(2, activation=tf.nn.softmax)(z)
model = tf.keras.Model(inputs=[x.input,y.input],outputs=z)
model.compile(optimizer = tf.optimizers.Adam(),
          loss = 'sparse_categorical_crossentropy',
          metrics=['accuracy'])

model.fit(train_dataset, epochs=epochs)

Все это прекрасно работает, пока не придет время что-то сделать с моей обученной моделью.

test_dataset = tf.data.Dataset.from_generator(functools.partial(pickleGen, phase=names[phase],band=band,chunks=testchunks),
  ({'img':tf.float32,'data':tf.float32},tf.bool),
  output_shapes=({'img':(1523,312,8,),'data':(439,)})
  ).batch(batchsize)
results = model.evaluate(test_dataset)

Я получаю та же ошибка при использовании предикта или оценки.

  File "./trial8_apply.py", line 127, in <module>
    output_shapes=({'img':(1523,312,8,),'data':(439,)})
  File "/stage/neocam/fops/sw/vsn1.0.0/ext/anaconda3/lib/python3.7/site-packages/tensorflow_core/python/data/ops/dataset_ops.py", line 540, in from_generator
    output_types, tensor_shape.as_shape, output_shapes)
  File "/stage/neocam/fops/sw/vsn1.0.0/ext/anaconda3/lib/python3.7/site-packages/tensorflow_core/python/data/util/nest.py", line 464, in map_structure_up_to
    assert_shallow_structure(shallow_tree, input_tree)
  File "/stage/neocam/fops/sw/vsn1.0.0/ext/anaconda3/lib/python3.7/site-packages/tensorflow_core/python/data/util/nest.py", line 305, in assert_shallow_structure
    % (type(input_tree), type(shallow_tree)))
TypeError: The two structures don't have the same sequence type. Input structure has type <class 'dict'>, while shallow structure has type <class 'tuple'>.

И так как я не уверен, правильно ли я строю свой тестовый набор данных, я попробовал два разных способа сделать это, и если я это сделаю:

test_dataset = tf.data.Dataset.from_generator(functools.partial(pickleGen, phase=names[phase],band=band,chunks=testchunks,train=False),
  ({'img':tf.float32,'data':tf.float32}),
  output_shapes=({'img':(1523,312,8,),'data':(439,)})
  ).batch(batchsize)

тогда я получаю другую ошибку от оценки или предсказания:

    results = model.evaluate(test_dataset)
  File "/stage/neocam/fops/sw/vsn1.0.0/ext/anaconda3/lib/python3.7/site-packages/tensorflow_core/python/keras/engine/training.py", line 833, in evaluate
    use_multiprocessing=use_multiprocessing)
  File "/stage/neocam/fops/sw/vsn1.0.0/ext/anaconda3/lib/python3.7/site-packages/tensorflow_core/python/keras/engine/training_v2.py", line 456, in evaluate
    sample_weight=sample_weight, steps=steps, callbacks=callbacks, **kwargs)
  File "/stage/neocam/fops/sw/vsn1.0.0/ext/anaconda3/lib/python3.7/site-packages/tensorflow_core/python/keras/engine/training_v2.py", line 444, in _model_iteration
    total_epochs=1)
  File "/stage/neocam/fops/sw/vsn1.0.0/ext/anaconda3/lib/python3.7/site-packages/tensorflow_core/python/keras/engine/training_v2.py", line 123, in run_one_epoch
    batch_outs = execution_function(iterator)
  File "/stage/neocam/fops/sw/vsn1.0.0/ext/anaconda3/lib/python3.7/site-packages/tensorflow_core/python/keras/engine/training_v2_utils.py", line 86, in execution_function
    distributed_function(input_fn))
  File "/stage/neocam/fops/sw/vsn1.0.0/ext/anaconda3/lib/python3.7/site-packages/tensorflow_core/python/eager/def_function.py", line 457, in __call__
    result = self._call(*args, **kwds)
  File "/stage/neocam/fops/sw/vsn1.0.0/ext/anaconda3/lib/python3.7/site-packages/tensorflow_core/python/eager/def_function.py", line 503, in _call
    self._initialize(args, kwds, add_initializers_to=initializer_map)
  File "/stage/neocam/fops/sw/vsn1.0.0/ext/anaconda3/lib/python3.7/site-packages/tensorflow_core/python/eager/def_function.py", line 408, in _initialize
    *args, **kwds))
  File "/stage/neocam/fops/sw/vsn1.0.0/ext/anaconda3/lib/python3.7/site-packages/tensorflow_core/python/eager/function.py", line 1848, in _get_concrete_function_internal_garbage_collected
    graph_function, _, _ = self._maybe_define_function(args, kwargs)
  File "/stage/neocam/fops/sw/vsn1.0.0/ext/anaconda3/lib/python3.7/site-packages/tensorflow_core/python/eager/function.py", line 2150, in _maybe_define_function
    graph_function = self._create_graph_function(args, kwargs)
  File "/stage/neocam/fops/sw/vsn1.0.0/ext/anaconda3/lib/python3.7/site-packages/tensorflow_core/python/eager/function.py", line 2041, in _create_graph_function
    capture_by_value=self._capture_by_value),
  File "/stage/neocam/fops/sw/vsn1.0.0/ext/anaconda3/lib/python3.7/site-packages/tensorflow_core/python/framework/func_graph.py", line 915, in func_graph_from_py_func
    func_outputs = python_func(*func_args, **func_kwargs)
  File "/stage/neocam/fops/sw/vsn1.0.0/ext/anaconda3/lib/python3.7/site-packages/tensorflow_core/python/eager/def_function.py", line 358, in wrapped_fn
    return weak_wrapped_fn().__wrapped__(*args, **kwds)
  File "/stage/neocam/fops/sw/vsn1.0.0/ext/anaconda3/lib/python3.7/site-packages/tensorflow_core/python/keras/engine/training_v2_utils.py", line 66, in distributed_function
    model, input_iterator, mode)
  File "/stage/neocam/fops/sw/vsn1.0.0/ext/anaconda3/lib/python3.7/site-packages/tensorflow_core/python/keras/engine/training_v2_utils.py", line 118, in _prepare_feed_values
    inputs = [inputs[key] for key in model._feed_input_names]
  File "/stage/neocam/fops/sw/vsn1.0.0/ext/anaconda3/lib/python3.7/site-packages/tensorflow_core/python/keras/engine/training_v2_utils.py", line 118, in <listcomp>
    inputs = [inputs[key] for key in model._feed_input_names]
KeyError: 'input_1'

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

Или кто-то может объяснить, как заставить этот набор работать с набором данных на основе кортежа?

Редактировать: Вот пример того, как выглядят мои данные обучения.

yielding with state: tf.Tensor(False, shape=(), dtype=bool)  and value:  {'img': <tf.Tensor: id=1768, shape=(1523, 312, 8), dtype=float32, numpy=
array([[[255., 255., 255., ..., 255., 255., 255.],
        [255., 255., 255., ..., 255., 255., 255.],
        [255., 255., 255., ..., 255., 255., 255.],
        ...,
        [255., 255., 255., ..., 255., 255., 255.],
        [255., 255., 255., ..., 255., 255., 255.],
        [255., 255., 255., ..., 255., 255., 255.]],

<snip>

       [[255., 255., 255., ..., 128., 128., 255.],
        [255., 255., 255., ..., 181., 181., 255.],
        [255., 255., 255., ..., 181., 181., 255.],
        ...,
        [  0.,   0.,   0., ..., 255., 255., 255.],
        [  0.,   0.,   0., ..., 255., 255., 255.],
        [  0.,   0.,   0., ..., 255., 255., 255.]]], dtype=float32)>, 'data': <tf.Tensor: id=1770, shape=(439,), dtype=float32, numpy=
array([ 6.8934107e-01,  2.1273675e+00,  3.7560204e-01,  1.7010291e+00,
        1.3698795e-02,  2.5334918e-01,  1.1520619e-01,  3.4945667e-02,
        3.4967816e+02,  2.7520111e+01,  0.0000000e+00, -4.2899999e-01,
       -2.0450001e+00,  3.0720000e+00,  1.1680000e+00, -7.1700001e-01,
       -1.7660000e+00,  2.8480000e+00,  1.2050000e+00, -2.3829999e+00,
       -2.4419999e+00,  2.3120000e+00,  1.3260000e+00, -3.0270000e+00
<snip>
        4.9300000e+02,  4.6000000e+02,  4.0500000e+02,  4.0700000e+02,
        1.3200000e+02,  1.1500000e+02,  1.4900000e+02,  4.9000000e+01,
        6.3000000e+01,  9.6000000e+01,  5.2000000e+01,  2.1000000e+01,
        3.5000000e+01,  0.0000000e+00,  0.0000000e+00,  0.0000000e+00,
        0.0000000e+00,  2.0000000e+01,  5.0000000e+00], dtype=float32)>}
...