diff --git a/index.html b/index.html index eafa664..fba5d9b 100644 --- a/index.html +++ b/index.html @@ -48,6 +48,8 @@ + + diff --git a/notebooks/convolutional/AtrousConvolution2D.ipynb b/notebooks/convolutional/AtrousConvolution2D.ipynb new file mode 100644 index 0000000..c8a1e4e --- /dev/null +++ b/notebooks/convolutional/AtrousConvolution2D.ipynb @@ -0,0 +1,367 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Using TensorFlow backend.\n" + ] + } + ], + "source": [ + "import numpy as np\n", + "from keras.models import Model\n", + "from keras.layers import Input\n", + "from keras.layers.convolutional import AtrousConvolution2D\n", + "from keras import backend as K" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "def format_decimal(arr, places=6):\n", + " return [round(x * 10**places) / 10**places for x in arr]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### AtrousConvolution2D" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**[convolutional.AtrousConvolution2D.0] 4 3x3 filters on 5x5x2 input, activation='linear', border_mode='valid', subsample=(1,1), atrous_rate=(2, 2), dim_ordering='tf', bias=True**" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "W shape: (3, 3, 2, 4)\n", + "W: [0.08681, -0.443261, -0.150965, 0.689552, -0.990562, -0.756862, 0.341498, 0.651706, -0.726587, 0.150187, 0.782644, -0.581596, -0.629344, -0.783246, -0.560605, 0.957248, 0.623366, -0.656118, 0.632449, -0.451853, -0.136592, 0.88006, 0.635299, -0.327776, -0.649179, -0.254336, -0.988623, -0.495147, 0.591325, -0.96949, 0.197687, 0.207609, -0.789705, -0.236113, -0.927048, 0.780823, 0.961842, -0.880116, 0.781092, 0.153803, 0.484959, 0.260368, 0.163684, -0.959122, -0.579947, 0.08937, 0.53823, -0.49861, -0.428209, 0.70479, 0.950013, 0.769707, -0.280984, 0.197718, -0.290409, -0.31962, -0.643838, -0.524612, -0.910275, 0.010863, -0.247495, 0.185611, 0.259884, -0.714799, 0.867683, 0.89276, 0.204593, -0.224467, -0.273624, -0.591309, -0.44647, -0.506928]\n", + "b shape: (4,)\n", + "b: [0.08681, -0.443261, -0.150965, 0.689552]\n", + "\n", + "in shape: (5, 5, 2)\n", + "in: [-0.990562, -0.756862, 0.341498, 0.651706, -0.726587, 0.150187, 0.782644, -0.581596, -0.629344, -0.783246, -0.560605, 0.957248, 0.623366, -0.656118, 0.632449, -0.451853, -0.136592, 0.88006, 0.635299, -0.327776, -0.649179, -0.254336, -0.988623, -0.495147, 0.591325, -0.96949, 0.197687, 0.207609, -0.789705, -0.236113, -0.927048, 0.780823, 0.961842, -0.880116, 0.781092, 0.153803, 0.484959, 0.260368, 0.163684, -0.959122, -0.579947, 0.08937, 0.53823, -0.49861, -0.428209, 0.70479, 0.950013, 0.769707, -0.280984, 0.197718]\n", + "out shape: (1, 1, 4)\n", + "out: [-0.449265, 0.56076, -2.92837, 1.056555]\n" + ] + } + ], + "source": [ + "data_in_shape = (5, 5, 2)\n", + "conv = AtrousConvolution2D(4, 3, 3, activation='linear', border_mode='valid', \n", + " subsample=(1, 1), atrous_rate=(2, 2), dim_ordering='tf', bias=True)\n", + "\n", + "layer_0 = Input(shape=data_in_shape)\n", + "layer_1 = conv(layer_0)\n", + "model = Model(input=layer_0, output=layer_1)\n", + "\n", + "# set weights to random (use seed for reproducibility)\n", + "weights = []\n", + "for w in model.get_weights():\n", + " np.random.seed(100)\n", + " weights.append(2 * np.random.random(w.shape) - 1)\n", + "model.set_weights(weights)\n", + "print('W shape:', weights[0].shape)\n", + "print('W:', format_decimal(weights[0].ravel().tolist()))\n", + "print('b shape:', weights[1].shape)\n", + "print('b:', format_decimal(weights[1].ravel().tolist()))\n", + "\n", + "data_in = 2 * np.random.random(data_in_shape) - 1\n", + "print('')\n", + "print('in shape:', data_in_shape)\n", + "print('in:', format_decimal(data_in.ravel().tolist()))\n", + "result = model.predict(np.array([data_in]))\n", + "print('out shape:', result[0].shape)\n", + "print('out:', format_decimal(result[0].ravel().tolist()))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**[convolutional.AtrousConvolution2D.1] 4 3x3 filters on 5x5x2 input, activation='linear', border_mode='valid', subsample=(1,1), atrous_rate=(2, 2), dim_ordering='tf', bias=False**" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "W shape: (3, 3, 2, 4)\n", + "W: [0.032797, 0.141335, -0.943052, -0.656957, 0.370554, 0.667794, -0.386068, 0.787226, 0.443088, -0.620122, 0.108455, -0.295736, -0.636215, 0.571204, 0.930966, -0.535293, -0.832877, 0.207097, 0.457986, -0.447522, 0.370613, 0.035735, -0.903031, -0.724262, -0.626065, 0.988636, 0.041331, 0.157579, 0.469638, 0.083924, 0.826307, 0.61584, -0.194004, -0.285551, 0.905753, -0.312737, 0.7302, 0.660555, 0.076323, 0.844939, -0.805707, -0.794305, 0.403015, 0.78096, -0.680879, -0.448855, 0.344983, -0.671394, 0.402742, -0.02473, 0.361356, 0.043096, -0.913207, -0.552127, 0.15041, -0.759133, 0.000233, -0.723981, -0.894383, -0.643446, -0.115264, 0.755175, 0.898528, -0.043665, -0.077761, 0.274578, -0.350784, -0.764844, -0.897798, 0.275317, 0.624532, 0.340521]\n", + "\n", + "in shape: (5, 5, 2)\n", + "in: [0.303535, -0.150862, 0.313191, -0.581677, 0.319849, 0.059247, 0.497041, -0.812486, 0.569044, 0.374484, 0.390157, -0.006267, 0.950722, -0.592945, -0.401959, -0.544688, -0.903662, 0.807943, -0.839793, 0.214433, 0.261693, -0.244116, -0.973518, 0.684439, -0.230125, 0.103332, 0.421076, 0.350558, 0.389129, -0.315086, -0.175219, -0.520418, 0.937672, -0.422886, -0.705377, -0.741319, 0.888112, -0.297131, 0.467135, 0.827779, 0.401975, -0.222937, 0.884519, 0.472983, -0.523071, 0.647547, 0.521227, -0.210582, -0.599624, 0.425193]\n", + "out shape: (1, 1, 4)\n", + "out: [-0.578839, 1.046696, 1.078234, 0.69352]\n" + ] + } + ], + "source": [ + "data_in_shape = (5, 5, 2)\n", + "conv = AtrousConvolution2D(4, 3, 3, activation='linear', border_mode='valid', \n", + " subsample=(1, 1), atrous_rate=(2, 2), dim_ordering='tf', bias=False)\n", + "\n", + "layer_0 = Input(shape=data_in_shape)\n", + "layer_1 = conv(layer_0)\n", + "model = Model(input=layer_0, output=layer_1)\n", + "\n", + "# set weights to random (use seed for reproducibility)\n", + "weights = []\n", + "for w in model.get_weights():\n", + " np.random.seed(101)\n", + " weights.append(2 * np.random.random(w.shape) - 1)\n", + "model.set_weights(weights)\n", + "print('W shape:', weights[0].shape)\n", + "print('W:', format_decimal(weights[0].ravel().tolist()))\n", + "\n", + "data_in = 2 * np.random.random(data_in_shape) - 1\n", + "print('')\n", + "print('in shape:', data_in_shape)\n", + "print('in:', format_decimal(data_in.ravel().tolist()))\n", + "result = model.predict(np.array([data_in]))\n", + "print('out shape:', result[0].shape)\n", + "print('out:', format_decimal(result[0].ravel().tolist()))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**[convolutional.AtrousConvolution2D.2] 4 3x3 filters on 7x7x2 input, activation='relu', border_mode='valid', subsample=(1,1), atrous_rate=(3,3), dim_ordering='tf', bias=True**" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "W shape: (3, 3, 2, 4)\n", + "W: [0.195363, 0.351974, -0.401437, 0.461481, 0.157479, 0.618035, -0.665503, -0.37571, -0.284137, -0.016505, -0.019604, 0.78882, -0.635179, -0.277676, 0.621183, -0.333106, 0.037901, -0.47676, -0.738144, -0.755166, 0.103315, -0.941233, 0.20555, 0.501765, -0.501859, -0.604645, 0.147912, 0.803597, 0.032433, -0.197603, 0.034979, 0.874782, 0.700816, -0.648994, 0.039638, 0.011529, -0.302879, -0.858314, 0.151964, -0.196575, 0.82283, 0.617771, -0.735886, 0.429729, -0.306674, 0.228823, -0.425021, 0.971139, -0.455574, 0.638783, 0.199032, 0.44091, 0.91975, -0.814286, -0.088979, 0.765096, 0.395408, -0.357503, -0.275416, 0.467275, 0.245085, -0.563436, 0.96541, -0.199388, 0.43292, -0.389609, 0.298369, -0.25199, -0.266434, -0.949491, -0.303867, -0.024641]\n", + "b shape: (4,)\n", + "b: [0.195363, 0.351974, -0.401437, 0.461481]\n", + "\n", + "in shape: (7, 7, 2)\n", + "in: [0.157479, 0.618035, -0.665503, -0.37571, -0.284137, -0.016505, -0.019604, 0.78882, -0.635179, -0.277676, 0.621183, -0.333106, 0.037901, -0.47676, -0.738144, -0.755166, 0.103315, -0.941233, 0.20555, 0.501765, -0.501859, -0.604645, 0.147912, 0.803597, 0.032433, -0.197603, 0.034979, 0.874782, 0.700816, -0.648994, 0.039638, 0.011529, -0.302879, -0.858314, 0.151964, -0.196575, 0.82283, 0.617771, -0.735886, 0.429729, -0.306674, 0.228823, -0.425021, 0.971139, -0.455574, 0.638783, 0.199032, 0.44091, 0.91975, -0.814286, -0.088979, 0.765096, 0.395408, -0.357503, -0.275416, 0.467275, 0.245085, -0.563436, 0.96541, -0.199388, 0.43292, -0.389609, 0.298369, -0.25199, -0.266434, -0.949491, -0.303867, -0.024641, -0.221058, -0.27166, -0.014907, -0.92768, -0.54906, -0.731149, 0.600323, 0.352064, -0.730288, 0.065041, 0.53791, -0.398966, -0.180102, -0.233353, 0.95265, 0.076114, 0.820989, -0.637627, -0.434933, -0.836859, -0.781756, 0.2022, 0.420213, -0.359623, 0.460477, 0.643565, -0.143274, -0.63885, -0.803257, 0.287415]\n", + "out shape: (1, 1, 4)\n", + "out: [0.0, 2.241294, 0.0, 1.107507]\n" + ] + } + ], + "source": [ + "data_in_shape = (7, 7, 2)\n", + "conv = AtrousConvolution2D(4, 3, 3, activation='relu', border_mode='valid', \n", + " subsample=(1, 1), atrous_rate=(3, 3), dim_ordering='tf', bias=True)\n", + "\n", + "layer_0 = Input(shape=data_in_shape)\n", + "layer_1 = conv(layer_0)\n", + "model = Model(input=layer_0, output=layer_1)\n", + "\n", + "# set weights to random (use seed for reproducibility)\n", + "weights = []\n", + "for w in model.get_weights():\n", + " np.random.seed(102)\n", + " weights.append(2 * np.random.random(w.shape) - 1)\n", + "model.set_weights(weights)\n", + "print('W shape:', weights[0].shape)\n", + "print('W:', format_decimal(weights[0].ravel().tolist()))\n", + "print('b shape:', weights[1].shape)\n", + "print('b:', format_decimal(weights[1].ravel().tolist()))\n", + "\n", + "data_in = 2 * np.random.random(data_in_shape) - 1\n", + "print('')\n", + "print('in shape:', data_in_shape)\n", + "print('in:', format_decimal(data_in.ravel().tolist()))\n", + "result = model.predict(np.array([data_in]))\n", + "print('out shape:', result[0].shape)\n", + "print('out:', format_decimal(result[0].ravel().tolist()))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**[convolutional.AtrousConvolution2D.3] 3 4x4 filters on 4x8x3 input, activation='relu', border_mode='same', subsample=(1,1), atrous_rate=(2,2), dim_ordering='tf', bias=True**" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "W shape: (4, 4, 3, 3)\n", + "W: [-0.135778, -0.651569, -0.658113, 0.655264, 0.174343, -0.081293, 0.64537, 0.643096, -0.385759, -0.598211, -0.193535, 0.895779, 0.355089, 0.21795, 0.344727, -0.984035, -0.32688, -0.285455, -0.02788, 0.756565, 0.509817, 0.26093, -0.247033, 0.180323, 0.474657, 0.192293, -0.815041, -0.195458, 0.179373, -0.769174, -0.223611, -0.880477, 0.167916, -0.666549, -0.303809, -0.156202, -0.501052, 0.539906, 0.10262, -0.947416, 0.541952, -0.813565, 0.405592, 0.159078, 0.198436, 0.71454, 0.102339, -0.835312, 0.466992, 0.067715, -0.315822, -0.056778, -0.556856, -0.647049, -0.050928, -0.277526, 0.64888, -0.708, 0.639138, -0.632262, 0.126027, -0.751824, 0.387838, -0.924068, -0.411933, 0.793635, -0.432359, -0.568279, -0.942986, -0.929277, 0.746907, 0.954599, -0.470971, 0.887461, -0.919761, -0.423457, 0.359481, 0.23833, 0.4367, 0.136035, 0.837921, 0.01252, 0.76166, -0.067006, -0.569453, 0.707085, -0.685992, -0.972653, 0.424172, -0.023413, -0.494544, 0.239537, -0.357146, -0.832116, 0.911805, -0.493355, 0.799492, 0.907763, 0.590698, -0.657319, -0.899599, 0.66576, -0.026552, -0.808517, 0.761201, 0.060031, 0.911167, -0.541875, -0.052366, -0.677874, -0.540037, 0.858037, 0.841428, 0.664757, 0.159247, -0.408513, 0.157763, 0.953228, -0.419758, 0.13644, 0.857617, 0.935383, -0.725736, 0.482768, 0.919937, 0.516163, 0.078243, 0.504286, 0.149417, 0.153285, -0.686413, -0.515197, 0.529735, -0.671812, 0.737835, 0.760286, -0.825563, 0.862511, -0.185154, 0.436687, -0.452091, -0.048684, 0.142544, 0.590622]\n", + "b shape: (3,)\n", + "b: [-0.135778, -0.651569, -0.658113]\n", + "\n", + "in shape: (4, 8, 3)\n", + "in: [0.655264, 0.174343, -0.081293, 0.64537, 0.643096, -0.385759, -0.598211, -0.193535, 0.895779, 0.355089, 0.21795, 0.344727, -0.984035, -0.32688, -0.285455, -0.02788, 0.756565, 0.509817, 0.26093, -0.247033, 0.180323, 0.474657, 0.192293, -0.815041, -0.195458, 0.179373, -0.769174, -0.223611, -0.880477, 0.167916, -0.666549, -0.303809, -0.156202, -0.501052, 0.539906, 0.10262, -0.947416, 0.541952, -0.813565, 0.405592, 0.159078, 0.198436, 0.71454, 0.102339, -0.835312, 0.466992, 0.067715, -0.315822, -0.056778, -0.556856, -0.647049, -0.050928, -0.277526, 0.64888, -0.708, 0.639138, -0.632262, 0.126027, -0.751824, 0.387838, -0.924068, -0.411933, 0.793635, -0.432359, -0.568279, -0.942986, -0.929277, 0.746907, 0.954599, -0.470971, 0.887461, -0.919761, -0.423457, 0.359481, 0.23833, 0.4367, 0.136035, 0.837921, 0.01252, 0.76166, -0.067006, -0.569453, 0.707085, -0.685992, -0.972653, 0.424172, -0.023413, -0.494544, 0.239537, -0.357146, -0.832116, 0.911805, -0.493355, 0.799492, 0.907763, 0.590698]\n", + "out shape: (4, 8, 3)\n", + "out: [1.131317, 0.0, 0.0, 0.809904, 0.0, 0.0, 0.056086, 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.251846, 0.0, 0.650556, 0.628197, 0.0, 0.0, 1.029379, 0.0, 2.939306, 0.23459, 0.0, 0.385831, 0.0, 0.0, 1.017464, 0.18825, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2.247988, 0.083916, 0.0, 0.0, 0.202801, 0.0, 0.137876, 1.309465, 0.0, 0.0, 0.969843, 0.531891, 0.0, 0.0, 0.06576, 0.0, 0.0, 0.0, 0.0, 0.096874, 0.0, 1.147747, 0.0, 0.0, 0.155811, 0.0, 0.331866, 0.0, 0.319746, 0.0, 0.0, 0.0, 0.0, 1.384199, 0.0, 1.856335, 0.0, 1.686605, 0.0, 0.0, 0.0, 0.0, 0.0, 1.802758, 0.0, 0.0, 0.0, 0.102891, 0.0, 0.0, 1.089357, 0.617667, 0.0, 0.0, 0.543751]\n" + ] + } + ], + "source": [ + "data_in_shape = (4, 8, 3)\n", + "conv = AtrousConvolution2D(3, 4, 4, activation='relu', border_mode='same', \n", + " subsample=(1, 1), atrous_rate=(2, 2), dim_ordering='tf', bias=True)\n", + "\n", + "layer_0 = Input(shape=data_in_shape)\n", + "layer_1 = conv(layer_0)\n", + "model = Model(input=layer_0, output=layer_1)\n", + "\n", + "# set weights to random (use seed for reproducibility)\n", + "weights = []\n", + "for w in model.get_weights():\n", + " np.random.seed(103)\n", + " weights.append(2 * np.random.random(w.shape) - 1)\n", + "model.set_weights(weights)\n", + "print('W shape:', weights[0].shape)\n", + "print('W:', format_decimal(weights[0].ravel().tolist()))\n", + "print('b shape:', weights[1].shape)\n", + "print('b:', format_decimal(weights[1].ravel().tolist()))\n", + "\n", + "data_in = 2 * np.random.random(data_in_shape) - 1\n", + "print('')\n", + "print('in shape:', data_in_shape)\n", + "print('in:', format_decimal(data_in.ravel().tolist()))\n", + "result = model.predict(np.array([data_in]))\n", + "print('out shape:', result[0].shape)\n", + "print('out:', format_decimal(result[0].ravel().tolist()))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**[convolutional.AtrousConvolution2D.4] 4 3x3 filters on 8x8x2 input, activation='relu', border_mode='same', subsample=(1,1), atrous_rate=(4,4), dim_ordering='tf', bias=True**" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "W shape: (3, 3, 2, 4)\n", + "W: [-0.704159, -0.543403, 0.614987, -0.403051, -0.628587, 0.544275, -0.189121, 0.991809, -0.028349, 0.30284, 0.201092, -0.953154, -0.343083, 0.640537, -0.117391, -0.526633, -0.163892, 0.861458, -0.665795, 0.51919, -0.753596, 0.337708, 0.402785, 0.315812, 0.541968, 0.870102, -0.141283, -0.469735, -0.574406, -0.571765, 0.046045, -0.790043, -0.953079, -0.774733, -0.58544, -0.882147, 0.282331, 0.214534, 0.862629, -0.446078, 0.230215, 0.308982, -0.361978, -0.850926, 0.409799, 0.710712, -0.391058, -0.542441, -0.41638, 0.558765, -0.149949, -0.864061, -0.759997, -0.265417, -0.331629, -0.845702, 0.426935, -0.731659, 0.062865, -0.255582, 0.396332, 0.639196, -0.078254, -0.253246, 0.792036, 0.044105, 0.879927, -0.987868, -0.35422, 0.924714, 0.304954, -0.870234]\n", + "b shape: (4,)\n", + "b: [-0.704159, -0.543403, 0.614987, -0.403051]\n", + "\n", + "in shape: (8, 8, 2)\n", + "in: [-0.628587, 0.544275, -0.189121, 0.991809, -0.028349, 0.30284, 0.201092, -0.953154, -0.343083, 0.640537, -0.117391, -0.526633, -0.163892, 0.861458, -0.665795, 0.51919, -0.753596, 0.337708, 0.402785, 0.315812, 0.541968, 0.870102, -0.141283, -0.469735, -0.574406, -0.571765, 0.046045, -0.790043, -0.953079, -0.774733, -0.58544, -0.882147, 0.282331, 0.214534, 0.862629, -0.446078, 0.230215, 0.308982, -0.361978, -0.850926, 0.409799, 0.710712, -0.391058, -0.542441, -0.41638, 0.558765, -0.149949, -0.864061, -0.759997, -0.265417, -0.331629, -0.845702, 0.426935, -0.731659, 0.062865, -0.255582, 0.396332, 0.639196, -0.078254, -0.253246, 0.792036, 0.044105, 0.879927, -0.987868, -0.35422, 0.924714, 0.304954, -0.870234, -0.611808, 0.138739, 0.526129, -0.170329, 0.504868, -0.454139, 0.245234, 0.479283, 0.651594, -0.447885, -0.78716, -0.537367, -0.578885, -0.3999, -0.981424, 0.584097, -0.461375, 0.948907, 0.763872, -0.720626, -0.572361, 0.780094, -0.385637, 0.90998, -0.697513, 0.366373, -0.427147, 0.423096, -0.55829, 0.769474, -0.484912, -0.731131, -0.794623, 0.19042, 0.537997, -0.390004, -0.697993, -0.710914, -0.222541, -0.375822, 0.236956, -0.978421, -0.834872, 0.29127, 0.125375, 0.82053, 0.953645, 0.931806, 0.170904, -0.474968, -0.266042, -0.021253, 0.449315, 0.266589, 0.405989, 0.663497, 0.762836, -0.421562, 0.664906, 0.130767]\n", + "out shape: (8, 8, 4)\n", + "out: [1.008111, 0.862141, 1.53732, 0.0, 0.0, 0.0, 2.278924, 0.0, 0.192175, 0.256028, 1.00272, 0.0, 0.0, 0.0, 0.0, 1.28356, 0.0, 0.0, 1.295987, 0.0, 0.0, 0.0, 0.522589, 0.0, 0.0, 0.0, 1.593745, 0.0, 0.094799, 1.375385, 1.350499, 0.637961, 0.0, 0.393093, 1.508163, 1.045792, 0.0, 0.580916, 0.774659, 0.0, 0.0, 0.0, 1.090937, 0.2098, 0.0, 0.0, 0.706958, 0.948835, 0.0, 0.0, 0.70246, 1.233015, 0.0, 0.0, 0.0, 0.0, 0.0, 0.237716, 0.150121, 0.0, 0.012937, 1.067614, 0.259571, 0.895802, 0.0, 0.127769, 0.0, 0.0, 0.0, 0.0, 0.0, 0.517957, 0.0, 0.0, 0.524233, 0.079491, 0.0, 0.0, 0.0, 1.424679, 0.0, 0.0, 0.798433, 0.0, 0.752754, 0.49452, 0.564184, 1.320468, 0.0, 0.0, 1.469927, 0.075539, 0.0, 0.760117, 0.0, 0.961547, 0.938599, 1.264279, 0.857871, 0.0, 0.114331, 0.0, 0.753579, 0.0, 0.0, 0.0, 0.020539, 0.0, 0.0, 0.0, 1.035394, 0.0, 0.0, 0.0, 0.745973, 0.0, 0.0, 0.070491, 0.0, 0.0, 0.0, 0.0, 0.308166, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.911015, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.178493, 1.44698, 0.0, 0.0, 0.0, 1.45985, 0.298695, 0.0, 0.0, 0.0, 0.0, 0.0, 0.402046, 0.536043, 1.160239, 0.0, 0.0, 0.0, 0.0, 0.575623, 0.009206, 0.639194, 0.0, 0.353097, 0.0, 0.471996, 0.411527, 1.148312, 0.966958, 1.172197, 0.0, 0.419191, 0.0, 2.142206, 0.0, 0.0, 0.0, 0.0, 0.0, 0.508378, 0.0, 1.110668, 1.82902, 0.0, 0.0, 2.081267, 0.05382, 0.0, 0.0, 1.5163, 1.476838, 1.364327, 0.033732, 1.076706, 0.609169, 0.0, 0.149234, 2.181282, 0.780896, 0.0, 0.0, 0.763411, 0.0, 0.0, 0.0, 2.053607, 0.12022, 0.0, 0.0, 0.0, 0.29116, 0.0, 0.0, 0.656705, 0.0, 0.0, 0.0, 1.055828, 0.634612, 0.0, 0.0, 0.0, 0.363467, 1.779839, 0.0, 1.270641, 0.15881, 0.0, 0.020913, 0.854418, 0.0, 0.0, 0.0, 0.436751, 0.0, 0.0, 0.0, 0.0, 0.0, 0.436203, 0.236268, 0.0, 0.0, 0.0, 0.0, 0.189446, 0.0, 0.0, 0.0, 0.827813, 0.0, 0.0, 0.0, 0.31375, 0.0, 0.0, 0.0, 0.755046, 0.0]\n" + ] + } + ], + "source": [ + "data_in_shape = (8, 8, 2)\n", + "conv = AtrousConvolution2D(4, 3, 3, activation='relu', border_mode='same', \n", + " subsample=(1, 1), atrous_rate=(4, 4), dim_ordering='tf', bias=True)\n", + "\n", + "layer_0 = Input(shape=data_in_shape)\n", + "layer_1 = conv(layer_0)\n", + "model = Model(input=layer_0, output=layer_1)\n", + "\n", + "# set weights to random (use seed for reproducibility)\n", + "weights = []\n", + "for w in model.get_weights():\n", + " np.random.seed(104)\n", + " weights.append(2 * np.random.random(w.shape) - 1)\n", + "model.set_weights(weights)\n", + "print('W shape:', weights[0].shape)\n", + "print('W:', format_decimal(weights[0].ravel().tolist()))\n", + "print('b shape:', weights[1].shape)\n", + "print('b:', format_decimal(weights[1].ravel().tolist()))\n", + "\n", + "data_in = 2 * np.random.random(data_in_shape) - 1\n", + "print('')\n", + "print('in shape:', data_in_shape)\n", + "print('in:', format_decimal(data_in.ravel().tolist()))\n", + "result = model.predict(np.array([data_in]))\n", + "print('out shape:', result[0].shape)\n", + "print('out:', format_decimal(result[0].ravel().tolist()))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.5.2" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} diff --git a/src/layers/convolutional/AtrousConvolution2D.js b/src/layers/convolutional/AtrousConvolution2D.js new file mode 100644 index 0000000..84174a2 --- /dev/null +++ b/src/layers/convolutional/AtrousConvolution2D.js @@ -0,0 +1,260 @@ +import * as activations from '../../activations' +import Tensor from '../../Tensor' +import Layer from '../../engine/Layer' +import ops from 'ndarray-ops' +import gemm from 'ndarray-gemm' +import unpack from 'ndarray-unpack' +import flattenDeep from 'lodash/flattenDeep' + +/** + * AtrousConvolution2D layer class + */ +export default class AtrousConvolution2D extends Layer { + /** + * Creates a AtrousConvolution2D layer + * @param {number} nbFilter - Number of convolution filters to use. + * @param {number} nbRow - Number of rows in the convolution kernel. + * @param {number} nbCol - Number of columns in the convolution kernel. + * @param {Object} [attrs] - layer attributes + */ + constructor (nbFilter, nbRow, nbCol, attrs = {}) { + super(attrs) + const { + activation = 'linear', + borderMode = 'valid', + subsample = [1, 1], + atrousRate = [1, 1], + dimOrdering = 'tf', + bias = true + } = attrs + + this.kernelShape = [nbFilter, nbRow, nbCol] + + this.activation = activations[activation] + + if (borderMode === 'valid' || borderMode === 'same') { + this.borderMode = borderMode + } else { + throw new Error(`${this.name} [AtrousConvolution2D layer] Invalid borderMode.`) + } + + this.subsample = subsample + + this.atrousRate = atrousRate + + if (dimOrdering === 'tf' || dimOrdering === 'th') { + this.dimOrdering = dimOrdering + } else { + throw new Error(`${this.name} [AtrousConvolution2D layer] Only tf and th dim ordering are allowed.`) + } + + this.bias = bias + + // Layer weights specification + this.params = this.bias ? ['W', 'b'] : ['W'] + } + + /** + * Method for setting layer weights. Extends `super` method. + * W weight tensor is converted to `tf` mode if in `th` mode. + * In `tf` mode, W weight tensor has shape [nbRow, nbCol, inputChannels, nbFilter] + * In `th` mode, W weight tensor has shape [nbFilter, inputChannels, nbRow, nbCol] + * @param {Tensor[]} weightsArr - array of weights which are instances of Tensor + */ + setWeights (weightsArr) { + if (this.dimOrdering === 'th') { + // W + weightsArr[0].tensor = weightsArr[0].tensor.transpose(2, 3, 1, 0) + } + super.setWeights(weightsArr) + } + + /** + * Method for computing output dimensions and padding, based on input + * dimensions, kernel size, and padding mode. + * For tensorflow implementation of padding, see: + * https://github.com/tensorflow/tensorflow/blob/master/tensorflow/core/framework/common_shape_fns.cc + * @param {Tensor} x + * @returns {number[]} [outputRows, outputCols, outputChannels] + */ + _calcOutputShape = x => { + const inputRows = x.tensor.shape[0] + const inputCols = x.tensor.shape[1] + const [nbFilter, nbRow, nbCol] = this.kernelShape + + // effective shape after filter dilation + const nbRowDilated = nbRow + (nbRow - 1) * (this.atrousRate[0] - 1) + const nbColDilated = nbCol + (nbCol - 1) * (this.atrousRate[1] - 1) + + const outputRows = this.borderMode === 'same' + ? Math.floor((inputRows + this.subsample[0] - 1) / this.subsample[0]) + : Math.floor((inputRows - nbRowDilated + this.subsample[0]) / this.subsample[0]) + const outputCols = this.borderMode === 'same' + ? Math.floor((inputCols + this.subsample[1] - 1) / this.subsample[1]) + : Math.floor((inputCols - nbColDilated + this.subsample[1]) / this.subsample[1]) + const outputChannels = nbFilter + + const paddingRow = this.borderMode === 'same' + ? Math.max(0, Math.floor((outputRows - 1) * this.subsample[0] + nbRowDilated - inputRows)) + : 0 + const paddingCol = this.borderMode === 'same' + ? Math.max(0, Math.floor((outputCols - 1) * this.subsample[1] + nbColDilated - inputCols)) + : 0 + const paddingRowBefore = Math.floor(paddingRow / 2) + const paddingRowAfter = paddingRow - paddingRowBefore + const paddingColBefore = Math.floor(paddingCol / 2) + const paddingColAfter = paddingCol - paddingColBefore + + this.outputShape = [outputRows, outputCols, outputChannels] + this.inputPadding = [paddingRowBefore, paddingRowAfter, paddingColBefore, paddingColAfter] + } + + /** + * Pad input tensor if necessary, for borderMode='same'. + * See above for notes on calculating padding. + * @param {Tensor} x + * @returns {Tensor} x + */ + _padInput = x => { + if (this.borderMode === 'same') { + const [inputRows, inputCols, inputChannels] = x.tensor.shape + const [paddingRowBefore, paddingRowAfter, paddingColBefore, paddingColAfter] = this.inputPadding + const newRows = inputRows + paddingRowBefore + paddingRowAfter + const newCols = inputCols + paddingColBefore + paddingColAfter + let _x = new Tensor([], [newRows, newCols, inputChannels]) + ops.assign( + _x.tensor + .hi(inputRows + paddingRowBefore, inputCols + paddingColBefore, inputChannels) + .lo(paddingRowBefore, paddingColBefore, 0), + x.tensor + ) + x.tensor = _x.tensor + } + return x + } + + /** + * Convert input image to column matrix + * @param {Tensor} x + * @returns {Tensor} x + */ + _im2col = x => { + const [inputRows, inputCols, inputChannels] = x.tensor.shape + const nbRow = this.kernelShape[1] + const nbCol = this.kernelShape[2] + const outputRows = this.outputShape[0] + const outputCols = this.outputShape[1] + const nbPatches = outputRows * outputCols + const patchLen = nbRow * nbCol * inputChannels + + // effective shape after filter dilation + const nbRowDilated = nbRow + (nbRow - 1) * (this.atrousRate[0] - 1) + const nbColDilated = nbCol + (nbCol - 1) * (this.atrousRate[1] - 1) + + const imColsMat = new Tensor([], [nbPatches, patchLen]) + + let patch = new Tensor([], [patchLen]) + let n = 0 + for (let i = 0; i <= inputRows - nbRowDilated; i += this.subsample[0]) { + for (let j = 0; j <= inputCols - nbColDilated; j += this.subsample[1]) { + const patchData = flattenDeep(unpack( + x.tensor + .hi(i + nbRowDilated, j + nbColDilated, inputChannels) + .lo(i, j, 0) + .step(this.atrousRate[0], this.atrousRate[1], 1) + )) + patch.replaceTensorData(patchData) + ops.assign(imColsMat.tensor.pick(n, null), patch.tensor) + n += 1 + } + } + + return imColsMat + } + + /** + * Convert filter weights to row matrix + * @param {Tensor} x + * @returns {Tensor} x + */ + _w2row = x => { + const inputChannels = x.tensor.shape[2] + const [nbFilter, nbRow, nbCol] = this.kernelShape + const patchLen = nbRow * nbCol * inputChannels + + const wRowsMat = new Tensor([], [patchLen, nbFilter]) + + let patch = new Tensor([], [patchLen]) + for (let n = 0; n < nbFilter; n++) { + const patchData = flattenDeep(unpack( + this.weights.W.tensor.pick(null, null, null, n) + )) + patch.replaceTensorData(patchData) + ops.assign(wRowsMat.tensor.pick(null, n), patch.tensor) + } + + return wRowsMat + } + + /** + * Method for layer computational logic + * @param {Tensor} x + * @returns {Tensor} x + */ + call = x => { + // convert to tf ordering + if (this.dimOrdering === 'th') { + x.tensor = x.tensor.transpose(1, 2, 0) + } + + this._calcOutputShape(x) + this._padInput(x) + + const imColsMat = this._im2col(x) + const wRowsMat = this._w2row(x) + + const nbFilter = this.kernelShape[0] + const outputRows = this.outputShape[0] + const outputCols = this.outputShape[1] + const nbPatches = outputRows * outputCols + const matMul = new Tensor([], [nbPatches, nbFilter]) + if (this.bias) { + for (let n = 0; n < nbFilter; n++) { + ops.assigns(matMul.tensor.pick(null, n), this.weights.b.tensor.get(n)) + } + } + + if (x._useWeblas) { + const bias = this.bias + ? this.weights.b.tensor.data + : new Float32Array(wRowsMat.tensor.shape[1]) + matMul.tensor.data = weblas.sgemm( + imColsMat.tensor.shape[0], wRowsMat.tensor.shape[1], imColsMat.tensor.shape[1], // M, N, K + 1, imColsMat.tensor.data, wRowsMat.tensor.data, // alpha, A, B + 1, bias // beta, C + ) + } else { + gemm(matMul.tensor, imColsMat.tensor, wRowsMat.tensor, 1, 1) + } + + let output = new Tensor([], this.outputShape) + let outputChannel = new Tensor([], [outputRows, outputCols]) + for (let n = 0; n < nbFilter; n++) { + const outputChannelData = flattenDeep(unpack( + matMul.tensor.pick(null, n) + )) + outputChannel.replaceTensorData(outputChannelData) + ops.assign(output.tensor.pick(null, null, n), outputChannel.tensor) + } + x.tensor = output.tensor + + this.activation(x) + + // convert back to th ordering if necessary + if (this.dimOrdering === 'th') { + x.tensor = x.tensor.transpose(2, 0, 1) + } + + return x + } +} diff --git a/src/layers/convolutional/index.js b/src/layers/convolutional/index.js index 93fe4bf..e2890ef 100644 --- a/src/layers/convolutional/index.js +++ b/src/layers/convolutional/index.js @@ -1,5 +1,6 @@ import Convolution1D from './Convolution1D' import Convolution2D from './Convolution2D' +import AtrousConvolution2D from './AtrousConvolution2D' import Convolution3D from './Convolution3D' import UpSampling1D from './UpSampling1D' import UpSampling2D from './UpSampling2D' @@ -11,6 +12,7 @@ import ZeroPadding3D from './ZeroPadding3D' export { Convolution1D, Convolution2D, + AtrousConvolution2D, Convolution3D, UpSampling1D, UpSampling2D, diff --git a/test/convolutional/AtrousConvolution2D.js b/test/convolutional/AtrousConvolution2D.js new file mode 100644 index 0000000..22295ad --- /dev/null +++ b/test/convolutional/AtrousConvolution2D.js @@ -0,0 +1,110 @@ +/* eslint-env browser, mocha */ + +describe('convolutional layer: AtrousConvolution2D', function () { + const assert = chai.assert + const styles = testGlobals.styles + const logTime = testGlobals.logTime + const stringifyCondensed = testGlobals.stringifyCondensed + const approxEquals = KerasJS.testUtils.approxEquals + const layers = KerasJS.layers + + const testParams = [ + { + inputShape: [5, 5, 2], + kernelShape: [4, 3, 3], + attrs: { activation: 'linear', borderMode: 'valid', subsample: [1, 1], atrousRate: [2, 2], dimOrdering: 'tf', bias: true } + }, + { + inputShape: [5, 5, 2], + kernelShape: [4, 3, 3], + attrs: { activation: 'linear', borderMode: 'valid', subsample: [1, 1], atrousRate: [2, 2], dimOrdering: 'tf', bias: false } + }, + { + inputShape: [7, 7, 2], + kernelShape: [4, 3, 3], + attrs: { activation: 'relu', borderMode: 'valid', subsample: [1, 1], atrousRate: [3, 3], dimOrdering: 'tf', bias: true } + }, + { + inputShape: [4, 8, 3], + kernelShape: [3, 4, 4], + attrs: { activation: 'relu', borderMode: 'same', subsample: [1, 1], atrousRate: [2, 2], dimOrdering: 'tf', bias: true } + }, + { + inputShape: [8, 8, 2], + kernelShape: [4, 3, 3], + attrs: { activation: 'relu', borderMode: 'same', subsample: [1, 1], atrousRate: [4, 4], dimOrdering: 'tf', bias: true } + } + ] + + before(function () { + console.log('\n%cconvolutional layer: AtrousConvolution2D', styles.h1) + }) + + /********************************************************* + * CPU + *********************************************************/ + + describe('CPU', function () { + before(function () { + console.log('\n%cCPU', styles.h2) + }) + + testParams.forEach(({ inputShape, kernelShape, attrs }, i) => { + const key = `convolutional.AtrousConvolution2D.${i}` + const [inputRows, inputCols, inputChannels] = inputShape + const [nbFilter, nbRow, nbCol] = kernelShape + const title = `[${key}] [CPU] test: ${nbFilter} ${nbRow}x${nbCol} filters on ${inputRows}x${inputCols}x${inputChannels} input, activation='${attrs.activation}', border_mode='${attrs.borderMode}', subsample=${attrs.subsample}, atrousRate=${attrs.atrousRate}, dim_ordering='${attrs.dimOrdering}', bias=${attrs.bias}` + + it(title, function () { + console.log(`\n%c${title}`, styles.h3) + let testLayer = new layers.AtrousConvolution2D(nbFilter, nbRow, nbCol, attrs) + testLayer.setWeights(TEST_DATA[key].weights.map(w => new KerasJS.Tensor(w.data, w.shape))) + let t = new KerasJS.Tensor(TEST_DATA[key].input.data, TEST_DATA[key].input.shape) + console.log('%cin', styles.h4, stringifyCondensed(t.tensor)) + const startTime = performance.now() + t = testLayer.call(t) + const endTime = performance.now() + console.log('%cout', styles.h4, stringifyCondensed(t.tensor)) + logTime(startTime, endTime) + const dataExpected = new Float32Array(TEST_DATA[key].expected.data) + const shapeExpected = TEST_DATA[key].expected.shape + assert.deepEqual(t.tensor.shape, shapeExpected) + assert.isTrue(approxEquals(t.tensor, dataExpected)) + }) + }) + }) + + /********************************************************* + * GPU + *********************************************************/ + + describe('GPU', function () { + before(function () { + console.log('\n%cGPU', styles.h2) + }) + + testParams.forEach(({ inputShape, kernelShape, attrs }, i) => { + const key = `convolutional.AtrousConvolution2D.${i}` + const [inputRows, inputCols, inputChannels] = inputShape + const [nbFilter, nbRow, nbCol] = kernelShape + const title = `[${key}] [GPU] test: ${nbFilter} ${nbRow}x${nbCol} filters on ${inputRows}x${inputCols}x${inputChannels} input, activation='${attrs.activation}', border_mode='${attrs.borderMode}', subsample=${attrs.subsample}, atrousRate=${attrs.atrousRate}, dim_ordering='${attrs.dimOrdering}', bias=${attrs.bias}` + + it(title, function () { + console.log(`\n%c${title}`, styles.h3) + let testLayer = new layers.AtrousConvolution2D(nbFilter, nbRow, nbCol, attrs) + testLayer.setWeights(TEST_DATA[key].weights.map(w => new KerasJS.Tensor(w.data, w.shape))) + let t = new KerasJS.Tensor(TEST_DATA[key].input.data, TEST_DATA[key].input.shape, { useWeblas: true }) + console.log('%cin', styles.h4, stringifyCondensed(t.tensor)) + const startTime = performance.now() + t = testLayer.call(t) + const endTime = performance.now() + console.log('%cout', styles.h4, stringifyCondensed(t.tensor)) + logTime(startTime, endTime) + const dataExpected = new Float32Array(TEST_DATA[key].expected.data) + const shapeExpected = TEST_DATA[key].expected.shape + assert.deepEqual(t.tensor.shape, shapeExpected) + assert.isTrue(approxEquals(t.tensor, dataExpected)) + }) + }) + }) +}) diff --git a/test/convolutional/data_AtrousConvolution2D.js b/test/convolutional/data_AtrousConvolution2D.js new file mode 100644 index 0000000..467b55d --- /dev/null +++ b/test/convolutional/data_AtrousConvolution2D.js @@ -0,0 +1,106 @@ +// TEST DATA +// Keyed by mocha test ID +// Python code for generating test data can be found in the matching jupyter notebook in folder `notebooks/`. + +(function () { + var DATA = { + 'convolutional.AtrousConvolution2D.0': { + input: { + data: [-0.990562, -0.756862, 0.341498, 0.651706, -0.726587, 0.150187, 0.782644, -0.581596, -0.629344, -0.783246, -0.560605, 0.957248, 0.623366, -0.656118, 0.632449, -0.451853, -0.136592, 0.88006, 0.635299, -0.327776, -0.649179, -0.254336, -0.988623, -0.495147, 0.591325, -0.96949, 0.197687, 0.207609, -0.789705, -0.236113, -0.927048, 0.780823, 0.961842, -0.880116, 0.781092, 0.153803, 0.484959, 0.260368, 0.163684, -0.959122, -0.579947, 0.08937, 0.53823, -0.49861, -0.428209, 0.70479, 0.950013, 0.769707, -0.280984, 0.197718], + shape: [5, 5, 2] + }, + weights: [ + { + data: [0.08681, -0.443261, -0.150965, 0.689552, -0.990562, -0.756862, 0.341498, 0.651706, -0.726587, 0.150187, 0.782644, -0.581596, -0.629344, -0.783246, -0.560605, 0.957248, 0.623366, -0.656118, 0.632449, -0.451853, -0.136592, 0.88006, 0.635299, -0.327776, -0.649179, -0.254336, -0.988623, -0.495147, 0.591325, -0.96949, 0.197687, 0.207609, -0.789705, -0.236113, -0.927048, 0.780823, 0.961842, -0.880116, 0.781092, 0.153803, 0.484959, 0.260368, 0.163684, -0.959122, -0.579947, 0.08937, 0.53823, -0.49861, -0.428209, 0.70479, 0.950013, 0.769707, -0.280984, 0.197718, -0.290409, -0.31962, -0.643838, -0.524612, -0.910275, 0.010863, -0.247495, 0.185611, 0.259884, -0.714799, 0.867683, 0.89276, 0.204593, -0.224467, -0.273624, -0.591309, -0.44647, -0.506928], + shape: [3, 3, 2, 4] + }, + { + data: [0.08681, -0.443261, -0.150965, 0.689552], + shape: [4] + } + ], + expected: { + data: [-0.449265, 0.56076, -2.92837, 1.056555], + shape: [1, 1, 4] + } + }, + 'convolutional.AtrousConvolution2D.1': { + input: { + data: [0.303535, -0.150862, 0.313191, -0.581677, 0.319849, 0.059247, 0.497041, -0.812486, 0.569044, 0.374484, 0.390157, -0.006267, 0.950722, -0.592945, -0.401959, -0.544688, -0.903662, 0.807943, -0.839793, 0.214433, 0.261693, -0.244116, -0.973518, 0.684439, -0.230125, 0.103332, 0.421076, 0.350558, 0.389129, -0.315086, -0.175219, -0.520418, 0.937672, -0.422886, -0.705377, -0.741319, 0.888112, -0.297131, 0.467135, 0.827779, 0.401975, -0.222937, 0.884519, 0.472983, -0.523071, 0.647547, 0.521227, -0.210582, -0.599624, 0.425193], + shape: [5, 5, 2] + }, + weights: [ + { + data: [0.032797, 0.141335, -0.943052, -0.656957, 0.370554, 0.667794, -0.386068, 0.787226, 0.443088, -0.620122, 0.108455, -0.295736, -0.636215, 0.571204, 0.930966, -0.535293, -0.832877, 0.207097, 0.457986, -0.447522, 0.370613, 0.035735, -0.903031, -0.724262, -0.626065, 0.988636, 0.041331, 0.157579, 0.469638, 0.083924, 0.826307, 0.61584, -0.194004, -0.285551, 0.905753, -0.312737, 0.7302, 0.660555, 0.076323, 0.844939, -0.805707, -0.794305, 0.403015, 0.78096, -0.680879, -0.448855, 0.344983, -0.671394, 0.402742, -0.02473, 0.361356, 0.043096, -0.913207, -0.552127, 0.15041, -0.759133, 0.000233, -0.723981, -0.894383, -0.643446, -0.115264, 0.755175, 0.898528, -0.043665, -0.077761, 0.274578, -0.350784, -0.764844, -0.897798, 0.275317, 0.624532, 0.340521], + shape: [3, 3, 2, 4] + } + ], + expected: { + data: [-0.578839, 1.046696, 1.078234, 0.69352], + shape: [1, 1, 4] + } + }, + 'convolutional.AtrousConvolution2D.2': { + input: { + data: [0.157479, 0.618035, -0.665503, -0.37571, -0.284137, -0.016505, -0.019604, 0.78882, -0.635179, -0.277676, 0.621183, -0.333106, 0.037901, -0.47676, -0.738144, -0.755166, 0.103315, -0.941233, 0.20555, 0.501765, -0.501859, -0.604645, 0.147912, 0.803597, 0.032433, -0.197603, 0.034979, 0.874782, 0.700816, -0.648994, 0.039638, 0.011529, -0.302879, -0.858314, 0.151964, -0.196575, 0.82283, 0.617771, -0.735886, 0.429729, -0.306674, 0.228823, -0.425021, 0.971139, -0.455574, 0.638783, 0.199032, 0.44091, 0.91975, -0.814286, -0.088979, 0.765096, 0.395408, -0.357503, -0.275416, 0.467275, 0.245085, -0.563436, 0.96541, -0.199388, 0.43292, -0.389609, 0.298369, -0.25199, -0.266434, -0.949491, -0.303867, -0.024641, -0.221058, -0.27166, -0.014907, -0.92768, -0.54906, -0.731149, 0.600323, 0.352064, -0.730288, 0.065041, 0.53791, -0.398966, -0.180102, -0.233353, 0.95265, 0.076114, 0.820989, -0.637627, -0.434933, -0.836859, -0.781756, 0.2022, 0.420213, -0.359623, 0.460477, 0.643565, -0.143274, -0.63885, -0.803257, 0.287415], + shape: [7, 7, 2] + }, + weights: [ + { + data: [0.195363, 0.351974, -0.401437, 0.461481, 0.157479, 0.618035, -0.665503, -0.37571, -0.284137, -0.016505, -0.019604, 0.78882, -0.635179, -0.277676, 0.621183, -0.333106, 0.037901, -0.47676, -0.738144, -0.755166, 0.103315, -0.941233, 0.20555, 0.501765, -0.501859, -0.604645, 0.147912, 0.803597, 0.032433, -0.197603, 0.034979, 0.874782, 0.700816, -0.648994, 0.039638, 0.011529, -0.302879, -0.858314, 0.151964, -0.196575, 0.82283, 0.617771, -0.735886, 0.429729, -0.306674, 0.228823, -0.425021, 0.971139, -0.455574, 0.638783, 0.199032, 0.44091, 0.91975, -0.814286, -0.088979, 0.765096, 0.395408, -0.357503, -0.275416, 0.467275, 0.245085, -0.563436, 0.96541, -0.199388, 0.43292, -0.389609, 0.298369, -0.25199, -0.266434, -0.949491, -0.303867, -0.024641], + shape: [3, 3, 2, 4] + }, + { + data: [0.195363, 0.351974, -0.401437, 0.461481], + shape: [4] + } + ], + expected: { + data: [0.0, 2.241294, 0.0, 1.107507], + shape: [1, 1, 4] + } + }, + 'convolutional.AtrousConvolution2D.3': { + input: { + data: [0.655264, 0.174343, -0.081293, 0.64537, 0.643096, -0.385759, -0.598211, -0.193535, 0.895779, 0.355089, 0.21795, 0.344727, -0.984035, -0.32688, -0.285455, -0.02788, 0.756565, 0.509817, 0.26093, -0.247033, 0.180323, 0.474657, 0.192293, -0.815041, -0.195458, 0.179373, -0.769174, -0.223611, -0.880477, 0.167916, -0.666549, -0.303809, -0.156202, -0.501052, 0.539906, 0.10262, -0.947416, 0.541952, -0.813565, 0.405592, 0.159078, 0.198436, 0.71454, 0.102339, -0.835312, 0.466992, 0.067715, -0.315822, -0.056778, -0.556856, -0.647049, -0.050928, -0.277526, 0.64888, -0.708, 0.639138, -0.632262, 0.126027, -0.751824, 0.387838, -0.924068, -0.411933, 0.793635, -0.432359, -0.568279, -0.942986, -0.929277, 0.746907, 0.954599, -0.470971, 0.887461, -0.919761, -0.423457, 0.359481, 0.23833, 0.4367, 0.136035, 0.837921, 0.01252, 0.76166, -0.067006, -0.569453, 0.707085, -0.685992, -0.972653, 0.424172, -0.023413, -0.494544, 0.239537, -0.357146, -0.832116, 0.911805, -0.493355, 0.799492, 0.907763, 0.590698], + shape: [4, 8, 3] + }, + weights: [ + { + data: [-0.135778, -0.651569, -0.658113, 0.655264, 0.174343, -0.081293, 0.64537, 0.643096, -0.385759, -0.598211, -0.193535, 0.895779, 0.355089, 0.21795, 0.344727, -0.984035, -0.32688, -0.285455, -0.02788, 0.756565, 0.509817, 0.26093, -0.247033, 0.180323, 0.474657, 0.192293, -0.815041, -0.195458, 0.179373, -0.769174, -0.223611, -0.880477, 0.167916, -0.666549, -0.303809, -0.156202, -0.501052, 0.539906, 0.10262, -0.947416, 0.541952, -0.813565, 0.405592, 0.159078, 0.198436, 0.71454, 0.102339, -0.835312, 0.466992, 0.067715, -0.315822, -0.056778, -0.556856, -0.647049, -0.050928, -0.277526, 0.64888, -0.708, 0.639138, -0.632262, 0.126027, -0.751824, 0.387838, -0.924068, -0.411933, 0.793635, -0.432359, -0.568279, -0.942986, -0.929277, 0.746907, 0.954599, -0.470971, 0.887461, -0.919761, -0.423457, 0.359481, 0.23833, 0.4367, 0.136035, 0.837921, 0.01252, 0.76166, -0.067006, -0.569453, 0.707085, -0.685992, -0.972653, 0.424172, -0.023413, -0.494544, 0.239537, -0.357146, -0.832116, 0.911805, -0.493355, 0.799492, 0.907763, 0.590698, -0.657319, -0.899599, 0.66576, -0.026552, -0.808517, 0.761201, 0.060031, 0.911167, -0.541875, -0.052366, -0.677874, -0.540037, 0.858037, 0.841428, 0.664757, 0.159247, -0.408513, 0.157763, 0.953228, -0.419758, 0.13644, 0.857617, 0.935383, -0.725736, 0.482768, 0.919937, 0.516163, 0.078243, 0.504286, 0.149417, 0.153285, -0.686413, -0.515197, 0.529735, -0.671812, 0.737835, 0.760286, -0.825563, 0.862511, -0.185154, 0.436687, -0.452091, -0.048684, 0.142544, 0.590622], + shape: [4, 4, 3, 3] + }, + { + data: [-0.135778, -0.651569, -0.658113], + shape: [3] + } + ], + expected: { + data: [1.131317, 0.0, 0.0, 0.809904, 0.0, 0.0, 0.056086, 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.251846, 0.0, 0.650556, 0.628197, 0.0, 0.0, 1.029379, 0.0, 2.939306, 0.23459, 0.0, 0.385831, 0.0, 0.0, 1.017464, 0.18825, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2.247988, 0.083916, 0.0, 0.0, 0.202801, 0.0, 0.137876, 1.309465, 0.0, 0.0, 0.969843, 0.531891, 0.0, 0.0, 0.06576, 0.0, 0.0, 0.0, 0.0, 0.096874, 0.0, 1.147747, 0.0, 0.0, 0.155811, 0.0, 0.331866, 0.0, 0.319746, 0.0, 0.0, 0.0, 0.0, 1.384199, 0.0, 1.856335, 0.0, 1.686605, 0.0, 0.0, 0.0, 0.0, 0.0, 1.802758, 0.0, 0.0, 0.0, 0.102891, 0.0, 0.0, 1.089357, 0.617667, 0.0, 0.0, 0.543751], + shape: [4, 8, 3] + } + }, + 'convolutional.AtrousConvolution2D.4': { + input: { + data: [-0.628587, 0.544275, -0.189121, 0.991809, -0.028349, 0.30284, 0.201092, -0.953154, -0.343083, 0.640537, -0.117391, -0.526633, -0.163892, 0.861458, -0.665795, 0.51919, -0.753596, 0.337708, 0.402785, 0.315812, 0.541968, 0.870102, -0.141283, -0.469735, -0.574406, -0.571765, 0.046045, -0.790043, -0.953079, -0.774733, -0.58544, -0.882147, 0.282331, 0.214534, 0.862629, -0.446078, 0.230215, 0.308982, -0.361978, -0.850926, 0.409799, 0.710712, -0.391058, -0.542441, -0.41638, 0.558765, -0.149949, -0.864061, -0.759997, -0.265417, -0.331629, -0.845702, 0.426935, -0.731659, 0.062865, -0.255582, 0.396332, 0.639196, -0.078254, -0.253246, 0.792036, 0.044105, 0.879927, -0.987868, -0.35422, 0.924714, 0.304954, -0.870234, -0.611808, 0.138739, 0.526129, -0.170329, 0.504868, -0.454139, 0.245234, 0.479283, 0.651594, -0.447885, -0.78716, -0.537367, -0.578885, -0.3999, -0.981424, 0.584097, -0.461375, 0.948907, 0.763872, -0.720626, -0.572361, 0.780094, -0.385637, 0.90998, -0.697513, 0.366373, -0.427147, 0.423096, -0.55829, 0.769474, -0.484912, -0.731131, -0.794623, 0.19042, 0.537997, -0.390004, -0.697993, -0.710914, -0.222541, -0.375822, 0.236956, -0.978421, -0.834872, 0.29127, 0.125375, 0.82053, 0.953645, 0.931806, 0.170904, -0.474968, -0.266042, -0.021253, 0.449315, 0.266589, 0.405989, 0.663497, 0.762836, -0.421562, 0.664906, 0.130767], + shape: [8, 8, 2] + }, + weights: [ + { + data: [-0.704159, -0.543403, 0.614987, -0.403051, -0.628587, 0.544275, -0.189121, 0.991809, -0.028349, 0.30284, 0.201092, -0.953154, -0.343083, 0.640537, -0.117391, -0.526633, -0.163892, 0.861458, -0.665795, 0.51919, -0.753596, 0.337708, 0.402785, 0.315812, 0.541968, 0.870102, -0.141283, -0.469735, -0.574406, -0.571765, 0.046045, -0.790043, -0.953079, -0.774733, -0.58544, -0.882147, 0.282331, 0.214534, 0.862629, -0.446078, 0.230215, 0.308982, -0.361978, -0.850926, 0.409799, 0.710712, -0.391058, -0.542441, -0.41638, 0.558765, -0.149949, -0.864061, -0.759997, -0.265417, -0.331629, -0.845702, 0.426935, -0.731659, 0.062865, -0.255582, 0.396332, 0.639196, -0.078254, -0.253246, 0.792036, 0.044105, 0.879927, -0.987868, -0.35422, 0.924714, 0.304954, -0.870234], + shape: [3, 3, 2, 4] + }, + { + data: [-0.704159, -0.543403, 0.614987, -0.403051], + shape: [4] + } + ], + expected: { + data: [1.008111, 0.862141, 1.53732, 0.0, 0.0, 0.0, 2.278924, 0.0, 0.192175, 0.256028, 1.00272, 0.0, 0.0, 0.0, 0.0, 1.28356, 0.0, 0.0, 1.295987, 0.0, 0.0, 0.0, 0.522589, 0.0, 0.0, 0.0, 1.593745, 0.0, 0.094799, 1.375385, 1.350499, 0.637961, 0.0, 0.393093, 1.508163, 1.045792, 0.0, 0.580916, 0.774659, 0.0, 0.0, 0.0, 1.090937, 0.2098, 0.0, 0.0, 0.706958, 0.948835, 0.0, 0.0, 0.70246, 1.233015, 0.0, 0.0, 0.0, 0.0, 0.0, 0.237716, 0.150121, 0.0, 0.012937, 1.067614, 0.259571, 0.895802, 0.0, 0.127769, 0.0, 0.0, 0.0, 0.0, 0.0, 0.517957, 0.0, 0.0, 0.524233, 0.079491, 0.0, 0.0, 0.0, 1.424679, 0.0, 0.0, 0.798433, 0.0, 0.752754, 0.49452, 0.564184, 1.320468, 0.0, 0.0, 1.469927, 0.075539, 0.0, 0.760117, 0.0, 0.961547, 0.938599, 1.264279, 0.857871, 0.0, 0.114331, 0.0, 0.753579, 0.0, 0.0, 0.0, 0.020539, 0.0, 0.0, 0.0, 1.035394, 0.0, 0.0, 0.0, 0.745973, 0.0, 0.0, 0.070491, 0.0, 0.0, 0.0, 0.0, 0.308166, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.911015, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.178493, 1.44698, 0.0, 0.0, 0.0, 1.45985, 0.298695, 0.0, 0.0, 0.0, 0.0, 0.0, 0.402046, 0.536043, 1.160239, 0.0, 0.0, 0.0, 0.0, 0.575623, 0.009206, 0.639194, 0.0, 0.353097, 0.0, 0.471996, 0.411527, 1.148312, 0.966958, 1.172197, 0.0, 0.419191, 0.0, 2.142206, 0.0, 0.0, 0.0, 0.0, 0.0, 0.508378, 0.0, 1.110668, 1.82902, 0.0, 0.0, 2.081267, 0.05382, 0.0, 0.0, 1.5163, 1.476838, 1.364327, 0.033732, 1.076706, 0.609169, 0.0, 0.149234, 2.181282, 0.780896, 0.0, 0.0, 0.763411, 0.0, 0.0, 0.0, 2.053607, 0.12022, 0.0, 0.0, 0.0, 0.29116, 0.0, 0.0, 0.656705, 0.0, 0.0, 0.0, 1.055828, 0.634612, 0.0, 0.0, 0.0, 0.363467, 1.779839, 0.0, 1.270641, 0.15881, 0.0, 0.020913, 0.854418, 0.0, 0.0, 0.0, 0.436751, 0.0, 0.0, 0.0, 0.0, 0.0, 0.436203, 0.236268, 0.0, 0.0, 0.0, 0.0, 0.189446, 0.0, 0.0, 0.0, 0.827813, 0.0, 0.0, 0.0, 0.31375, 0.0, 0.0, 0.0, 0.755046, 0.0], + shape: [8, 8, 4] + } + } + } + + window.TEST_DATA = Object.assign({}, window.TEST_DATA, DATA) +})()