2017-07-11 3 views
2

J'ai implémenté un auto-codeur convolutif avec Keras, en utilisant le backend Theano. Je change d'approche pour essayer de traiter des images de tailles différentes. Tant que j'utilise la fonction stack de numpy pour construire l'ensemble de données (images de taille égale), je suis en or. Cependant, pour des images de tailles différentes, nous ne pouvons pas utiliser stack, et fit attend un tableau numpy. J'ai donc changé à fit_generator pour éviter les contrôles de taille. Le problème est que la dernière couche attend 16 comme la dernière dimension de l'entrée, et je ne peux pas comprendre pourquoi elle obtient les dimensions de l'image originale. Regardez le code ci-dessous et la sortie d'erreur.2D Réseaux de neurones convolutifs avec des images de taille variable


import numpy as np 
import keras 
from keras.models import Sequential, Model 
from keras.layers import Input, Conv2D, MaxPooling2D, UpSampling2D 

AE_EPOCHS = 10 
VERB = 1 
batchsz = 16 
outfun = 'sigmoid' 

data = [] 
dimensions = [(10, 15), (12, 15), (7,15), (20,15), (25,15)] 

for d in dimensions: 
    dd = np.random.rand(*d) 
    dd = dd.reshape((1,)+dd.shape) 
    data.append(dd) 

input_img = Input(shape=(1, None, 15)) 
filtersz = 3 
pad_it = 'same' 
size1 = 16 
size2 = 8 
x = Conv2D(size1, (filtersz, filtersz), activation='relu', padding=pad_it)(input_img) 
x = MaxPooling2D((2, 2), padding=pad_it)(x) 
x = Conv2D(size2, (filtersz, filtersz), activation='relu', padding=pad_it)(x) 
x = MaxPooling2D((2, 2), padding=pad_it)(x) 
x = Conv2D(size2, (filtersz, filtersz), activation='relu', padding=pad_it)(x) 
encoded = MaxPooling2D((2, 2), padding=pad_it)(x) 

x = Conv2D(size2, (filtersz, filtersz), activation='relu', padding=pad_it)(encoded) 
x = UpSampling2D((2, 2), data_format="channels_first")(x) 
x = Conv2D(size2, (filtersz, filtersz), activation='relu', padding=pad_it)(x) 
x = UpSampling2D((2, 2), data_format="channels_first")(x) 
x = Conv2D(size1, (filtersz, filtersz), activation='relu', padding=pad_it)(x) 
x = UpSampling2D((2, 2), data_format="channels_first")(x) 
decoded = Conv2D(1, (filtersz, filtersz), activation=outfun, padding=pad_it)(x) 

autoencoder = Model(input_img, decoded) 
autoencoder.compile(optimizer='adadelta', loss= 'binary_crossentropy') 

x_train = data[1:] 
x_test= data[0].reshape((1,)+ data[0].shape) 

def mygen(xx, *args, **kwargs): 
    for i in xx: 
     yield (i,i) 

thegen = mygen(x_train) 
#If I use this generator somehow None is returned so it is not used 
thegenval = mygen(np.array([x_test])) 

hist = autoencoder.fit_generator(thegen, 
       epochs=AE_EPOCHS, 
       steps_per_epoch=4, 
       verbose=VERB, 
       validation_data=(x_test, x_test), 
       validation_steps=1 
       ) 

Traceback (most recent call last):

File "stacko.py", line 107, in validation_steps=1

File "/usr/local/lib/python3.5/dist-packages/keras/legacy/interfaces.py", line 88, in wrapper return func(*args, **kwargs)

File "/usr/local/lib/python3.5/dist-packages/keras/engine/training.py", line 1847, in fit_generator val_x, val_y, val_sample_weight)

File "/usr/local/lib/python3.5/dist-packages/keras/engine/training.py", line 1315, in _standardize_user_data exception_prefix='target')

File "/usr/local/lib/python3.5/dist-packages/keras/engine/training.py", line 139, in _standardize_input_data str(array.shape))

ValueError: Error when checking target: expected conv2d_7 to have shape (None, 1, None, 16) but got array with shape (1, 1, 10, 15)

Répondre

0

Il y a deux problèmes avec le code ci-dessus: tout d'abord, la taille de l'axe des images doit être un multiple du plus petit nombre de filtres par couche (dans ce cas, 8); deuxièmement, les générateurs pour fit_generator doivent renvoyer des lots (tableaux 4D numpy).

Le générateur est implémenté avec itertools.cycle et remodèle les figures en lots d'un échantillon (si vous travaillez avec plusieurs images avec des tailles communes, vous pouvez avoir des lots de taille variable pour chaque groupe de dimensions). L'exemple de travail est ci-dessous.


import numpy as np 
from itertools import cycle 

import keras 
from keras.models import Sequential, Model 
from keras.layers import Input, Dense, Conv2D, MaxPooling2D, UpSampling2D 

AE_EPOCHS = 10 
VERB = 1 
outfun = 'sigmoid' 

data = [] 
dimensions = [(16, 32), (24, 32), (8,32), (32,32)] 
for d in dimensions: 
    dd = np.random.rand(*d) 
    dd = dd.reshape((1,)+dd.shape) 
    data.append(dd) 

input_img = Input(shape=(1, None, 32)) 
filtersz = 3 
pad_it = 'same' 
size1 = 16 
size2 = 8 
x = Conv2D(size1, (filtersz, filtersz), activation='relu', padding=pad_it)(input_img) 
x = MaxPooling2D((2, 2), padding=pad_it)(x) 
x = Conv2D(size2, (filtersz, filtersz), activation='relu', padding=pad_it)(x) 
x = MaxPooling2D((2, 2), padding=pad_it)(x) 
x = Conv2D(size2, (filtersz, filtersz), activation='relu', padding=pad_it)(x) 
encoded = MaxPooling2D((2, 2), padding=pad_it)(x) 

x = Conv2D(size2, (filtersz, filtersz), activation='relu', padding=pad_it)(encoded) 
x = UpSampling2D((2, 2), data_format="channels_first")(x) 
x = Conv2D(size2, (filtersz, filtersz), activation='relu', padding=pad_it)(x) 
x = UpSampling2D((2, 2), data_format="channels_first")(x) 
x = Conv2D(size1, (filtersz, filtersz), activation='relu', padding=pad_it)(x) 
x = UpSampling2D((2, 2), data_format="channels_first")(x) 
decoded = Conv2D(1, (filtersz, filtersz), activation=outfun, padding=pad_it)(x) 

autoencoder = Model(input_img, decoded) 
autoencoder.compile(optimizer='adadelta', loss= 'binary_crossentropy') 


x_train = data[1:] 
x_test= [data[0]] 

def mygen(xx, *args, **kwargs): 
    for i in cycle(xx): 
     ii = i.reshape((1,)+i.shape) 
     yield ii,ii 

thegen = mygen(x_train) 
thegenval = mygen(x_test) 

hist = autoencoder.fit_generator(
       thegen, 
       epochs=AE_EPOCHS, 
       steps_per_epoch=3, 
       verbose=VERB, 
       validation_data=thegenval, 
       validation_steps=1 
       )