diff --git a/index.html b/index.html
index fba5d9b..98f3977 100644
--- a/index.html
+++ b/index.html
@@ -50,6 +50,8 @@
+
+
diff --git a/notebooks/convolutional/Deconvolution2D.ipynb b/notebooks/convolutional/Deconvolution2D.ipynb
new file mode 100644
index 0000000..941b3dc
--- /dev/null
+++ b/notebooks/convolutional/Deconvolution2D.ipynb
@@ -0,0 +1,428 @@
+{
+ "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 Deconvolution2D\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": [
+ "### Deconvolution2D"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "**[convolutional.Deconvolution2D.0] 4 3x3 filters on 4x4x2 input, output_shape=(1, 6, 6, 4), activation='linear', border_mode='valid', subsample=(1,1), dim_ordering='tf', bias=False**"
+ ]
+ },
+ {
+ "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.817168, -0.484057, 0.75531, 0.477931, 0.396153, 0.034417, 0.904219, 0.827289, -0.843651, 0.564641, -0.772669, 0.2817, -0.840474, -0.536068, -0.228097, -0.52653, 0.996766, -0.221318, 0.447674, -0.096508, -0.046254, 0.090528, -0.13441, 0.179412, -0.790058, 0.722203, -0.383929, -0.026572, -0.579839, 0.240175, -0.317323, -0.010873, -0.385402, -0.164789, 0.520344, -0.918119, -0.000266, 0.625388, 0.040686, -0.136983, 0.477384, 0.485779, 0.761687, 0.965039, -0.560193, -0.813418, -0.708546, -0.178286, -0.283609, 0.943543, 0.314461, 0.343435, 0.480156, 0.274123, 0.794715, -0.361677, -0.763759, -0.54021, -0.794172, 0.943047, -0.073416, -0.57276, -0.091824, 0.998847, -0.802122, -0.525324, -0.731307, 0.449204, -0.313752, -0.823668, 0.671953, -0.761801]\n",
+ "\n",
+ "in shape: (4, 4, 2)\n",
+ "in: [-0.929961, -0.63673, 0.945405, -0.573858, 0.000985, 0.681999, -0.080736, 0.575131, -0.614662, -0.588668, 0.80306, 0.256132, -0.307227, -0.077013, 0.21169, -0.678163, 0.451697, -0.680262, -0.125876, -0.335162, -0.258573, 0.105624, -0.63008, -0.384056, -0.816483, 0.552606, 0.332199, -0.201029, -0.480198, 0.2547, 0.712057, -0.072584]\n",
+ "out shape: (6, 6, 4)\n",
+ "out: [-1.012177, 0.428239, -1.278153, -0.971217, 1.864937, -0.661143, 1.058969, 0.05038, -0.941801, 1.012612, -0.312905, 1.108666, 0.556722, -0.567351, 0.803105, -0.115799, -0.445832, -0.292374, -0.16003, -0.203303, -0.107077, 0.069934, -0.113447, 0.110977, 0.368439, -0.547277, -0.437457, -0.74913, 1.715421, -0.111417, 0.756687, 1.654658, -2.607478, 0.260953, -1.182048, -1.746234, 1.5194, 1.019677, 1.13018, 0.378821, -0.261903, 0.362806, -0.637153, 0.307241, -0.118354, -0.615285, -0.283082, -0.322552, 0.88459, -1.879354, -0.649606, -0.41325, -0.377555, 2.645532, -0.687108, -0.211925, 1.307261, 1.062389, 0.983577, -1.173076, -0.393386, -0.072744, -0.966372, 1.536638, 0.211478, -1.476756, 0.816467, -0.336362, -0.245008, 0.32784, 0.856805, -0.157302, -0.519041, -0.164249, -0.735688, 0.064148, 0.943986, -0.0991, 1.934291, -1.827528, -0.358115, 1.106049, -0.735497, 2.190809, 1.162497, -1.482633, 0.699504, 0.241831, -0.811117, 0.721315, -1.331029, 0.136491, 0.670442, 0.289532, -0.489781, -0.009605, -0.130091, -0.217225, -0.260457, 0.416851, -0.251642, 0.606745, -1.068321, 0.491773, -0.499707, -0.944252, -1.399293, -1.01329, 0.325871, 0.781719, -0.53524, 0.727235, 0.037364, 0.006004, 0.617063, -2.327055, 1.006486, 1.052275, 0.796508, 0.709643, 0.496899, -0.618905, 0.182412, -0.480274, 0.392287, 0.382899, 0.542389, -0.031217, 0.50106, -0.47383, 0.774471, -0.932296, -0.092132, 0.756554, 0.146181, 0.374723, -0.233247, -0.300615, -0.036513, 0.189266, -0.548384, -0.314276, -0.569505, 0.375154]\n"
+ ]
+ }
+ ],
+ "source": [
+ "data_in_shape = (4, 4, 2)\n",
+ "conv = Deconvolution2D(4, 3, 3, output_shape=(1, 6, 6, 4), activation='linear', border_mode='valid', \n",
+ " subsample=(1, 1), 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(150)\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.Deconvolution2D.1] 4 3x3 filters on 4x4x2 input, output_shape=(1, 6, 6, 4), activation='linear', border_mode='valid', subsample=(1,1), dim_ordering='tf', bias=True**"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "metadata": {
+ "collapsed": false
+ },
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "W shape: (3, 3, 2, 4)\n",
+ "W: [0.539589, -0.646357, -0.378579, 0.600628, 0.148989, 0.539942, 0.901522, 0.505578, -0.106529, 0.052912, 0.212682, 0.154012, 0.907638, -0.157428, -0.539244, 0.908274, -0.805752, 0.802096, 0.832403, 0.18143, 0.805057, -0.915723, -0.056526, 0.826083, -0.930412, 0.568274, 0.688561, 0.945088, 0.215499, -0.855602, 0.23233, -0.568225, 0.855135, 0.162787, 0.965045, 0.048574, 0.23368, -0.215715, 0.303608, -0.981652, 0.943344, -0.172658, 0.245129, 0.753963, -0.941923, 0.131806, 0.860396, 0.286018, 0.92336, 0.270758, -0.859684, -0.482492, -0.702331, -0.68649, -0.945042, -0.458865, -0.130765, -0.706792, 0.634812, 0.665099, 0.984552, -0.442333, -0.395297, 0.281599, -0.587822, 0.298219, -0.52161, 0.871918, 0.986648, -0.139607, -0.149301, -0.75598]\n",
+ "b shape: (4,)\n",
+ "b: [0.539589, -0.646357, -0.378579, 0.600628]\n",
+ "\n",
+ "in shape: (4, 4, 2)\n",
+ "in: [0.148989, 0.539942, 0.901522, 0.505578, -0.106529, 0.052912, 0.212682, 0.154012, 0.907638, -0.157428, -0.539244, 0.908274, -0.805752, 0.802096, 0.832403, 0.18143, 0.805057, -0.915723, -0.056526, 0.826083, -0.930412, 0.568274, 0.688561, 0.945088, 0.215499, -0.855602, 0.23233, -0.568225, 0.855135, 0.162787, 0.965045, 0.048574]\n",
+ "out shape: (6, 6, 4)\n",
+ "out: [0.700427, -0.45112, 0.051786, 0.963097, 1.575565, -1.033198, -0.52356, 1.911077, 1.167469, -0.955755, -0.277941, 1.634511, 0.417286, -0.454497, 0.350411, 1.419101, 0.785153, -0.793249, -0.508062, 0.797651, 0.492208, -0.616798, -0.210248, 0.766442, 0.98362, -1.695325, -0.636085, 0.900187, -0.331893, 0.252929, 1.968253, 0.774684, 0.879627, 0.985514, 2.273053, 0.982236, 3.126138, -2.648267, -0.882778, 3.329913, 1.978084, -1.984895, -0.744007, 1.203985, 0.070505, -0.161251, 0.488706, 1.105932, -0.282495, -1.340989, -1.558865, 1.248805, 2.141538, -1.325992, 0.34873, -0.966352, 1.859792, -0.949173, 0.480017, -0.544663, -0.100628, -1.093168, -0.617422, 2.421925, 2.008457, -1.941762, -0.075571, 1.401888, 1.386915, -1.037387, 0.367375, 2.254779, 0.530665, 0.34719, -1.521432, 1.212986, -0.923692, -2.708969, 0.42394, 0.526906, 1.345705, -2.0119, -2.0915, -0.794072, 1.297688, -1.062393, -1.28526, -1.190259, 0.654391, -0.9432, 2.472624, -1.054459, -0.749841, 0.311814, 0.942641, 2.193933, 1.541203, 1.054772, -0.255676, 1.322227, -1.45391, -0.554865, -0.261469, 1.919241, -0.960103, -0.888831, -0.766406, 3.580549, 2.67732, -0.338729, -1.654299, -0.519009, 3.977589, -1.887441, 1.381146, 0.774372, 1.931923, -0.733176, -0.600488, 1.22803, 1.339488, -0.000646, 0.24474, 0.889257, 0.282631, 0.032778, 0.433705, 0.65166, -0.345825, -0.255725, -0.880127, 0.942561, 0.747801, -0.946204, -0.811967, 1.359443, 0.119164, -1.117638, -0.255509, 1.878702, 0.020239, -0.365343, -0.889209, 1.405347]\n"
+ ]
+ }
+ ],
+ "source": [
+ "data_in_shape = (4, 4, 2)\n",
+ "conv = Deconvolution2D(4, 3, 3, output_shape=(1, 6, 6, 4), activation='linear', border_mode='valid', \n",
+ " subsample=(1, 1), 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(151)\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.Deconvolution2D.2] 4 3x3 filters on 4x4x2 input, output_shape=(1, 9, 9, 4), activation='relu', border_mode='valid', subsample=(2,2), 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.897456, 0.487288, -0.923342, -0.349253, -0.358135, -0.188918, -0.854928, -0.340478, 0.552639, -0.654335, 0.054774, -0.504375, -0.879382, -0.611747, -0.127514, 0.302488, -0.190093, 0.825193, 0.313868, 0.409695, 0.074585, -0.158004, -0.796628, -0.238881, -0.386481, 0.984118, 0.835142, -0.393954, -0.594307, -0.446792, -0.88912, 0.340353, -0.419182, 0.636229, 0.665132, -0.306754, 0.068433, -0.062402, -0.41091, 0.148379, -0.289494, -0.286142, -0.843449, -0.755613, 0.440714, -0.89768, -0.517294, -0.691731, -0.558247, 0.548046, -0.743271, 0.318663, -0.951589, -0.680511, 0.054639, -0.342901, 0.359072, 0.98732, 0.60034, -0.951034, 0.957127, -0.215193, -0.025811, -0.572621, 0.967642, -0.106668, 0.796646, 0.227034, 0.278936, 0.737666, 0.885642, -0.240247]\n",
+ "b shape: (4,)\n",
+ "b: [0.897456, 0.487288, -0.923342, -0.349253]\n",
+ "\n",
+ "in shape: (4, 4, 2)\n",
+ "in: [-0.358135, -0.188918, -0.854928, -0.340478, 0.552639, -0.654335, 0.054774, -0.504375, -0.879382, -0.611747, -0.127514, 0.302488, -0.190093, 0.825193, 0.313868, 0.409695, 0.074585, -0.158004, -0.796628, -0.238881, -0.386481, 0.984118, 0.835142, -0.393954, -0.594307, -0.446792, -0.88912, 0.340353, -0.419182, 0.636229, 0.665132, -0.306754]\n",
+ "out shape: (9, 9, 4)\n",
+ "out: [0.643703, 0.348463, 0.0, 0.0, 0.865667, 0.837198, 0.0, 0.0, 0.306121, 0.0, 0.195225, 0.0, 0.7244, 1.254985, 0.0, 0.0, 1.764886, 0.228513, 0.0, 0.0, 1.778276, 0.525964, 0.0, 0.0, 0.973391, 1.168686, 0.152004, 0.186067, 1.371264, 0.759997, 0.0, 0.0, 0.849425, 0.61218, 0.0, 0.0, 1.148143, 0.219248, 0.0, 0.0, 1.034651, 0.271221, 0.0, 0.0, 1.450637, 0.070126, 0.0, 0.272958, 1.232526, 0.0, 0.0, 0.0, 1.170191, 1.873773, 1.017189, 0.091842, 0.621021, 0.879725, 0.0, 0.0, 0.727679, 1.195794, 0.0, 0.0, 0.839979, 0.553611, 0.0, 0.0, 0.659314, 0.924382, 0.0, 0.0, 0.707038, 0.106632, 0.667498, 0.116816, 0.64002, 1.123993, 0.0, 0.358016, 1.198236, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.814592, 0.0, 0.673934, 0.0, 0.0, 0.0, 0.793302, 0.0, 0.0, 1.931713, 0.107207, 0.0, 0.0, 0.24755, 0.193901, 0.0, 0.0, 0.780662, 0.303653, 0.0, 0.0, 1.600885, 0.0, 0.0, 0.0, 1.224213, 0.0, 0.0, 0.0, 0.751937, 1.027431, 0.0, 0.891571, 0.971607, 0.387284, 0.0, 0.0, 0.65073, 0.0, 0.0, 0.0, 1.033609, 0.314851, 0.0, 0.0, 0.951373, 0.0, 0.0, 0.0, 0.793925, 0.661414, 0.0, 0.0, 0.987151, 0.029702, 0.0, 0.0, 2.094023, 0.487841, 0.0, 0.0, 0.176339, 0.0, 0.0, 0.751955, 0.0, 0.0, 0.0, 0.0, 0.911008, 0.963694, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.540014, 0.0, 0.0, 0.0, 1.416072, 1.016457, 0.0, 0.0, 2.210254, 0.403549, 0.0, 0.0, 1.127308, 1.507426, 0.265501, 0.059838, 0.962533, 0.631283, 0.0, 0.0, 0.855378, 0.544601, 0.0, 0.0, 1.256079, 0.0, 0.0, 0.0, 1.21504, 0.0, 0.0, 0.0, 0.587296, 0.109636, 0.0, 0.905133, 1.126807, 0.179987, 0.0, 0.0, 1.354418, 0.712346, 0.0, 0.0, 0.52042, 1.043213, 0.0, 0.0, 0.482066, 0.601963, 0.0, 0.0, 0.632821, 0.430496, 0.0, 0.088381, 0.837471, 1.257129, 0.0, 0.0, 0.757397, 0.0, 0.274577, 0.0, 0.0, 0.125739, 0.0, 1.096557, 0.0, 0.0, 0.0, 0.0, 0.909462, 0.0, 0.0, 0.0, 1.540575, 1.915879, 0.0, 0.0, 1.4576, 1.149052, 0.0, 0.0, 1.44637, 0.70493, 0.0, 0.280777, 1.392676, 0.102043, 0.0, 0.0, 1.116003, 0.137053, 0.0, 0.0, 1.01395, 0.031355, 0.0, 0.874985, 1.29345, 0.0, 0.0, 0.0, 1.088739, 0.0, 0.0, 0.468825, 1.116708, 0.18089, 0.0, 0.0, 1.224447, 0.827726, 0.0, 0.0, 0.597652, 0.929606, 0.0, 0.0, 0.569713, 0.572333, 0.0, 0.0, 1.654388, 0.465627, 0.0, 0.0, 0.25642, 0.0, 0.0, 0.471796, 0.370225, 0.0, 0.0, 0.0, 0.903959, 0.0, 0.0, 0.301436, 0.0, 0.170503, 0.0, 0.0, 1.355891, 0.0, 0.0, 0.0, 0.5899, 1.574599, 0.0, 0.0, 0.842684, 1.209997, 0.0, 0.0, 1.455501, 0.190058, 0.0, 0.0]\n"
+ ]
+ }
+ ],
+ "source": [
+ "data_in_shape = (4, 4, 2)\n",
+ "conv = Deconvolution2D(4, 3, 3, output_shape=(1, 9, 9, 4), activation='relu', border_mode='valid', \n",
+ " subsample=(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(152)\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.Deconvolution2D.3] 4 3x3 filters on 4x4x2 input, output_shape=(1, 4, 4, 4), activation='relu', border_mode='same', subsample=(1,1), 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.7046, 0.058369, -0.012661, -0.889136, -0.007435, 0.615048, -0.558658, -0.008729, 0.041294, -0.438168, 0.529679, 0.266543, 0.550212, -0.183091, 0.3534, 0.109289, -0.621224, -0.674319, 0.15753, -0.648414, 0.830683, -0.934728, 0.16761, 0.50837, 0.086898, -0.035362, -0.851074, -0.016054, -0.545162, -0.344549, 0.467416, 0.926628, -0.560706, -0.569233, 0.855837, -0.009762, 0.293612, -0.714253, -0.817222, 0.023038, -0.85581, 0.539004, 0.741369, -0.823095, -0.859253, -0.035201, 0.737323, 0.025245, 0.366923, -0.220199, 0.028247, 0.196676, 0.835236, 0.376875, 0.771537, -0.449685, 0.756239, 0.813555, 0.931644, 0.659618, 0.742881, -0.696761, 0.246132, -0.088558, -0.595887, 0.278583, -0.957392, -0.062303, -0.402006, 0.976563, -0.887975, 0.147616]\n",
+ "b shape: (4,)\n",
+ "b: [-0.7046, 0.058369, -0.012661, -0.889136]\n",
+ "\n",
+ "in shape: (4, 4, 2)\n",
+ "in: [-0.007435, 0.615048, -0.558658, -0.008729, 0.041294, -0.438168, 0.529679, 0.266543, 0.550212, -0.183091, 0.3534, 0.109289, -0.621224, -0.674319, 0.15753, -0.648414, 0.830683, -0.934728, 0.16761, 0.50837, 0.086898, -0.035362, -0.851074, -0.016054, -0.545162, -0.344549, 0.467416, 0.926628, -0.560706, -0.569233, 0.855837, -0.009762]\n",
+ "out shape: (4, 4, 4)\n",
+ "out: [0.0, 0.0, 0.110927, 0.0, 0.0, 0.0, 0.390755, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.703063, 0.0, 0.0, 0.0, 0.0, 0.303646, 0.0, 0.0, 0.442749, 0.0, 0.0, 0.777761, 0.777295, 0.7709, 0.0, 0.750528, 0.299845, 0.154226, 0.0, 0.0, 1.509791, 1.18485, 0.0, 0.0, 0.090488, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.88771, 0.757259, 0.0, 0.0, 1.760764, 0.778453, 0.394454, 0.71713, 0.0, 0.0, 0.0, 0.0, 1.796376, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]\n"
+ ]
+ }
+ ],
+ "source": [
+ "data_in_shape = (4, 4, 2)\n",
+ "conv = Deconvolution2D(4, 3, 3, output_shape=(1, 4, 4, 4), activation='relu', border_mode='same', \n",
+ " subsample=(1, 1), 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(153)\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.Deconvolution2D.4] 5 3x3 filters on 4x4x2 input, output_shape=(1, 8, 8, 5), activation='relu', border_mode='same', subsample=(2,2), dim_ordering='tf', bias=True**"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 15,
+ "metadata": {
+ "collapsed": false
+ },
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "W shape: (3, 3, 2, 5)\n",
+ "W: [0.015448, 0.261101, 0.371131, 0.970987, 0.733096, 0.656737, 0.433335, 0.19508, 0.702874, 0.204501, -0.719665, 0.652834, -0.165006, 0.065511, 0.376121, 0.755842, 0.602262, -0.479869, -0.721179, 0.979413, 0.487952, 0.353365, 0.379881, -0.725052, 0.794477, -0.748911, 0.150616, -0.830063, 0.781869, -0.467526, -0.294391, -0.927268, 0.293802, 0.49534, 0.456641, 0.610365, -0.549942, 0.126156, 0.450587, -0.837003, 0.361856, 0.138717, -0.473225, 0.432004, 0.46321, -0.042096, -0.481635, -0.730053, 0.724533, 0.657809, -0.088475, 0.224629, -0.287917, -0.394062, -0.498412, -0.523992, 0.638287, -0.400103, 0.456819, -0.150058, -0.459513, 0.357662, 0.287583, -0.448432, 0.805097, 0.529896, -0.935158, -0.723581, -0.926538, -0.389357, 0.673302, 0.696614, -0.819421, 0.580246, 0.249636, -0.53035, -0.599139, -0.987449, -0.679439, 0.024594, -0.686301, -0.575677, -0.655428, -0.185761, 0.946483, 0.12546, -0.358746, 0.039991, -0.701225, -0.987664]\n",
+ "b shape: (5,)\n",
+ "b: [0.015448, 0.261101, 0.371131, 0.970987, 0.733096]\n",
+ "\n",
+ "in shape: (4, 4, 2)\n",
+ "in: [0.656737, 0.433335, 0.19508, 0.702874, 0.204501, -0.719665, 0.652834, -0.165006, 0.065511, 0.376121, 0.755842, 0.602262, -0.479869, -0.721179, 0.979413, 0.487952, 0.353365, 0.379881, -0.725052, 0.794477, -0.748911, 0.150616, -0.830063, 0.781869, -0.467526, -0.294391, -0.927268, 0.293802, 0.49534, 0.456641, 0.610365, -0.549942]\n",
+ "out shape: (8, 8, 5)\n",
+ "out: [0.31018, 0.620355, 0.699402, 1.913249, 1.303165, 0.0, 0.950822, 0.054822, 0.701498, 1.404523, 0.475991, 0.913952, 0.470435, 1.517081, 1.339014, 0.406317, 0.81177, 0.001654, 0.476869, 1.494874, 0.0, 0.177439, 0.0, 1.071832, 0.562218, 0.0, 0.0, 0.682732, 1.503391, 0.105164, 0.555919, 0.323925, 1.256283, 0.777944, 1.676876, 0.0, 0.587917, 0.342591, 1.132753, 0.817032, 0.086603, 0.0, 0.618749, 1.49155, 0.670287, 0.23485, 0.143492, 0.0, 1.568665, 1.322355, 0.101858, 0.117784, 0.154654, 1.323484, 0.0, 0.05645, 0.0, 0.0, 1.564517, 1.285816, 0.0, 0.959704, 0.003035, 0.992225, 1.22614, 0.119742, 0.636085, 0.79975, 0.537911, 0.35442, 0.081551, 0.0, 0.771179, 0.810669, 1.175383, 0.258626, 0.431133, 0.182657, 1.133461, 0.926953, 0.191316, 0.270846, 0.344131, 0.602959, 1.218054, 0.464954, 0.728256, 0.0, 0.790672, 1.300717, 0.05939, 0.0, 0.0, 1.210212, 1.363556, 0.0, 0.832037, 0.0, 0.221798, 1.673233, 0.0, 0.56278, 0.319359, 0.0, 0.488038, 0.33506, 0.087126, 1.339444, 2.067279, 0.0, 0.038919, 0.978335, 1.390465, 2.375806, 3.000996, 0.206478, 1.748005, 0.0, 1.174163, 1.738294, 0.225733, 0.0, 0.437828, 1.172912, 0.448196, 0.02332, 0.089035, 0.065541, 1.2718, 1.010857, 0.0, 0.0, 0.499829, 1.762761, 0.485059, 0.263601, 0.075879, 0.0, 1.733872, 1.479383, 0.0, 1.656875, 0.0, 0.38561, 0.650502, 0.0, 0.54188, 1.124716, 0.241164, 0.036418, 0.445295, 0.0, 1.147151, 1.535644, 1.11931, 0.349313, 0.161947, 0.0, 1.747634, 1.507749, 0.439591, 0.189679, 0.323069, 1.20324, 0.97613, 0.0, 0.540865, 0.0, 0.502634, 1.263669, 0.387982, 0.132628, 0.0, 0.0, 0.531725, 1.327243, 0.431937, 0.0, 0.379902, 1.442007, 0.0, 0.0, 0.0, 1.817207, 0.0, 0.727635, 0.0, 1.527772, 1.024859, 0.4614, 0.085243, 0.570184, 0.020346, 1.078867, 0.475692, 1.604441, 0.580019, 0.0, 0.589507, 1.443162, 0.143286, 0.0, 0.522875, 1.317192, 0.576495, 0.127323, 0.127155, 0.0, 1.398878, 1.146668, 0.483498, 0.818352, 0.004606, 1.004109, 0.0, 0.0, 0.0, 0.134233, 1.233386, 0.919859, 0.0, 1.216949, 0.060984, 1.316534, 0.507204, 0.0, 0.084673, 0.615577, 0.75658, 0.48527, 0.724375, 0.528718, 0.381258, 1.276045, 0.050294, 0.0, 0.0, 0.193131, 1.178886, 0.862924, 0.0, 0.0, 0.0, 0.0, 0.466735, 0.165848, 0.0, 0.0, 1.099599, 0.366475, 0.745723, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.192767, 0.0, 0.510624, 0.671723, 0.028575, 0.230558, 2.448812, 0.0, 0.0, 0.247552, 0.535217, 0.13723, 1.183393, 0.892037, 0.0, 0.0, 0.856287, 0.0, 0.0, 0.0, 0.442432, 0.394705, 0.236063, 0.0, 0.856521, 0.196632, 0.606754, 0.766011, 0.0, 0.338037, 0.807297, 0.555718, 0.322881, 0.663376, 0.666427, 0.388159, 0.693807, 0.340951, 0.0, 0.0, 0.595446, 0.783272, 0.496842, 0.076432, 0.0, 0.723697, 1.921721, 0.995153, 0.175467, 0.109879, 0.0, 1.515827, 1.262925, 0.0, 0.400301, 0.155759, 1.038936, 1.156711, 0.259462, 0.610641, 0.483778, 0.836216, 0.654066]\n"
+ ]
+ }
+ ],
+ "source": [
+ "data_in_shape = (4, 4, 2)\n",
+ "conv = Deconvolution2D(5, 3, 3, output_shape=(1, 8, 8, 5), activation='relu', border_mode='same', \n",
+ " subsample=(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(154)\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.Deconvolution2D.5] 5 3x3 filters on 4x4x2 input, output_shape=(1, 7, 7, 5), activation='relu', border_mode='same', subsample=(2,2), dim_ordering='tf', bias=True**"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 16,
+ "metadata": {
+ "collapsed": false
+ },
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "W shape: (3, 3, 2, 5)\n",
+ "W: [0.304653, 0.842246, -0.653708, 0.24125, -0.786747, -0.629124, -0.519787, -0.038861, -0.715188, 0.71707, -0.180419, 0.054783, 0.458147, 0.631702, -0.028843, 0.586737, -0.21045, 0.463067, -0.16224, 0.36397, -0.958481, -0.793514, -0.985689, -0.380946, -0.946773, -0.259217, 0.266228, -0.671058, -0.358071, -0.200672, 0.343247, 0.883116, 0.945544, 8.8e-05, -0.43253, 0.375163, -0.655772, -0.806227, -0.026706, -0.789484, 0.347693, -0.133666, 0.520664, -0.663529, 0.171618, -0.768326, 0.43348, -0.892969, -0.518967, -0.046671, -0.446649, -0.676726, -0.949549, 0.182767, -0.929755, 0.138988, -0.979159, 0.232577, 0.247578, 0.333053, -0.44899, 0.209367, -0.289982, -0.141429, -0.968415, -0.3587, 0.573399, -0.127767, -0.257376, -0.54742, -0.511472, 0.228512, 0.950914, -0.234276, 0.074906, 0.869786, 0.565649, 0.708036, 0.876331, -0.51019, -0.101183, -0.21937, 0.958957, -0.388422, -0.064355, 0.184026, -0.286808, 0.56959, 0.966958, -0.7823]\n",
+ "b shape: (5,)\n",
+ "b: [0.304653, 0.842246, -0.653708, 0.24125, -0.786747]\n",
+ "\n",
+ "in shape: (4, 4, 2)\n",
+ "in: [-0.629124, -0.519787, -0.038861, -0.715188, 0.71707, -0.180419, 0.054783, 0.458147, 0.631702, -0.028843, 0.586737, -0.21045, 0.463067, -0.16224, 0.36397, -0.958481, -0.793514, -0.985689, -0.380946, -0.946773, -0.259217, 0.266228, -0.671058, -0.358071, -0.200672, 0.343247, 0.883116, 0.945544, 8.8e-05, -0.43253, 0.375163, -0.655772]\n",
+ "out shape: (7, 7, 5)\n",
+ "out: [0.485277, 0.701021, 0.0, 0.928445, 0.0, 0.231755, 2.211627, 0.362644, 0.016676, 0.206506, 0.840639, 0.537421, 0.0, 0.638195, 0.0, 0.401053, 2.320396, 0.040336, 0.061964, 0.0, 0.692594, 0.66819, 0.0, 0.0, 0.0, 0.149982, 0.281585, 0.0, 0.315409, 0.0, 0.0, 1.033521, 0.0, 0.0, 0.0, 0.043434, 0.445142, 0.0, 0.33686, 0.0, 0.259794, 0.805735, 0.0, 0.234317, 0.0, 0.0, 0.505252, 0.0, 0.028399, 0.0, 0.0, 1.055305, 0.0, 0.0, 0.0, 0.0, 0.963562, 0.037445, 0.233993, 0.0, 0.322064, 1.404974, 0.0, 0.317595, 0.0, 0.047079, 1.335566, 0.0, 1.015328, 0.0, 0.546452, 0.745306, 0.0, 0.0, 0.0, 0.140938, 1.099162, 0.0, 0.355236, 0.0, 0.670351, 0.672593, 0.0, 0.0, 0.0, 0.111417, 1.166584, 0.0, 0.300757, 0.0, 0.590311, 0.710022, 0.0, 0.018189, 0.0, 0.0, 1.637707, 0.0, 0.311346, 0.0, 1.167628, 0.378113, 0.391691, 0.497166, 0.0, 0.0, 1.13425, 0.0, 0.0, 0.0, 1.543133, 1.25263, 1.521816, 1.179627, 0.0, 0.0, 1.035661, 0.0, 0.0, 0.0, 0.420927, 0.471338, 0.845466, 0.017311, 0.0, 0.129666, 0.786063, 0.0, 0.0, 0.0, 0.608605, 0.2113, 0.244304, 0.197334, 0.0, 0.0, 0.421847, 0.0, 0.0, 0.0, 0.786085, 0.521035, 0.0, 1.27931, 0.0, 0.036123, 2.628832, 0.273636, 0.0, 0.534973, 0.899631, 0.482758, 0.0, 0.985363, 0.0, 0.354115, 1.62358, 0.0, 0.0, 0.0, 0.009975, 0.992299, 0.0, 0.275085, 0.0, 0.09276, 0.399176, 0.0, 0.26929, 0.115874, 0.346446, 0.776727, 0.0, 0.872344, 0.0, 0.090775, 0.020134, 0.0, 0.0, 0.0, 0.491742, 1.179323, 0.0, 0.0, 1.026965, 0.07146, 0.069043, 0.0, 0.0, 0.0, 0.0, 1.071602, 0.0, 0.0, 0.0, 0.414998, 1.024634, 0.0, 0.605511, 0.0, 1.448504, 1.018559, 0.0, 1.500783, 0.0, 0.0, 0.644918, 0.0, 0.428058, 0.0, 0.0, 1.01786, 0.0, 0.196268, 0.0, 1.09985, 0.801785, 0.0, 0.26438, 0.0, 0.0, 1.134078, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.648302, 0.0, 0.637008, 0.654741, 0.0, 0.465661, 0.0, 0.127249, 2.027051, 0.129045, 0.151727, 0.0, 0.938941, 0.507835, 0.127209, 0.332643, 0.0]\n"
+ ]
+ }
+ ],
+ "source": [
+ "data_in_shape = (4, 4, 2)\n",
+ "conv = Deconvolution2D(5, 3, 3, output_shape=(1, 7, 7, 5), activation='relu', border_mode='same', \n",
+ " subsample=(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(155)\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
index c3f64b9..8554399 100644
--- a/src/layers/convolutional/AtrousConvolution2D.js
+++ b/src/layers/convolutional/AtrousConvolution2D.js
@@ -32,7 +32,6 @@ export default class AtrousConvolution2D extends Convolution2D {
* 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]
diff --git a/src/layers/convolutional/Convolution2D.js b/src/layers/convolutional/Convolution2D.js
index 89698d1..317efe0 100644
--- a/src/layers/convolutional/Convolution2D.js
+++ b/src/layers/convolutional/Convolution2D.js
@@ -72,7 +72,6 @@ export default class Convolution2D extends Layer {
* 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]
diff --git a/src/layers/convolutional/Convolution3D.js b/src/layers/convolutional/Convolution3D.js
index 0f0734d..464ff90 100644
--- a/src/layers/convolutional/Convolution3D.js
+++ b/src/layers/convolutional/Convolution3D.js
@@ -73,7 +73,6 @@ export default class Convolution3D extends Layer {
* 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[]} [outputDim1, outputDim2, outputDim3, outputChannels]
*/
_calcOutputShape (x) {
const inputDim1 = x.tensor.shape[0]
diff --git a/src/layers/convolutional/Deconvolution2D.js b/src/layers/convolutional/Deconvolution2D.js
new file mode 100644
index 0000000..85448eb
--- /dev/null
+++ b/src/layers/convolutional/Deconvolution2D.js
@@ -0,0 +1,239 @@
+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'
+
+/**
+ * Deconvolution2D layer class
+ */
+export default class Deconvolution2D extends Layer {
+ /**
+ * Creates a Deconvolution2D 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 {number[]} outputShape - Output shape of the transposed convolution operation.
+ * Array of integers [nbFilter, outputRows, outputCols]
+ * @param {Object} [attrs] - layer attributes
+ */
+ constructor (nbFilter, nbRow, nbCol, outputShape, attrs = {}) {
+ super(attrs)
+ const {
+ activation = 'linear',
+ borderMode = 'valid',
+ subsample = [1, 1],
+ dimOrdering = 'tf',
+ bias = true
+ } = attrs
+
+ this.kernelShape = [nbFilter, nbRow, nbCol]
+
+ this.outputShape = outputShape
+
+ this.activation = activations[activation]
+
+ if (borderMode === 'valid' || borderMode === 'same') {
+ this.borderMode = borderMode
+ } else {
+ throw new Error(`${this.name} [Deconvolution2D layer] Invalid borderMode.`)
+ }
+
+ this.subsample = subsample
+
+ if (dimOrdering === 'tf' || dimOrdering === 'th') {
+ this.dimOrdering = dimOrdering
+ } else {
+ throw new Error(`${this.name} [Deconvolution2D 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
+ * For deconvolution, we will "take away" padding from the output rather than add padding
+ * to the input.
+ * For more details on calculating output shapes and padding for transposed convolutions
+ * (deconvolution here), see: https://arxiv.org/pdf/1603.07285v1.pdf
+ * @param {Tensor} x
+ */
+ _calcOutputPadding (x) {
+ const inputRows = x.tensor.shape[0]
+ const inputCols = x.tensor.shape[1]
+ const nbRow = this.kernelShape[1]
+ const nbCol = this.kernelShape[2]
+
+ // In contrast to Convolution2D, where we calculate the output shape,
+ // the output shape is taken from the construtor variable, since
+ // there is some level of ambiguity: input of shape [4, 4, inputChannels]
+ // can have an output shape of either [7, 7, nbFilter] or [8, 8, nbFilter]
+ // with borderMode `same` and subsample (stride) [2, 2].
+ const outputRows = this.outputShape[0]
+ const outputCols = this.outputShape[1]
+
+ const paddingRow = this.borderMode === 'same'
+ ? Math.max(0, Math.floor((inputRows - 1) * this.subsample[0] + nbRow - outputRows))
+ : 0
+ const paddingCol = this.borderMode === 'same'
+ ? Math.max(0, Math.floor((inputCols - 1) * this.subsample[1] + nbCol - outputCols))
+ : 0
+ const paddingRowBefore = Math.floor(paddingRow / 2)
+ const paddingRowAfter = paddingRow - paddingRowBefore
+ const paddingColBefore = Math.floor(paddingCol / 2)
+ const paddingColAfter = paddingCol - paddingColBefore
+
+ this.outputPadding = [paddingRowBefore, paddingRowAfter, paddingColBefore, paddingColAfter]
+ }
+
+ /**
+ * Convert input image to column matrix, along channels axis
+ * shape: [inputRows, inputCols, inputChannels] -> [inputRows * inputCols, inputChannels]
+ * @param {Tensor} x
+ * @returns {Tensor} x
+ */
+ _im2col (x) {
+ const [inputRows, inputCols, inputChannels] = x.tensor.shape
+
+ const imColsMat = new Tensor([], [inputRows * inputCols, inputChannels])
+ let channel = new Tensor([], [inputRows * inputCols])
+ for (let c = 0; c < inputChannels; c++) {
+ const channelData = flattenDeep(unpack(
+ x.tensor.pick(null, null, c)
+ ))
+ channel.replaceTensorData(channelData)
+ ops.assign(imColsMat.tensor.pick(null, c), channel.tensor)
+ }
+ return imColsMat
+ }
+
+ /**
+ * Convert filter weights to row matrix, along channels axis
+ * shape: [nbRow, nbCol, inputChannels, nbFilter] -> [inputChannels, nbRow * nbCol * nbFilter]
+ * @param {Tensor} x
+ * @returns {Tensor} x
+ */
+ _w2row (x) {
+ const [nbRow, nbCol, inputChannels, nbFilter] = this.weights.W.tensor.shape
+
+ const wRowsMat = new Tensor([], [inputChannels, nbRow * nbCol * nbFilter])
+ let channel = new Tensor([], [nbRow * nbCol * nbFilter])
+ for (let c = 0; c < inputChannels; c++) {
+ const channelData = flattenDeep(unpack(
+ this.weights.W.tensor.pick(null, null, c, null)
+ ))
+ channel.replaceTensorData(channelData)
+ ops.assign(wRowsMat.tensor.pick(c, null), channel.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)
+ }
+
+ const imColsMat = this._im2col(x)
+ const wRowsMat = this._w2row(x)
+
+ const inputRows = x.tensor.shape[0]
+ const inputCols = x.tensor.shape[1]
+ const [nbFilter, nbRow, nbCol] = this.kernelShape
+ const matMul = new Tensor([], [inputRows * inputCols, nbRow * nbCol * nbFilter])
+
+ if (x._useWeblas) {
+ const zeros = 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
+ 0, zeros // beta, C
+ )
+ } else {
+ gemm(matMul.tensor, imColsMat.tensor, wRowsMat.tensor, 1, 1)
+ }
+
+ this._calcOutputPadding(x)
+
+ // add padding which we will take away later
+ const [paddingRowBefore, paddingRowAfter, paddingColBefore, paddingColAfter] = this.outputPadding
+ let output = new Tensor([], this.outputShape)
+ let outputPadded = new Tensor([], [
+ this.outputShape[0] + paddingRowBefore + paddingRowAfter,
+ this.outputShape[1] + paddingColBefore + paddingColAfter,
+ this.outputShape[2]
+ ])
+
+ // bias
+ if (this.bias) {
+ for (let n = 0; n < nbFilter; n++) {
+ ops.assigns(outputPadded.tensor.pick(null, null, n), this.weights.b.tensor.get(n))
+ }
+ }
+
+ const patchShape = [nbRow, nbCol, nbFilter]
+ let patch = new Tensor([], patchShape)
+ let index = 0
+ for (let i = 0; i < inputRows; i++) {
+ for (let j = 0; j < inputCols; j++) {
+ const patchData = unpack(matMul.tensor.pick(index, null))
+ patch.replaceTensorData(patchData)
+ const iOutPos = i * this.subsample[0]
+ const jOutPos = j * this.subsample[1]
+ ops.addeq(
+ outputPadded.tensor
+ .hi(iOutPos + nbRow, jOutPos + nbCol, this.outputShape[2])
+ .lo(iOutPos, jOutPos, 0),
+ patch.tensor
+ )
+ index += 1
+ }
+ }
+
+ // remove padding
+ ops.assign(
+ output.tensor,
+ outputPadded.tensor
+ .hi(this.outputShape[0] + paddingRowBefore, this.outputShape[1] + paddingColBefore, this.outputShape[2])
+ .lo(paddingRowBefore, paddingColBefore, 0)
+ )
+
+ 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 e2890ef..2686fb4 100644
--- a/src/layers/convolutional/index.js
+++ b/src/layers/convolutional/index.js
@@ -1,6 +1,7 @@
import Convolution1D from './Convolution1D'
import Convolution2D from './Convolution2D'
import AtrousConvolution2D from './AtrousConvolution2D'
+import Deconvolution2D from './Deconvolution2D'
import Convolution3D from './Convolution3D'
import UpSampling1D from './UpSampling1D'
import UpSampling2D from './UpSampling2D'
@@ -13,6 +14,7 @@ export {
Convolution1D,
Convolution2D,
AtrousConvolution2D,
+ Deconvolution2D,
Convolution3D,
UpSampling1D,
UpSampling2D,
diff --git a/test/convolutional/Deconvolution2D.js b/test/convolutional/Deconvolution2D.js
new file mode 100644
index 0000000..59c1009
--- /dev/null
+++ b/test/convolutional/Deconvolution2D.js
@@ -0,0 +1,123 @@
+/* eslint-env browser, mocha */
+
+describe('convolutional layer: Deconvolution2D', 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: [4, 4, 2],
+ kernelShape: [4, 3, 3],
+ outputShape: [6, 6, 4],
+ attrs: { activation: 'linear', borderMode: 'valid', subsample: [1, 1], dimOrdering: 'tf', bias: false }
+ },
+ {
+ inputShape: [4, 4, 2],
+ kernelShape: [4, 3, 3],
+ outputShape: [6, 6, 4],
+ attrs: { activation: 'linear', borderMode: 'valid', subsample: [1, 1], dimOrdering: 'tf', bias: true }
+ },
+ {
+ inputShape: [4, 4, 2],
+ kernelShape: [4, 3, 3],
+ outputShape: [9, 9, 4],
+ attrs: { activation: 'relu', borderMode: 'valid', subsample: [2, 2], dimOrdering: 'tf', bias: true }
+ },
+ {
+ inputShape: [4, 4, 2],
+ kernelShape: [4, 3, 3],
+ outputShape: [4, 4, 4],
+ attrs: { activation: 'relu', borderMode: 'same', subsample: [1, 1], dimOrdering: 'tf', bias: true }
+ },
+ {
+ inputShape: [4, 4, 2],
+ kernelShape: [5, 3, 3],
+ outputShape: [8, 8, 5],
+ attrs: { activation: 'relu', borderMode: 'same', subsample: [2, 2], dimOrdering: 'tf', bias: true }
+ },
+ {
+ inputShape: [4, 4, 2],
+ kernelShape: [5, 3, 3],
+ outputShape: [7, 7, 5],
+ attrs: { activation: 'relu', borderMode: 'same', subsample: [2, 2], dimOrdering: 'tf', bias: true }
+ }
+ ]
+
+ before(function () {
+ console.log('\n%cconvolutional layer: Deconvolution2D', styles.h1)
+ })
+
+ /*********************************************************
+ * CPU
+ *********************************************************/
+
+ describe('CPU', function () {
+ before(function () {
+ console.log('\n%cCPU', styles.h2)
+ })
+
+ testParams.forEach(({ inputShape, kernelShape, outputShape, attrs }, i) => {
+ const key = `convolutional.Deconvolution2D.${i}`
+ const [inputRows, inputCols, inputChannels] = inputShape
+ const [nbFilter, nbRow, nbCol] = kernelShape
+ const [outputRows, outputCols, outputChannels] = outputShape
+ const title = `[${key}] [CPU] test: ${nbFilter} ${nbRow}x${nbCol} filters on ${inputRows}x${inputCols}x${inputChannels} input, ${outputRows}x${outputCols}x${outputChannels} output, activation='${attrs.activation}', border_mode='${attrs.borderMode}', subsample=${attrs.subsample}, dim_ordering='${attrs.dimOrdering}', bias=${attrs.bias}`
+
+ it(title, function () {
+ console.log(`\n%c${title}`, styles.h3)
+ let testLayer = new layers.Deconvolution2D(nbFilter, nbRow, nbCol, outputShape, 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, outputShape, attrs }, i) => {
+ const key = `convolutional.Deconvolution2D.${i}`
+ const [inputRows, inputCols, inputChannels] = inputShape
+ const [nbFilter, nbRow, nbCol] = kernelShape
+ const [outputRows, outputCols, outputChannels] = outputShape
+ const title = `[${key}] [GPU] test: ${nbFilter} ${nbRow}x${nbCol} filters on ${inputRows}x${inputCols}x${inputChannels} input, ${outputRows}x${outputCols}x${outputChannels} output, activation='${attrs.activation}', border_mode='${attrs.borderMode}', subsample=${attrs.subsample}, dim_ordering='${attrs.dimOrdering}', bias=${attrs.bias}`
+
+ it(title, function () {
+ console.log(`\n%c${title}`, styles.h3)
+ let testLayer = new layers.Deconvolution2D(nbFilter, nbRow, nbCol, outputShape, 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_Deconvolution2D.js b/test/convolutional/data_Deconvolution2D.js
new file mode 100644
index 0000000..b704977
--- /dev/null
+++ b/test/convolutional/data_Deconvolution2D.js
@@ -0,0 +1,126 @@
+// 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.Deconvolution2D.0': {
+ input: {
+ data: [-0.929961, -0.63673, 0.945405, -0.573858, 0.000985, 0.681999, -0.080736, 0.575131, -0.614662, -0.588668, 0.80306, 0.256132, -0.307227, -0.077013, 0.21169, -0.678163, 0.451697, -0.680262, -0.125876, -0.335162, -0.258573, 0.105624, -0.63008, -0.384056, -0.816483, 0.552606, 0.332199, -0.201029, -0.480198, 0.2547, 0.712057, -0.072584],
+ shape: [4, 4, 2]
+ },
+ weights: [
+ {
+ data: [0.817168, -0.484057, 0.75531, 0.477931, 0.396153, 0.034417, 0.904219, 0.827289, -0.843651, 0.564641, -0.772669, 0.2817, -0.840474, -0.536068, -0.228097, -0.52653, 0.996766, -0.221318, 0.447674, -0.096508, -0.046254, 0.090528, -0.13441, 0.179412, -0.790058, 0.722203, -0.383929, -0.026572, -0.579839, 0.240175, -0.317323, -0.010873, -0.385402, -0.164789, 0.520344, -0.918119, -0.000266, 0.625388, 0.040686, -0.136983, 0.477384, 0.485779, 0.761687, 0.965039, -0.560193, -0.813418, -0.708546, -0.178286, -0.283609, 0.943543, 0.314461, 0.343435, 0.480156, 0.274123, 0.794715, -0.361677, -0.763759, -0.54021, -0.794172, 0.943047, -0.073416, -0.57276, -0.091824, 0.998847, -0.802122, -0.525324, -0.731307, 0.449204, -0.313752, -0.823668, 0.671953, -0.761801],
+ shape: [3, 3, 2, 4]
+ }
+ ],
+ expected: {
+ data: [-1.012177, 0.428239, -1.278153, -0.971217, 1.864937, -0.661143, 1.058969, 0.05038, -0.941801, 1.012612, -0.312905, 1.108666, 0.556722, -0.567351, 0.803105, -0.115799, -0.445832, -0.292374, -0.16003, -0.203303, -0.107077, 0.069934, -0.113447, 0.110977, 0.368439, -0.547277, -0.437457, -0.74913, 1.715421, -0.111417, 0.756687, 1.654658, -2.607478, 0.260953, -1.182048, -1.746234, 1.5194, 1.019677, 1.13018, 0.378821, -0.261903, 0.362806, -0.637153, 0.307241, -0.118354, -0.615285, -0.283082, -0.322552, 0.88459, -1.879354, -0.649606, -0.41325, -0.377555, 2.645532, -0.687108, -0.211925, 1.307261, 1.062389, 0.983577, -1.173076, -0.393386, -0.072744, -0.966372, 1.536638, 0.211478, -1.476756, 0.816467, -0.336362, -0.245008, 0.32784, 0.856805, -0.157302, -0.519041, -0.164249, -0.735688, 0.064148, 0.943986, -0.0991, 1.934291, -1.827528, -0.358115, 1.106049, -0.735497, 2.190809, 1.162497, -1.482633, 0.699504, 0.241831, -0.811117, 0.721315, -1.331029, 0.136491, 0.670442, 0.289532, -0.489781, -0.009605, -0.130091, -0.217225, -0.260457, 0.416851, -0.251642, 0.606745, -1.068321, 0.491773, -0.499707, -0.944252, -1.399293, -1.01329, 0.325871, 0.781719, -0.53524, 0.727235, 0.037364, 0.006004, 0.617063, -2.327055, 1.006486, 1.052275, 0.796508, 0.709643, 0.496899, -0.618905, 0.182412, -0.480274, 0.392287, 0.382899, 0.542389, -0.031217, 0.50106, -0.47383, 0.774471, -0.932296, -0.092132, 0.756554, 0.146181, 0.374723, -0.233247, -0.300615, -0.036513, 0.189266, -0.548384, -0.314276, -0.569505, 0.375154],
+ shape: [6, 6, 4]
+ }
+ },
+ 'convolutional.Deconvolution2D.1': {
+ input: {
+ data: [0.148989, 0.539942, 0.901522, 0.505578, -0.106529, 0.052912, 0.212682, 0.154012, 0.907638, -0.157428, -0.539244, 0.908274, -0.805752, 0.802096, 0.832403, 0.18143, 0.805057, -0.915723, -0.056526, 0.826083, -0.930412, 0.568274, 0.688561, 0.945088, 0.215499, -0.855602, 0.23233, -0.568225, 0.855135, 0.162787, 0.965045, 0.048574],
+ shape: [4, 4, 2]
+ },
+ weights: [
+ {
+ data: [0.539589, -0.646357, -0.378579, 0.600628, 0.148989, 0.539942, 0.901522, 0.505578, -0.106529, 0.052912, 0.212682, 0.154012, 0.907638, -0.157428, -0.539244, 0.908274, -0.805752, 0.802096, 0.832403, 0.18143, 0.805057, -0.915723, -0.056526, 0.826083, -0.930412, 0.568274, 0.688561, 0.945088, 0.215499, -0.855602, 0.23233, -0.568225, 0.855135, 0.162787, 0.965045, 0.048574, 0.23368, -0.215715, 0.303608, -0.981652, 0.943344, -0.172658, 0.245129, 0.753963, -0.941923, 0.131806, 0.860396, 0.286018, 0.92336, 0.270758, -0.859684, -0.482492, -0.702331, -0.68649, -0.945042, -0.458865, -0.130765, -0.706792, 0.634812, 0.665099, 0.984552, -0.442333, -0.395297, 0.281599, -0.587822, 0.298219, -0.52161, 0.871918, 0.986648, -0.139607, -0.149301, -0.75598],
+ shape: [3, 3, 2, 4]
+ },
+ {
+ data: [0.539589, -0.646357, -0.378579, 0.600628],
+ shape: [4]
+ }
+ ],
+ expected: {
+ data: [0.700427, -0.45112, 0.051786, 0.963097, 1.575565, -1.033198, -0.52356, 1.911077, 1.167469, -0.955755, -0.277941, 1.634511, 0.417286, -0.454497, 0.350411, 1.419101, 0.785153, -0.793249, -0.508062, 0.797651, 0.492208, -0.616798, -0.210248, 0.766442, 0.98362, -1.695325, -0.636085, 0.900187, -0.331893, 0.252929, 1.968253, 0.774684, 0.879627, 0.985514, 2.273053, 0.982236, 3.126138, -2.648267, -0.882778, 3.329913, 1.978084, -1.984895, -0.744007, 1.203985, 0.070505, -0.161251, 0.488706, 1.105932, -0.282495, -1.340989, -1.558865, 1.248805, 2.141538, -1.325992, 0.34873, -0.966352, 1.859792, -0.949173, 0.480017, -0.544663, -0.100628, -1.093168, -0.617422, 2.421925, 2.008457, -1.941762, -0.075571, 1.401888, 1.386915, -1.037387, 0.367375, 2.254779, 0.530665, 0.34719, -1.521432, 1.212986, -0.923692, -2.708969, 0.42394, 0.526906, 1.345705, -2.0119, -2.0915, -0.794072, 1.297688, -1.062393, -1.28526, -1.190259, 0.654391, -0.9432, 2.472624, -1.054459, -0.749841, 0.311814, 0.942641, 2.193933, 1.541203, 1.054772, -0.255676, 1.322227, -1.45391, -0.554865, -0.261469, 1.919241, -0.960103, -0.888831, -0.766406, 3.580549, 2.67732, -0.338729, -1.654299, -0.519009, 3.977589, -1.887441, 1.381146, 0.774372, 1.931923, -0.733176, -0.600488, 1.22803, 1.339488, -0.000646, 0.24474, 0.889257, 0.282631, 0.032778, 0.433705, 0.65166, -0.345825, -0.255725, -0.880127, 0.942561, 0.747801, -0.946204, -0.811967, 1.359443, 0.119164, -1.117638, -0.255509, 1.878702, 0.020239, -0.365343, -0.889209, 1.405347],
+ shape: [6, 6, 4]
+ }
+ },
+ 'convolutional.Deconvolution2D.2': {
+ input: {
+ data: [-0.358135, -0.188918, -0.854928, -0.340478, 0.552639, -0.654335, 0.054774, -0.504375, -0.879382, -0.611747, -0.127514, 0.302488, -0.190093, 0.825193, 0.313868, 0.409695, 0.074585, -0.158004, -0.796628, -0.238881, -0.386481, 0.984118, 0.835142, -0.393954, -0.594307, -0.446792, -0.88912, 0.340353, -0.419182, 0.636229, 0.665132, -0.306754],
+ shape: [4, 4, 2]
+ },
+ weights: [
+ {
+ data: [0.897456, 0.487288, -0.923342, -0.349253, -0.358135, -0.188918, -0.854928, -0.340478, 0.552639, -0.654335, 0.054774, -0.504375, -0.879382, -0.611747, -0.127514, 0.302488, -0.190093, 0.825193, 0.313868, 0.409695, 0.074585, -0.158004, -0.796628, -0.238881, -0.386481, 0.984118, 0.835142, -0.393954, -0.594307, -0.446792, -0.88912, 0.340353, -0.419182, 0.636229, 0.665132, -0.306754, 0.068433, -0.062402, -0.41091, 0.148379, -0.289494, -0.286142, -0.843449, -0.755613, 0.440714, -0.89768, -0.517294, -0.691731, -0.558247, 0.548046, -0.743271, 0.318663, -0.951589, -0.680511, 0.054639, -0.342901, 0.359072, 0.98732, 0.60034, -0.951034, 0.957127, -0.215193, -0.025811, -0.572621, 0.967642, -0.106668, 0.796646, 0.227034, 0.278936, 0.737666, 0.885642, -0.240247],
+ shape: [3, 3, 2, 4]
+ },
+ {
+ data: [0.897456, 0.487288, -0.923342, -0.349253],
+ shape: [4]
+ }
+ ],
+ expected: {
+ data: [0.643703, 0.348463, 0.0, 0.0, 0.865667, 0.837198, 0.0, 0.0, 0.306121, 0.0, 0.195225, 0.0, 0.7244, 1.254985, 0.0, 0.0, 1.764886, 0.228513, 0.0, 0.0, 1.778276, 0.525964, 0.0, 0.0, 0.973391, 1.168686, 0.152004, 0.186067, 1.371264, 0.759997, 0.0, 0.0, 0.849425, 0.61218, 0.0, 0.0, 1.148143, 0.219248, 0.0, 0.0, 1.034651, 0.271221, 0.0, 0.0, 1.450637, 0.070126, 0.0, 0.272958, 1.232526, 0.0, 0.0, 0.0, 1.170191, 1.873773, 1.017189, 0.091842, 0.621021, 0.879725, 0.0, 0.0, 0.727679, 1.195794, 0.0, 0.0, 0.839979, 0.553611, 0.0, 0.0, 0.659314, 0.924382, 0.0, 0.0, 0.707038, 0.106632, 0.667498, 0.116816, 0.64002, 1.123993, 0.0, 0.358016, 1.198236, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.814592, 0.0, 0.673934, 0.0, 0.0, 0.0, 0.793302, 0.0, 0.0, 1.931713, 0.107207, 0.0, 0.0, 0.24755, 0.193901, 0.0, 0.0, 0.780662, 0.303653, 0.0, 0.0, 1.600885, 0.0, 0.0, 0.0, 1.224213, 0.0, 0.0, 0.0, 0.751937, 1.027431, 0.0, 0.891571, 0.971607, 0.387284, 0.0, 0.0, 0.65073, 0.0, 0.0, 0.0, 1.033609, 0.314851, 0.0, 0.0, 0.951373, 0.0, 0.0, 0.0, 0.793925, 0.661414, 0.0, 0.0, 0.987151, 0.029702, 0.0, 0.0, 2.094023, 0.487841, 0.0, 0.0, 0.176339, 0.0, 0.0, 0.751955, 0.0, 0.0, 0.0, 0.0, 0.911008, 0.963694, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.540014, 0.0, 0.0, 0.0, 1.416072, 1.016457, 0.0, 0.0, 2.210254, 0.403549, 0.0, 0.0, 1.127308, 1.507426, 0.265501, 0.059838, 0.962533, 0.631283, 0.0, 0.0, 0.855378, 0.544601, 0.0, 0.0, 1.256079, 0.0, 0.0, 0.0, 1.21504, 0.0, 0.0, 0.0, 0.587296, 0.109636, 0.0, 0.905133, 1.126807, 0.179987, 0.0, 0.0, 1.354418, 0.712346, 0.0, 0.0, 0.52042, 1.043213, 0.0, 0.0, 0.482066, 0.601963, 0.0, 0.0, 0.632821, 0.430496, 0.0, 0.088381, 0.837471, 1.257129, 0.0, 0.0, 0.757397, 0.0, 0.274577, 0.0, 0.0, 0.125739, 0.0, 1.096557, 0.0, 0.0, 0.0, 0.0, 0.909462, 0.0, 0.0, 0.0, 1.540575, 1.915879, 0.0, 0.0, 1.4576, 1.149052, 0.0, 0.0, 1.44637, 0.70493, 0.0, 0.280777, 1.392676, 0.102043, 0.0, 0.0, 1.116003, 0.137053, 0.0, 0.0, 1.01395, 0.031355, 0.0, 0.874985, 1.29345, 0.0, 0.0, 0.0, 1.088739, 0.0, 0.0, 0.468825, 1.116708, 0.18089, 0.0, 0.0, 1.224447, 0.827726, 0.0, 0.0, 0.597652, 0.929606, 0.0, 0.0, 0.569713, 0.572333, 0.0, 0.0, 1.654388, 0.465627, 0.0, 0.0, 0.25642, 0.0, 0.0, 0.471796, 0.370225, 0.0, 0.0, 0.0, 0.903959, 0.0, 0.0, 0.301436, 0.0, 0.170503, 0.0, 0.0, 1.355891, 0.0, 0.0, 0.0, 0.5899, 1.574599, 0.0, 0.0, 0.842684, 1.209997, 0.0, 0.0, 1.455501, 0.190058, 0.0, 0.0],
+ shape: [9, 9, 4]
+ }
+ },
+ 'convolutional.Deconvolution2D.3': {
+ input: {
+ data: [-0.007435, 0.615048, -0.558658, -0.008729, 0.041294, -0.438168, 0.529679, 0.266543, 0.550212, -0.183091, 0.3534, 0.109289, -0.621224, -0.674319, 0.15753, -0.648414, 0.830683, -0.934728, 0.16761, 0.50837, 0.086898, -0.035362, -0.851074, -0.016054, -0.545162, -0.344549, 0.467416, 0.926628, -0.560706, -0.569233, 0.855837, -0.009762],
+ shape: [4, 4, 2]
+ },
+ weights: [
+ {
+ data: [-0.7046, 0.058369, -0.012661, -0.889136, -0.007435, 0.615048, -0.558658, -0.008729, 0.041294, -0.438168, 0.529679, 0.266543, 0.550212, -0.183091, 0.3534, 0.109289, -0.621224, -0.674319, 0.15753, -0.648414, 0.830683, -0.934728, 0.16761, 0.50837, 0.086898, -0.035362, -0.851074, -0.016054, -0.545162, -0.344549, 0.467416, 0.926628, -0.560706, -0.569233, 0.855837, -0.009762, 0.293612, -0.714253, -0.817222, 0.023038, -0.85581, 0.539004, 0.741369, -0.823095, -0.859253, -0.035201, 0.737323, 0.025245, 0.366923, -0.220199, 0.028247, 0.196676, 0.835236, 0.376875, 0.771537, -0.449685, 0.756239, 0.813555, 0.931644, 0.659618, 0.742881, -0.696761, 0.246132, -0.088558, -0.595887, 0.278583, -0.957392, -0.062303, -0.402006, 0.976563, -0.887975, 0.147616],
+ shape: [3, 3, 2, 4]
+ },
+ {
+ data: [-0.7046, 0.058369, -0.012661, -0.889136],
+ shape: [4]
+ }
+ ],
+ expected: {
+ data: [0.0, 0.0, 0.110927, 0.0, 0.0, 0.0, 0.390755, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.703063, 0.0, 0.0, 0.0, 0.0, 0.303646, 0.0, 0.0, 0.442749, 0.0, 0.0, 0.777761, 0.777295, 0.7709, 0.0, 0.750528, 0.299845, 0.154226, 0.0, 0.0, 1.509791, 1.18485, 0.0, 0.0, 0.090488, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.88771, 0.757259, 0.0, 0.0, 1.760764, 0.778453, 0.394454, 0.71713, 0.0, 0.0, 0.0, 0.0, 1.796376, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ shape: [4, 4, 4]
+ }
+ },
+ 'convolutional.Deconvolution2D.4': {
+ input: {
+ data: [0.656737, 0.433335, 0.19508, 0.702874, 0.204501, -0.719665, 0.652834, -0.165006, 0.065511, 0.376121, 0.755842, 0.602262, -0.479869, -0.721179, 0.979413, 0.487952, 0.353365, 0.379881, -0.725052, 0.794477, -0.748911, 0.150616, -0.830063, 0.781869, -0.467526, -0.294391, -0.927268, 0.293802, 0.49534, 0.456641, 0.610365, -0.549942],
+ shape: [4, 4, 2]
+ },
+ weights: [
+ {
+ data: [0.015448, 0.261101, 0.371131, 0.970987, 0.733096, 0.656737, 0.433335, 0.19508, 0.702874, 0.204501, -0.719665, 0.652834, -0.165006, 0.065511, 0.376121, 0.755842, 0.602262, -0.479869, -0.721179, 0.979413, 0.487952, 0.353365, 0.379881, -0.725052, 0.794477, -0.748911, 0.150616, -0.830063, 0.781869, -0.467526, -0.294391, -0.927268, 0.293802, 0.49534, 0.456641, 0.610365, -0.549942, 0.126156, 0.450587, -0.837003, 0.361856, 0.138717, -0.473225, 0.432004, 0.46321, -0.042096, -0.481635, -0.730053, 0.724533, 0.657809, -0.088475, 0.224629, -0.287917, -0.394062, -0.498412, -0.523992, 0.638287, -0.400103, 0.456819, -0.150058, -0.459513, 0.357662, 0.287583, -0.448432, 0.805097, 0.529896, -0.935158, -0.723581, -0.926538, -0.389357, 0.673302, 0.696614, -0.819421, 0.580246, 0.249636, -0.53035, -0.599139, -0.987449, -0.679439, 0.024594, -0.686301, -0.575677, -0.655428, -0.185761, 0.946483, 0.12546, -0.358746, 0.039991, -0.701225, -0.987664],
+ shape: [3, 3, 2, 5]
+ },
+ {
+ data: [0.015448, 0.261101, 0.371131, 0.970987, 0.733096],
+ shape: [5]
+ }
+ ],
+ expected: {
+ data: [0.31018, 0.620355, 0.699402, 1.913249, 1.303165, 0.0, 0.950822, 0.054822, 0.701498, 1.404523, 0.475991, 0.913952, 0.470435, 1.517081, 1.339014, 0.406317, 0.81177, 0.001654, 0.476869, 1.494874, 0.0, 0.177439, 0.0, 1.071832, 0.562218, 0.0, 0.0, 0.682732, 1.503391, 0.105164, 0.555919, 0.323925, 1.256283, 0.777944, 1.676876, 0.0, 0.587917, 0.342591, 1.132753, 0.817032, 0.086603, 0.0, 0.618749, 1.49155, 0.670287, 0.23485, 0.143492, 0.0, 1.568665, 1.322355, 0.101858, 0.117784, 0.154654, 1.323484, 0.0, 0.05645, 0.0, 0.0, 1.564517, 1.285816, 0.0, 0.959704, 0.003035, 0.992225, 1.22614, 0.119742, 0.636085, 0.79975, 0.537911, 0.35442, 0.081551, 0.0, 0.771179, 0.810669, 1.175383, 0.258626, 0.431133, 0.182657, 1.133461, 0.926953, 0.191316, 0.270846, 0.344131, 0.602959, 1.218054, 0.464954, 0.728256, 0.0, 0.790672, 1.300717, 0.05939, 0.0, 0.0, 1.210212, 1.363556, 0.0, 0.832037, 0.0, 0.221798, 1.673233, 0.0, 0.56278, 0.319359, 0.0, 0.488038, 0.33506, 0.087126, 1.339444, 2.067279, 0.0, 0.038919, 0.978335, 1.390465, 2.375806, 3.000996, 0.206478, 1.748005, 0.0, 1.174163, 1.738294, 0.225733, 0.0, 0.437828, 1.172912, 0.448196, 0.02332, 0.089035, 0.065541, 1.2718, 1.010857, 0.0, 0.0, 0.499829, 1.762761, 0.485059, 0.263601, 0.075879, 0.0, 1.733872, 1.479383, 0.0, 1.656875, 0.0, 0.38561, 0.650502, 0.0, 0.54188, 1.124716, 0.241164, 0.036418, 0.445295, 0.0, 1.147151, 1.535644, 1.11931, 0.349313, 0.161947, 0.0, 1.747634, 1.507749, 0.439591, 0.189679, 0.323069, 1.20324, 0.97613, 0.0, 0.540865, 0.0, 0.502634, 1.263669, 0.387982, 0.132628, 0.0, 0.0, 0.531725, 1.327243, 0.431937, 0.0, 0.379902, 1.442007, 0.0, 0.0, 0.0, 1.817207, 0.0, 0.727635, 0.0, 1.527772, 1.024859, 0.4614, 0.085243, 0.570184, 0.020346, 1.078867, 0.475692, 1.604441, 0.580019, 0.0, 0.589507, 1.443162, 0.143286, 0.0, 0.522875, 1.317192, 0.576495, 0.127323, 0.127155, 0.0, 1.398878, 1.146668, 0.483498, 0.818352, 0.004606, 1.004109, 0.0, 0.0, 0.0, 0.134233, 1.233386, 0.919859, 0.0, 1.216949, 0.060984, 1.316534, 0.507204, 0.0, 0.084673, 0.615577, 0.75658, 0.48527, 0.724375, 0.528718, 0.381258, 1.276045, 0.050294, 0.0, 0.0, 0.193131, 1.178886, 0.862924, 0.0, 0.0, 0.0, 0.0, 0.466735, 0.165848, 0.0, 0.0, 1.099599, 0.366475, 0.745723, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.192767, 0.0, 0.510624, 0.671723, 0.028575, 0.230558, 2.448812, 0.0, 0.0, 0.247552, 0.535217, 0.13723, 1.183393, 0.892037, 0.0, 0.0, 0.856287, 0.0, 0.0, 0.0, 0.442432, 0.394705, 0.236063, 0.0, 0.856521, 0.196632, 0.606754, 0.766011, 0.0, 0.338037, 0.807297, 0.555718, 0.322881, 0.663376, 0.666427, 0.388159, 0.693807, 0.340951, 0.0, 0.0, 0.595446, 0.783272, 0.496842, 0.076432, 0.0, 0.723697, 1.921721, 0.995153, 0.175467, 0.109879, 0.0, 1.515827, 1.262925, 0.0, 0.400301, 0.155759, 1.038936, 1.156711, 0.259462, 0.610641, 0.483778, 0.836216, 0.654066],
+ shape: [8, 8, 5]
+ }
+ },
+ 'convolutional.Deconvolution2D.5': {
+ input: {
+ data: [-0.629124, -0.519787, -0.038861, -0.715188, 0.71707, -0.180419, 0.054783, 0.458147, 0.631702, -0.028843, 0.586737, -0.21045, 0.463067, -0.16224, 0.36397, -0.958481, -0.793514, -0.985689, -0.380946, -0.946773, -0.259217, 0.266228, -0.671058, -0.358071, -0.200672, 0.343247, 0.883116, 0.945544, 8.8e-05, -0.43253, 0.375163, -0.655772],
+ shape: [4, 4, 2]
+ },
+ weights: [
+ {
+ data: [0.304653, 0.842246, -0.653708, 0.24125, -0.786747, -0.629124, -0.519787, -0.038861, -0.715188, 0.71707, -0.180419, 0.054783, 0.458147, 0.631702, -0.028843, 0.586737, -0.21045, 0.463067, -0.16224, 0.36397, -0.958481, -0.793514, -0.985689, -0.380946, -0.946773, -0.259217, 0.266228, -0.671058, -0.358071, -0.200672, 0.343247, 0.883116, 0.945544, 8.8e-05, -0.43253, 0.375163, -0.655772, -0.806227, -0.026706, -0.789484, 0.347693, -0.133666, 0.520664, -0.663529, 0.171618, -0.768326, 0.43348, -0.892969, -0.518967, -0.046671, -0.446649, -0.676726, -0.949549, 0.182767, -0.929755, 0.138988, -0.979159, 0.232577, 0.247578, 0.333053, -0.44899, 0.209367, -0.289982, -0.141429, -0.968415, -0.3587, 0.573399, -0.127767, -0.257376, -0.54742, -0.511472, 0.228512, 0.950914, -0.234276, 0.074906, 0.869786, 0.565649, 0.708036, 0.876331, -0.51019, -0.101183, -0.21937, 0.958957, -0.388422, -0.064355, 0.184026, -0.286808, 0.56959, 0.966958, -0.7823],
+ shape: [3, 3, 2, 5]
+ },
+ {
+ data: [0.304653, 0.842246, -0.653708, 0.24125, -0.786747],
+ shape: [5]
+ }
+ ],
+ expected: {
+ data: [0.485277, 0.701021, 0.0, 0.928445, 0.0, 0.231755, 2.211627, 0.362644, 0.016676, 0.206506, 0.840639, 0.537421, 0.0, 0.638195, 0.0, 0.401053, 2.320396, 0.040336, 0.061964, 0.0, 0.692594, 0.66819, 0.0, 0.0, 0.0, 0.149982, 0.281585, 0.0, 0.315409, 0.0, 0.0, 1.033521, 0.0, 0.0, 0.0, 0.043434, 0.445142, 0.0, 0.33686, 0.0, 0.259794, 0.805735, 0.0, 0.234317, 0.0, 0.0, 0.505252, 0.0, 0.028399, 0.0, 0.0, 1.055305, 0.0, 0.0, 0.0, 0.0, 0.963562, 0.037445, 0.233993, 0.0, 0.322064, 1.404974, 0.0, 0.317595, 0.0, 0.047079, 1.335566, 0.0, 1.015328, 0.0, 0.546452, 0.745306, 0.0, 0.0, 0.0, 0.140938, 1.099162, 0.0, 0.355236, 0.0, 0.670351, 0.672593, 0.0, 0.0, 0.0, 0.111417, 1.166584, 0.0, 0.300757, 0.0, 0.590311, 0.710022, 0.0, 0.018189, 0.0, 0.0, 1.637707, 0.0, 0.311346, 0.0, 1.167628, 0.378113, 0.391691, 0.497166, 0.0, 0.0, 1.13425, 0.0, 0.0, 0.0, 1.543133, 1.25263, 1.521816, 1.179627, 0.0, 0.0, 1.035661, 0.0, 0.0, 0.0, 0.420927, 0.471338, 0.845466, 0.017311, 0.0, 0.129666, 0.786063, 0.0, 0.0, 0.0, 0.608605, 0.2113, 0.244304, 0.197334, 0.0, 0.0, 0.421847, 0.0, 0.0, 0.0, 0.786085, 0.521035, 0.0, 1.27931, 0.0, 0.036123, 2.628832, 0.273636, 0.0, 0.534973, 0.899631, 0.482758, 0.0, 0.985363, 0.0, 0.354115, 1.62358, 0.0, 0.0, 0.0, 0.009975, 0.992299, 0.0, 0.275085, 0.0, 0.09276, 0.399176, 0.0, 0.26929, 0.115874, 0.346446, 0.776727, 0.0, 0.872344, 0.0, 0.090775, 0.020134, 0.0, 0.0, 0.0, 0.491742, 1.179323, 0.0, 0.0, 1.026965, 0.07146, 0.069043, 0.0, 0.0, 0.0, 0.0, 1.071602, 0.0, 0.0, 0.0, 0.414998, 1.024634, 0.0, 0.605511, 0.0, 1.448504, 1.018559, 0.0, 1.500783, 0.0, 0.0, 0.644918, 0.0, 0.428058, 0.0, 0.0, 1.01786, 0.0, 0.196268, 0.0, 1.09985, 0.801785, 0.0, 0.26438, 0.0, 0.0, 1.134078, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.648302, 0.0, 0.637008, 0.654741, 0.0, 0.465661, 0.0, 0.127249, 2.027051, 0.129045, 0.151727, 0.0, 0.938941, 0.507835, 0.127209, 0.332643, 0.0],
+ shape: [7, 7, 5]
+ }
+ }
+ }
+
+ window.TEST_DATA = Object.assign({}, window.TEST_DATA, DATA)
+})()