Sunday, March 29, 2020

Neural Networks on the Arduino Part 3: Details and tests of the matrix multiplication


(Read these Part 1 and Part 2 before reading this page)

Since I'm interested in getting all the neural network running on the Arduino and since neural networks use matrices, it is natural for me to use the MatrixMath.cpp library written for the Arduino by Charlie Matlack.

There was one thing I was not sure about though, can I use Matrix.Multiply function with vectors? I.e not just fully blown matrices with more than one row and more than one column. Maybe a silly question, but there your go.

I looked at the code for multiply:

//Matrix Multiplication Routine
// C = A*B
void MatrixMath::Multiply(mtx_type* A, mtx_type* B, int m, int p, int n, mtx_type* C)
{
    // A = input matrix (m x p)
    // B = input matrix (p x n)
    // m = number of rows in A
    // p = number of columns in A = number of rows in B
    // n = number of columns in B
    // C = output matrix = A*B (m x n)
    int i, j, k;
    for (i = 0; i < m; i++)
        for(j = 0; j < n; j++)
        {
            C[n * i + j] = 0;
            for (k = 0; k < p; k++)
                C[n * i + j] = C[n * i + j] + A[p * i + k] * B[n * k + j];
        }
}

...and it looked like it should work fine, even with row vectors (a vector of a single row and many columns) and column vectors (a vector which is a single column and many rows).

However trust but verify! Since in my program there will be a lot of row vectors multiplied by matrices and yielding new row vectors I thought I'd verify this:



Here is the equivalent in Arduino code:

    mtx_type ARowVector_1x3[3] = {1,2,3} ;
    mtx_type AMatrix_3x2[3][2] = {{1,2},{3,4},{5,6}} ;
    mtx_type Answer_1x2[2] ;

    Matrix.Multiply ((mtx_type*)ARowVector_1x3,
                     (mtx_type*)AMatrix_3x2,
                     1,
                     3,
                     2,
                     (mtx_type*)Answer_1x2) ;

    Matrix.Print((mtx_type*)Answer_1x2, 1, 2, "Answer 2x1");

And running the program I get the answer:
 Answer 2x1
 22.00    28.00   

which confirms that I can use Matrix.Multiply for (row vector) x (matrix) to get new a new (row vector).

And I can now easily check my code to make sure that when the first parameter is a row vector, then the third parameter should be 1. Graphically:


There are lots of places in the code where I need to be careful about these sizes, so the diagram above helps me understand if I've got it right or not.

Part 4 Hidden Errors

No comments:

Post a Comment