PyTorch is best known as a machine learning framework. And it’s true that the Python library is a fantastic option for anyone working within that context. But one of PyTorch’s less discussed elements is how well it can be used for general data science. Any kind of machine learning depends on advanced mathematical processing. And PyTorch’s system can handle a wide variety of data-centered tasks. For example, you can easily aggregate a tensor along an axis in PyTorch using the sum function. But doing so requires a little extra investigation into PyTorch’s relationship to both data and Python’s working environment.

### A Tensor Review

Standard mathematical tensors are a subject unto themselves. But they can essentially be described as an algebraic construct. A tensor consists of a multilinear pairing of multiple mathematical construct points or sets which are mapped to a vector space. In a more general sense, you can think of tensors as a relationship defined by spatial and often momentum-based positioning which have solid relationships with each other. This often fits into the context of machine learning since working with tensors can provide predictive value for object positioning. Though that’s only the tip of the iceberg when considering the potential of PyTorch’s tensors.

### Practical Work With Tensors

A tensor provides a lot of data points for a program to keep track of. They’re often large, complex, collections of spatially related data. But collections are one of the areas that Python excels within. A tensor can be created and used within PyTorch in much the same way as any other collection. In fact, if you’re familiar with NumPy you’ll probably notice how similar PyTorch’s tensor is to NumPy’s multidimensional array. And just like with multidimensional arrays, Python’s syntax makes it easy to aggregate or manipulate portions of it with very little effort. With that in mind, how would we go about creating, manipulating, and aggregating tensors in NumPy’s system? Take a look at the following code.

import torch as pt

pt.manual_seed(999)

ourTensor = pt.rand(3, 4)

print(type(ourTensor))

print(ourTensor)

We begin by importing PyTorch as pt. In line 3 we set a seed value for pseudo-random numbers. This is then implemented in PyTorch’s random function on the next line. The contents of this random generation are assigned into three rows. It also has 4 column sets within it. This expands the dimension count of ourTensor to 2. We can proceed to print out ourTensor’s type and contents. When we do so it’s apparent that we have a 2d tensor definition with set values for each position. Note that the new tensor should have session-static values for its element structure due to the way random numbers work in digital systems. We could force a more random seed pattern, but keeping predictable values is useful for later manipulation of the tensor’s contents.

We can also access individual elements within ourTensor just as we would with any other collection. For example, try putting the following lines at the end of the previous code.

print(ourTensor[0])

As you can see, we’re able to access individual rows and columns just as we would with most other multidimensional structures. But to aggregate a tensor’s contents, we’ll make use of some predefined functionality within PyTorch’s lexicon.

### Using PyTorch’s Sum

Python’s default syntax gives us a lot of freedom to access elements of almost any collection. But we can often gain both speed and ease of use by leveraging a library’s own functions. The data science libraries in particular tend to have heavy optimizations to speed processing when compared to Python’s default functionality. For example, PyTorch provides functions specific to embeddings to speed up lookup speed. And this is quite true for PyTorch’s tensors as well. When we’re working with a tensor’s sums we actually have a special torch sum function. Consider the following code.

import torch as pt

pt.manual_seed(999)

ourTensor = pt.rand(3, 4)

print(ourTensor)

print(pt.select(ourTensor, 1, 1))

print(pt.sum(pt.select(ourTensor, 1, 1)))

We start out with similar code to the previous example. We make a new tensor, called ourTensor, and fill it with pseudo-random values derived from a manual_seed. Then we print the result to the screen in order to verify that the operation worked as intended.

Things begin to change on line 6. We print out part of ourTensor, but we’re selecting that segment in a manner unique to PyTorch’s system. PyTorch’s select takes an input tensor and slices it along a specified dimension and index. Using this method we can select an axis point. Again, we could use Python’s standard syntax at this point and work with a for loop. But PyTorch has a special torch sum we can use to quickly aggregate values. And that’s exactly what we do on line 7. We use select to essentially slice along an axis point. This process creates a new output tensor that we can pass to PyTorch’s sum function to aggregate the values. In doing so we receive a new value that contains the total sum of the axis.