/*- * * * Copyright 2015 Skymind,Inc. * * * * Licensed under the Apache License, Version 2.0 (the "License"); * * you may not use this file except in compliance with the License. * * You may obtain a copy of the License at * * * * http://www.apache.org/licenses/LICENSE-2.0 * * * * Unless required by applicable law or agreed to in writing, software * * distributed under the License is distributed on an "AS IS" BASIS, * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * * See the License for the specific language governing permissions and * * limitations under the License. * * */ package org.nd4j.linalg.convolution; import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import org.nd4j.linalg.BaseNd4jTest; import org.nd4j.linalg.api.buffer.DataBuffer; import org.nd4j.linalg.api.buffer.util.AllocUtil; import org.nd4j.linalg.api.buffer.util.DataTypeUtil; import org.nd4j.linalg.api.ndarray.INDArray; import org.nd4j.linalg.factory.Nd4j; import org.nd4j.linalg.factory.Nd4jBackend; import java.util.Arrays; import static org.junit.Assert.assertEquals; /** * Created by agibsonccc on 9/6/14. */ @RunWith(Parameterized.class) public class ConvolutionTestsC extends BaseNd4jTest { public ConvolutionTestsC(Nd4jBackend backend) { super(backend); } @Test public void testConvOutWidthAndHeight() { int outSize = Convolution.outSize(2, 1, 1, 2, false); assertEquals(6, outSize); } @Test public void testIm2Col() { INDArray linspaced = Nd4j.linspace(1, 16, 16).reshape(2, 2, 2, 2); INDArray ret = Convolution.im2col(linspaced, 1, 1, 1, 1, 2, 2, 0, false); INDArray im2colAssertion = Nd4j.create(new double[] {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 2.0, 0.0, 0.0, 0.0, 0.0, 3.0, 4.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 5.0, 6.0, 0.0, 0.0, 0.0, 0.0, 7.0, 8.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 9.0, 10.0, 0.0, 0.0, 0.0, 0.0, 11.0, 12.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 13.0, 14.0, 0.0, 0.0, 0.0, 0.0, 15.0, 16.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, new int[] {2, 2, 1, 1, 6, 6}); assertEquals(im2colAssertion, ret); INDArray col2ImAssertion = Nd4j.create(new double[] {1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0 }, new int[] {2, 2, 2, 2}); INDArray otherConv = Convolution.col2im(ret, 1, 1, 2, 2, 2, 2); assertEquals(col2ImAssertion, otherConv); } @Test public void testIm2Col2() { int kh = 2; int kw = 2; int ph = 0; int pw = 0; int sy = 2; int sx = 2; int depth = 2; INDArray assertion = Nd4j.create(new double[] {1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 3, 3, 3, 3, 2, 2, 2, 2, 4, 4, 4, 4, 2, 2, 2, 2, 4, 4, 4, 4, 2, 2, 2, 2, 4, 4, 4, 4, 2, 2, 2, 2, 4, 4, 4, 4}, new int[] {1, 1, 2, 2, 4, 4}); INDArray ret = Nd4j.create(new double[] {1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4}, new int[] {1, 1, 8, 8}); INDArray test = Convolution.im2col(ret, kh, kw, sy, sx, ph, pw, 0, false); assertEquals(assertion, test); } @Test @Ignore public void testCompareIm2ColImpl() { int[] miniBatches = {1, 3, 5}; int[] depths = {1, 3, 5}; int[] inHeights = {5, 21}; int[] inWidths = {5, 21}; int[] strideH = {1, 2}; int[] strideW = {1, 2}; int[] sizeW = {1, 2, 3}; int[] sizeH = {1, 2, 3}; int[] padH = {0, 1, 2}; int[] padW = {0, 1, 2}; boolean[] coverall = {false, true}; DataBuffer.Type[] types = new DataBuffer.Type[] {DataBuffer.Type.FLOAT, DataBuffer.Type.DOUBLE, DataBuffer.Type.FLOAT, DataBuffer.Type.DOUBLE}; DataBuffer.AllocationMode[] modes = new DataBuffer.AllocationMode[] {DataBuffer.AllocationMode.HEAP, DataBuffer.AllocationMode.HEAP, DataBuffer.AllocationMode.DIRECT, DataBuffer.AllocationMode.DIRECT}; String factoryClassName = Nd4j.factory().getClass().toString().toLowerCase(); if (factoryClassName.contains("jcublas") || factoryClassName.contains("cuda")) { //Only test direct for CUDA; test all for CPU types = new DataBuffer.Type[] {DataBuffer.Type.FLOAT, DataBuffer.Type.DOUBLE}; modes = new DataBuffer.AllocationMode[] {DataBuffer.AllocationMode.DIRECT, DataBuffer.AllocationMode.DIRECT}; } DataBuffer.Type initialType = Nd4j.dataType(); for (int i = 0; i < types.length; i++) { DataBuffer.Type type = types[i]; DataBuffer.AllocationMode mode = modes[i]; DataTypeUtil.setDTypeForContext(type); Nd4j.alloc = mode; AllocUtil.setAllocationModeForContext(mode); for (int m : miniBatches) { for (int d : depths) { for (int h : inHeights) { for (int w : inWidths) { for (int sh : strideH) { for (int sw : strideW) { for (int kh : sizeH) { for (int kw : sizeW) { for (int ph : padH) { for (int pw : padW) { if ((w - kw + 2 * pw) % sw != 0 || (h - kh + 2 * ph) % sh != 0) continue; //(w-kp+2*pw)/sw + 1 is not an integer, i.e., number of outputs doesn't fit System.out.println("Running " + m + " " + d + " " + h + " " + w); for (boolean cAll : coverall) { INDArray in = Nd4j.rand(new int[] {m, d, h, w}); //assertEquals(in.data().allocationMode(), mode); //assertEquals(in.data().dataType(), type); INDArray outOrig = OldConvolution.im2col(in, kh, kw, sh, sw, ph, pw, -1, cAll); //Old implementation INDArray outNew = Convolution.im2col(in, kh, kw, sh, sw, ph, pw, cAll); //Current implementation assertEquals(outOrig, outNew); } } } } } } } } } } } } DataTypeUtil.setDTypeForContext(initialType); } @Test public void testMoreIm2Col2() { int kh = 2; int kw = 2; int ph = 0; int pw = 0; int sy = 2; int sx = 2; INDArray ret = Nd4j.create(new double[] {1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4}, new int[] {1, 1, 8, 8}); INDArray assertion = Nd4j.create(new double[] {1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 3, 3, 3, 3, 2, 2, 2, 2, 4, 4, 4, 4, 2, 2, 2, 2, 4, 4, 4, 4, 2, 2, 2, 2, 4, 4, 4, 4, 2, 2, 2, 2, 4, 4, 4, 4}, new int[] {1, 1, 2, 2, 4, 4}); INDArray im2colTest = Convolution.im2col(ret, kh, kw, sy, sx, ph, pw, 0, false); assertEquals(assertion, im2colTest); } @Test public void testCol2Im() { int kh = 1; int kw = 1; int sy = 1; int sx = 1; int ph = 1; int pw = 1; INDArray linspaced = Nd4j.linspace(1, 64, 64).reshape(2, 2, 2, 2, 2, 2); INDArray newTest = Convolution.col2im(linspaced, sy, sx, ph, pw, 2, 2); INDArray assertion = OldConvolution.col2im(linspaced, sy, sx, ph, pw, 2, 2); System.out.println("Assertion dimensions: " + Arrays.toString(assertion.shape())); assertEquals(assertion, newTest); } @Test public void testimcolim() { int nEx = 2; int depth = 3; int width = 7; int height = 7; int[] kernel = {3, 2}; int[] stride = {2, 3}; int[] padding = {1, 2}; int prod = nEx * depth * width * height; INDArray in = Nd4j.linspace(1, prod, prod).reshape(nEx, depth, width, height); INDArray assertim2col = OldConvolution.im2col(in, kernel, stride, padding); INDArray im2col = Convolution.im2col(in, kernel, stride, padding); assertEquals(assertim2col, im2col); INDArray assertcol2im = OldConvolution.col2im(im2col, stride, padding, height, width); INDArray col2im = Convolution.col2im(im2col, stride, padding, height, width); assertEquals(assertcol2im, col2im); } @Override public char ordering() { return 'c'; } }