public (I3DTensor Result, IReadOnlyList <(object X, object Y)> Index) MaxPool( int filterWidth, int filterHeight, int stride, bool calculateIndex) { var newColumns = (ColumnCount - filterWidth) / stride + 1; var newRows = (RowCount - filterHeight) / stride + 1; var matrixList = new List <CpuMatrix>(); var indexList = calculateIndex ? new List <(object X, object Y)>() : null; var posList = ConvolutionHelper.Default(ColumnCount, RowCount, filterWidth, filterHeight, stride); for (var k = 0; k < Depth; k++) { var matrix = _data[k]; var xIndex = new int[newColumns * newRows]; var yIndex = new int[newColumns * newRows]; var layer = new CpuMatrix(DenseMatrix.Create(newRows, newColumns, 0f)); foreach (var item in posList) { var first = item.First(); var targetX = first.X / stride; var targetY = first.Y / stride; var maxVal = float.MinValue; var bestX = -1; var bestY = -1; foreach (var pos in item) { var val = matrix[pos.Y, pos.X]; if (val > maxVal || bestX == -1) { bestX = pos.X; bestY = pos.Y; maxVal = val; } } var index = targetX * newRows + targetY; xIndex[index] = bestX; yIndex[index] = bestY; layer[targetY, targetX] = maxVal; } matrixList.Add(layer); indexList?.Add((xIndex, yIndex)); } return(new Cpu3DTensor(matrixList), indexList); }
public IMatrix Im2Col(int filterWidth, int filterHeight, int stride) { var rowList = new List <float[]>(); var convolutions = ConvolutionHelper.Default(ColumnCount, RowCount, filterWidth, filterHeight, stride); foreach (var filter in convolutions) { var row = new float[filter.Length * Depth]; int index = 0; for (var k = 0; k < Depth; k++) { foreach (var item in filter) { row[index++] = this[item.Y, item.X, k]; } } rowList.Add(row); } var firstRow = rowList.First(); return(new CpuMatrix(DenseMatrix.Create(rowList.Count, firstRow.Length, (i, j) => rowList[i][j]))); }