|
13 | 13 | "import numpy as np"
|
14 | 14 | ]
|
15 | 15 | },
|
| 16 | + { |
| 17 | + "cell_type": "markdown", |
| 18 | + "metadata": {}, |
| 19 | + "source": [ |
| 20 | + "### Setting up the data\n", |
| 21 | + "\n", |
| 22 | + "The image is in the format: batch_size, width, height, colors\n", |
| 23 | + "\n", |
| 24 | + "The filter is: width, height, in_colors, out_colors" |
| 25 | + ] |
| 26 | + }, |
16 | 27 | {
|
17 | 28 | "cell_type": "code",
|
18 | 29 | "execution_count": 2,
|
|
23 | 34 | },
|
24 | 35 | "outputs": [],
|
25 | 36 | "source": [
|
26 |
| - "batch_size, dim_x, dim_y, colors=2, 10,11,5\n", |
27 |
| - "kernel_x, kernel_y, in_colors, out_colors=2,3,colors, 4" |
| 37 | + "# dimensions of the image\n", |
| 38 | + "batch_size, dim_x, dim_y, colors=2, 10, 11, 5\n", |
| 39 | + "\n", |
| 40 | + "# dimensions of the filter\n", |
| 41 | + "kernel_x, kernel_y, in_colors, out_colors=2, 3, colors, 4" |
28 | 42 | ]
|
29 | 43 | },
|
30 | 44 | {
|
|
37 | 51 | },
|
38 | 52 | "outputs": [],
|
39 | 53 | "source": [
|
| 54 | + "# using random numbers to fill the image and the weights\n", |
40 | 55 | "im=np.random.rand(batch_size, dim_x, dim_y, colors)\n",
|
41 |
| - "weights=np.random.rand(kernel_x, kernel_y, in_colors, out_colors)*0.1\n", |
42 |
| - "\n", |
43 |
| - "debug_weights=np.random.rand(*(batch_size,dim_x-kernel_x+1, dim_y-kernel_y+1, out_colors))*0.1" |
| 56 | + "weights=np.random.rand(kernel_x, kernel_y, in_colors, out_colors)" |
44 | 57 | ]
|
45 | 58 | },
|
46 | 59 | {
|
47 |
| - "cell_type": "code", |
48 |
| - "execution_count": 4, |
49 |
| - "metadata": { |
50 |
| - "collapsed": false, |
51 |
| - "deletable": true, |
52 |
| - "editable": true |
53 |
| - }, |
54 |
| - "outputs": [ |
55 |
| - { |
56 |
| - "data": { |
57 |
| - "text/plain": [ |
58 |
| - "(2, 10, 11, 5)" |
59 |
| - ] |
60 |
| - }, |
61 |
| - "execution_count": 4, |
62 |
| - "metadata": {}, |
63 |
| - "output_type": "execute_result" |
64 |
| - } |
65 |
| - ], |
| 60 | + "cell_type": "markdown", |
| 61 | + "metadata": {}, |
66 | 62 | "source": [
|
67 |
| - "im.shape" |
| 63 | + "### Defining a convolution operation" |
68 | 64 | ]
|
69 | 65 | },
|
70 | 66 | {
|
71 | 67 | "cell_type": "code",
|
72 |
| - "execution_count": 5, |
| 68 | + "execution_count": 4, |
73 | 69 | "metadata": {
|
74 | 70 | "collapsed": true,
|
75 | 71 | "deletable": true,
|
76 | 72 | "editable": true
|
77 | 73 | },
|
78 | 74 | "outputs": [],
|
79 | 75 | "source": [
|
80 |
| - "def forward(im, weights):\n", |
| 76 | + "def convolve(im, weights):\n", |
| 77 | + " \n", |
| 78 | + " # get the dimensions of image and kernel\n", |
81 | 79 | " kernel_x, kernel_y, in_colors, out_colors=weights.shape\n",
|
82 | 80 | " batch_size, dim_x, dim_y, colors=im.shape\n",
|
83 | 81 | " \n",
|
84 |
| - " \n", |
| 82 | + " # allocate an output array\n", |
| 83 | + " # the batch_size stays the same, the number of colors is specified in the shape of the filter\n", |
| 84 | + " # but the x and y dimensions of the output need to be calculated\n", |
| 85 | + " # the formula is:\n", |
| 86 | + " # out_x = in_x - filter_x +1\n", |
85 | 87 | " out=np.empty((batch_size, dim_x-kernel_x+1, dim_y-kernel_y+1, out_colors))\n",
|
86 | 88 | " \n",
|
| 89 | + " # look at every coordinate in the output\n", |
87 | 90 | " for i in range(out.shape[1]):\n",
|
88 | 91 | " for j in range(out.shape[2]):\n",
|
| 92 | + " \n", |
| 93 | + " # at this location, slice a rectangle out of the input image\n", |
| 94 | + " # the batch_size and the colors are retained\n", |
| 95 | + " # crop has the shape: batch_size, kernel_x, kernel_y, in_colors\n", |
89 | 96 | " crop=im[:,i:i+kernel_x, j:j+kernel_y]\n",
|
90 |
| - " #expand crops so the dimensions match\n", |
| 97 | + " \n", |
| 98 | + " # the values in crop will be multiplied by the weights\n", |
| 99 | + " # look how the shapes match:\n", |
| 100 | + " # crop: batch_size, x, y, in_colors\n", |
| 101 | + " # weights: x, y, in_colors, out_colors\n", |
| 102 | + " \n", |
| 103 | + " # numpy can broadcast this, but ONLY if an extra dimension is added to crop\n", |
| 104 | + " # crop now has the shape: batch_size, x, y, in_colors, 1\n", |
91 | 105 | " crop=np.expand_dims(crop, axis=-1)\n",
|
92 | 106 | " \n",
|
| 107 | + " # numpy broadcast magic\n", |
| 108 | + " # in parallel along the batch_size\n", |
| 109 | + " # matches the x, y and in_colors dimensions and multiplies them pairwise\n", |
93 | 110 | " res=crop*weights\n",
|
94 | 111 | " \n",
|
95 |
| - " #sum everything except the output\n", |
| 112 | + " # res has the shape: batch_size, x, y, in_colors, out_colors\n", |
| 113 | + " # we want to sum along x, y, and in_colors\n", |
| 114 | + " # those are the dimensions 1, 2, 3\n", |
| 115 | + " # we want to keep the batch_size and the out_colors\n", |
96 | 116 | " res=np.apply_over_axes(np.sum, res, [1,2,3]).reshape(batch_size,-1)\n",
|
97 | 117 | " \n",
|
98 | 118 | " out[:,i,j]=res\n",
|
|
101 | 121 | ]
|
102 | 122 | },
|
103 | 123 | {
|
104 |
| - "cell_type": "code", |
105 |
| - "execution_count": 6, |
106 |
| - "metadata": { |
107 |
| - "collapsed": false, |
108 |
| - "deletable": true, |
109 |
| - "editable": true |
110 |
| - }, |
111 |
| - "outputs": [], |
| 124 | + "cell_type": "markdown", |
| 125 | + "metadata": {}, |
112 | 126 | "source": [
|
113 |
| - "out=forward(im, weights)" |
| 127 | + "### Apply\n", |
| 128 | + "\n", |
| 129 | + "Use the new convolve function to compute the output of the convolution.\n", |
| 130 | + "Calculate an output value which will be used to test the backward pass later on." |
114 | 131 | ]
|
115 | 132 | },
|
116 | 133 | {
|
117 | 134 | "cell_type": "code",
|
118 |
| - "execution_count": 7, |
| 135 | + "execution_count": 5, |
119 | 136 | "metadata": {
|
120 | 137 | "collapsed": false,
|
121 | 138 | "deletable": true,
|
122 | 139 | "editable": true
|
123 | 140 | },
|
124 |
| - "outputs": [ |
125 |
| - { |
126 |
| - "data": { |
127 |
| - "text/plain": [ |
128 |
| - "1.1859898389506995" |
129 |
| - ] |
130 |
| - }, |
131 |
| - "execution_count": 7, |
132 |
| - "metadata": {}, |
133 |
| - "output_type": "execute_result" |
134 |
| - } |
135 |
| - ], |
| 141 | + "outputs": [], |
136 | 142 | "source": [
|
137 |
| - "out.max()" |
| 143 | + "out=convolve(im, weights)" |
138 | 144 | ]
|
139 | 145 | },
|
140 | 146 | {
|
141 | 147 | "cell_type": "code",
|
142 |
| - "execution_count": 8, |
| 148 | + "execution_count": 6, |
143 | 149 | "metadata": {
|
144 | 150 | "collapsed": false,
|
145 | 151 | "deletable": true,
|
146 | 152 | "editable": true
|
147 | 153 | },
|
148 | 154 | "outputs": [],
|
149 | 155 | "source": [
|
150 |
| - "#debug_out=np.apply_over_axes(np.sum, out*debug_weights, [1,2,3])\n", |
| 156 | + "# set up a random weight for every entry in the output\n", |
| 157 | + "debug_weights=np.random.rand(*out.shape)\n", |
| 158 | + "\n", |
| 159 | + "# multiply the output with the random weights, reduce it by summing everything\n", |
| 160 | + "# This scalar output value depends on every entry in the output\n", |
| 161 | + "# If you change an entry, the output value will change with the random weight\n", |
| 162 | + "# therefore, it is possible to identify which value in the output has changed\n", |
151 | 163 | "debug_out=np.sum(out*debug_weights)"
|
152 | 164 | ]
|
153 | 165 | },
|
154 | 166 | {
|
155 | 167 | "cell_type": "code",
|
156 |
| - "execution_count": 9, |
| 168 | + "execution_count": 7, |
157 | 169 | "metadata": {
|
158 | 170 | "collapsed": false,
|
159 | 171 | "deletable": true,
|
|
163 | 175 | {
|
164 | 176 | "data": {
|
165 | 177 | "text/plain": [
|
166 |
| - "25.960989431769082" |
| 178 | + "2472.7945262736876" |
167 | 179 | ]
|
168 | 180 | },
|
169 |
| - "execution_count": 9, |
| 181 | + "execution_count": 7, |
170 | 182 | "metadata": {},
|
171 | 183 | "output_type": "execute_result"
|
172 | 184 | }
|
|
176 | 188 | ]
|
177 | 189 | },
|
178 | 190 | {
|
179 |
| - "cell_type": "code", |
180 |
| - "execution_count": 10, |
181 |
| - "metadata": { |
182 |
| - "collapsed": false, |
183 |
| - "deletable": true, |
184 |
| - "editable": true |
185 |
| - }, |
186 |
| - "outputs": [], |
| 191 | + "cell_type": "markdown", |
| 192 | + "metadata": {}, |
187 | 193 | "source": [
|
188 |
| - "debug_shape=debug_weights.shape\n", |
| 194 | + "### Backward pass\n", |
| 195 | + "\n", |
| 196 | + "The backward pass is a convolution with weights that are:\n", |
| 197 | + "1. mirrored along the x axis\n", |
| 198 | + "2. mirrored along the y axis\n", |
| 199 | + "3. transposed: in_colors and out_colors are switched\n", |
| 200 | + "\n", |
| 201 | + "This convolution has to be performed in a padded output.\n", |
| 202 | + "The gradients (output of this convolution) need to match the shape of the input.\n", |
| 203 | + "By applying the convolution, the x and y dimensions are reduced by (kernel_x-1) and (kernel_y-1) respectively.\n", |
189 | 204 | "\n",
|
190 |
| - "padded=np.zeros((batch_size, debug_shape[1]+2*(kernel_x-1), debug_shape[2]+2*(kernel_y-1), out_colors))\n", |
191 |
| - "padded[:, kernel_x-1:kernel_x-1+debug_shape[1], kernel_y-1:kernel_y-1+debug_shape[2]]=debug_weights" |
| 205 | + "Before applying the convolution for the backward pass, the output will be padded with 2(kernel_x-1)." |
192 | 206 | ]
|
193 | 207 | },
|
194 | 208 | {
|
195 | 209 | "cell_type": "code",
|
196 |
| - "execution_count": 11, |
| 210 | + "execution_count": 8, |
197 | 211 | "metadata": {
|
198 | 212 | "collapsed": false,
|
199 | 213 | "deletable": true,
|
200 | 214 | "editable": true
|
201 | 215 | },
|
202 | 216 | "outputs": [],
|
203 | 217 | "source": [
|
204 |
| - "import matplotlib.pyplot as plt\n", |
205 |
| - "%matplotlib inline" |
| 218 | + "out_shape=out.shape\n", |
| 219 | + "\n", |
| 220 | + "# set up an array for the padded output\n", |
| 221 | + "padded=np.zeros((batch_size, out_shape[1]+2*(kernel_x-1), out_shape[2]+2*(kernel_y-1), out_colors))\n", |
| 222 | + "\n", |
| 223 | + "# copy the output to its center\n", |
| 224 | + "padded[:, kernel_x-1:kernel_x-1+out_shape[1], kernel_y-1:kernel_y-1+out_shape[2]]=debug_weights" |
206 | 225 | ]
|
207 | 226 | },
|
208 | 227 | {
|
209 | 228 | "cell_type": "code",
|
210 |
| - "execution_count": 12, |
| 229 | + "execution_count": 15, |
211 | 230 | "metadata": {
|
212 | 231 | "collapsed": false,
|
213 | 232 | "deletable": true,
|
|
217 | 236 | {
|
218 | 237 | "data": {
|
219 | 238 | "text/plain": [
|
220 |
| - "<matplotlib.image.AxesImage at 0x7f7102474a90>" |
| 239 | + "<matplotlib.image.AxesImage at 0x7f19ebbb7780>" |
221 | 240 | ]
|
222 | 241 | },
|
223 |
| - "execution_count": 12, |
| 242 | + "execution_count": 15, |
224 | 243 | "metadata": {},
|
225 | 244 | "output_type": "execute_result"
|
226 | 245 | },
|
227 | 246 | {
|
228 | 247 | "data": {
|
229 | 248 | "image/png": "iVBORw0KGgoAAAANSUhEUgAAASYAAAD8CAYAAADaFgknAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAACx9JREFUeJzt3W+o3YV9x/H3Z7kxadJSO1bKTGTmgTiCdFouna3QB8ZR\n24ruwR4os7TbIE/W1pZCUfagz8ZgpbSw0hHsP2hQRuqYlK7q+ocx2KTXKK1J+kdsq9E4U7a10oGJ\n9LsH97gld4kJ5/czv6/9vV8Qcs/Jyfl98Hrf/s65x3tSVUhSJ78x9QBJ2sgwSWrHMElqxzBJascw\nSWrHMElqxzBJascwSWrHMElqZ+VCHuyibKmtbL+Qh5TUyPP858+q6o3nut0FDdNWtvP72XMhDymp\nkX+qAz89n9v5UE5SO4ZJUjuGSVI7hklSO4ZJUjuDwpTkhiQ/SPJ4kjvGGiVp3pYOU5JNwGeAdwG7\ngVuT7B5rmKT5GnLG9Fbg8ap6oqpOAPcAN48zS9KcDQnTDuCpUy4fXVx3miR7k6wlWTvJCwMOJ2ku\nXvEnv6tqX1WtVtXqZra80oeT9GtgSJieBi495fLOxXWSNMiQMH0HuDzJriQXAbcA940zS9KcLf0/\n8VbVi0k+ANwPbAI+X1WHRlsmabYG/XSBqvoa8LWRtkgS4Cu/JTVkmCS1Y5gktWOYJLVzQX+0bnf3\nP/Po1BOkQd55yVVTTxiFZ0yS2jFMktoxTJLaMUyS2jFMktoxTJLaMUyS2jFMktoxTJLaMUyS2jFM\nktoxTJLaMUyS2jFMktoxTJLaMUyS2jFMktoxTJLaMUyS2jFMktoxTJLaMUyS2jFMktoxTJLaMUyS\n2lk6TEkuTfKtJIeTHEpy+5jDJM3XkLcIfxH4aFUdTPI64OEkD1bV4ZG2SZqppc+YqupYVR1cfPw8\ncATYMdYwSfM1ynNMSS4DrgYeGuP+JM3bkIdyACR5LfAV4MNV9Ysz/PleYC/AVrYNPZykGRh0xpRk\nM+tR2l9V957pNlW1r6pWq2p1M1uGHE7STAz5rlyAzwFHquqT402SNHdDzpiuBd4LXJfk0cWvd4+0\nS9KMLf0cU1X9C5ARt0gS4Cu/JTVkmCS1Y5gktWOYJLVjmCS1Y5gktWOYJLVjmCS1Y5gktWOYJLVj\nmCS1Y5gktWOYJLVjmCS1Y5gktWOYJLVjmCS1Y5gktWOYJLVjmCS1Y5gktWOYJLVjmCS1Y5gktWOY\nJLVjmCS1Y5gktWOYJLVjmCS1Y5gktWOYJLUzOExJNiV5JMlXxxgkSWOcMd0OHBnhfiQJGBimJDuB\n9wB3jTNHkoafMX0K+Bjwq7PdIMneJGtJ1k7ywsDDSZqDpcOU5Ebguap6+OVuV1X7qmq1qlY3s2XZ\nw0makSFnTNcCNyX5CXAPcF2SL4+yStKsLR2mqrqzqnZW1WXALcA3q+q20ZZJmi1fxySpnZUx7qSq\nvg18e4z7kiTPmCS1Y5gktWOYJLVjmCS1Y5gktWOYJLVjmCS1Y5gktWOYJLVjmCS1Y5gktWOYJLVj\nmCS1Y5gktWOYJLVjmCS1Y5gktWOYJLVjmCS1Y5gktWOYJLVjmCS1Y5gktWOYJLVjmCS1Y5gktWOY\nJLVjmCS1Y5gktWOYJLUzKExJLk5yIMn3kxxJ8raxhkmar5WBf//TwNer6o+SXARsG2GTpJlbOkxJ\nXg+8A3g/QFWdAE6MM0vSnA15KLcLOA58IckjSe5Ksn2kXZJmbEiYVoC3AJ+tqquBXwJ3bLxRkr1J\n1pKsneSFAYeTNBdDwnQUOFpVDy0uH2A9VKepqn1VtVpVq5vZMuBwkuZi6TBV1bPAU0muWFy1Bzg8\nyipJszb0u3IfBPYvviP3BPAnwydJmrtBYaqqR4HVkbZIEuArvyU1ZJgktWOYJLVjmCS1Y5gktWOY\nJLVjmCS1Y5gktWOYJLVjmCS1Y5gktWOYJLVjmCS1Y5gktWOYJLVjmCS1Y5gktWOYJLVjmCS1Y5gk\ntWOYJLVjmCS1Y5gktWOYJLVjmCS1Y5gktWOYJLVjmCS1Y5gktWOYJLVjmCS1MyhMST6S5FCSx5Lc\nnWTrWMMkzdfSYUqyA/gQsFpVVwKbgFvGGiZpvoY+lFsBXpNkBdgGPDN8kqS5WzpMVfU08AngSeAY\n8POqemDj7ZLsTbKWZO0kLyy/VNJsDHko9wbgZmAXcAmwPcltG29XVfuqarWqVjezZfmlkmZjyEO5\n64EfV9XxqjoJ3Au8fZxZkuZsSJieBK5Jsi1JgD3AkXFmSZqzIc8xPQQcAA4C31vc176RdkmasZUh\nf7mqPg58fKQtkgT4ym9JDRkmSe0YJkntGCZJ7RgmSe0YJkntGCZJ7RgmSe0YJkntGCZJ7RgmSe0Y\nJkntGCZJ7RgmSe0YJkntGCZJ7RgmSe0YJkntGCZJ7RgmSe0YJkntGCZJ7RgmSe0YJkntDHrDy183\n77zkqqknSMIzJkkNGSZJ7RgmSe0YJkntGCZJ7ZwzTEk+n+S5JI+dct1vJnkwyY8Wv7/hlZ0paU7O\n54zpi8ANG667A/hGVV0OfGNxWZJGcc4wVdU/A/+x4eqbgS8tPv4S8Icj75I0Y8s+x/Smqjq2+PhZ\n4E0j7ZGk4U9+V1UBdbY/T7I3yVqStZO8MPRwkmZg2TD9e5LfBlj8/tzZblhV+6pqtapWN7NlycNJ\nmpNlw3Qf8L7Fx+8D/mGcOZJ0fi8XuBv4V+CKJEeT/BnwV8AfJPkRcP3isiSN4pw/XaCqbj3LH+0Z\neYskAb7yW1JDhklSO4ZJUjuGSVI7hklSO1l/4fYFOlhyHPjpedz0t4CfvcJzltV5G/Te13kb9N7X\neRuc/77fqao3nutGFzRM5yvJWlWtTr3jTDpvg977Om+D3vs6b4Px9/lQTlI7hklSO13DtG/qAS+j\n8zbova/zNui9r/M2GHlfy+eYJM1b1zMmSTPWKkxJbkjygySPJ2n1c8STXJrkW0kOJzmU5PapN22U\nZFOSR5J8deotGyW5OMmBJN9PciTJ26be9JIkH1l8Th9LcneSrRPvaf0GIGfZ99eLz+13k/x9kouH\nHKNNmJJsAj4DvAvYDdyaZPe0q07zIvDRqtoNXAP8ebN9ALcDR6YecRafBr5eVb8L/B5NdibZAXwI\nWK2qK4FNwC3Trmr/BiBf5P/vexC4sqreDPwQuHPIAdqECXgr8HhVPVFVJ4B7WH/Tgxaq6lhVHVx8\n/DzrX1g7pl31f5LsBN4D3DX1lo2SvB54B/A5gKo6UVX/Ne2q06wAr0myAmwDnplyTPc3ADnTvqp6\noKpeXFz8N2DnkGN0CtMO4KlTLh+l0Rf+qZJcBlwNPDTtktN8CvgY8Kuph5zBLuA48IXFQ827kmyf\nehRAVT0NfAJ4EjgG/LyqHph21Rm9mt4A5E+BfxxyB53C9KqQ5LXAV4APV9Uvpt4DkORG4Lmqenjq\nLWexArwF+GxVXQ38kibvRbh4ruZm1uN5CbA9yW3Trnp553oDkCkl+QvWn/bYP+R+OoXpaeDSUy7v\nXFzXRpLNrEdpf1XdO/WeU1wL3JTkJ6w/BL4uyZennXSao8DRqnrpDPMA66Hq4Hrgx1V1vKpOAvcC\nb59405mc9xuATCXJ+4EbgT+uga9D6hSm7wCXJ9mV5CLWn4C8b+JN/ytJWH+O5EhVfXLqPaeqqjur\namdVXcb6P7dvVlWb/+pX1bPAU0muWFy1Bzg84aRTPQlck2Tb4nO8hyZPzG/Q+g1AktzA+lMJN1XV\nfw+9vzZhWjxx9gHgftb/xfi7qjo07arTXAu8l/WzkUcXv9499ahXkQ8C+5N8F7gK+MuJ9wCwOIs7\nABwEvsf618Skr7Lu/gYgZ9n3N8DrgAcXXxt/O+gYvvJbUjdtzpgk6SWGSVI7hklSO4ZJUjuGSVI7\nhklSO4ZJUjuGSVI7/wPX24/f+sdr0AAAAABJRU5ErkJggg==\n",
|
230 | 249 | "text/plain": [
|
231 |
| - "<matplotlib.figure.Figure at 0x7f7104766198>" |
| 250 | + "<matplotlib.figure.Figure at 0x7f19c33470b8>" |
232 | 251 | ]
|
233 | 252 | },
|
234 | 253 | "metadata": {},
|
235 | 254 | "output_type": "display_data"
|
236 | 255 | }
|
237 | 256 | ],
|
238 | 257 | "source": [
|
| 258 | + "# plotting the padded output.\n", |
| 259 | + "\n", |
| 260 | + "import matplotlib.pyplot as plt\n", |
| 261 | + "%matplotlib inline\n", |
| 262 | + "\n", |
239 | 263 | "plt.imshow((padded[0]>0).sum(axis=-1))"
|
240 | 264 | ]
|
241 | 265 | },
|
242 | 266 | {
|
243 | 267 | "cell_type": "code",
|
244 |
| - "execution_count": 13, |
| 268 | + "execution_count": 11, |
245 | 269 | "metadata": {
|
246 | 270 | "collapsed": true,
|
247 | 271 | "deletable": true,
|
248 | 272 | "editable": true
|
249 | 273 | },
|
250 | 274 | "outputs": [],
|
251 | 275 | "source": [
|
| 276 | + "# the weights for the backward pass have to be adap\n", |
252 | 277 | "backward_weights=weights[::-1,::-1].transpose((0,1,3,2))"
|
253 | 278 | ]
|
254 | 279 | },
|
255 | 280 | {
|
256 | 281 | "cell_type": "code",
|
257 |
| - "execution_count": 14, |
| 282 | + "execution_count": 12, |
258 | 283 | "metadata": {
|
259 | 284 | "collapsed": false,
|
260 | 285 | "deletable": true,
|
261 | 286 | "editable": true
|
262 | 287 | },
|
263 | 288 | "outputs": [],
|
264 | 289 | "source": [
|
265 |
| - "grads=forward(padded, backward_weights)" |
| 290 | + "grads=convolve(padded, backward_weights)" |
266 | 291 | ]
|
267 | 292 | },
|
268 | 293 | {
|
269 | 294 | "cell_type": "code",
|
270 |
| - "execution_count": 15, |
| 295 | + "execution_count": 13, |
271 | 296 | "metadata": {
|
272 | 297 | "collapsed": false,
|
273 | 298 | "deletable": true,
|
|
280 | 305 | "(2, 10, 11, 5)"
|
281 | 306 | ]
|
282 | 307 | },
|
283 |
| - "execution_count": 15, |
| 308 | + "execution_count": 13, |
284 | 309 | "metadata": {},
|
285 | 310 | "output_type": "execute_result"
|
286 | 311 | }
|
|
291 | 316 | },
|
292 | 317 | {
|
293 | 318 | "cell_type": "code",
|
294 |
| - "execution_count": 16, |
| 319 | + "execution_count": 14, |
295 | 320 | "metadata": {
|
296 | 321 | "collapsed": false,
|
297 | 322 | "deletable": true,
|
|
306 | 331 | " \n",
|
307 | 332 | " d_im=im.copy()\n",
|
308 | 333 | " d_im[idx]+=eps\n",
|
309 |
| - " d_out=forward(d_im, weights)\n", |
| 334 | + " d_out=convolve(d_im, weights)\n", |
310 | 335 | " d_debug_out=np.sum(d_out*debug_weights)\n",
|
311 | 336 | "\n",
|
312 | 337 | " grad=(d_debug_out-debug_out)/eps\n",
|
|
0 commit comments