Automatic conversion of list of tensorflow ops inside a Model to ListWrapper

Viewed 582

I am examining a tf.keras code and I found out that when inside a custom model.Model instance every list of tf ops assigned to a self variable is automatically converted to ListWrapper object. An example of this functionality is shown with the code:

from tensorflow.keras import models
from tensorflow.keras import layers
from tensorflow.keras import initializers


class CustomModel(models.Model):
    def __init__(self, width, depth, **kwargs):
        super(CustomModel, self).__init__(**kwargs)
        self.width = width
        options = {
            'kernel_size': 3,
            'strides': 1,
            'padding': 'same',
            'kernel_initializer': initializers.RandomNormal(mean=0.0, stddev=0.01, seed=None)
        }
        self.convs = [layers.Conv2D(filters=width, bias_initializer='zeros', name='convs_{}'.format(i), **options)
                      for i in range(depth)]
        self.conv = layers.Conv2D(filters=width, bias_initializer='zeros', name='conv_{}'.format(0), **options)
        self.conv2 = [layers.Conv2D(filters=width, bias_initializer='zeros', name='conv_{}'.format(0), **options)]

        self.depth = depth

where if checked (in a debugger for example):

type(self.convs)

tensorflow.python.training.tracking.data_structures.ListWrapper

type(self.conv)

tensorflow.python.keras.layers.convolutional.Conv2D

type(self.conv2)

tensorflow.python.training.tracking.data_structures.ListWrapper

where it can be seen that self.convs and self.conv2 are ListWrapper instead of list. On the contrary if the class does not inherit from Model:

class CustomModel2(object):
    def __init__(self, width, depth, **kwargs):
        # super(CustomModel, self).__init__(**kwargs)
        self.width = width
        options = {
            'kernel_size': 3,
            'strides': 1,
            'padding': 'same',
            'kernel_initializer': initializers.RandomNormal(mean=0.0, stddev=0.01, seed=None)
        }
        self.convs = [layers.Conv2D(filters=width, bias_initializer='zeros', name='convs_{}'.format(i), **options)
                      for i in range(depth)]
        self.conv = layers.Conv2D(filters=width, bias_initializer='zeros', name='conv_{}'.format(0), **options)
        self.conv2 = [layers.Conv2D(filters=width, bias_initializer='zeros', name='conv_{}'.format(0), **options)]

        self.depth = depth

the usual lists are created:

type(self.convs)

list

type(self.conv)

tensorflow.python.keras.layers.convolutional.Conv2D

type(self.conv2)

list

So, my question is why is this happening? What's the advantages of using ListWrapper over list? Also, how can I use this type? I know I can access its members via a for loop for example. Are there any other properties I should know about?

There is a similar question here but neither the question nor the answer satisfied me.

0 Answers
Related