const matrix = [ [0, 1], [2, 3], [4, 5], ];
const matrix = math.matrix([[0, 1], [2, 3], [4, 5]]);
You can get its dimension by using the
size() method and its value as array with the
valueOf() method. Furthermore, you can apply matrix operations such as addition, subtraction, multiplication and division:
const matrixA = math.matrix([[0, 1], [2, 3], [4, -5]]); const matrixB = math.matrix([[1, -1], [-2, 4], [-7, 4]]); // addition const matrixAdditionAB = math.add(matrixA, matrixB); // [ [ 1, 0 ], [ 0, 7 ], [ -3, -1 ] ] // subtraction const matrixAdditionAB = math.subtract(matrixA, matrixB); // [ [ -1, 2 ], [ 4, -1 ], [ 11, -9 ] ] // multiplication const matrixK = math.matrix([[0, 1], [2, 3], [4, 5]]); const matrixL = math.matrix([[2, 4], [6, 2]]); const matrixKL = math.multiply(matrixK, matrixL); // [ [ 6, 2 ], [ 22, 14 ], [ 38, 26 ] ] // division const matrixY = math.matrix([[0, 2], [2, 4], [4, 6]]); const matrixZ = math.matrix([[2, 1], [2, 2]]); const matrixYZ = math.divide(matrixY, matrixZ); // [ [ -2, 2 ], [ -2, 3 ], [ -2, 4 ] ]
In addition, you can perform matrix scalar multiplication and division.
// matrix scalar multiplication const matrixG = math.matrix([[0, 1], [2, 3], [4, -5]]); const matrixG3 = math.multiply(3, matrixG); // [ [ 0, 3 ], [ 6, 9 ], [ 12, -15 ] ] // matrix scalar division const matrixH = math.matrix([[2, 4], [6, 2], [4, -4]]); const matrixH2 = math.divide(matrixH, 2); // [ [ 1, 2 ], [ 3, 1 ], [ 2, -2 ] ]
Since a vector is only a specific form of a matrix, you can perform matrix-vector multiplication as well.
const matrixI = math.matrix([[0, 1], [2, 3], [4, 5]]); const vectorJ = math.matrix([, ]); const vectorIJ = math.multiply(matrixI, vectorJ); // [ [ 1 ], [ 7 ], [ 13 ] ]
math.dotMultiply(matrixI, vectorJ); or
math.dotDivide(matrixY, matrixZ). Otherwise, when using the default operators on matrices with math.js, you will apply matrix operations.
After all, dealing with matrices in math.js isn’t that difficult anymore. But you have to know the dimensions of each matrix in your operation, because not every matrix operates on another matrix. Another good thing to know are the associative and commutative matrix operations.
Is matrix multiplication associative and commutative?
There are two important properties for matrix multiplication. First, matrix multiplication is not commutative: A x B != B x A.
const matrixN = math.matrix([[0, 1], [2, 3]]); const matrixO = math.matrix([[2, 4], [6, 2]]); const matrixNO = math.multiply(matrixN, matrixO); const matrixON = math.multiply(matrixO, matrixN); console.log('Is matrix multiplication commutative?'); console.log(math.equal(matrixNO.valueOf(), matrixON.valueOf())); // false
Second, matrix multiplication is associative: A x (B x C) == (A x B) x C.
const matrixP = math.matrix([[0, 1], [2, 3], [4, 5]]); const matrixQ = math.matrix([[2, 4], [6, 2]]); const matrixR = math.matrix([[5, 2], [2, -2]]); const matrixPQ_R = math.multiply(math.multiply(matrixP, matrixQ), matrixR); const matrixP_QR = math.multiply(matrixP, math.multiply(matrixQ, matrixR)); console.log('Is matrix multiplication associative?'); console.log(math.equal(matrixPQ_R.valueOf(), matrixP_QR.valueOf())); // true
These matrix multiplication properties should be internalized before making any further more complex operations on matrices.
There are a couple of other matrix operations and matrix types in linear algebra. First, the Identity (I) Matrix with the dimension i * j is defined as i-dimensional matrix whereas i == j. The following matrix is an identity matrix.
const matrix = [ [1, 0, 0], [0, 1, 0], [0, 0, 1], ];
In math.js you can use the
eye(i) method to generate those with the dimension of i.
const matrixI3 = math.eye(3); // [ [ 1, 0, 0 ], [ 0, 1, 0 ], [ 0, 0, 1 ] ]
Identity matrices are used later on for more sophisticated matrix operations. Used with another matrix in a matrix operation, identity matrices are a special case because they are commutative: A x I == I x A.
Another type of matrix is the transposed matrix. It is a matrix where the dimensions are flipped. Basically the rows become columns and the columns become rows. In the following example, the vector becomes a so called row vector.
const matrixV = math.matrix([, , ]); const matrixV_T = math.transpose(matrixV); // [ [ 0, 1, 2 ] ]
Last but not least, matrices can have an inverse A’ but not all matrices (called singular or degenerate) have one. You can find the inverse of a matrix by using the identity matrix: A(A’) = (A’)A = I.
const matrixT = math.matrix([[0, 1], [2, 3]]); const matrixU = math.eye(2); const matrixT_I = math.divide(matrixU, matrixT); // [ [ -1.5, 0.5 ], [ 1, -0 ] ]
Math.js gives you the inverse operation for free. You can use the same matrix from the previous example and call the
inv() method on it.
const matrixS = math.matrix([[0, 1], [2, 3]]); const matrixS_I = math.inv(matrixS); // [ [ -1.5, 0.5 ], [ 1, -0 ] ]
In the end, regardless of the programming language you are using, you will find one powerful math library such as math.js to apply all of these operations.
How to apply those learnings in Machine learning?
// Predicting Housing Prices with 3 competing Hypotheses // const HOUSE_SIZES = [2104, 1416, 1534, 852]; // const h1 = x => -40 + 0.25 * x; // const h2 = x => 200 + 0.1 * x; // const h3 = x => -150 + 0.4 * x; const houseSizeMatrix = math.matrix([ [1, 2104], [1, 1416], [1, 1534], [1, 852], ]); const hypothesesMatrix = math.matrix([ [-40, 200, -150], [0.25, 0.1, 0.4], ]); const competingResults = math.multiply(houseSizeMatrix, hypothesesMatrix); // Column: Result for each Hypothesis // Row: Result for each House Size // [ // [ 486, 410.4, 691.6 ], // [ 314, 341.6, 416.4 ], // [ 343.5, 353.4, 463.6 ], // [ 173, 285.2, 190.8 ], // ]
You can put these things in matrices now, rather than executing every function on its own. A loop becomes one matrix operation. On a higher level you can say that a unvectorized implementation becomes a vectorized implementation. Thus is becomes computational efficient when performing machine learning algorithms and simpler as well. Furthermore, these matrix operations are used in a normal equation which is used as an alternative to gradient descent.
At some point, using math.js this way doesn’t scale anymore. You will do more than one matrix operation in complex mathematical expressions. What about the following expressions?
theta - ALPHA / m * ((X * theta - y)' * X)'
Yes, it is taken from a multivariate linear regression with gradient descent. It can be easily expressed in mathematical programming languages such as Matlab or Octave. In math.js it wouldn’t scale when using the standard methods.
That’s a mess. However, fortunately you can do it concise by using the eval functionality that takes a mathematical expression and the scoped values to apply those in the expression.
Still not as concise as using Octave or Matlab, but you can evaluate complex mathematical expression now. It helps you in other scenarios too. For instance, it helps you to extract a subset of a Matrix by range indices:
It returns the first and second column (indices start with 1) with all their rows as two vectors in a new matrix. It goes even further by assigning columns in a matrix a new vector.
Perhaps it helps others as well. I will collect more of these utility functions in the library. If you can point out how it can be done in math.js, I will remove it from the util library again.
Did the article help you? You can share it with your friends on social media , support me on Patreon or take one of my courses
The Road to learn React
Build a Hacker News App along the way. No setup configuration. No tooling. No Redux. Plain React in 190+ pages of learning material. Learn React like 13.000+ readers.Get the Book