I've just started to learn Tensorflow (2.1.0), Keras (2.3.1) and Python 3.7.7.
By the way, I'm running all my code on an Anaconda Environment on Windows 7 64bit. I have also tried on an Anaconda Environment on Linux and I get the same error.
I'm following this Tensorflow's tutorial: "Custom training: walkthrough".
Everything is ok, but when I typed this piece of code:
def grad(model, inputs, targets):
with tf.GradientTape() as tape:
loss_value = loss(model, inputs, targets, training=True)
return loss_value, tape.gradient(loss_value, model.trainable_variables)
I get the error:
Instance of 'Model' has no 'trainable_variables' member
This is my model, with all of its imports:
import keras
from keras.models import Input, Model
from keras.layers import Dense, Conv2D, Conv2DTranspose, UpSampling2D, MaxPooling2D, Flatten, ZeroPadding2D
from keras.preprocessing.image import ImageDataGenerator
from keras.optimizers import Adam
import numpy as np
import tensorflow as tf
def vgg16_encoder_decoder(input_size = (200,200,1)):
#################################
# Encoder
#################################
inputs = Input(input_size, name = 'input')
conv1 = Conv2D(64, (3, 3), activation = 'relu', padding = 'same', name ='conv1_1')(inputs)
conv1 = Conv2D(64, (3, 3), activation = 'relu', padding = 'same', name ='conv1_2')(conv1)
pool1 = MaxPooling2D(pool_size = (2,2), strides = (2,2), name = 'pool_1')(conv1)
conv2 = Conv2D(128, (3, 3), activation = 'relu', padding = 'same', name ='conv2_1')(pool1)
conv2 = Conv2D(128, (3, 3), activation = 'relu', padding = 'same', name ='conv2_2')(conv2)
pool2 = MaxPooling2D(pool_size = (2,2), strides = (2,2), name = 'pool_2')(conv2)
conv3 = Conv2D(256, (3, 3), activation = 'relu', padding = 'same', name ='conv3_1')(pool2)
conv3 = Conv2D(256, (3, 3), activation = 'relu', padding = 'same', name ='conv3_2')(conv3)
conv3 = Conv2D(256, (3, 3), activation = 'relu', padding = 'same', name ='conv3_3')(conv3)
pool3 = MaxPooling2D(pool_size = (2,2), strides = (2,2), name = 'pool_3')(conv3)
conv4 = Conv2D(512, (3, 3), activation = 'relu', padding = 'same', name ='conv4_1')(pool3)
conv4 = Conv2D(512, (3, 3), activation = 'relu', padding = 'same', name ='conv4_2')(conv4)
conv4 = Conv2D(512, (3, 3), activation = 'relu', padding = 'same', name ='conv4_3')(conv4)
pool4 = MaxPooling2D(pool_size = (2,2), strides = (2,2), name = 'pool_4')(conv4)
conv5 = Conv2D(512, (3, 3), activation = 'relu', padding = 'same', name ='conv5_1')(pool4)
conv5 = Conv2D(512, (3, 3), activation = 'relu', padding = 'same', name ='conv5_2')(conv5)
conv5 = Conv2D(512, (3, 3), activation = 'relu', padding = 'same', name ='conv5_3')(conv5)
pool5 = MaxPooling2D(pool_size = (2,2), strides = (2,2), name = 'pool_5')(conv5)
#################################
# Decoder
#################################
#conv1 = Conv2DTranspose(512, (2, 2), strides = 2, name = 'conv1')(pool5)
upsp1 = UpSampling2D(size = (2,2), name = 'upsp1')(pool5)
conv6 = Conv2D(512, 3, activation = 'relu', padding = 'same', name = 'conv6_1')(upsp1)
conv6 = Conv2D(512, 3, activation = 'relu', padding = 'same', name = 'conv6_2')(conv6)
conv6 = Conv2D(512, 3, activation = 'relu', padding = 'same', name = 'conv6_3')(conv6)
upsp2 = UpSampling2D(size = (2,2), name = 'upsp2')(conv6)
conv7 = Conv2D(512, 3, activation = 'relu', padding = 'same', name = 'conv7_1')(upsp2)
conv7 = Conv2D(512, 3, activation = 'relu', padding = 'same', name = 'conv7_2')(conv7)
conv7 = Conv2D(512, 3, activation = 'relu', padding = 'same', name = 'conv7_3')(conv7)
zero1 = ZeroPadding2D(padding = ((1, 0), (1, 0)), data_format = 'channels_last', name='zero1')(conv7)
upsp3 = UpSampling2D(size = (2,2), name = 'upsp3')(zero1)
conv8 = Conv2D(256, 3, activation = 'relu', padding = 'same', name = 'conv8_1')(upsp3)
conv8 = Conv2D(256, 3, activation = 'relu', padding = 'same', name = 'conv8_2')(conv8)
conv8 = Conv2D(256, 3, activation = 'relu', padding = 'same', name = 'conv8_3')(conv8)
upsp4 = UpSampling2D(size = (2,2), name = 'upsp4')(conv8)
conv9 = Conv2D(128, 3, activation = 'relu', padding = 'same', name = 'conv9_1')(upsp4)
conv9 = Conv2D(128, 3, activation = 'relu', padding = 'same', name = 'conv9_2')(conv9)
upsp5 = UpSampling2D(size = (2,2), name = 'upsp5')(conv9)
conv10 = Conv2D(64, 3, activation = 'relu', padding = 'same', name = 'conv10_1')(upsp5)
conv10 = Conv2D(64, 3, activation = 'relu', padding = 'same', name = 'conv10_2')(conv10)
conv11 = Conv2D(1, 3, activation = 'relu', padding = 'same', name = 'conv11')(conv10)
model = Model(inputs = inputs, outputs = conv11, name = 'vgg-16_encoder_decoder')
return model
I have found any reference for that attribute in Tensorflow Keras Model documentation.
On "Migrate your TensorFlow 1 code to TensorFlow 2 - 2. Make the code 2.0-native", say:
If you need to aggregate lists of variables (like tf.Graph.get_collection(tf.GraphKeys.VARIABLES)), use the .variables and .trainable_variables attributes of the Layer and Model objects.
The network in Tensorflow's tutorial "Custom training: walkthrough" is:
model = tf.keras.Sequential([
tf.keras.layers.Dense(10, activation=tf.nn.relu, input_shape=(4,)), # input shape required
tf.keras.layers.Dense(10, activation=tf.nn.relu),
tf.keras.layers.Dense(3)
])
When I do:
print(type(model))
I get:
<class 'tensorflow.python.keras.engine.sequential.Sequential'>
But if I print the type of my network, vgg16_encoder_decoder, I get:
<class 'keras.engine.training.Model'>
So, the problem is the type of the network. I haven't say the above class, 'keras.engine.training.Model', before.
How can I fix this problem to let me use the attribute trainable_variables?