mathnet / mathnet-numerics

Math.NET Numerics
http://numerics.mathdotnet.com
MIT License
3.51k stars 898 forks source link

Matrix.MapPatch function #356

Open MarcoROG opened 8 years ago

MarcoROG commented 8 years ago

It would be cool to have a function that applies a function to all the patches of a matrix. For example: Matrix.MapPatch(PatchWidth,PatchHeight,Function); or Matrix.MapPatch(HorizontalPatches,VerticalPatches,Function); or even Matrix.MapPatch(PatchWidth,PatchHeight,PatchStep,Function); Where PatchStep is the distance between two patches, so that you can have them even overlapping if you want, or side by side.

I see this especially usefull for machine learning tasks, such as convolution and pooling.

I made this toy code in order to implement convolution between matrix A and B;

Parallel.For(0, HorizontalPatches, i => {
                Parallel.For(0, VerticalPatches, j =>
                 {
                     var patch = A.SubMatrix(i, B.RowCount, j, B.ColumnCount);
                     result[i, j] = patch.PointwiseMultiply(patch).ColumnSums().Sum();
                 });
            });
cdrnet commented 8 years ago

Sounds interesting. What is a matrix patch exactly?

MarcoROG commented 8 years ago

For patch i mean a SubMatrix, like i do in the sample code i pasted previously. Basically you extract a series of SubMatrixes from the original matrix, and apply the same function to all the submatrixes. For example convolution : http://ufldl.stanford.edu/tutorial/images/Convolution_schematic.gif Or Pooling : http://ufldl.stanford.edu/tutorial/images/Pooling_schematic.gif

This is, for example, extremely important in Convolutional Neural Networks for Computer Vision and Natural Language Processing. Some of the most common tasks are: -Pointwise Multiply each SubMatrix by another matrix and sum all the elements in every result, as you see in the first gif -Take the average of each SubMatrix as in the second gif -Take only the maximum value of each SubMatrix

The results of those operations should all be matrices, however i'm not sure about what should be the return type of the invoked function, since sometimes it is a decimal number, and sometimes a matrix itself

I already did some tests and this type of tasks benefit a lot from parallelisation (almost 3.8x performance boost going from singlethreaded to multithreaded by swapping the Parallel.for in the code i showed with a regular for)

pes7 commented 6 years ago
private double[,] getSubMatrix(double[,] _a, int i_start, int i_end, int j_start, int j_end)
        {
            double[,] _nex = new double[i_end - i_start + 1, j_end - j_start + 1];
            for(int i = i_start, i_sub = 0; i <= i_end; i++, i_sub++)
            {
                for(int j = j_start, j_sub = 0; j <= j_end; j++, j_sub++)
                {
                    _nex[i_sub, j_sub] = _a[i, j];
                }
            }
            return _nex;
        }

Exampe:

double[,] _a = { {22, 15, 1 },
                 {42, 5, 38 },
                 {28, 9, 4} };
getSubMatrix(_a, 1, 2, 1, 2);
//If u use MathNet
Console.WriteLine(DenseMatrix.OfArray(getSubMatrix(_a, 1, 2, 1, 2)).ToString());

U will get: {5,38}, {9,4} matrix