Note that the output contains the number of rows found in matrix a
and the number of columns found in matrix b
. So how does this all work? To obtain the value found in the output array at index [0,0] of 22, you sum the values of a[0,0] * b[0,0] (which is 1), a[0,1] * b[1,0] (which is 6), and a[0,2] * b[2,0] (which is 15) to obtain the value of 22. The other entries work precisely the same way.
To perform an element-by-element multiplication using two
matrix
objects, you must use the numpy
multiply()
function.
Defining advanced matrix operations
This book takes you through all sorts of interesting matrix operations, but you use some of them commonly, which is why they appear in this chapter. When working with arrays, you sometimes get data in a shape that doesn't work with the algorithm. Fortunately, numpy
comes with a special reshape()
function that lets you put the data into any shape needed. In fact, you can use it to reshape a vector into a matrix, as shown in the following code:
changeIt = np.array([1,2,3,4,5,6,7,8])print(changeIt) changeIt = changeIt.reshape(2,4)print(changeIt) changeIt = changeIt.reshape(2,2,2)print(changeIt)
When you run this code, you see these outputs (spaces added for clarity):
[1 2 3 4 5 6 7 8] [[1 2 3 4] [5 6 7 8]] [[[1 2] [3 4]] [[5 6] [7 8]]]
The starting shape of
changeIt
is a vector, but using the reshape()
function turns it into a matrix. In addition, you can shape the matrix into any number of dimensions that work with the data. However, you must provide a shape that fits with the required number of elements. For example, calling changeIt.reshape(2,3,2)
will fail because there aren't enough elements to provide a matrix of that size.
You may encounter two important matrix operations in some algorithm formulations. They are the transposition and inverse of a matrix. Transposition occurs when a matrix of shape n x m is transformed into a matrix m x n by exchanging the rows with the columns. Most texts indicate this operation by using the superscript T, as in AT. You see this operation used most often for multiplication in order to obtain the right dimensions. When working with numpy
, you use the transpose
function to perform the required work. For example, when starting with a matrix that has two rows and four columns, you can transpose it to contain four rows with two columns each, as shown in this example:
changeIt = np.array([[1, 2, 3, 4], [5, 6, 7, 8]])print(changeIt) changeIt = np.transpose(changeIt)print(changeIt)
The outputs look like this:
[[1 2 3 4] [5 6 7 8]] [[1 5] [2 6] [3 7] [4 8]]
You apply matrix inversion to matrixes of shape m x m, which are square matrixes that have the same number of rows and columns. This operation is quite important because it allows the immediate resolution of equations involving matrix multiplication, such as y = bX
, where you know vector y and matrix X, and you have to discover the values in the vector b. Because most scalar numbers (exceptions include zero) have a number whose multiplication results in a value of 1, the idea is to find a matrix inverse whose multiplication will result in a special matrix called the identity matrix. To see an identity matrix in numpy
, use the identity
function, like this:
print(np.identity(4))
which produces an output of:
[[1. 0. 0. 0.] [0. 1. 0. 0.] [0. 0. 1. 0.] [0. 0. 0. 1.]]
Note that an identity matrix contains all ones on the diagonal. Finding the inverse of a scalar is quite easy (the scalar number n has an inverse of n–1 that is 1/n). It's a different story for a matrix. Matrix inversion involves quite a large number of computations. The inverse of a matrix A is indicated as A–1. When working with numpy
, you use the linalg.inv()
function to create an inverse. The following example shows how to create an inverse, use it to obtain a dot product, and then compare that dot product to the identity matrix by using the allclose()
function.
a = np.array([[1,2], [3,4]])b = np.linalg.inv(a) print(np.allclose(np.dot(a,b), np.identity(2)))
The output of
True
tells you b
is the inverse of a
. Sometimes, finding the inverse of a matrix is impossible. When a matrix cannot be inverted, it is referred to as a singular matrix or a degenerate matrix. Singular matrixes aren't the norm; they’re quite rare.
Creating Combinations the Right Way
Shaping data often involves viewing the data in multiple ways. Data isn’t simply a sequence of numbers — it presents a meaningful sequence that, when ordered the proper way, conveys information to the viewer. Creating the right data combinations by manipulating data sequences is an essential part of making algorithms do what you want them to do. The following sections look at three data-shaping techniques: permutations, combinations, and repetitions.
Distinguishing permutations
When you receive raw data, it appears in a specific order. The order can represent just about anything, such as the log of a data input device that monitors something like a production line. Perhaps the data is a series of numbers representing the number of products made at any particular moment in time. The reason that you receive the data in a particular order is important, but that order might not lend itself to obtaining the output you need from an algorithm. Creating a data permutation, a reordering of the data so that it presents a different view, might help to achieve a desired result.
You can view permutations in a number of ways. One method of viewing a permutation is as a random presentation of the sequence order. In this case, you can use the numpy
random.permutation()
function, as shown here:
a = np.array([1,2,3])print(np.random.permutation(a))
What you see is a randomized version of the original data, such as [2 1 3]. Each time you run this code, you receive a different random ordering of the data sequence, which comes in handy with algorithms that require you to randomize the dataset to obtain the desired results. For example, sampling is an essential part of data analytics, and the technique shown is an efficient way to perform this task.
Another way to view the issue is the need to obtain all the permutations for a dataset so that you can try each one in turn. To perform this task, you need to import the itertools
package. The following code shows a technique you can use to obtain a list of all the permutations of a particular vector:
from itertools import permutations a = np.array([1,2,3]) for p in permutations(a): print(p)
The output you see looks like this:
(1, 2, 3)(1, 3, 2)(2, 1, 3)(2, 3, 1)(3, 1, 2)(3, 2, 1)
If you want to use the list comprehension (https://www.w3schools.com/python/python_lists_comprehension.asp
) approach, which is a shorter method of performing repetitive tasks, you can use [print(p) for p in permutations(a)]
instead. You can read more about itertools
at https://docs.python.org/3/library/itertools.html
.