## DEV Community is a community of 662,780 amazing developers

We're a place where coders share, stay up-to-date and grow their careers.

# A tale of Tensorflow.js - Chapter 1: Tensors

Álvaro
I'm a young spanish developer and React / GraphQL enthusiast, interested in AI/DL, python ecosystem and self-drived devices.

So it's been a while since I posted here, but here I am again!
Hey everyone, it's Álvaro, and today we are going to start a series about deep learning with tensorflow.js.

What is Tensorflow?
Well, Tensorflow is an open-source machine learning framework. It has a lot of tools and resources to make our development so so easy.

Why it's named Tensorflow?
The basic operation unit in this framework it's called Tensor, it can be either a variable or a constant, and depending on it, it can be trained or not.
A tensor usually is a multi-dimensial vector or matrix.

What is training a tensor?
We usually train our models, our neuronal networks, and training is the process that our models go through meanwhile they learn their input parameters to produce optimal outputs parameters.

For the sake of simplicity, let's keep it simple today.

First, let's start making a blank HTML template and add the tensorflow.js library.

``````<!DOCTYPE html>
<html lang="en">
<meta charset="UTF-8">
<title>A Tale of Tensorflow.js</title>
<script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@2.0.0/dist/tf.min.js"></script>
<body>

</body>
</html>
``````

Now, we can start playing with tensors:

``````  <script>
async function main() {
const tensorOne = tf.tensor(1)
const tensorTwo = tf.tensor([1.0, 2.0, 3.0, 4.0])
const tensorThree = tf.tensor([[1.0, 2.0], [3.0, 4.0]])

console.log(tensorOne)
console.log(tensorTwo)
console.log(tensorThree)
}
main();
</script>
``````

If we watch our console, we can see a lot of properties on the tensor:
dtype: also inferred, we can specify it when we create the tensor.
id: Each tensor has an unique ID, and now it's autogenerated as you can see.
rankType: it's the number of dimensions that our tensor has.
shape: shape it's inferred of the values we passed to the tensor. We can play with this next. We can see that for our first tensor the shape is 0, it has no dimensions, for the second tensor it's 4, it has one dimension with 4 values (let's say values for now). On the last tensor we can see `[2, 2]`, we have two dimesions with 2 values.

For now let's keep these in mind.

The API it's not limited only to `tf.tensor`, we can define beforehand the dimesions of our tensor with `tf.tensor2d`, `tf.tensor3d`, even `tf.tensor6d`, and, as you can intuit, we can pass arrays previously created to this function calls.

Now... how we access the tensors data?
The tensor API has a variety of methods we can use, synchronously and asynchronously, we'll go with the async methods:

``````<script>
async function main() {
const tensorOne = tf.tensor(1)
const tensorTwo = tf.tensor([1.0, 2.0, 3.0, 4.0])
const tensorThree = tf.tensor([[1.0, 2.0], [3.0, 4.0]])

// Print the values
tensorOne.array().then(values => console.log(values))
tensorTwo.array().then(values => console.log(values))
tensorThree.array().then(values => console.log(values))

const tensorOneValues = await tensorOne.data()
const tensorTwoValues = await tensorTwo.data()
const tensorThreeValues = await tensorThree.data()
return {
tensorOneValues,
tensorTwoValues,
tensorThreeValues
}
}

}
main();
</script>
``````

Note: tensor.data() will flatten our arrays.

What if we create a tensor with different array shapes?

``````  <script>
async function main() {
const tensor = tf.tensor([[1, 2], [3]])
console.log(tensor)
tensor.array().then(console.log)
}
main();
</script>
``````

We can see that the console prints our tensor, but throws an error when trying to see the values:
`Error: [2,2] does not match the input size.`
That's because we defined our first array with 2 values (size of 2), it expects that all our arrays are the same size:

``````  <script>
async function main() {
const tensor = tf.tensor([[1, 2, 3], [3]])
console.log(tensor)
tensor.array().then(console.log)
}
main();
</script>
``````

Now it's expecting 2 arrays, with a length of 3.

What if we pass an incorrect shape to the tensor as a second value?

``````  <script>
async function main() {
const tensor = tf.tensor([1, 2, 3], [3, 3])
console.log(tensor)
}
main();
</script>
``````

`Error: Based on the provided shape, [3,3], the tensor should have 9 values but has 3`

It's expecting a matrix with 3 columns and 3 rows:

``````  <script>
async function main() {
const tensor = tf.tensor([[1, 2, 3], [1, 2, 3], [1, 2, 3]], [3, 3])
console.log(tensor)
tensor.array().then(console.log)
}
main();
</script>
``````

We can make operations with our tensors:

``````<script>
async function main() {
const tensor = tf.tensor([1, 2, 3])
const tensor2 = tf.tensor([4, 5, 6])

// returns a new tensor with bit wise sum included
sum.array().then(console.log)

// what if we pass diferent shapes?
const tensor3 = tf.tensor([[1, 1], [2, 2]])
// const sum2 = tf.add(tensor, tensor3)
// Error: Operands could not be broadcast together with shapes 3 and 2,2.

// Clone a tensor
const clonedTensor = tensor3.clone()
clonedTensor.array().then(console.log)

// reshape a tensor
// we have a tensor with shape [4]
const tensor4 = tf.tensor([1, 2, 3, 4])
console.log(tensor4)
// we reshape it to [2, 2]
const tensor4reshaped = tf.reshape(tensor4, [2, 2])
console.log(tensor4reshaped)
// due to async operations maybe you see this logs at the top of your console

// we can also add values at the start and end of ours tensors with tf.pad
const paddedTensor = tf.tensor([1, 2, 3, 4]);