I try to understand the calculations of tensorflow and created a simple example with the mnist dataset. First I train this model (I know this won't train well):
model.add(Conv2D(4, (1, 1), activation='relu', kernel_initializer='he_uniform', padding='valid', strides=1, input_shape = input_shape))
model.add(MaxPooling2D((7, 7), padding='valid'))
model.add(Flatten())
model.add(Dense(10, activation='relu', kernel_initializer='he_uniform'))
Then I create arrays with weights and biases:
CNN Layer:
[[ 1.54 -0. ] <- filter 1: [weight bias]
[-2.43 0. ]
[ 1.2 -0.11]
[-2.06 0. ]] <- filter 4: [weight bias]
NN Layer:
[[ 0.09 -0.07 -0.29 0.29 ... -0.03] <- output 1: [weight1-64 bias]
[-0.35 -0.01 -0.3 -0.1 ... 0.05]
...
[-0.13 0.26 -0.42 0.29 ... 0.04]] <- output 10: [weight1-64 bias]
For that I use this code:
cnn = np.zeros((4,2))
for f in range(0,4):
cnn[f][0] = model.layers[0].weights[0][0][0][0][f]
cnn[f][1] = model.layers[0].bias[f]
print(cnn)
nn = np.zeros((10,65))
for f in range(0,10):
for i in range(0,64):
nn[f][i] = model.layers[3].weights[0][i][f]
nn[f][64] = float(model.layers[3].bias[f])
print(nn)
I assume that the order of the weights are: row * 16 + column * 4 + f Because this is how the flatten layer works.
After that I calculate the prediction myself with this code:
max=np.zeros((4,4,4))
out=np.zeros(10)
#Conv2D
for f in range(0,4):
for y in range(0,28):
for x in range(0,28):
#Calculate convolution for pixel with one weight and bias
d = test_data[0][y][x][0] * cnn[f][0] + cnn[f][1]
#Only keep maximum value in 7x7 area -> Max Pooling
if max[f][int(y/7)][int(x/7)] < d:
max[f][int(y/7)][int(x/7)] = d
#Dense
for o in range(0,10):
#Add Bias
out[o] = nn[o][64]
for f in range(0,4):
for y in range(0,4):
for x in range(0,4):
#Apply weight to output from Max Pooling
out[o] = out[o] + max[f][y][x] * nn[o][y*16+x*4+f]
#ReLu
if out[o] < 0:
out[o] = 0
Sometimes I get exactly the same results as the prediction function. But often I get slightly different results like:
my calculation -> tensorflow
0.4958455 -> 0.4100589
0.0
0.3867072 -> 0.3395536
0.3473713
0.5230042 -> 0.2298216
0.7953386 -> 0.7953387
0.6598828 -> 0.5722865
1.6494241
0.6117965 -> 0.5601089
1.4232064
Is there some specific operation that I miss or is there documentation on how the tensorflow calculations work or the order of weights from the get_weights() function? My calculation can't be that way off, but maybe you spot an error. Or is there a way to calculate the result after one layer, so I could compare the result of my Conv2D and tensorflow's Conv2D calculation?