J'ai de nombreux problèmes à essayer de commencer à former mon modèle (un DCGAN). Il m'envoie l'erreur: "L'objet 'Tuple' n'a pas d'attribut 'layer'". J'ai lu que cela pourrait être dû à la fois à la version tensorflow 1.14.0 et à la version keras 2.2 ou supérieure. J'ai essayé de résoudre ce problème en rétrogradant la version keras vers la 2.1.5, mais cela m'envoie le même problème. Aidez-moi! Merci
J'ai essayé de résoudre ce problème en rétrogradant la version keras vers la 2.1.5, mais cela m'envoie le même problème.
from google.colab import drive
drive.mount('/mntDrive')
import os,sys #os es para gestionar directorios (trabajar con archivos); sys es para trabajar con variables del sistema
# numpy
import numpy as np
# data processing, CSV file I/O (e.g. pd.read_csv)
import pandas as pd
from sklearn.model_selection import train_test_split
# Charts
import matplotlib.pyplot as plt
from matplotlib.pyplot import imread
#process
from tqdm import tqdm
# Image IO
from PIL import Image
import skimage.io
import skimage.transform
from skimage.transform import resize
# Deep learning
import tensorflow as tf
from tensorflow.keras import layers
from keras import optimizers
from keras.models import Sequential, Model
from keras.layers.advanced_activations import LeakyReLU
from keras.layers import Dense, Conv2D, Flatten, MaxPool2D, Dropout, Input
from keras.callbacks import ModelCheckpoint
from keras.preprocessing.image import ImageDataGenerator
from keras.optimizers import Adam
from keras import initializers
from __future__ import absolute_import, division, print_function, unicode_literals
# To make sure that we can reproduce the experiment and get the same results
np.random.seed(21)
# The dimension of our random noise vector.
random_dim = 100
from skimage.color import rgb2gray
import scipy.ndimage
import scipy.misc
import re
images = []
for root, dirnames, filenames in os.walk("/mntDrive/My Drive/Colab Notebooks/cubism"):
for filename in filenames:
if re.search("\.(jpg|jpeg|png)$", filename):
filepath = os.path.join(root, filename)
image = plt.imread(filepath, )
image = (image.astype(np.float32) - 127.5)/127.5
image_resized = resize(image, (112, 112))
images.append(image_resized)
images = np.array(images)
print('Original image shape: {}'.format(images.shape))
im_gray = rgb2gray(images)
print('New image shape: {}'.format(im_gray.shape))
images_resized = im_gray.reshape(320,12544)
def get_optimizer():
optimizer=tf.keras.optimizers.Adam(0.001)
return optimizer
def make_generator_model(optimizer):
generator = tf.keras.Sequential()
generator.add(layers.Dense(7*7*256, use_bias=False, input_shape=(random_dim,)))
generator.add(layers.BatchNormalization())
generator.add(layers.LeakyReLU())
generator.add(layers.Reshape((7, 7, 256)))
assert generator.output_shape == (None, 7, 7, 256) # Note: None is the batch size
generator.add(layers.Conv2DTranspose(128, (5, 5), strides=(2, 2), padding='same', use_bias=False))
assert generator.output_shape == (None, 14, 14, 128)
generator.add(layers.BatchNormalization())
generator.add(layers.LeakyReLU())
generator.add(layers.Conv2DTranspose(64, (5, 5), strides=(2, 2), padding='same', use_bias=False))
assert generator.output_shape == (None, 28, 28, 64)
generator.add(layers.BatchNormalization())
generator.add(layers.LeakyReLU())
generator.add(layers.Conv2DTranspose(32, (5, 5), strides=(2, 2), padding='same', use_bias=False))
assert generator.output_shape == (None, 56, 56, 32)
generator.add(layers.BatchNormalization())
generator.add(layers.LeakyReLU())
generator.add(layers.Conv2DTranspose(1, (5, 5), strides=(2, 2), padding='same', use_bias=False, activation='tanh'))
assert generator.output_shape == (None, 112, 112, 1)
generator.compile(loss='binary_crossentropy', optimizer=tf.keras.optimizers.Adam(0.001))
return generator
def make_discriminator_model(optimizer):
discriminator = tf.keras.Sequential()
discriminator.add(layers.Conv2D(64, (5, 5), strides=(2, 2), padding='same', input_shape=[112, 112, 1]))
discriminator.add(layers.LeakyReLU())
discriminator.add(layers.Dropout(0.3))
discriminator.add(layers.Conv2D(128, (5, 5), strides=(2, 2), padding='same'))
discriminator.add(layers.LeakyReLU())
discriminator.add(layers.Dropout(0.3))
discriminator.add(layers.Conv2D(256, (5, 5), strides=(2, 2), padding='same'))
discriminator.add(layers.LeakyReLU())
discriminator.add(layers.Dropout(0.3))
discriminator.add(layers.Flatten())
discriminator.add(layers.Dense(1, activation='sigmoid' ))
discriminator.compile(loss='binary_crossentropy', optimizer=tf.keras.optimizers.Adam(0.001))
return discriminator
def get_gan_network(discriminator, random_dim, generator, optimizer):
# We initially set trainable to False since we only want to train either the
# generator or discriminator at a time
discriminator.trainable = False
# gan input (noise) will be 100-dimensional vectors
gan_input = Input(shape=(random_dim,))
# the output of the generator (an image)
x = generator(gan_input)
# get the output of the discriminator (probability if the image is real or not)
gan_output = discriminator(x)
gan = Model(inputs=gan_input, outputs=gan_output)
gan.compile(loss='binary_crossentropy', optimizer=tf.keras.optimizers.Adam(0.001))
return gan
def plot_generated_images(Epoch, generator, examples=64, dim=(10, 10), figsize=(100, 100)):
noise = np.random.normal(0, 1, size=[examples, random_dim]) #mean, std deviation, size
generated_images = generator.predict(noise)
generated_images = generated_images.reshape(examples, 112, 112)
plt.figure(figsize=figsize)
for i in range(generated_images.shape[0]):
plt.subplot(dim[0], dim[1], i+1)
plt.imshow(generated_images[i], interpolation='nearest', cmap='gray_r')
plt.axis('off')
plt.tight_layout()
plt.savefig('dcgan_generated_Originals_2_Epoch_%d.png' % Epoch)
#you can create a function which will save your generated images every 20 epochs
# Create a wall of generated MNIST images
def train(epochs=15000, batch_size=80):
# Get the training and testing data
images_resized
# Split the training data into batches of size 80
batch_count = images_resized.shape[0] // batch_size
# Build our GAN network
optimizer=get_optimizer()
generator = make_generator_model(optimizer)
discriminator = make_discriminator_model(optimizer)
gan = get_gan_network(discriminator, random_dim, generator, optimizer)
for e in range(1, epochs+1):
print ('-'*15, 'Epoch %d' % e, '-'*15)
for _ in tqdm(range(batch_count)):
# Get a random set of input noise and images
noise = np.random.normal(0, 1, size=[batch_size, random_dim])
image_batch = images_resized[np.random.randint(0, images_resized.shape[0], size=batch_size)]
# Generate fake MNIST images
generated_images = generator.predict(noise)
X = np.concatenate([image_batch, generated_images]) #128x4096 --- 'a' x 4096
# Labels for generated and real data
y_dis = np.zeros(2*batch_size)
y_dis[:batch_size] = 0.9 # One-sided label smoothing. Se refiere a que la mitad de y_dis seran 0.9 (reales) y la otra mitad seran 0 (falsos)
# Train discriminator
discriminator.trainable = True
discriminator.train_on_batch(X, y_dis) #Se entrena el Discriminador con dos vectores: X(tiene un batch(128) imagenes reales y un batch de imagenes generadas); y_dis(tiene un batch de 128 0.9(serian las reales) y otro batch de 128 ceros(serian las generadas). De esta manera, el algoritmo generador, aunque las genere bien, va a seguir optimizandose el numero de epochs que haga falta(seguimos en la fase de entrenamiento), ya que sus imagenes son continuamente rechazadas, comparandose con las reales y sacando continuamente diferencias. )
#Entra X(imagenes reales, imagenes generadas)--->y_dis(0.9 , 0)
#train_on_batch(x,y)---> realiza una actualizacion del gradiente en un batch----> x=array de training data (si el modelo tiene varias entradas pueden ser varios); y= array de target data (si el modelo tiene varias salidas pueden ser varios)
# Train generator
noise = np.random.normal(0, 1, size=[batch_size, random_dim])
y_gen = np.ones(batch_size)
discriminator.trainable = False
gan.train_on_batch(noise, y_gen) #Entra noise(pixeles desordenados)---->y_gen(todo son 1)
if e == 1 or e % 50 == 0:
plot_generated_images(e, generator)
if __name__ == '__main__':
train(30000, 80)
Voici la sortie:
Drive already mounted at /mntDrive; to attempt to forcibly remount, call drive.mount("/mntDrive", force_remount=True).
Original image shape: (320, 112, 112, 3)
New image shape: (320, 112, 112)
WARNING:tensorflow:From /usr/local/lib/python3.6/dist-packages/tensorflow/python/ops/init_ops.py:1251: calling VarianceScaling.__init__ (from tensorflow.python.ops.init_ops) with dtype is deprecated and will be removed in a future version.
Instructions for updating:
Call initializer instance with the dtype argument instead of passing it to the constructor
WARNING:tensorflow:From /usr/local/lib/python3.6/dist-packages/tensorflow/python/ops/nn_impl.py:180: add_dispatch_support.<locals>.wrapper (from tensorflow.python.ops.array_ops) is deprecated and will be removed in a future version.
Instructions for updating:
Use tf.where in 2.0, which has the same broadcast rule as np.where
WARNING:tensorflow:From /usr/local/lib/python3.6/dist-packages/keras/backend/tensorflow_backend.py:68: The name tf.get_default_graph is deprecated. Please use tf.compat.v1.get_default_graph instead.
WARNING:tensorflow:From /usr/local/lib/python3.6/dist-packages/keras/backend/tensorflow_backend.py:507: The name tf.placeholder is deprecated. Please use tf.compat.v1.placeholder instead.
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-18-6e3c9ece87ff> in <module>()
196
197 if __name__ == '__main__':
--> 198 train(30000, 80)
11 frames
<ipython-input-18-6e3c9ece87ff> in train(epochs, batch_size)
161 generator = make_generator_model(optimizer)
162 discriminator = make_discriminator_model(optimizer)
--> 163 gan = get_gan_network(discriminator, random_dim, generator, optimizer)
164
165 for e in range(1, epochs+1):
<ipython-input-18-6e3c9ece87ff> in get_gan_network(discriminator, random_dim, generator, optimizer)
128 gan_input = Input(shape=(random_dim,))
129 # the output of the generator (an image)
--> 130 x = generator(gan_input)
131 # get the output of the discriminator (probability if the image is real or not)
132 gan_output = discriminator(x)
/usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/engine/base_layer.py in __call__(self, inputs, *args, **kwargs)
632 outputs = base_layer_utils.mark_as_return(outputs, acd)
633 else:
--> 634 outputs = call_fn(inputs, *args, **kwargs)
635
636 except TypeError as e:
/usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/engine/sequential.py in call(self, inputs, training, mask)
245 if not self.built:
246 self._init_graph_network(self.inputs, self.outputs, name=self.name)
--> 247 return super(Sequential, self).call(inputs, training=training, mask=mask)
248
249 outputs = inputs # handle the corner case where self.layers is empty
/usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/engine/network.py in call(self, inputs, training, mask)
749 ' implement a `call` method.')
750
--> 751 return self._run_internal_graph(inputs, training=training, mask=mask)
752
753 def compute_output_shape(self, input_shape):
/usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/engine/network.py in _run_internal_graph(self, inputs, training, mask)
891
892 # Compute outputs.
--> 893 output_tensors = layer(computed_tensors, **kwargs)
894
895 # Update tensor_dict.
/usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/engine/base_layer.py in __call__(self, inputs, *args, **kwargs)
661 kwargs.pop('training')
662 inputs, outputs = self._set_connectivity_metadata_(
--> 663 inputs, outputs, args, kwargs)
664 self._handle_activity_regularization(inputs, outputs)
665 self._set_mask_metadata(inputs, outputs, previous_mask)
/usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/engine/base_layer.py in _set_connectivity_metadata_(self, inputs, outputs, args, kwargs)
1706 kwargs.pop('mask', None) # `mask` should not be serialized.
1707 self._add_inbound_node(
-> 1708 input_tensors=inputs, output_tensors=outputs, arguments=kwargs)
1709 return inputs, outputs
1710
/usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/engine/base_layer.py in _add_inbound_node(self, input_tensors, output_tensors, arguments)
1793 """
1794 inbound_layers = nest.map_structure(lambda t: t._keras_history.layer,
-> 1795 input_tensors)
1796 node_indices = nest.map_structure(lambda t: t._keras_history.node_index,
1797 input_tensors)
/usr/local/lib/python3.6/dist-packages/tensorflow/python/util/nest.py in map_structure(func, *structure, **kwargs)
513
514 return pack_sequence_as(
--> 515 structure[0], [func(*x) for x in entries],
516 expand_composites=expand_composites)
517
/usr/local/lib/python3.6/dist-packages/tensorflow/python/util/nest.py in <listcomp>(.0)
513
514 return pack_sequence_as(
--> 515 structure[0], [func(*x) for x in entries],
516 expand_composites=expand_composites)
517
/usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/engine/base_layer.py in <lambda>(t)
1792 `call` method of the layer at the call that created the node.
1793 """
-> 1794 inbound_layers = nest.map_structure(lambda t: t._keras_history.layer,
1795 input_tensors)
1796 node_indices = nest.map_structure(lambda t: t._keras_history.node_index,
AttributeError: 'Tuple' object has no attribute 'layer'
AttributeError: 'Tuple' object has no attribute 'layer'
Ran dans ce problème lorsque vous utilisez GPU/TPU sur Colab et essayez d'utiliser Tensorflow v1.14 en l'installant à l'aide de pip. Les docs déconseillent d'installer tensorflow à l'aide de pip sur GPU/TPU, ils recommandent plutôt d'utiliser %tensorflow_version 1.x
. Le définir comme ceci, a résolu mon problème.
Documents: https://colab.research.google.com/notebooks/tensorflow_version.ipynb