Keras fit_generator с множественным тензорным вводом

#python #tensorflow #keras

#python #tensorflow #keras

Вопрос:

У меня есть модель Keras с 4 тензорными входными данными и одним выводом массива. Он работает должным образом, используя model.fit метод

 model.fit([inputUM, inputMU, inputUU, inputMM],outputY , validation_data=([inputTestUM, inputTestMU, inputTestUU, inputTestMM],outputTest), batch_size=None, epochs=3, steps_per_epoch=200,validation_steps=200, callbacks=[checkpointer])
  

Теперь я меняю model.fit на model.fit_generator как

 batchSize = 10
samples = int(outputY.shape[0]) #number of all samples
stepsPerEpoch = int(samples/batchSize)
model.fit_generator(dataGenerator(inputUM, inputMU, inputUU, inputMM, outputY, batchSize),
    steps_per_epoch=stepsPerEpoch,
    epochs=2,
    verbose=1,
    callbacks=[checkpointer],
    validation_data=dataGenerator(inputTestUM, inputTestMU, inputTestUU, inputTestMM, outputTest, batchSize),
    validation_steps=stepsPerEpoch))
  

В dataGenerator каждый тензор разделен следующим образом

 def dataGenerator(inputUM, inputMU, inputUU, inputMM, outputY, batchSize):       
    samples = int(outputY.shape[0]) #number of all samples
    batchNumber = int(samples/batchSize)  #number of batches
    counter=0

    while True:
        if counter > batchNumber: #restart counter at the end of each epoch
            counter = 0
        inUM = tf.slice(inputUM,[counter*batchSize,0,0],[batchSize,60,1])            
        inMU = tf.slice(inputMU,[counter*batchSize,0,0],[batchSize,60,1])            
        inUU = tf.slice(inputUU,[counter*batchSize,0,0],[batchSize,60,1])    
        inMM = tf.slice(inputMM,[counter*batchSize,0,0],[batchSize,60,1])            
        outY = outputY[counter*batchSize:(counter 1)*batchSize]

        counter  = 1
        yield ([inUM, inMU, inUU, inMM], outY)
  

Однако я получаю эту ошибку:

 File "C:ProgramDataAnaconda3libsite-packagesspyderutilssitesitecustomize.py", line 705, in runfile
execfile(filename, namespace)
File "C:ProgramDataAnaconda3libsite-packagesspyderutilssitesitecustomize.py", line 102, in execfile
exec(compile(f.read(), filename, 'exec'), namespace)
File "mycode.py", line 529, in <module>
main(data)
File "mycode.py", line 236, in main
initial_epoch=0)
File "C:ProgramDataAnaconda3libsite-packageskeraslegacyinterfaces.py", line 91, in wrapper
return func(*args, **kwargs)
File "C:ProgramDataAnaconda3libsite-packageskerasenginetraining.py", line 1418, in fit_generator
initial_epoch=initial_epoch)
File "C:ProgramDataAnaconda3libsite-packageskerasenginetraining_generator.py", line 223, in fit_generator
callbacks.on_batch_end(batch_index, batch_logs)
File "C:ProgramDataAnaconda3libsite-packageskerascallbacks.py", line 115, in on_batch_end
callback.on_batch_end(batch, logs)
File "C:ProgramDataAnaconda3libsite-packageskerascallbacks.py", line 238, in on_batch_end
self.totals[k] = v * batch_size
File "C:ProgramDataAnaconda3libsite-packagestensorflowpythonframeworktensor_shape.py", line 410, in __rmul__
return self * other
TypeError: unsupported operand type(s) for *: 'Dimension' and 'float'
  

Я знаю, что для этого нужна какая-то целочисленная переменная, однако она получает данные другого типа. Я не могу понять, какой тип параметра неверен. Я преобразовал все переменные 1, такие как stepsPerEpoch и samples , в целое число. Также кажется, что генератор работает должным образом, в режиме отладки он возвращает [<tf.Tensor 'Slice_48:0' shape=(100, 60, 1) dtype=float32>, <tf.Tensor 'Slice_49:0' shape=(100, 60, 1) dtype=float32>, <tf.Tensor 'Slice_50:0' shape=(100, 60, 1) dtype=float32>, <tf.Tensor 'Slice_51:0' shape=(100, 60, 1) dtype=float32>] как входные данные и array([4., 5., 4., ..., 4., 4., 5.]) как выходные.

Комментарии:

1. Попробуйте преобразовать counter*batchSize и batchSize в int во время нарезки. inUM = tf.slice(inputUM,[int(counter*batchSize),0,0],[int(batchSize),60,1]) Потому что, возможно, проблема в batch_size , как видно из журналов.

2. Спасибо @Anakin, ничего не происходит, я получаю ту же ошибку.

Ответ №1:

В определении модели вы могли бы использовать name параметр для присвоения имени каждому слою. Например:

 x1in = Input(shape = x1[0].shape, name='in1')
x2in = Input(shape = x2[0].shape, name='in2')
  

В вашем генераторе вы можете создать dict для соответствия данным:

 yield {'in1' : in1, 'in2' : in2}, out
  

Наконец, просто установите генератор как обычно:

 model.fit_generator(datagen, epochs=300, steps_per_epoch=int(data_size/batch_size))