Introduction to TensorFlow Fundamentals

This is the first lab in the Machine Learning with TensorFlow series. The primary focus of this lab is to help you understand the fundamental components of TensorFlow.

### Learning Objectives:

- Creating scalars, vectors, matrices, and tensors
- Inspecting different attributes of a tensor.
- Performing basic operations on tensors.
- Learn to index and slice tensors.
- Reshaping and manipulating tensors.

### To get the most out of this series:

- you should know how to write code, ideally have some experience programming in Python.
- have a decent understanding of variables, linear equations, matrices, calculus, and statistics.
- don't just stick to the examples and code I've provided, play around and break things - that's the best way to learn.

### Code/Environment Setup

In order to try out the code snippets or complete to-do tasks mentioned in each section, you can use Google Colaboratory notebook. Colab is basically Google's implementation of Jupyter Notebooks where you can run your code.

You can learn more about working with Colabs by following this notebook.

Performing Basic Math Operations

Now, that you know how to create tensors, it's time to learn to manipulate or perform basic operations on tensors.

Here's a list of common operations that we use while crunching data with arrays and numbers:

- Update a value.
- Basic arithmetic operation on two tensors(vectors or matrices).
- Finding minimum/maximum value in a tensor.
- Computing mean.

Let's cover them one-by-one here:

We defined two tensors:

```
a = tf.constant([[1,2], [3,4]]) # a constant tensor
b = tf.Variable([[5,6], [7,8]]) # a variable tensor
print(a)
print(b)
```

### 1. Update a Value - Changing a tensor!

In order to update a value, first try to update tensor a using the assign() method.

```
##let's try to update the 1st element of the 1st row
a[0,0].assign(10)
```

Whoops! did you see that? It isn't allowing us to assign any new value to the constant tensor.

Let's try to do the same with b:

```
##let's try to update the 1st element of the 1st row
b[0,0].assign(10)
```

Voila! It worked. So, this gives us some insight into the difference between constant and Variable object.

### 2. Adding two tensors

```
## elementwise addition
print(a + b). # try out for -, *, /
print(tf.add(a, b))
```

Arithmentic operators perform elementwise computation.

If you want to multiply matrices, you can use tf.matmul or @

```
## matrix multiplication
tf.matmul(a, b)
```

Or @

```
## matrix multiplication
a @ b
```

### 3. Finding minimum/maximum value or index of the min/max value in a tensor

```
##finding the min/max
print(f"Index of the smallest value in the tensor: {tf.argmin(a)}")
print(f"Largest value in the tensor: {tf.reduce_min(b)}")
```

### 4. Computing mean of the data

```
##finding the min/max
print(f"Mean: {tf.reduce_mean(b)}")
```

This gives you the mean of the 2D tensor b.

### Output:

### Next Steps!

You have seen how easy it is to add multiply and play around with variable tensors. All of this is possible because of a technique called broadcasting that you can read more about.

Apart from mathematical operations, you must also know how to access individual elements, how to create a subset of an N-dimensional tensor and how to play across multiple dimensions/axes.

Hop onto the next step!

2