diff --git a/index.html b/index.html
index 8f1e023..566cdc3 100644
--- a/index.html
+++ b/index.html
@@ -49,6 +49,8 @@
+
+
diff --git a/notebooks/convolutional/Convolution3D.ipynb b/notebooks/convolutional/Convolution3D.ipynb
new file mode 100644
index 0000000..00f85e7
--- /dev/null
+++ b/notebooks/convolutional/Convolution3D.ipynb
@@ -0,0 +1,369 @@
+{
+ "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 Convolution3D\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": [
+ "### Convolution3D"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "**[convolutional.Convolution3D.0] 4 3x3x3 filters on 5x5x5x2 input, activation='linear', border_mode='valid', subsample=(1,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, 3, 2, 4)\n",
+ "W: [-0.716739, -0.376911, 0.109585, -0.748377, -0.012235, 0.842256, -0.24031, -0.747101, 0.997502, 0.541847, 0.46022, -0.936762, 0.620677, -0.897006, 0.142436, -0.321119, -0.564347, 0.528326, 0.895515, 0.412205, 0.863293, -0.122241, 0.253835, 0.334585, -0.843125, -0.865964, -0.033224, 0.770519, 0.602345, 0.482129, -0.534779, 0.882924, 0.845752, -0.040631, 0.674428, -0.779344, 0.053258, -0.70852, -0.956298, -0.280062, 0.627909, 0.725718, -0.103394, -0.791248, 0.74844, -0.409891, 0.60642, -0.703554, -0.678996, -0.865614, 0.557983, 0.833801, 0.422953, -0.214554, 0.234606, -0.723627, 0.379456, -0.783448, 0.413208, 0.570398, -0.073524, -0.77024, -0.435243, -0.660294, 0.276208, -0.676938, 0.11366, 0.073336, 0.485568, -0.38602, 0.963383, -0.28129, 0.757856, 0.342945, 0.083787, 0.138463, 0.67179, 0.519043, 0.654146, 0.465576, 0.784872, -0.364478, -0.423446, -0.572558, -0.083876, -0.54903, -0.295645, 0.2349, 0.215547, -0.08804, -0.935702, -0.804254, 0.842041, 0.891524, 0.53582, 0.816882, -0.31899, 0.761039, 0.092443, -0.013288, 0.81033, 0.095114, 0.948258, -0.974729, -0.187374, -0.227432, 0.102514, -0.06137, 0.344298, -0.700357, 0.793725, -0.390442, 0.561325, 0.069437, 0.297307, -0.139713, 0.796003, -0.873413, 0.228104, -0.447393, -0.246792, 0.931166, 0.149258, -0.122052, 0.027526, 0.592017, 0.470149, 0.726634, 0.151077, -0.513093, 0.558565, -0.242539, -0.411284, -0.713388, -0.522539, 0.78801, -0.702311, -0.891064, -0.871238, -0.853877, 0.333665, 0.438522, -0.491023, -0.868654, -0.742188, -0.832603, -0.0604, 0.638536, -0.235743, 0.508252, -0.443941, 0.710677, 0.194301, 0.17929, 0.235854, -0.376182, -0.346676, 0.670737, -0.94404, -0.64212, -0.512999, 0.97764, 0.463103, 0.791414, 0.814634, 0.309827, -0.210593, -0.142933, 0.201831, -0.440759, -0.217137, -0.893463, -0.788414, -0.099469, 0.806605, -0.388143, -0.322186, 0.899655, 0.08527, -0.805031, 0.833597, 0.228396, -0.942825, -0.954152, 0.750815, 0.178301, -0.528541, -0.533345, -0.760308, -0.384974, -0.031988, 0.52894, -0.898135, 0.379761, 0.207095, 0.882652, 0.444118, -0.014279, -0.333001, -0.812251, -0.186455, -0.778118, -0.459847, 0.402095, 0.610382, 0.477684, -0.86357, -0.420118, 0.503587, -0.730952, 0.904388, 0.272979, -0.98017, -0.192944, 0.500952, 0.98925]\n",
+ "b shape: (4,)\n",
+ "b: [-0.716739, -0.376911, 0.109585, -0.748377]\n",
+ "\n",
+ "in shape: (5, 5, 5, 2)\n",
+ "in: [-0.012235, 0.842256, -0.24031, -0.747101, 0.997502, 0.541847, 0.46022, -0.936762, 0.620677, -0.897006, 0.142436, -0.321119, -0.564347, 0.528326, 0.895515, 0.412205, 0.863293, -0.122241, 0.253835, 0.334585, -0.843125, -0.865964, -0.033224, 0.770519, 0.602345, 0.482129, -0.534779, 0.882924, 0.845752, -0.040631, 0.674428, -0.779344, 0.053258, -0.70852, -0.956298, -0.280062, 0.627909, 0.725718, -0.103394, -0.791248, 0.74844, -0.409891, 0.60642, -0.703554, -0.678996, -0.865614, 0.557983, 0.833801, 0.422953, -0.214554, 0.234606, -0.723627, 0.379456, -0.783448, 0.413208, 0.570398, -0.073524, -0.77024, -0.435243, -0.660294, 0.276208, -0.676938, 0.11366, 0.073336, 0.485568, -0.38602, 0.963383, -0.28129, 0.757856, 0.342945, 0.083787, 0.138463, 0.67179, 0.519043, 0.654146, 0.465576, 0.784872, -0.364478, -0.423446, -0.572558, -0.083876, -0.54903, -0.295645, 0.2349, 0.215547, -0.08804, -0.935702, -0.804254, 0.842041, 0.891524, 0.53582, 0.816882, -0.31899, 0.761039, 0.092443, -0.013288, 0.81033, 0.095114, 0.948258, -0.974729, -0.187374, -0.227432, 0.102514, -0.06137, 0.344298, -0.700357, 0.793725, -0.390442, 0.561325, 0.069437, 0.297307, -0.139713, 0.796003, -0.873413, 0.228104, -0.447393, -0.246792, 0.931166, 0.149258, -0.122052, 0.027526, 0.592017, 0.470149, 0.726634, 0.151077, -0.513093, 0.558565, -0.242539, -0.411284, -0.713388, -0.522539, 0.78801, -0.702311, -0.891064, -0.871238, -0.853877, 0.333665, 0.438522, -0.491023, -0.868654, -0.742188, -0.832603, -0.0604, 0.638536, -0.235743, 0.508252, -0.443941, 0.710677, 0.194301, 0.17929, 0.235854, -0.376182, -0.346676, 0.670737, -0.94404, -0.64212, -0.512999, 0.97764, 0.463103, 0.791414, 0.814634, 0.309827, -0.210593, -0.142933, 0.201831, -0.440759, -0.217137, -0.893463, -0.788414, -0.099469, 0.806605, -0.388143, -0.322186, 0.899655, 0.08527, -0.805031, 0.833597, 0.228396, -0.942825, -0.954152, 0.750815, 0.178301, -0.528541, -0.533345, -0.760308, -0.384974, -0.031988, 0.52894, -0.898135, 0.379761, 0.207095, 0.882652, 0.444118, -0.014279, -0.333001, -0.812251, -0.186455, -0.778118, -0.459847, 0.402095, 0.610382, 0.477684, -0.86357, -0.420118, 0.503587, -0.730952, 0.904388, 0.272979, -0.98017, -0.192944, 0.500952, 0.98925, 0.341975, -0.562962, 0.049861, -0.202414, -0.830072, -0.905711, -0.925835, 0.781849, -0.920591, -0.307965, -0.471503, -0.554001, 0.713829, -0.412998, -0.516655, -0.631432, 0.976909, -0.804501, 0.406977, 0.791254, 0.294557, 0.437734, -0.094275, -0.820109, -0.48955, 0.396867, -0.827079, -0.419779, -0.037705, -0.387553, 0.871437, -0.444237, -0.928096, 0.759913, 0.824767, -0.391281, 0.80935, 0.556379]\n",
+ "out shape: (3, 3, 3, 4)\n",
+ "out: [-0.990212, 1.639581, -1.948825, -3.684331, 0.257052, -2.808133, 2.076573, -2.729982, -0.78123, 0.347783, 2.327393, -2.657676, -0.107308, -1.605268, 0.62405, -5.659127, 2.852406, -0.649643, 6.126531, -2.272969, 1.019947, 3.255988, -6.427436, -7.437248, -4.01012, -1.170293, 1.765438, 6.611716, -0.59429, -0.561376, -0.271424, 1.316552, 1.801865, -2.038508, -1.221814, -3.836679, -2.255499, -2.756532, -1.162019, -2.273401, 0.959788, -2.926484, 0.890316, -2.095109, -0.56757, 0.593196, -0.404296, -2.956032, 1.313724, 0.757657, 1.019654, -2.681708, -1.103542, 2.976485, 1.964336, -2.199447, -1.192246, -1.618244, 0.738719, 0.553589, -1.725408, -3.353908, -1.78493, -3.942136, 0.091989, 1.563757, 0.504778, 2.773416, -4.433075, -2.957799, -1.355837, -0.652115, -4.728858, -1.700152, 3.67987, 0.592441, -1.557015, 2.452404, 5.097181, 0.639657, -4.788903, -3.806307, 1.558109, 3.81415, 0.053524, 6.426715, -1.117815, 0.510982, -0.930588, 0.263227, 0.744451, -2.02314, -0.781206, -1.206907, -2.087747, 0.768416, -3.891211, 2.946293, 0.308395, 1.134286, -1.11568, 2.414839, 4.610423, -3.157369, -1.071085, -5.993021, -0.112579, -3.090427]\n"
+ ]
+ }
+ ],
+ "source": [
+ "data_in_shape = (5, 5, 5, 2)\n",
+ "conv = Convolution3D(4, 3, 3, 3, activation='linear', border_mode='valid', \n",
+ " subsample=(1, 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(130)\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.Convolution3D.1] 2 3x3x3 filters on 4x4x4x2 input, activation='sigmoid', border_mode='valid', subsample=(1,1,1), dim_ordering='tf', bias=False**"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 7,
+ "metadata": {
+ "collapsed": false
+ },
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "W shape: (3, 3, 3, 2, 2)\n",
+ "W: [0.300307, 0.896218, -0.223942, 0.282592, 0.381024, -0.746781, -0.521066, -0.491686, -0.147117, 0.678005, 0.490067, -0.238641, -0.476614, -0.893332, -0.126207, -0.582042, 0.188822, -0.802193, -0.551813, 0.168525, 0.918162, -0.580232, 0.322675, 0.005226, -0.359417, -0.74987, 0.613778, 0.97392, 0.086083, -0.537354, 0.207025, -0.646608, 0.773075, 0.178045, 0.442345, -0.448659, 0.576229, -0.734755, -0.200568, 0.259648, -0.151913, -0.676254, 0.040688, 0.214083, 0.161611, 0.642232, 0.969984, 0.86899, 0.80611, -0.323948, 0.566489, 0.487469, 0.161171, -0.134673, 0.335856, -0.526625, -0.096527, 0.839995, 0.933746, 0.538101, -0.346576, 0.24568, -0.616796, -0.503357, -0.766323, -0.979349, 0.697389, 0.061332, -0.01233, 0.304615, -0.546648, 0.234325, -0.598896, -0.018136, 0.89706, 0.963941, -0.653697, 0.485039, -0.227064, 0.302214, 0.486927, -0.504459, -0.015408, -0.1505, -0.419861, 0.973378, -0.3211, -0.600593, 0.657395, -0.274736, 0.42005, -0.193936, -0.222912, 0.005268, 0.593099, -0.977881, -0.911958, 0.794233, 0.506375, 0.724717, 0.980406, 0.160665, 0.907777, -0.158316, -0.663804, -0.93618, 0.166131, 0.47488]\n",
+ "\n",
+ "in shape: (4, 4, 4, 2)\n",
+ "in: [0.54298, -0.369581, 0.787756, -0.413208, -0.451769, 0.474871, 0.955491, -0.993053, 0.892644, 0.317005, -0.299495, -0.282463, 0.092705, 0.847179, 0.355861, -0.356589, -0.34065, -0.644927, 0.294664, 0.525887, -0.45672, 0.109351, -0.232926, -0.322716, 0.708476, 0.133826, 0.942949, 0.509234, 0.666986, 0.647692, 0.46106, 0.294315, -0.531805, 0.742175, -0.943787, 0.452597, -0.223524, -0.821973, 0.130818, -0.241084, -0.709061, -0.410544, -0.779838, 0.3187, 0.449769, -0.098487, -0.717268, -0.820627, -0.03977, 0.212835, 0.322279, -0.365277, 0.551029, -0.791009, 0.454023, -0.151234, 0.241568, 0.728562, 0.92247, -0.61221, 0.023427, 0.923886, -0.594403, 0.111887, 0.721627, -0.170876, 0.134098, -0.790903, -0.692903, 0.184462, -0.64679, -0.812958, -0.352592, 0.373439, 0.244427, 0.524303, 0.772487, -0.929582, 0.019085, -0.569751, 0.950518, 0.539197, 0.102938, -0.81072, -0.658932, 0.458097, -0.984345, -0.563091, -0.842868, -0.816919, 0.144705, 0.110019, 0.637162, -0.055083, -0.830439, -0.275994, -0.926286, 0.692921, -0.816955, 0.94607, 0.303029, 0.221167, 0.703979, 0.010576, 0.093083, 0.709286, -0.301982, 0.70202, 0.968466, 0.722557, -0.378228, 0.671395, -0.132298, 0.81306, -0.922057, -0.662015, 0.404419, -0.017544, 0.939241, 0.452875, -0.436359, -0.918861, -0.685562, 0.2343, -0.344733, 0.058154, 0.883477, -0.027478]\n",
+ "out shape: (2, 2, 2, 2)\n",
+ "out: [0.028378, 0.571757, 0.006776, 0.886406, 0.155123, 0.446979, 0.280513, 0.76513, 0.107532, 0.596331, 0.958001, 0.078373, 0.762681, 0.216897, 0.14058, 0.000131]\n"
+ ]
+ }
+ ],
+ "source": [
+ "data_in_shape = (4, 4, 4, 2)\n",
+ "conv = Convolution3D(2, 3, 3, 3, activation='sigmoid', border_mode='valid', \n",
+ " subsample=(1, 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(131)\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.Convolution3D.2] 2 3x3x3 filters on 4x4x3x2 input, activation='relu', border_mode='same', subsample=(1,1,1), 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, 3, 2, 2)\n",
+ "W: [0.561808, -0.237711, 0.657275, 0.563366, 0.603194, -0.286196, 0.924244, -0.28752, 0.637161, 0.810376, -0.914473, -0.967621, 0.112092, -0.838944, 0.928514, -0.182969, -0.348933, -0.07114, 0.743005, -0.294021, -0.568579, -0.596645, -0.517913, -0.571138, -0.497605, -0.358416, 0.073639, -0.83844, -0.915183, 0.412981, 0.909286, 0.226941, 0.373944, -0.563635, 0.753859, -0.681375, 0.022101, -0.582124, -0.280116, -0.82489, -0.757258, 0.989785, 0.028165, 0.366484, -0.778942, 0.27204, -0.25007, -0.967536, 0.28709, -0.797754, -0.68149, 0.394872, -0.43468, 0.665998, 0.869927, -0.606877, -0.134099, 0.652508, -0.603352, 0.633151, -0.836046, -0.196456, 0.947196, 0.760248, -0.921493, -0.372249, -0.982245, -0.864395, -0.339177, -0.904094, 0.959217, 0.147402, 0.504567, 0.769068, 0.629401, -0.441415, 0.813767, -0.350138, 0.864937, -0.10205, 0.145076, -0.590264, 0.733088, -0.45583, 0.040498, -0.05256, 0.022563, -0.375014, 0.700348, 0.75455, 0.610168, 0.194477, -0.810708, -0.19662, -0.842144, 0.285245, -0.305602, -0.714785, -0.389563, 0.487303, 0.384339, -0.825992, 0.655456, 0.015094, 0.069932, -0.350014, -0.852013, -0.034763]\n",
+ "b shape: (2,)\n",
+ "b: [0.561808, -0.237711]\n",
+ "\n",
+ "in shape: (4, 4, 3, 2)\n",
+ "in: [0.657275, 0.563366, 0.603194, -0.286196, 0.924244, -0.28752, 0.637161, 0.810376, -0.914473, -0.967621, 0.112092, -0.838944, 0.928514, -0.182969, -0.348933, -0.07114, 0.743005, -0.294021, -0.568579, -0.596645, -0.517913, -0.571138, -0.497605, -0.358416, 0.073639, -0.83844, -0.915183, 0.412981, 0.909286, 0.226941, 0.373944, -0.563635, 0.753859, -0.681375, 0.022101, -0.582124, -0.280116, -0.82489, -0.757258, 0.989785, 0.028165, 0.366484, -0.778942, 0.27204, -0.25007, -0.967536, 0.28709, -0.797754, -0.68149, 0.394872, -0.43468, 0.665998, 0.869927, -0.606877, -0.134099, 0.652508, -0.603352, 0.633151, -0.836046, -0.196456, 0.947196, 0.760248, -0.921493, -0.372249, -0.982245, -0.864395, -0.339177, -0.904094, 0.959217, 0.147402, 0.504567, 0.769068, 0.629401, -0.441415, 0.813767, -0.350138, 0.864937, -0.10205, 0.145076, -0.590264, 0.733088, -0.45583, 0.040498, -0.05256, 0.022563, -0.375014, 0.700348, 0.75455, 0.610168, 0.194477, -0.810708, -0.19662, -0.842144, 0.285245, -0.305602, -0.714785]\n",
+ "out shape: (4, 4, 3, 2)\n",
+ "out: [0.0, 0.0, 0.202974, 0.32343, 1.256458, 0.0, 0.0, 0.59227, 0.0, 0.0, 0.0, 1.277499, 0.514505, 3.565827, 1.717093, 0.0, 0.518093, 2.13386, 0.597589, 0.0, 0.145479, 0.0, 0.411267, 0.096419, 0.0, 0.911234, 0.0, 0.0, 0.0, 3.251087, 6.37503, 3.037017, 2.607065, 0.0, 0.0, 1.6602, 1.164416, 2.613473, 3.836789, 0.679142, 0.0, 0.0, 2.195455, 0.0, 0.0, 5.636247, 0.0, 0.948504, 0.0, 0.0, 0.0, 0.583949, 0.805164, 3.08051, 0.0, 0.0, 3.62315, 1.695895, 2.409393, 0.738817, 0.177071, 1.258827, 1.401754, 0.0, 0.0, 0.919304, 0.0, 0.423109, 2.58729, 0.0, 1.76654, 0.0, 1.167698, 0.297612, 0.896641, 0.102354, 0.287512, 0.0, 0.0, 1.459626, 0.0, 1.226061, 1.221153, 0.68316, 1.060495, 1.016869, 3.17602, 2.120962, 0.636249, 2.750501, 0.0, 0.0, 0.0, 0.401625, 0.0, 0.0]\n"
+ ]
+ }
+ ],
+ "source": [
+ "data_in_shape = (4, 4, 3, 2)\n",
+ "conv = Convolution3D(2, 3, 3, 3, activation='relu', border_mode='same', \n",
+ " subsample=(1, 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(132)\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.Convolution3D.3] 2 3x3x2 filters on 4x4x3x2 input, activation='relu', border_mode='same', subsample=(2,1,1), dim_ordering='tf', bias=True**"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 11,
+ "metadata": {
+ "collapsed": false
+ },
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "W shape: (3, 3, 2, 2, 2)\n",
+ "W: [-0.160983, -0.740678, -0.780888, -0.715513, -0.121464, 0.475806, -0.594872, -0.377686, 0.116261, 0.792104, -0.256096, 0.879075, -0.36824, 0.543525, 0.394369, 0.858105, -0.755411, -0.121975, -0.06772, -0.070284, -0.00725, 0.064283, -0.248044, -0.679932, -0.289603, 0.951553, 0.722203, 0.732689, 0.334081, 0.730298, -0.464328, 0.955306, 0.991716, -0.649746, -0.679444, 0.241959, -0.305542, 0.442359, 0.66645, 0.09566, 0.097175, -0.583151, -0.84885, -0.88039, -0.245959, 0.440772, -0.576763, -0.839252, -0.189355, -0.312547, -0.240347, 0.037718, 0.270261, 0.740958, -0.080857, -0.34412, -0.776913, 0.119299, 0.715073, 0.65029, -0.303087, -0.742422, 0.283872, -0.453492, 0.657322, 0.294547, -0.211275, -0.676264, -0.362203, -0.414399, -0.820797, 0.065655]\n",
+ "b shape: (2,)\n",
+ "b: [-0.160983, -0.740678]\n",
+ "\n",
+ "in shape: (4, 4, 3, 2)\n",
+ "in: [-0.780888, -0.715513, -0.121464, 0.475806, -0.594872, -0.377686, 0.116261, 0.792104, -0.256096, 0.879075, -0.36824, 0.543525, 0.394369, 0.858105, -0.755411, -0.121975, -0.06772, -0.070284, -0.00725, 0.064283, -0.248044, -0.679932, -0.289603, 0.951553, 0.722203, 0.732689, 0.334081, 0.730298, -0.464328, 0.955306, 0.991716, -0.649746, -0.679444, 0.241959, -0.305542, 0.442359, 0.66645, 0.09566, 0.097175, -0.583151, -0.84885, -0.88039, -0.245959, 0.440772, -0.576763, -0.839252, -0.189355, -0.312547, -0.240347, 0.037718, 0.270261, 0.740958, -0.080857, -0.34412, -0.776913, 0.119299, 0.715073, 0.65029, -0.303087, -0.742422, 0.283872, -0.453492, 0.657322, 0.294547, -0.211275, -0.676264, -0.362203, -0.414399, -0.820797, 0.065655, 0.892713, 0.922155, -0.495448, 0.794696, -0.998576, 0.689174, -0.94489, -0.97599, 0.608171, 0.634289, 0.350419, -0.967604, -0.024661, -0.816395, 0.316404, -0.849656, 0.324503, 0.389871, 0.534612, -0.283795, 0.495473, 0.079537, 0.128614, -0.781724, -0.215271, -0.022468]\n",
+ "out shape: (2, 4, 3, 2)\n",
+ "out: [0.09816, 0.0, 1.235674, 0.0, 0.0, 0.0, 2.877764, 1.905926, 1.647481, 3.613319, 0.795886, 1.891695, 0.0, 0.0, 0.0, 0.0, 0.357909, 0.0, 0.0, 0.0, 0.734974, 0.0, 0.0, 0.0, 0.132112, 0.0, 0.0, 1.763944, 0.613645, 0.092832, 0.0, 0.0, 0.0, 0.0, 0.872912, 0.0, 2.011758, 0.754629, 0.0, 0.0, 0.018068, 0.0, 0.0, 0.0, 1.061294, 0.0, 0.0, 1.852663]\n"
+ ]
+ }
+ ],
+ "source": [
+ "data_in_shape = (4, 4, 3, 2)\n",
+ "conv = Convolution3D(2, 3, 3, 2, activation='relu', border_mode='same', \n",
+ " subsample=(2, 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(133)\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.Convolution3D.4] 2 3x3x3 filters on 6x6x4x2 input, activation='relu', border_mode='same', subsample=(3,3,2), 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, 3, 2, 2)\n",
+ "W: [0.622807, -0.104472, 0.255491, 0.763798, 0.330149, 0.766733, 0.42334, 0.330543, -0.75135, -0.922873, -0.583415, -0.466281, -0.717938, 0.731792, -0.400509, 0.612512, -0.498783, -0.14186, -0.737372, 0.781319, 0.651852, 0.673768, 0.431092, -0.299636, -0.592396, -0.25223, 0.660295, 0.014915, -0.737261, -0.683528, 0.991536, 0.863046, -0.857707, -0.709703, 0.619649, 0.440344, -0.075421, 0.792503, -0.7677, 0.799309, -0.819924, 0.230663, 0.585082, -0.65765, 0.912941, 0.378832, -0.756722, -0.282432, -0.619629, 0.971307, 0.261786, 0.695286, 0.447511, -0.336526, 0.823161, 0.964889, -0.567008, -0.256448, -0.630859, -0.033653, -0.068675, -0.307193, -0.746842, -0.749483, -0.750777, 0.40137, 0.546076, 0.989245, -0.156364, -0.439605, -0.342656, -0.89142, 0.671516, -0.96313, 0.415092, 0.10452, -0.933763, -0.493381, 0.680007, -0.064914, 0.552154, 0.420418, -0.104774, 0.339607, -0.840586, 0.34762, 0.456402, 0.917853, 0.427665, 0.478747, 0.994486, 0.549693, -0.779373, -0.078222, 0.580719, -0.961111, 0.459178, -0.165215, -0.315997, -0.727695, -0.717506, -0.101921, -0.155999, 0.242368, -0.952067, -0.00297, -0.331119, -0.101121]\n",
+ "b shape: (2,)\n",
+ "b: [0.622807, -0.104472]\n",
+ "\n",
+ "in shape: (6, 6, 4, 2)\n",
+ "in: [0.255491, 0.763798, 0.330149, 0.766733, 0.42334, 0.330543, -0.75135, -0.922873, -0.583415, -0.466281, -0.717938, 0.731792, -0.400509, 0.612512, -0.498783, -0.14186, -0.737372, 0.781319, 0.651852, 0.673768, 0.431092, -0.299636, -0.592396, -0.25223, 0.660295, 0.014915, -0.737261, -0.683528, 0.991536, 0.863046, -0.857707, -0.709703, 0.619649, 0.440344, -0.075421, 0.792503, -0.7677, 0.799309, -0.819924, 0.230663, 0.585082, -0.65765, 0.912941, 0.378832, -0.756722, -0.282432, -0.619629, 0.971307, 0.261786, 0.695286, 0.447511, -0.336526, 0.823161, 0.964889, -0.567008, -0.256448, -0.630859, -0.033653, -0.068675, -0.307193, -0.746842, -0.749483, -0.750777, 0.40137, 0.546076, 0.989245, -0.156364, -0.439605, -0.342656, -0.89142, 0.671516, -0.96313, 0.415092, 0.10452, -0.933763, -0.493381, 0.680007, -0.064914, 0.552154, 0.420418, -0.104774, 0.339607, -0.840586, 0.34762, 0.456402, 0.917853, 0.427665, 0.478747, 0.994486, 0.549693, -0.779373, -0.078222, 0.580719, -0.961111, 0.459178, -0.165215, -0.315997, -0.727695, -0.717506, -0.101921, -0.155999, 0.242368, -0.952067, -0.00297, -0.331119, -0.101121, 0.979275, 0.999252, 0.521731, -0.683745, 0.13268, -0.02283, -0.333171, 0.084336, 0.967829, -0.243099, -0.65592, 0.265795, -0.738191, 0.748515, 0.055295, -0.71117, -0.849279, 0.946324, 0.91352, -0.922913, 0.905676, 0.42188, -0.327285, -0.631911, -0.775742, -0.696021, 0.996116, 0.288415, -0.134258, -0.118686, 0.047865, 0.599197, -0.267092, 0.326933, -0.118315, 0.288843, -0.088352, 0.873786, 0.367592, -0.2835, 0.062748, 0.124767, -0.306431, -0.797375, -0.338658, 0.090141, 0.399011, 0.270202, 0.735773, 0.576237, 0.49903, 0.950745, 0.445642, 0.789956, -0.591685, -0.091733, 0.452208, 0.572278, -0.014814, 0.178051, 0.750801, -0.077224, -0.005775, -0.548912, -0.58962, -0.665754, 0.286856, 0.843047, -0.17934, -0.562433, 0.751457, -0.253229, -0.003361, -0.883475, 0.401674, 0.241623, -0.285594, 0.401469, 0.069789, 0.889598, 0.970932, -0.905932, -0.699628, 0.545623, 0.781924, 0.834341, 0.167673, -0.684819, -0.554758, 0.87348, 0.113279, -0.027234, -0.154146, -0.572187, -0.082501, 0.745653, 0.437841, 0.672742, -0.20552, -0.731811, 0.639947, 0.865838, 0.04588, 0.139607, 0.521049, 0.906016, 0.439766, 0.161608, 0.988467, 0.116776, -0.141933, 0.658322, 0.407769, 0.706881, 0.278246, -0.176282, -0.232731, 0.89114, 0.906824, 0.486935, -0.599041, 0.191432, 0.812589, -0.281513, 0.47336, 0.24849, -0.912168, -0.017699, 0.072546, 0.9249, 0.367322, -0.154274, -0.847056, -0.207236, 0.571427, -0.904635, 0.260295, -0.835689, -0.578835, 0.918011, 0.048527, -0.674753, -0.7327, -0.209332, 0.87192, -0.526782, -0.47431, 0.198573, 0.274862, -0.570459, 0.357794, -0.923848, -0.326055, -0.621309, -0.298064, 0.588621, -0.434224, 0.26631, -0.458417, 0.699587, 0.586844, 0.157536, 0.777812, -0.811094, 0.749212, -0.492543, -0.482318, 0.783566, -0.881362, -0.826629, -0.808297, 0.990087, -0.97475, -0.076858, 0.684759, -0.449941, -0.237982, -0.847246, -0.809583, 0.119563, -0.316425, -0.679099]\n",
+ "out shape: (2, 2, 2, 2)\n",
+ "out: [1.786687, 1.633532, 0.087363, 0.705533, 0.0, 0.0, 2.178441, 2.592993, 5.30457, 1.575011, 0.0, 0.831551, 1.727915, 0.0, 2.197441, 0.0]\n"
+ ]
+ }
+ ],
+ "source": [
+ "data_in_shape = (6, 6, 4, 2)\n",
+ "conv = Convolution3D(2, 3, 3, 3, activation='relu', border_mode='same', \n",
+ " subsample=(3, 3, 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(134)\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/Convolution3D.js b/src/layers/convolutional/Convolution3D.js
new file mode 100644
index 0000000..92fa07a
--- /dev/null
+++ b/src/layers/convolutional/Convolution3D.js
@@ -0,0 +1,265 @@
+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'
+
+/**
+ * Convolution3D layer class
+ */
+export default class Convolution3D extends Layer {
+ /**
+ * Creates a Convolution3D layer
+ * @param {number} nbFilter - Number of convolution filters to use.
+ * @param {number} kernelDim1 - Length of the first dimension in the convolution kernel.
+ * @param {number} kernelDim2 - Length of the second dimension in the convolution kernel.
+ * @param {number} kernelDim3 - Length of the third dimension in the convolution kernel.
+ * @param {Object} [attrs] - layer attributes
+ */
+ constructor (nbFilter, kernelDim1, kernelDim2, kernelDim3, attrs = {}) {
+ super(attrs)
+ const {
+ activation = 'linear',
+ borderMode = 'valid',
+ subsample = [1, 1, 1],
+ dimOrdering = 'tf',
+ bias = true
+ } = attrs
+
+ this.kernelShape = [nbFilter, kernelDim1, kernelDim2, kernelDim3]
+
+ this.activation = activations[activation]
+
+ if (borderMode === 'valid' || borderMode === 'same') {
+ this.borderMode = borderMode
+ } else {
+ throw new Error(`${this.name} [Convolution3D layer] Invalid borderMode.`)
+ }
+
+ this.subsample = subsample
+
+ if (dimOrdering === 'tf' || dimOrdering === 'th') {
+ this.dimOrdering = dimOrdering
+ } else {
+ throw new Error(`${this.name} [Convolution3D 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 [kernelDim1, kernelDim2, kernelDim3, inputChannels, nbFilter]
+ * In `th` mode, W weight tensor has shape [nbFilter, inputChannels, kernelDim1, kernelDim2, kernelDim3]
+ * @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, 4, 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[]} [outputDim1, outputDim2, outputDim3, outputChannels]
+ */
+ _calcOutputShape = x => {
+ const inputDim1 = x.tensor.shape[0]
+ const inputDim2 = x.tensor.shape[1]
+ const inputDim3 = x.tensor.shape[2]
+ const [nbFilter, kernelDim1, kernelDim2, kernelDim3] = this.kernelShape
+
+ const outputDim1 = this.borderMode === 'same'
+ ? Math.floor((inputDim1 + this.subsample[0] - 1) / this.subsample[0])
+ : Math.floor((inputDim1 - kernelDim1 + this.subsample[0]) / this.subsample[0])
+ const outputDim2 = this.borderMode === 'same'
+ ? Math.floor((inputDim2 + this.subsample[1] - 1) / this.subsample[1])
+ : Math.floor((inputDim2 - kernelDim2 + this.subsample[1]) / this.subsample[1])
+ const outputDim3 = this.borderMode === 'same'
+ ? Math.floor((inputDim3 + this.subsample[2] - 1) / this.subsample[2])
+ : Math.floor((inputDim3 - kernelDim3 + this.subsample[2]) / this.subsample[2])
+ const outputChannels = nbFilter
+
+ const paddingDim1 = this.borderMode === 'same'
+ ? Math.max(0, Math.floor((outputDim1 - 1) * this.subsample[0] + kernelDim1 - inputDim1))
+ : 0
+ const paddingDim2 = this.borderMode === 'same'
+ ? Math.max(0, Math.floor((outputDim2 - 1) * this.subsample[1] + kernelDim2 - inputDim2))
+ : 0
+ const paddingDim3 = this.borderMode === 'same'
+ ? Math.max(0, Math.floor((outputDim3 - 1) * this.subsample[2] + kernelDim3 - inputDim3))
+ : 0
+ const paddingDim1Before = Math.floor(paddingDim1 / 2)
+ const paddingDim1After = paddingDim1 - paddingDim1Before
+ const paddingDim2Before = Math.floor(paddingDim2 / 2)
+ const paddingDim2After = paddingDim2 - paddingDim2Before
+ const paddingDim3Before = Math.floor(paddingDim3 / 2)
+ const paddingDim3After = paddingDim3 - paddingDim3Before
+
+ this.outputShape = [outputDim1, outputDim2, outputDim3, outputChannels]
+ this.inputPadding = [paddingDim1Before, paddingDim1After, paddingDim2Before, paddingDim2After, paddingDim3Before, paddingDim3After]
+ }
+
+ /**
+ * Pad input tensor if necessary, for borderMode='same'
+ * @param {Tensor} x
+ * @returns {Tensor} x
+ */
+ _padInput = x => {
+ if (this.borderMode === 'same') {
+ const [inputDim1, inputDim2, inputDim3, inputChannels] = x.tensor.shape
+ const [
+ paddingDim1Before, paddingDim1After,
+ paddingDim2Before, paddingDim2After,
+ paddingDim3Before, paddingDim3After
+ ] = this.inputPadding
+ const newDim1 = inputDim1 + paddingDim1Before + paddingDim1After
+ const newDim2 = inputDim2 + paddingDim2Before + paddingDim2After
+ const newDim3 = inputDim3 + paddingDim3Before + paddingDim3After
+ let _x = new Tensor([], [newDim1, newDim2, newDim3, inputChannels])
+ ops.assign(
+ _x.tensor
+ .hi(inputDim1 + paddingDim1Before, inputDim2 + paddingDim2Before, inputDim3 + paddingDim3Before, inputChannels)
+ .lo(paddingDim1Before, paddingDim2Before, paddingDim3Before, 0),
+ x.tensor
+ )
+ x.tensor = _x.tensor
+ }
+ return x
+ }
+
+ /**
+ * Convert input volume to column matrix
+ * @param {Tensor} x
+ * @returns {Tensor} x
+ */
+ _vol2col = x => {
+ const [inputDim1, inputDim2, inputDim3, inputChannels] = x.tensor.shape
+ const kernelDim1 = this.kernelShape[1]
+ const kernelDim2 = this.kernelShape[2]
+ const kernelDim3 = this.kernelShape[3]
+ const outputDim1 = this.outputShape[0]
+ const outputDim2 = this.outputShape[1]
+ const outputDim3 = this.outputShape[2]
+ const nbPatches = outputDim1 * outputDim2 * outputDim3
+ const patchLen = kernelDim1 * kernelDim2 * kernelDim3 * inputChannels
+
+ const volColsMat = new Tensor([], [nbPatches, patchLen])
+
+ let patch = new Tensor([], [patchLen])
+ let n = 0
+ for (let i = 0; i <= inputDim1 - kernelDim1; i += this.subsample[0]) {
+ for (let j = 0; j <= inputDim2 - kernelDim2; j += this.subsample[1]) {
+ for (let k = 0; k <= inputDim3 - kernelDim3; k += this.subsample[2]) {
+ const patchData = flattenDeep(unpack(
+ x.tensor.hi(i + kernelDim1, j + kernelDim2, k + kernelDim3, inputChannels).lo(i, j, k, 0)
+ ))
+ patch.replaceTensorData(patchData)
+ ops.assign(volColsMat.tensor.pick(n, null), patch.tensor)
+ n += 1
+ }
+ }
+ }
+
+ return volColsMat
+ }
+
+ /**
+ * Convert filter weights to row matrix
+ * @param {Tensor} x
+ * @returns {Tensor} x
+ */
+ _w2row = x => {
+ const inputChannels = x.tensor.shape[3]
+ const [nbFilter, kernelDim1, kernelDim2, kernelDim3] = this.kernelShape
+ const patchLen = kernelDim1 * kernelDim2 * kernelDim3 * 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, 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, 3, 0)
+ }
+
+ this._calcOutputShape(x)
+ this._padInput(x)
+
+ const volColsMat = this._vol2col(x)
+ const wRowsMat = this._w2row(x)
+
+ const nbFilter = this.kernelShape[0]
+ const outputDim1 = this.outputShape[0]
+ const outputDim2 = this.outputShape[1]
+ const outputDim3 = this.outputShape[2]
+ const nbPatches = outputDim1 * outputDim2 * outputDim3
+ 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(
+ volColsMat.tensor.shape[0], wRowsMat.tensor.shape[1], volColsMat.tensor.shape[1], // M, N, K
+ 1, volColsMat.tensor.data, wRowsMat.tensor.data, // alpha, A, B
+ 1, bias // beta, C
+ )
+ } else {
+ gemm(matMul.tensor, volColsMat.tensor, wRowsMat.tensor, 1, 1)
+ }
+
+ let output = new Tensor([], this.outputShape)
+ let outputChannel = new Tensor([], [outputDim1, outputDim2, outputDim3])
+ 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, 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(3, 0, 1, 2)
+ }
+
+ return x
+ }
+}
diff --git a/src/layers/convolutional/index.js b/src/layers/convolutional/index.js
index 872d0e1..b55a7d1 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 Convolution3D from './Convolution3D'
import UpSampling1D from './UpSampling1D'
import UpSampling2D from './UpSampling2D'
import UpSampling3D from './UpSampling3D'
@@ -7,6 +8,7 @@ import UpSampling3D from './UpSampling3D'
export {
Convolution1D,
Convolution2D,
+ Convolution3D,
UpSampling1D,
UpSampling2D,
UpSampling3D
diff --git a/test/convolutional/Convolution3D.js b/test/convolutional/Convolution3D.js
new file mode 100644
index 0000000..80a9ad3
--- /dev/null
+++ b/test/convolutional/Convolution3D.js
@@ -0,0 +1,110 @@
+/* eslint-env browser, mocha */
+
+describe('convolutional layer: Convolution3D', 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, 5, 2],
+ kernelShape: [4, 3, 3, 3],
+ attrs: { activation: 'linear', borderMode: 'valid', subsample: [1, 1, 1], dimOrdering: 'tf', bias: true }
+ },
+ {
+ inputShape: [4, 4, 4, 2],
+ kernelShape: [2, 3, 3, 3],
+ attrs: { activation: 'sigmoid', borderMode: 'valid', subsample: [1, 1, 1], dimOrdering: 'tf', bias: false }
+ },
+ {
+ inputShape: [4, 4, 3, 2],
+ kernelShape: [2, 3, 3, 3],
+ attrs: { activation: 'relu', borderMode: 'same', subsample: [1, 1, 1], dimOrdering: 'tf', bias: true }
+ },
+ {
+ inputShape: [4, 4, 3, 2],
+ kernelShape: [2, 3, 3, 2],
+ attrs: { activation: 'relu', borderMode: 'same', subsample: [2, 1, 1], dimOrdering: 'tf', bias: true }
+ },
+ {
+ inputShape: [6, 6, 4, 2],
+ kernelShape: [2, 3, 3, 3],
+ attrs: { activation: 'relu', borderMode: 'same', subsample: [3, 3, 2], dimOrdering: 'tf', bias: true }
+ }
+ ]
+
+ before(function () {
+ console.log('\n%cconvolutional layer: Convolution3D', styles.h1)
+ })
+
+ /*********************************************************
+ * CPU
+ *********************************************************/
+
+ describe('CPU', function () {
+ before(function () {
+ console.log('\n%cCPU', styles.h2)
+ })
+
+ testParams.forEach(({ inputShape, kernelShape, attrs }, i) => {
+ const key = `convolutional.Convolution3D.${i}`
+ const [inputDim1, inputDim2, inputDim3, inputChannels] = inputShape
+ const [nbFilter, kernelDim1, kernelDim2, kernelDim3] = kernelShape
+ const title = `[${key}] [CPU] test: ${nbFilter} ${kernelDim1}x${kernelDim2}x${kernelDim3} filters on ${inputDim1}x${inputDim2}x${inputDim3}x${inputChannels} input, 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.Convolution3D(nbFilter, kernelDim1, kernelDim2, kernelDim3, 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.Convolution3D.${i}`
+ const [inputDim1, inputDim2, inputDim3, inputChannels] = inputShape
+ const [nbFilter, kernelDim1, kernelDim2, kernelDim3] = kernelShape
+ const title = `[${key}] [GPU] test: ${nbFilter} ${kernelDim1}x${kernelDim2}x${kernelDim3} filters on ${inputDim1}x${inputDim2}x${inputDim3}x${inputChannels} input, 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.Convolution3D(nbFilter, kernelDim1, kernelDim2, kernelDim3, 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_Convolution3D.js b/test/convolutional/data_Convolution3D.js
new file mode 100644
index 0000000..0c7085c
--- /dev/null
+++ b/test/convolutional/data_Convolution3D.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.Convolution3D.0': {
+ input: {
+ data: [-0.012235, 0.842256, -0.24031, -0.747101, 0.997502, 0.541847, 0.46022, -0.936762, 0.620677, -0.897006, 0.142436, -0.321119, -0.564347, 0.528326, 0.895515, 0.412205, 0.863293, -0.122241, 0.253835, 0.334585, -0.843125, -0.865964, -0.033224, 0.770519, 0.602345, 0.482129, -0.534779, 0.882924, 0.845752, -0.040631, 0.674428, -0.779344, 0.053258, -0.70852, -0.956298, -0.280062, 0.627909, 0.725718, -0.103394, -0.791248, 0.74844, -0.409891, 0.60642, -0.703554, -0.678996, -0.865614, 0.557983, 0.833801, 0.422953, -0.214554, 0.234606, -0.723627, 0.379456, -0.783448, 0.413208, 0.570398, -0.073524, -0.77024, -0.435243, -0.660294, 0.276208, -0.676938, 0.11366, 0.073336, 0.485568, -0.38602, 0.963383, -0.28129, 0.757856, 0.342945, 0.083787, 0.138463, 0.67179, 0.519043, 0.654146, 0.465576, 0.784872, -0.364478, -0.423446, -0.572558, -0.083876, -0.54903, -0.295645, 0.2349, 0.215547, -0.08804, -0.935702, -0.804254, 0.842041, 0.891524, 0.53582, 0.816882, -0.31899, 0.761039, 0.092443, -0.013288, 0.81033, 0.095114, 0.948258, -0.974729, -0.187374, -0.227432, 0.102514, -0.06137, 0.344298, -0.700357, 0.793725, -0.390442, 0.561325, 0.069437, 0.297307, -0.139713, 0.796003, -0.873413, 0.228104, -0.447393, -0.246792, 0.931166, 0.149258, -0.122052, 0.027526, 0.592017, 0.470149, 0.726634, 0.151077, -0.513093, 0.558565, -0.242539, -0.411284, -0.713388, -0.522539, 0.78801, -0.702311, -0.891064, -0.871238, -0.853877, 0.333665, 0.438522, -0.491023, -0.868654, -0.742188, -0.832603, -0.0604, 0.638536, -0.235743, 0.508252, -0.443941, 0.710677, 0.194301, 0.17929, 0.235854, -0.376182, -0.346676, 0.670737, -0.94404, -0.64212, -0.512999, 0.97764, 0.463103, 0.791414, 0.814634, 0.309827, -0.210593, -0.142933, 0.201831, -0.440759, -0.217137, -0.893463, -0.788414, -0.099469, 0.806605, -0.388143, -0.322186, 0.899655, 0.08527, -0.805031, 0.833597, 0.228396, -0.942825, -0.954152, 0.750815, 0.178301, -0.528541, -0.533345, -0.760308, -0.384974, -0.031988, 0.52894, -0.898135, 0.379761, 0.207095, 0.882652, 0.444118, -0.014279, -0.333001, -0.812251, -0.186455, -0.778118, -0.459847, 0.402095, 0.610382, 0.477684, -0.86357, -0.420118, 0.503587, -0.730952, 0.904388, 0.272979, -0.98017, -0.192944, 0.500952, 0.98925, 0.341975, -0.562962, 0.049861, -0.202414, -0.830072, -0.905711, -0.925835, 0.781849, -0.920591, -0.307965, -0.471503, -0.554001, 0.713829, -0.412998, -0.516655, -0.631432, 0.976909, -0.804501, 0.406977, 0.791254, 0.294557, 0.437734, -0.094275, -0.820109, -0.48955, 0.396867, -0.827079, -0.419779, -0.037705, -0.387553, 0.871437, -0.444237, -0.928096, 0.759913, 0.824767, -0.391281, 0.80935, 0.556379],
+ shape: [5, 5, 5, 2]
+ },
+ weights: [
+ {
+ data: [-0.716739, -0.376911, 0.109585, -0.748377, -0.012235, 0.842256, -0.24031, -0.747101, 0.997502, 0.541847, 0.46022, -0.936762, 0.620677, -0.897006, 0.142436, -0.321119, -0.564347, 0.528326, 0.895515, 0.412205, 0.863293, -0.122241, 0.253835, 0.334585, -0.843125, -0.865964, -0.033224, 0.770519, 0.602345, 0.482129, -0.534779, 0.882924, 0.845752, -0.040631, 0.674428, -0.779344, 0.053258, -0.70852, -0.956298, -0.280062, 0.627909, 0.725718, -0.103394, -0.791248, 0.74844, -0.409891, 0.60642, -0.703554, -0.678996, -0.865614, 0.557983, 0.833801, 0.422953, -0.214554, 0.234606, -0.723627, 0.379456, -0.783448, 0.413208, 0.570398, -0.073524, -0.77024, -0.435243, -0.660294, 0.276208, -0.676938, 0.11366, 0.073336, 0.485568, -0.38602, 0.963383, -0.28129, 0.757856, 0.342945, 0.083787, 0.138463, 0.67179, 0.519043, 0.654146, 0.465576, 0.784872, -0.364478, -0.423446, -0.572558, -0.083876, -0.54903, -0.295645, 0.2349, 0.215547, -0.08804, -0.935702, -0.804254, 0.842041, 0.891524, 0.53582, 0.816882, -0.31899, 0.761039, 0.092443, -0.013288, 0.81033, 0.095114, 0.948258, -0.974729, -0.187374, -0.227432, 0.102514, -0.06137, 0.344298, -0.700357, 0.793725, -0.390442, 0.561325, 0.069437, 0.297307, -0.139713, 0.796003, -0.873413, 0.228104, -0.447393, -0.246792, 0.931166, 0.149258, -0.122052, 0.027526, 0.592017, 0.470149, 0.726634, 0.151077, -0.513093, 0.558565, -0.242539, -0.411284, -0.713388, -0.522539, 0.78801, -0.702311, -0.891064, -0.871238, -0.853877, 0.333665, 0.438522, -0.491023, -0.868654, -0.742188, -0.832603, -0.0604, 0.638536, -0.235743, 0.508252, -0.443941, 0.710677, 0.194301, 0.17929, 0.235854, -0.376182, -0.346676, 0.670737, -0.94404, -0.64212, -0.512999, 0.97764, 0.463103, 0.791414, 0.814634, 0.309827, -0.210593, -0.142933, 0.201831, -0.440759, -0.217137, -0.893463, -0.788414, -0.099469, 0.806605, -0.388143, -0.322186, 0.899655, 0.08527, -0.805031, 0.833597, 0.228396, -0.942825, -0.954152, 0.750815, 0.178301, -0.528541, -0.533345, -0.760308, -0.384974, -0.031988, 0.52894, -0.898135, 0.379761, 0.207095, 0.882652, 0.444118, -0.014279, -0.333001, -0.812251, -0.186455, -0.778118, -0.459847, 0.402095, 0.610382, 0.477684, -0.86357, -0.420118, 0.503587, -0.730952, 0.904388, 0.272979, -0.98017, -0.192944, 0.500952, 0.98925],
+ shape: [3, 3, 3, 2, 4]
+ },
+ {
+ data: [-0.716739, -0.376911, 0.109585, -0.748377],
+ shape: [4]
+ }
+ ],
+ expected: {
+ data: [-0.990212, 1.639581, -1.948825, -3.684331, 0.257052, -2.808133, 2.076573, -2.729982, -0.78123, 0.347783, 2.327393, -2.657676, -0.107308, -1.605268, 0.62405, -5.659127, 2.852406, -0.649643, 6.126531, -2.272969, 1.019947, 3.255988, -6.427436, -7.437248, -4.01012, -1.170293, 1.765438, 6.611716, -0.59429, -0.561376, -0.271424, 1.316552, 1.801865, -2.038508, -1.221814, -3.836679, -2.255499, -2.756532, -1.162019, -2.273401, 0.959788, -2.926484, 0.890316, -2.095109, -0.56757, 0.593196, -0.404296, -2.956032, 1.313724, 0.757657, 1.019654, -2.681708, -1.103542, 2.976485, 1.964336, -2.199447, -1.192246, -1.618244, 0.738719, 0.553589, -1.725408, -3.353908, -1.78493, -3.942136, 0.091989, 1.563757, 0.504778, 2.773416, -4.433075, -2.957799, -1.355837, -0.652115, -4.728858, -1.700152, 3.67987, 0.592441, -1.557015, 2.452404, 5.097181, 0.639657, -4.788903, -3.806307, 1.558109, 3.81415, 0.053524, 6.426715, -1.117815, 0.510982, -0.930588, 0.263227, 0.744451, -2.02314, -0.781206, -1.206907, -2.087747, 0.768416, -3.891211, 2.946293, 0.308395, 1.134286, -1.11568, 2.414839, 4.610423, -3.157369, -1.071085, -5.993021, -0.112579, -3.090427],
+ shape: [3, 3, 3, 4]
+ }
+ },
+ 'convolutional.Convolution3D.1': {
+ input: {
+ data: [0.54298, -0.369581, 0.787756, -0.413208, -0.451769, 0.474871, 0.955491, -0.993053, 0.892644, 0.317005, -0.299495, -0.282463, 0.092705, 0.847179, 0.355861, -0.356589, -0.34065, -0.644927, 0.294664, 0.525887, -0.45672, 0.109351, -0.232926, -0.322716, 0.708476, 0.133826, 0.942949, 0.509234, 0.666986, 0.647692, 0.46106, 0.294315, -0.531805, 0.742175, -0.943787, 0.452597, -0.223524, -0.821973, 0.130818, -0.241084, -0.709061, -0.410544, -0.779838, 0.3187, 0.449769, -0.098487, -0.717268, -0.820627, -0.03977, 0.212835, 0.322279, -0.365277, 0.551029, -0.791009, 0.454023, -0.151234, 0.241568, 0.728562, 0.92247, -0.61221, 0.023427, 0.923886, -0.594403, 0.111887, 0.721627, -0.170876, 0.134098, -0.790903, -0.692903, 0.184462, -0.64679, -0.812958, -0.352592, 0.373439, 0.244427, 0.524303, 0.772487, -0.929582, 0.019085, -0.569751, 0.950518, 0.539197, 0.102938, -0.81072, -0.658932, 0.458097, -0.984345, -0.563091, -0.842868, -0.816919, 0.144705, 0.110019, 0.637162, -0.055083, -0.830439, -0.275994, -0.926286, 0.692921, -0.816955, 0.94607, 0.303029, 0.221167, 0.703979, 0.010576, 0.093083, 0.709286, -0.301982, 0.70202, 0.968466, 0.722557, -0.378228, 0.671395, -0.132298, 0.81306, -0.922057, -0.662015, 0.404419, -0.017544, 0.939241, 0.452875, -0.436359, -0.918861, -0.685562, 0.2343, -0.344733, 0.058154, 0.883477, -0.027478],
+ shape: [4, 4, 4, 2]
+ },
+ weights: [
+ {
+ data: [0.300307, 0.896218, -0.223942, 0.282592, 0.381024, -0.746781, -0.521066, -0.491686, -0.147117, 0.678005, 0.490067, -0.238641, -0.476614, -0.893332, -0.126207, -0.582042, 0.188822, -0.802193, -0.551813, 0.168525, 0.918162, -0.580232, 0.322675, 0.005226, -0.359417, -0.74987, 0.613778, 0.97392, 0.086083, -0.537354, 0.207025, -0.646608, 0.773075, 0.178045, 0.442345, -0.448659, 0.576229, -0.734755, -0.200568, 0.259648, -0.151913, -0.676254, 0.040688, 0.214083, 0.161611, 0.642232, 0.969984, 0.86899, 0.80611, -0.323948, 0.566489, 0.487469, 0.161171, -0.134673, 0.335856, -0.526625, -0.096527, 0.839995, 0.933746, 0.538101, -0.346576, 0.24568, -0.616796, -0.503357, -0.766323, -0.979349, 0.697389, 0.061332, -0.01233, 0.304615, -0.546648, 0.234325, -0.598896, -0.018136, 0.89706, 0.963941, -0.653697, 0.485039, -0.227064, 0.302214, 0.486927, -0.504459, -0.015408, -0.1505, -0.419861, 0.973378, -0.3211, -0.600593, 0.657395, -0.274736, 0.42005, -0.193936, -0.222912, 0.005268, 0.593099, -0.977881, -0.911958, 0.794233, 0.506375, 0.724717, 0.980406, 0.160665, 0.907777, -0.158316, -0.663804, -0.93618, 0.166131, 0.47488],
+ shape: [3, 3, 3, 2, 2]
+ }
+ ],
+ expected: {
+ data: [0.028378, 0.571757, 0.006776, 0.886406, 0.155123, 0.446979, 0.280513, 0.76513, 0.107532, 0.596331, 0.958001, 0.078373, 0.762681, 0.216897, 0.14058, 0.000131],
+ shape: [2, 2, 2, 2]
+ }
+ },
+ 'convolutional.Convolution3D.2': {
+ input: {
+ data: [0.657275, 0.563366, 0.603194, -0.286196, 0.924244, -0.28752, 0.637161, 0.810376, -0.914473, -0.967621, 0.112092, -0.838944, 0.928514, -0.182969, -0.348933, -0.07114, 0.743005, -0.294021, -0.568579, -0.596645, -0.517913, -0.571138, -0.497605, -0.358416, 0.073639, -0.83844, -0.915183, 0.412981, 0.909286, 0.226941, 0.373944, -0.563635, 0.753859, -0.681375, 0.022101, -0.582124, -0.280116, -0.82489, -0.757258, 0.989785, 0.028165, 0.366484, -0.778942, 0.27204, -0.25007, -0.967536, 0.28709, -0.797754, -0.68149, 0.394872, -0.43468, 0.665998, 0.869927, -0.606877, -0.134099, 0.652508, -0.603352, 0.633151, -0.836046, -0.196456, 0.947196, 0.760248, -0.921493, -0.372249, -0.982245, -0.864395, -0.339177, -0.904094, 0.959217, 0.147402, 0.504567, 0.769068, 0.629401, -0.441415, 0.813767, -0.350138, 0.864937, -0.10205, 0.145076, -0.590264, 0.733088, -0.45583, 0.040498, -0.05256, 0.022563, -0.375014, 0.700348, 0.75455, 0.610168, 0.194477, -0.810708, -0.19662, -0.842144, 0.285245, -0.305602, -0.714785],
+ shape: [4, 4, 3, 2]
+ },
+ weights: [
+ {
+ data: [0.561808, -0.237711, 0.657275, 0.563366, 0.603194, -0.286196, 0.924244, -0.28752, 0.637161, 0.810376, -0.914473, -0.967621, 0.112092, -0.838944, 0.928514, -0.182969, -0.348933, -0.07114, 0.743005, -0.294021, -0.568579, -0.596645, -0.517913, -0.571138, -0.497605, -0.358416, 0.073639, -0.83844, -0.915183, 0.412981, 0.909286, 0.226941, 0.373944, -0.563635, 0.753859, -0.681375, 0.022101, -0.582124, -0.280116, -0.82489, -0.757258, 0.989785, 0.028165, 0.366484, -0.778942, 0.27204, -0.25007, -0.967536, 0.28709, -0.797754, -0.68149, 0.394872, -0.43468, 0.665998, 0.869927, -0.606877, -0.134099, 0.652508, -0.603352, 0.633151, -0.836046, -0.196456, 0.947196, 0.760248, -0.921493, -0.372249, -0.982245, -0.864395, -0.339177, -0.904094, 0.959217, 0.147402, 0.504567, 0.769068, 0.629401, -0.441415, 0.813767, -0.350138, 0.864937, -0.10205, 0.145076, -0.590264, 0.733088, -0.45583, 0.040498, -0.05256, 0.022563, -0.375014, 0.700348, 0.75455, 0.610168, 0.194477, -0.810708, -0.19662, -0.842144, 0.285245, -0.305602, -0.714785, -0.389563, 0.487303, 0.384339, -0.825992, 0.655456, 0.015094, 0.069932, -0.350014, -0.852013, -0.034763],
+ shape: [3, 3, 3, 2, 2]
+ },
+ {
+ data: [0.561808, -0.237711],
+ shape: [2]
+ }
+ ],
+ expected: {
+ data: [0.0, 0.0, 0.202974, 0.32343, 1.256458, 0.0, 0.0, 0.59227, 0.0, 0.0, 0.0, 1.277499, 0.514505, 3.565827, 1.717093, 0.0, 0.518093, 2.13386, 0.597589, 0.0, 0.145479, 0.0, 0.411267, 0.096419, 0.0, 0.911234, 0.0, 0.0, 0.0, 3.251087, 6.37503, 3.037017, 2.607065, 0.0, 0.0, 1.6602, 1.164416, 2.613473, 3.836789, 0.679142, 0.0, 0.0, 2.195455, 0.0, 0.0, 5.636247, 0.0, 0.948504, 0.0, 0.0, 0.0, 0.583949, 0.805164, 3.08051, 0.0, 0.0, 3.62315, 1.695895, 2.409393, 0.738817, 0.177071, 1.258827, 1.401754, 0.0, 0.0, 0.919304, 0.0, 0.423109, 2.58729, 0.0, 1.76654, 0.0, 1.167698, 0.297612, 0.896641, 0.102354, 0.287512, 0.0, 0.0, 1.459626, 0.0, 1.226061, 1.221153, 0.68316, 1.060495, 1.016869, 3.17602, 2.120962, 0.636249, 2.750501, 0.0, 0.0, 0.0, 0.401625, 0.0, 0.0],
+ shape: [4, 4, 3, 2]
+ }
+ },
+ 'convolutional.Convolution3D.3': {
+ input: {
+ data: [-0.780888, -0.715513, -0.121464, 0.475806, -0.594872, -0.377686, 0.116261, 0.792104, -0.256096, 0.879075, -0.36824, 0.543525, 0.394369, 0.858105, -0.755411, -0.121975, -0.06772, -0.070284, -0.00725, 0.064283, -0.248044, -0.679932, -0.289603, 0.951553, 0.722203, 0.732689, 0.334081, 0.730298, -0.464328, 0.955306, 0.991716, -0.649746, -0.679444, 0.241959, -0.305542, 0.442359, 0.66645, 0.09566, 0.097175, -0.583151, -0.84885, -0.88039, -0.245959, 0.440772, -0.576763, -0.839252, -0.189355, -0.312547, -0.240347, 0.037718, 0.270261, 0.740958, -0.080857, -0.34412, -0.776913, 0.119299, 0.715073, 0.65029, -0.303087, -0.742422, 0.283872, -0.453492, 0.657322, 0.294547, -0.211275, -0.676264, -0.362203, -0.414399, -0.820797, 0.065655, 0.892713, 0.922155, -0.495448, 0.794696, -0.998576, 0.689174, -0.94489, -0.97599, 0.608171, 0.634289, 0.350419, -0.967604, -0.024661, -0.816395, 0.316404, -0.849656, 0.324503, 0.389871, 0.534612, -0.283795, 0.495473, 0.079537, 0.128614, -0.781724, -0.215271, -0.022468],
+ shape: [4, 4, 3, 2]
+ },
+ weights: [
+ {
+ data: [-0.160983, -0.740678, -0.780888, -0.715513, -0.121464, 0.475806, -0.594872, -0.377686, 0.116261, 0.792104, -0.256096, 0.879075, -0.36824, 0.543525, 0.394369, 0.858105, -0.755411, -0.121975, -0.06772, -0.070284, -0.00725, 0.064283, -0.248044, -0.679932, -0.289603, 0.951553, 0.722203, 0.732689, 0.334081, 0.730298, -0.464328, 0.955306, 0.991716, -0.649746, -0.679444, 0.241959, -0.305542, 0.442359, 0.66645, 0.09566, 0.097175, -0.583151, -0.84885, -0.88039, -0.245959, 0.440772, -0.576763, -0.839252, -0.189355, -0.312547, -0.240347, 0.037718, 0.270261, 0.740958, -0.080857, -0.34412, -0.776913, 0.119299, 0.715073, 0.65029, -0.303087, -0.742422, 0.283872, -0.453492, 0.657322, 0.294547, -0.211275, -0.676264, -0.362203, -0.414399, -0.820797, 0.065655],
+ shape: [3, 3, 2, 2, 2]
+ },
+ {
+ data: [-0.160983, -0.740678],
+ shape: [2]
+ }
+ ],
+ expected: {
+ data: [0.09816, 0.0, 1.235674, 0.0, 0.0, 0.0, 2.877764, 1.905926, 1.647481, 3.613319, 0.795886, 1.891695, 0.0, 0.0, 0.0, 0.0, 0.357909, 0.0, 0.0, 0.0, 0.734974, 0.0, 0.0, 0.0, 0.132112, 0.0, 0.0, 1.763944, 0.613645, 0.092832, 0.0, 0.0, 0.0, 0.0, 0.872912, 0.0, 2.011758, 0.754629, 0.0, 0.0, 0.018068, 0.0, 0.0, 0.0, 1.061294, 0.0, 0.0, 1.852663],
+ shape: [2, 4, 3, 2]
+ }
+ },
+ 'convolutional.Convolution3D.4': {
+ input: {
+ data: [0.255491, 0.763798, 0.330149, 0.766733, 0.42334, 0.330543, -0.75135, -0.922873, -0.583415, -0.466281, -0.717938, 0.731792, -0.400509, 0.612512, -0.498783, -0.14186, -0.737372, 0.781319, 0.651852, 0.673768, 0.431092, -0.299636, -0.592396, -0.25223, 0.660295, 0.014915, -0.737261, -0.683528, 0.991536, 0.863046, -0.857707, -0.709703, 0.619649, 0.440344, -0.075421, 0.792503, -0.7677, 0.799309, -0.819924, 0.230663, 0.585082, -0.65765, 0.912941, 0.378832, -0.756722, -0.282432, -0.619629, 0.971307, 0.261786, 0.695286, 0.447511, -0.336526, 0.823161, 0.964889, -0.567008, -0.256448, -0.630859, -0.033653, -0.068675, -0.307193, -0.746842, -0.749483, -0.750777, 0.40137, 0.546076, 0.989245, -0.156364, -0.439605, -0.342656, -0.89142, 0.671516, -0.96313, 0.415092, 0.10452, -0.933763, -0.493381, 0.680007, -0.064914, 0.552154, 0.420418, -0.104774, 0.339607, -0.840586, 0.34762, 0.456402, 0.917853, 0.427665, 0.478747, 0.994486, 0.549693, -0.779373, -0.078222, 0.580719, -0.961111, 0.459178, -0.165215, -0.315997, -0.727695, -0.717506, -0.101921, -0.155999, 0.242368, -0.952067, -0.00297, -0.331119, -0.101121, 0.979275, 0.999252, 0.521731, -0.683745, 0.13268, -0.02283, -0.333171, 0.084336, 0.967829, -0.243099, -0.65592, 0.265795, -0.738191, 0.748515, 0.055295, -0.71117, -0.849279, 0.946324, 0.91352, -0.922913, 0.905676, 0.42188, -0.327285, -0.631911, -0.775742, -0.696021, 0.996116, 0.288415, -0.134258, -0.118686, 0.047865, 0.599197, -0.267092, 0.326933, -0.118315, 0.288843, -0.088352, 0.873786, 0.367592, -0.2835, 0.062748, 0.124767, -0.306431, -0.797375, -0.338658, 0.090141, 0.399011, 0.270202, 0.735773, 0.576237, 0.49903, 0.950745, 0.445642, 0.789956, -0.591685, -0.091733, 0.452208, 0.572278, -0.014814, 0.178051, 0.750801, -0.077224, -0.005775, -0.548912, -0.58962, -0.665754, 0.286856, 0.843047, -0.17934, -0.562433, 0.751457, -0.253229, -0.003361, -0.883475, 0.401674, 0.241623, -0.285594, 0.401469, 0.069789, 0.889598, 0.970932, -0.905932, -0.699628, 0.545623, 0.781924, 0.834341, 0.167673, -0.684819, -0.554758, 0.87348, 0.113279, -0.027234, -0.154146, -0.572187, -0.082501, 0.745653, 0.437841, 0.672742, -0.20552, -0.731811, 0.639947, 0.865838, 0.04588, 0.139607, 0.521049, 0.906016, 0.439766, 0.161608, 0.988467, 0.116776, -0.141933, 0.658322, 0.407769, 0.706881, 0.278246, -0.176282, -0.232731, 0.89114, 0.906824, 0.486935, -0.599041, 0.191432, 0.812589, -0.281513, 0.47336, 0.24849, -0.912168, -0.017699, 0.072546, 0.9249, 0.367322, -0.154274, -0.847056, -0.207236, 0.571427, -0.904635, 0.260295, -0.835689, -0.578835, 0.918011, 0.048527, -0.674753, -0.7327, -0.209332, 0.87192, -0.526782, -0.47431, 0.198573, 0.274862, -0.570459, 0.357794, -0.923848, -0.326055, -0.621309, -0.298064, 0.588621, -0.434224, 0.26631, -0.458417, 0.699587, 0.586844, 0.157536, 0.777812, -0.811094, 0.749212, -0.492543, -0.482318, 0.783566, -0.881362, -0.826629, -0.808297, 0.990087, -0.97475, -0.076858, 0.684759, -0.449941, -0.237982, -0.847246, -0.809583, 0.119563, -0.316425, -0.679099],
+ shape: [6, 6, 4, 2]
+ },
+ weights: [
+ {
+ data: [0.622807, -0.104472, 0.255491, 0.763798, 0.330149, 0.766733, 0.42334, 0.330543, -0.75135, -0.922873, -0.583415, -0.466281, -0.717938, 0.731792, -0.400509, 0.612512, -0.498783, -0.14186, -0.737372, 0.781319, 0.651852, 0.673768, 0.431092, -0.299636, -0.592396, -0.25223, 0.660295, 0.014915, -0.737261, -0.683528, 0.991536, 0.863046, -0.857707, -0.709703, 0.619649, 0.440344, -0.075421, 0.792503, -0.7677, 0.799309, -0.819924, 0.230663, 0.585082, -0.65765, 0.912941, 0.378832, -0.756722, -0.282432, -0.619629, 0.971307, 0.261786, 0.695286, 0.447511, -0.336526, 0.823161, 0.964889, -0.567008, -0.256448, -0.630859, -0.033653, -0.068675, -0.307193, -0.746842, -0.749483, -0.750777, 0.40137, 0.546076, 0.989245, -0.156364, -0.439605, -0.342656, -0.89142, 0.671516, -0.96313, 0.415092, 0.10452, -0.933763, -0.493381, 0.680007, -0.064914, 0.552154, 0.420418, -0.104774, 0.339607, -0.840586, 0.34762, 0.456402, 0.917853, 0.427665, 0.478747, 0.994486, 0.549693, -0.779373, -0.078222, 0.580719, -0.961111, 0.459178, -0.165215, -0.315997, -0.727695, -0.717506, -0.101921, -0.155999, 0.242368, -0.952067, -0.00297, -0.331119, -0.101121],
+ shape: [3, 3, 3, 2, 2]
+ },
+ {
+ data: [0.622807, -0.104472],
+ shape: [2]
+ }
+ ],
+ expected: {
+ data: [1.786687, 1.633532, 0.087363, 0.705533, 0.0, 0.0, 2.178441, 2.592993, 5.30457, 1.575011, 0.0, 0.831551, 1.727915, 0.0, 2.197441, 0.0],
+ shape: [2, 2, 2, 2]
+ }
+ }
+ }
+
+ window.TEST_DATA = Object.assign({}, window.TEST_DATA, DATA)
+})()