W2 - yet another tensorflow question

Hello again,

In the alpaca transfer training part, we’re creating a model where we remove the top layer of MobileNetV2 to add our own output layer.
While writing the alpaca_model function, there’s something I don’t quite understand. We start by defining base_model = tf.keras.applications.MobileNetV2(...), which, according to the API, returns a model. In my mind, this means that base_model is an instance of model. But then, to precise the inputs, we call x = base_model(inputs=..., training=...), which is the way to instanciate a model according to this.

I’m completly lost on what I just did in the assignment. If someone could shed some light, it’d be appreciated!

Thanks

Hey @Goudout,
I am a little confused as to what exactly are you confused with, ironical isn’t it :joy: Anyways, let me ignite this discussion with a little fact. If you take a look towards the end of this page of the docs, you will find that calling tf.keras.applications.MobileNetV2 will return a keras.Model instance, which is simply this. Now, after knowing this fact, can you please elaborate on what exactly are you confused with, since we have been using this class throughout the specialization.

P.S. - The docs that I have mentioned above are of v2.9.1, and I guess the Coursera labs are using v2.3.x, so please take a look at this for exact reference.

Regards,
Elemento

My confusion comes from the fact that we have a model after calling tf.keras.applications.MobileNetV2, so we already have an instance.
But how am I supposed to know that one can write base_model(inputs=...) to add information to this instance?

I might be unclear I’m sorry, I don’t really come from computer world, more from math world, and my ocabulary regarding instances, classes, functions, etc… is not totally on point.

Thanks again.

Hey @Goudout,
Check out the Version 7 of this Kernel. In this, I have tried to answer your question with a little bit of code revolving around keras.Model. Also, I have included some resources to help you differentiate between Classes and Objects in Python, and in general, any Object Oriented Programming (OOP) language. Feel free to let us know if this doesn’t help.

Regards,
Elemento

1 Like

Dear @Elemento,

Thank you soooooo much for your code, I think I completly understand what I missed before!! The fact that the API doc gives and example model = tf.keras.Model(inputs=inputs, outputs=outputs) got me confused with the call(inputs, training=None, mask=None) method.

In fact, what I learned here, is that the fact that we can pass arguments to an object with obj(args) is just a specific case of calling a method, literally called call() to our object. I was previously confusing base_model(inputs=...), which is simply applying the method call(inputs=...) to our object, with the instanciation of base_model via tf.keras.applications.MobileNetV2(...)

I think lots of things will make more sense to me now, but if I’m mistaking, please correct me!

Cheers.
Élie

Hey @Goudout,
You are on the right track but some of the things that you have mentioned might not be correct. Frankly, this is a bit of a confusing example to learn about the concept of classes and objects, primarily, because of the fact that this keras.Model class exposes a call method, which may confuse some learners to believe that it is similar to __call__ method.

Specifically this statement is incorrect. Let me quote GeeksforGeeks here:

Python has a set of built-in methods and __call__ is one of them. The __call__ method enables Python programmers to write classes where the instances behave like functions and can be called like a function. When the instance is called as a function; if this method is defined, x(arg1, arg2, ...) is a shorthand for x.__call__(arg1, arg2, ...).

You can find the source of the above quote here. So, your statement should be:

In fact, what I learned here, is that the fact that we can pass arguments to an object with obj(args) is just a specific case of calling a method, literally called __call__() to our object.

Up to now, I have discussed the generic case for Python classes and Objects. Now, coming to the keras.Model class, it exposes another method called as call, which you can find here. Personally, I have never used this method till now. However, I would like to highlight one important note about this method (mentioned in the docs):

Note: This method should not be called directly. It is only meant to be overridden when subclassing tf.keras.Model. To call a model on an input, always use the __call__() method, i.e. model(inputs), which relies on the underlying call() method.

I hope this clarifies the concept. As always, feel free to ask if any queries.

Regards,
Elemento

1 Like

Thanks for the clarification. I did notice the difference between call() and __call__() a bit after I answered to you!

My final question regarding this topic is: imagine keras.Model didn’t have a call() function implemented at all (which is credible since it’s written “please do not use”). How would I know, as a programmer, that I can use model(inputs=..., training=...)?
I think the answer is:

  1. notice that keras.Model “inherits From: Layer”,
  2. check out the doc of tf.keras.layers.Layer,
  3. see that it implements a __call__() method and read it
  4. see that it wraps another tf.keras.layers.Layer.call() method and read it
  5. finally, read that we can (/should) pass inputs and training arguments to it.

Is that correct or am I missing any subtlety?

Best regards.
Élie

Hey @Goudout,
I literally went over the documentations of various versions to write as much of an inclusive answer as possible. But before starting, I would like to mention a few points.

  • First, I am not a Tensorflow expert (unfortunately :joy:), so, I might miss out on some of the things.
  • Second, Tensorflow is a humongous framework, so trying to find a one-size-fits-all solution to any concept or idea may not be practically possible.
  • I am mentioning this because whenever you are using Tensorflow (or any framework for that matter), I want you to keep an open mind, so whenever a piece of code that was working in all the scenarios till now doesn’t work any more, there may be a multitude of reasons.
  • For instance, Tensorflow might change the version, and when it does, a lot of things change usually.
  • Tensorflow might even incorporate other libraries such as it incorporated Keras, and when it does, both Tensorflow and the other library will naturally undergo a lot of changes.

Keeping these points in mind, let’s start with the answer :nerd_face: I will be using 2 versions of Tensorflow in this answer of mine, v2.3.0 and v.2.9.1, so make sure to look out for the differences. This will not help me to answer your query more suitably, but will also tell you how much Tensorflow changes from one version to another (sub-versions to be more precise).

As a programmer, in order to know how a new thing works, I try to find some tutorials and examples first :joy: instead of diving straight in the documentation. 2 reasons, helps to save time and avoids dealing with extensive documentation of these frameworks. Since these frameworks are written by thousands of programmers collectively, hence, it’s natural to be unfamiliar with a lot of things used in the documentation, which will appear daunting to any newbie. So, let’s see how we can adopt this strategy with the 2 different versions.

P.S. - You can find tutorials and examples on the entire web but for the sake of this answer, let’s say that we are only considering tutorials and examples available in the docs of Tensorflow.

v.2.3.0

So, consider the docs of v2.3.0. I want to know how to use tf.keras.applications.MobileNetv2. I open it’s doc, no tutorial, no examples. I see that it inherits from keras.model, I open it’s doc, no tutorial. So, I take a look at the examples. However, I want to use this model as a layer in a larger model (our transfer learning based model), and there are no examples for that. I see that it inherits from Layer, I open it’s doc, and before I could look for tutorials or examples, I find this


We recommend that descendants of Layer implement the following methods:

call(self, *args, **kwargs): Called in __call__ after making sure build() has been called. call() performs the logic of applying the layer to the input tensors (which should be passed in as argument). Two reserved keyword arguments you can optionally use in call() are:

  • training (boolean, whether the call is in inference mode or training mode)
  • mask (boolean tensor encoding masked timesteps in the input, used in RNN layers)

I have shrunk the above recommendation to it’s bare essentials for this post. Now, since we know that keras.Model is a descendant of Layer, keras.Model should implement a call method, and it does indeed, which you can view in the source code, and voila I am done.

v.2.9.1.

Now, consider the docs of v2.9.1. This takes a complete different approach. Once again, I want to know how to use tf.keras.applications.mobilenet_v2.MobileNetV2. I open it’s doc, and here only, I find a tutorial entitled Transfer learning and fine-tuning, and that’s it, I am done. In the tutorial, it has been clearly depicted how to use this model as the part of a larger model.

Conclusions

  • Now, you might ask why did I choose v.2.3.0 in the first place. This is because it is a nice analogy to what you mentioned in your post, i.e.,
  • Even though keras.Model implements a call method, this is not mentioned in the docs of keras.Model. It is only mentioned in the source code of the class.
  • However, a programmer might prefer the attractive docs instead of the daunting code. So, it is only after visiting the docs of Layer, I got to know that it’s descendants should implement a call method, and hence, I went back to the docs of keras.Model (a descendant of Layer), took a look at it’s source code and found the call method.
  • Now, this is only one of the ways (as I mentioned before) in which a programmer could have figured out how to use an instance of tf.keras.applications.MobileNetv2.
  • An experienced Tensorflow programmer perhaps could have seen that tf.keras.applications.MobileNetv2 returns an instance of keras.Model, which further inherits from Layer, and could have simply tried to use the base_model as a layer without taking a look at the source code or even the docs, and it would have worked out.
  • So, the answer to the question;

There is no single way out. It could have been one of the above mentioned ways, or it could have been one of the 100 other ways. I hope this helps.

Regards,
Elemento

1 Like

Thank you very much, this helps a lot!!