Skip to content

Commit 11ff396

Browse files
committed
adding more comments to the batch_conv
1 parent 9140c1e commit 11ff396

File tree

1 file changed

+108
-83
lines changed

1 file changed

+108
-83
lines changed

batch_conv.ipynb

+108-83
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,17 @@
1313
"import numpy as np"
1414
]
1515
},
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+
},
1627
{
1728
"cell_type": "code",
1829
"execution_count": 2,
@@ -23,8 +34,11 @@
2334
},
2435
"outputs": [],
2536
"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"
2842
]
2943
},
3044
{
@@ -37,62 +51,68 @@
3751
},
3852
"outputs": [],
3953
"source": [
54+
"# using random numbers to fill the image and the weights\n",
4055
"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)"
4457
]
4558
},
4659
{
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": {},
6662
"source": [
67-
"im.shape"
63+
"### Defining a convolution operation"
6864
]
6965
},
7066
{
7167
"cell_type": "code",
72-
"execution_count": 5,
68+
"execution_count": 4,
7369
"metadata": {
7470
"collapsed": true,
7571
"deletable": true,
7672
"editable": true
7773
},
7874
"outputs": [],
7975
"source": [
80-
"def forward(im, weights):\n",
76+
"def convolve(im, weights):\n",
77+
" \n",
78+
" # get the dimensions of image and kernel\n",
8179
" kernel_x, kernel_y, in_colors, out_colors=weights.shape\n",
8280
" batch_size, dim_x, dim_y, colors=im.shape\n",
8381
" \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",
8587
" out=np.empty((batch_size, dim_x-kernel_x+1, dim_y-kernel_y+1, out_colors))\n",
8688
" \n",
89+
" # look at every coordinate in the output\n",
8790
" for i in range(out.shape[1]):\n",
8891
" 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",
8996
" 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",
91105
" crop=np.expand_dims(crop, axis=-1)\n",
92106
" \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",
93110
" res=crop*weights\n",
94111
" \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",
96116
" res=np.apply_over_axes(np.sum, res, [1,2,3]).reshape(batch_size,-1)\n",
97117
" \n",
98118
" out[:,i,j]=res\n",
@@ -101,59 +121,51 @@
101121
]
102122
},
103123
{
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": {},
112126
"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."
114131
]
115132
},
116133
{
117134
"cell_type": "code",
118-
"execution_count": 7,
135+
"execution_count": 5,
119136
"metadata": {
120137
"collapsed": false,
121138
"deletable": true,
122139
"editable": true
123140
},
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": [],
136142
"source": [
137-
"out.max()"
143+
"out=convolve(im, weights)"
138144
]
139145
},
140146
{
141147
"cell_type": "code",
142-
"execution_count": 8,
148+
"execution_count": 6,
143149
"metadata": {
144150
"collapsed": false,
145151
"deletable": true,
146152
"editable": true
147153
},
148154
"outputs": [],
149155
"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",
151163
"debug_out=np.sum(out*debug_weights)"
152164
]
153165
},
154166
{
155167
"cell_type": "code",
156-
"execution_count": 9,
168+
"execution_count": 7,
157169
"metadata": {
158170
"collapsed": false,
159171
"deletable": true,
@@ -163,10 +175,10 @@
163175
{
164176
"data": {
165177
"text/plain": [
166-
"25.960989431769082"
178+
"2472.7945262736876"
167179
]
168180
},
169-
"execution_count": 9,
181+
"execution_count": 7,
170182
"metadata": {},
171183
"output_type": "execute_result"
172184
}
@@ -176,38 +188,45 @@
176188
]
177189
},
178190
{
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": {},
187193
"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",
189204
"\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)."
192206
]
193207
},
194208
{
195209
"cell_type": "code",
196-
"execution_count": 11,
210+
"execution_count": 8,
197211
"metadata": {
198212
"collapsed": false,
199213
"deletable": true,
200214
"editable": true
201215
},
202216
"outputs": [],
203217
"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"
206225
]
207226
},
208227
{
209228
"cell_type": "code",
210-
"execution_count": 12,
229+
"execution_count": 15,
211230
"metadata": {
212231
"collapsed": false,
213232
"deletable": true,
@@ -217,57 +236,63 @@
217236
{
218237
"data": {
219238
"text/plain": [
220-
"<matplotlib.image.AxesImage at 0x7f7102474a90>"
239+
"<matplotlib.image.AxesImage at 0x7f19ebbb7780>"
221240
]
222241
},
223-
"execution_count": 12,
242+
"execution_count": 15,
224243
"metadata": {},
225244
"output_type": "execute_result"
226245
},
227246
{
228247
"data": {
229248
"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",
230249
"text/plain": [
231-
"<matplotlib.figure.Figure at 0x7f7104766198>"
250+
"<matplotlib.figure.Figure at 0x7f19c33470b8>"
232251
]
233252
},
234253
"metadata": {},
235254
"output_type": "display_data"
236255
}
237256
],
238257
"source": [
258+
"# plotting the padded output.\n",
259+
"\n",
260+
"import matplotlib.pyplot as plt\n",
261+
"%matplotlib inline\n",
262+
"\n",
239263
"plt.imshow((padded[0]>0).sum(axis=-1))"
240264
]
241265
},
242266
{
243267
"cell_type": "code",
244-
"execution_count": 13,
268+
"execution_count": 11,
245269
"metadata": {
246270
"collapsed": true,
247271
"deletable": true,
248272
"editable": true
249273
},
250274
"outputs": [],
251275
"source": [
276+
"# the weights for the backward pass have to be adap\n",
252277
"backward_weights=weights[::-1,::-1].transpose((0,1,3,2))"
253278
]
254279
},
255280
{
256281
"cell_type": "code",
257-
"execution_count": 14,
282+
"execution_count": 12,
258283
"metadata": {
259284
"collapsed": false,
260285
"deletable": true,
261286
"editable": true
262287
},
263288
"outputs": [],
264289
"source": [
265-
"grads=forward(padded, backward_weights)"
290+
"grads=convolve(padded, backward_weights)"
266291
]
267292
},
268293
{
269294
"cell_type": "code",
270-
"execution_count": 15,
295+
"execution_count": 13,
271296
"metadata": {
272297
"collapsed": false,
273298
"deletable": true,
@@ -280,7 +305,7 @@
280305
"(2, 10, 11, 5)"
281306
]
282307
},
283-
"execution_count": 15,
308+
"execution_count": 13,
284309
"metadata": {},
285310
"output_type": "execute_result"
286311
}
@@ -291,7 +316,7 @@
291316
},
292317
{
293318
"cell_type": "code",
294-
"execution_count": 16,
319+
"execution_count": 14,
295320
"metadata": {
296321
"collapsed": false,
297322
"deletable": true,
@@ -306,7 +331,7 @@
306331
" \n",
307332
" d_im=im.copy()\n",
308333
" d_im[idx]+=eps\n",
309-
" d_out=forward(d_im, weights)\n",
334+
" d_out=convolve(d_im, weights)\n",
310335
" d_debug_out=np.sum(d_out*debug_weights)\n",
311336
"\n",
312337
" grad=(d_debug_out-debug_out)/eps\n",

0 commit comments

Comments
 (0)