A Quick Overview of TensorFlow Basics in 10 Minutes

A guide to learning the basics of TensorFlow for deep learning

Tirendaz AI
Geek Culture

--

Image by Freepik

AI is now at the center of our daily lives. We all leverage AI tools such as ChatGPT to get recommendations, generate images, translate, and even write code. Well, have you ever wondered how these tools are built? When you look under the hood, you see that these tools are built with TensorFlow or PyTorch.

You may ask which one should be preferred. Good question. Both frameworks are awesome, but each has its own pros and cons.

TensorFlow vs PyTorch (Image by Author)

TensorFlow is usually used in industry as it is easy to learn and has great tools for performing end-to-end projects. On the other hand, PyTorch is mostly utilized in academic research because it is more Pythonic and more flexible.

If you are new to deep learning, I encourage you to learn TensorFlow. Trust me, you’ll likely become familiar with both frameworks over time as you dive into deep learning projects.

In this blog, I’ll walk you through the basics of TensorFlow and unleash the power of crucial methods in it.

If you don’t feel like reading, you can watch my video instead!

Let’s dive in!

What is TensorFlow?

TensorFlow is an open-source framework for carrying out end-to-end machine learning (ML) projects. It actually is more than a library. This is because you can implement all the steps of an ML project with this framework, such as data preprocessing, model building, and model serving.

TensorFlow was launched by the Google Brain team for internal Google use in research, and then it was released as an open-source library in 2015. With TensorFlow, you can tackle a lot of machine learning problems such as image classification, NLP, recommendation systems, and time series analysis.

TensorFlow has many APIs that make your projects easier. The most important of these is undoubtedly Keras. Keras is an API designed for humans that allows you to easily build deep learning models. Another important API for loading data is tf.data.

The TensorFlow Ecosystem

TensorFlow has a large ecosystem. But don’t worry. Keras and tf.data are enough for implementing many deep learning projects.

TensorFlow performs mathematical operations quickly. This is because this framework is written in C++, which is close to computer language. However, you can also use this framework with other languages such as Python, Java, Swift, and R. You can even use TensorFlow.js to run your models directly in the browser.

Awesome, we briefly looked at what TensorFlow is. It’s time to get our hands dirty with coding.

Getting started with TensorFlow

You can install TensorFlow on your own computer. However, you can use this framework with Colab, a cloud service of Google. Fortunately, TensorFlow is preinstalled in Colab.

To work with this framework, all we need to do is import. Let’s import TensorFlow and take a look at its version.

import tensorflow as tf
print(tf.__version__)

#Output:
2.12.0

You can find the link to the notebook I used in this blog here.

Using TensorFlow like NumPy

TensorFlow revolves around a data structure called tensors. These tensors flow from one operation to another. This is where the name of TensorFlow comes from.

Computational Graph in TensorFlow

It is crucial to understand the tensor concept for implementing AI projects. You can think of the tensor as a container that holds the data. Actually, a tensor is very similar to a multidimensional NumPy array. But the tensor also holds a simple number like 42. So, a tensor can be zero-dimensional or multidimensional.

Now, let’s explore how to work with tensors. For example, let me create a 0-dimensional tensor. We can leverage the constant method for this.

scalar = tf.constant(3)
print(scalar)

#Output:
<tf.Tensor: shape=(), dtype=int32, numpy=3>

As you can see, the tensor has no dimension. We can see the dimension of this tensor with the ndim method.

print(scalar.ndim)

#Output:
0

As you can see, the dimension is 0. A tensor containing only one number is called a scalar. A sequence of numbers is called a vector, it’s actually a 1-dimensional tensor.

Image Source

Note that the dimension of a tensor may be called an axis or rank. We can use them interchangeably. Let’s create a vector now.

vector = tf.constant([1,2])
print(vector)

#Output:
<tf.Tensor: shape=(2,), dtype=int32, numpy=array([1, 2], dtype=int32)>

Let’s look at the dimension of this vector.

print(vector.ndim)

#Output:
1

As you can see, we have created a 1-rank tensor. Let’s move on to creating a matrix.

matrix = tf.constant([[1,2],[3,4]])
print(matrix)

#Output:
2

Let’s see the dimension of this matrix.

print(matrix.ndim)

#Output:
2

By default, the data type of integers is int32 and the data type of floats is float32. Note that the higher the precision, the slower the mathematical operations are. Float32 is often used for quick calculations. For example, let’s explore the MNIST dataset.

from tensorflow.keras.datasets import mnist
(train_images, train_labels), (test_images, test_labels) = mnist.load_data()
print("The dimension of the training input: ",train_images.ndim)
print("The shape of the training input: ",train_images.shape)
print("The datatype of the training input: ",train_images.dtype)

# Output:
The dimension of the training input: 3
The shape of the training input: (60000, 28, 28)
The datatype of the training input: dtype('uint8')

As you can see, the training set consists of 60,000 images with the size 28 x 28, and their data type is 8 bits.

Another way to create a tensor is to use the Variable method. This method is used like the constant method. The difference between these methods is that the tensor you create with the constant method is immutable, while the tensor you create with the Variable method is mutable. To show this, let’s first create two tensors with these two methods.

v = tf.Variable([1,2])
c = tf.constant([1,2])
print(v,c)

#Output:
(<tf.Variable 'Variable:0' shape=(2,) dtype=int32, numpy=array([1, 2], dtype=int32)>,
<tf.Tensor: shape=(2,), dtype=int32, numpy=array([1, 2], dtype=int32)>)

Now, let’s change the first value with the assign method.

v[0].assign(7)
print(v)

#Output:
<tf.Variable 'Variable:0' shape=(2,) dtype=int32, numpy=array([7, 2], dtype=int32)>

Now, let’s try to change the first value of c.

c[0].assign(7)
print(c)

#Output:
...
...
AttributeError: 'tensorflow.python.framework.ops.EagerTensor' object has no attribute 'assign'

As you can see, we got an error message that we cannot change the value.

Great, we’ve seen how to create a tensor with the Variable. Let’s go ahead and discuss how to create random tensors.

Generating Random Tensors

When we build neural networks, we often want to randomly initialize the weights. The random module in TensorFlow allows us to generate random data. Now, let’s create data from a normal distribution.

tf.random.set_seed(42)
print(tf.random.normal(shape=(3, 2)))

# Output:
<tf.Tensor: shape=(3, 2), dtype=float32, numpy=
array([[ 0.3274685, -0.8426258],
[ 0.3194337, -1.4075519],
[-2.3880599, -1.0392479]], dtype=float32)>

Note that the set_seed method helps you fix randomness. You can also create a tensor with all elements set to one or zero:

print(tf.ones(shape=(3, 2)))

#Output:
<tf.Tensor: shape=(3, 2), dtype=float32, numpy=
array([[1., 1.],
[1., 1.],
[1., 1.]], dtype=float32)>

print(tf.zeros(shape=[3,2]))

#Output:
<tf.Tensor: shape=(3, 2), dtype=float32, numpy=
array([[0., 0.],
[0., 0.],
[0., 0.]], dtype=float32)>

Moreover, you can convert NumPy arrays to tensors with the constant method. To demonstrate this, let’s first create a NumPy array and then convert it to a tensor as follows:

import numpy as np
numpy_A = np.arange(1, 25, dtype=np.int32)
tensor_A = tf.constant(numpy_A, shape=[2, 4, 3])
print(tensor_A)

#Output:
<tf.Tensor: shape=(2, 4, 3), dtype=int32, numpy=
array([[[ 1, 2, 3],
[ 4, 5, 6],
[ 7, 8, 9],
[10, 11, 12]],

[[13, 14, 15],
[16, 17, 18],
[19, 20, 21],
[22, 23, 24]]], dtype=int32)>

Adding a Dimension to the Tensor

To go images through neural networks, you can need to adjust the dimensions of the images. tf.newaxis enables you to add a dimension to your tensor while keeping the same information available. Let me show you this. First, let’s create a tensor with the zeros method and then have a look at the dimension of this tensor with ndim.

rank_4_tensor = tf.zeros([2,3,4,5])
print(rank_4_tensor.ndim)

#Output:
4

Next, let’s add this tensor to a dimension using tf.newaxis.

rank_5_tensor = rank_4_tensor[..., tf.newaxis]
print("Dimension: ", rank_5_tensor.ndim)
print("Shape: ", rank_5_tensor.shape)

#Output:
Dimension: 5
Shape: TensorShape([2, 3, 4, 5, 1])

As you can see, we added a dimension to the end. You can also leverage the expand_dims method to add a dimension. Let’s use the axis=-1 parameter to add a dimension to the end.

rank_6_tensor = tf.expand_dims(rank_5_tensor, axis=-1)
print(rank_6_tensor.shape)

#Output:
TensorShape([2, 3, 4, 5, 1, 1])

Tensor Operations

It is easy to perform the basic mathematical operations directly on tensors with Python operators such as, +, -, *. To show this, let’s first create a tensor as follows:

tensor = tf.constant([[1,2], [3, 4]])

Let’s add 10 to this tensor.

print(tensor + 10)

#Output:
<tf.Tensor: shape=(2, 2), dtype=int32, numpy=
array([[11, 12],
[13, 14]], dtype=int32)>

Next, let’s subtract 10 from the elements.

print(tensor - 10)

#Output:
<tf.Tensor: shape=(2, 2), dtype=int32, numpy=
array([[-9, -8],
[-7, -6]], dtype=int32)>

After that, let’s multiply the elements by 10.

print(tensor * 10)

#Output:
<tf.Tensor: shape=(2, 2), dtype=int32, numpy=
array([[10, 20],
[30, 40]], dtype=int32)>

You can also use functions in TensorFlow to perform these operations. These methods allow you to quickly perform mathematical operators. For example, we can leverage the multiply method for multiplication.

print(tf.multiply(tensor, 10))

#Output:
<tf.Tensor: shape=(2, 2), dtype=int32, numpy=
array([[10, 20],
[30, 40]], dtype=int32)>

One of the most used operators in ML is matrix multiplication. You can use the matmul method for this.

print(tf.matmul(tensor, tensor))

#Output:
<tf.Tensor: shape=(2, 2), dtype=int32, numpy=
array([[ 7, 10],
[15, 22]], dtype=int32)>

You can also employ @ for matrix multiplication.

print(tensor @ tensor)

#Output:
<tf.Tensor: shape=(2, 2), dtype=int32, numpy=
array([[ 7, 10],
[15, 22]], dtype=int32)>

Note that when multiplying two matrices, the inner dimensions must be equal. The result will be equal to the outer dimensions.

Matrix Multiplication

If the internal dimensions are not equal, you can change the tensor dimension with the reshape method. Let me show you this.

tensor = tf.constant([[1,2,3], [4, 5,6]])
print(tensor.shape)

#Output:
TensorShape([2,3])

Let’s reshape this tensor like this:

print(tf.reshape(tensor , shape=(3,2)))

#Output:
TensorShape([2,3])

Now, let’s take a look at how to change the datatype of a tensor.

Changing the Datatype of a Tensor

You may want to change the data type of the tensor to perform mathematical operators faster. As mentioned earlier, the default data type for float numbers is float32. Let’s check it out.

tensor = tf.constant([1.2, 3.4])
print(tensor)

#Output
<tf.Tensor: shape=(2,), dtype=float32, numpy=array([1.2, 3.4], dtype=float32)>

Now, let’s convert this data type to float16 with the cast method.

print(tf.cast(tensor, dtype=tf.float16))

#Output:
<tf.Tensor: shape=(2,), dtype=float16, numpy=array([1.2, 3.4], dtype=float16)>

Let’s go ahead and take a look at how to remove all single dimensions.

Removing all single dimensions

In the previous section, we’ve seen how to add a dimension to a tensor. In this section, we’re going to handle how to remove all single dimensions.

The squeeze method helps you remove dimensions of size 1 from the shape of a tensor. To show this, let’s create a tensor.

tensor = tf.constant(np.random.randint(0, 100, 30), shape=(1, 1, 1, 1, 30))
print(tensor.shape)

#Output
TensorShape([1, 1, 1, 1, 50])

Now, let’s remove the dimensions of size 1 with the squeeze method.

tensor = tf.squeeze(tensor)
print(tensor.shape)

#Output
TensorShape([50])

As you can see, all single dimensions have been removed.

One-Hot Encoding

When building machine learning models, we often want to convert categorical data into one-hot encoding. We can use the one-hot method to do this with TensorFlow. Let me show you this. Let’s create a variable named data and then convert it to one-hot code, as follows:

data = [0,1,2,3]
print(tf.one_hot(data, depth=4))

#Output:
<tf.Tensor: shape=(4, 4), dtype=float32, numpy=
array([[1., 0., 0., 0.],
[0., 1., 0., 0.],
[0., 0., 1., 0.],
[0., 0., 0., 1.]], dtype=float32)>

The @tf.function Decorator

As you may know, a decorator simply modifies the behavior of a method. The @tf.function decorator takes a Python function and returns it to the TensorFlow graph. To show this, let’s first create a function and add this decorator at the top.

@tf.function
def function(x):
return x** 2

Now, let’s take data and pass this data to the function.

data = tf.constant(np.arange(0, 10))
print(function(data))

#Output:
<tf.Tensor: shape=(10,), dtype=int64, numpy=array([ 0,1,4,9,16,25,36,49,64,81])>

This decorator allows you to perform mathematical operations faster.

Wrap-Up

When it comes to building a deep neural networks model, you need to perform many mathematical operations. Instead of building the model from scratch, you can leverage deep learning frameworks such as TensorFlow and PyTorch.

In this blog, we explored TensorFlow and saw that it has great methods for implementing deep learning projects. The working principle is very simple. First, convert data into tensors and then build deep learning models to extract hidden patterns in them.

You can find the link to the notebook I used in this blog here. That’s it. Thanks for reading. Let’s connect YouTube | Twitter | LinkedIn.

Resources

--

--