In [1]:
import tensorflow as tf
import numpy as np

In [2]:
np.set_printoptions(formatter={'float': lambda x: "{0:0.3f}".format(x)})

In [3]:
# Filter is the block of data (pixels) to scan an image and produce a value
filter_size = [3, 3]

# A grey scale image would have one, RGB would have 3
input_channel = 1

# Number of channels to produce. With data aggregated, each channel 
output_channel = 2

In [4]:
image_1 = [
    [[0.11], [0.12], [0.13], [0.14]],
    [[0.21], [0.22], [0.23], [0.24]],
    [[0.31], [0.32], [0.33], [0.34]],
    [[0.41], [0.42], [0.43], [0.44]]
]

input_x = [image_1]

height = len(image_1)
width = len(image_1[0])
channel = len(image_1[0][0])
print("%d x %d" % (height, width))


4 x 4

In [5]:
input_shape = [None, height, width, input_channel]
X = tf.placeholder(tf.float32, input_shape)

Convolutional Weights and Bias

Weight Shape: 3 x 3 x 1 x 2

* Filter sizes: 3 x 3 (Modeler's choice)
* Input Channels: 1 (Greyscale)
* Output Channels: 2 (Modeler's choice) 

In [6]:
# 3 x 3 filter shape
filter1 = [
    [.1, .1, .2],
    [.1, .1, .2],
    [.2, .2, .2], 
]

# Each filter only has one input channel (grey scale)
# 3 x 3 x 1
channel_filters1 = [filter1]

# We want to output 2 channels which requires another set of 3 x 3 x 1

filter2 = [
    [.9, .5, .9],
    [.5, .3, .5],
    [.9, .5, .9],
]
channel_filters2 = [filter2]

# Initialized Weights
# 3 x 3 x 1 x 2
convolution_layer1 = [channel_filters1, channel_filters2]

print(convolution_layer1[0][0][2][0])


0.2

In [7]:
for filters in convolution_layer1:
    for channel_filter in filters:
        for row in channel_filter:
            print(row)
        print()


[0.1, 0.1, 0.2]
[0.1, 0.1, 0.2]
[0.2, 0.2, 0.2]

[0.9, 0.5, 0.9]
[0.5, 0.3, 0.5]
[0.9, 0.5, 0.9]

Bias Shape: 2

Matches the number of output channels


In [8]:
biases_1 = [0.1, 0.1]

Convolutional Layers


In [9]:
# Number of pixels to shift want evaluating a filter
stride_1 = 1

# Transpose to match inputs 
W1 = tf.Variable(np.transpose(convolution_layer1), dtype=tf.float32)
B1 = tf.Variable(biases_1, dtype=tf.float32)
print(W1.shape)


(3, 3, 1, 2)

Activation Shape: 4 x 4 x 2

  • dimension_1 = hight / stride
  • dimension_2 = width / stride
  • dimension_3 = output_channel

In [10]:
stride_shape = [1, stride_1, stride_1, 1]
preactivation = tf.nn.conv2d(X, W1, strides=stride_shape, padding='SAME') + B1
activation_1 = tf.nn.relu(preactivation)

print(activation_1.shape)


(?, 4, 4, 2)

In [11]:
# Create a session
init = tf.global_variables_initializer()

sess = tf.Session()
sess.run(init)

In [12]:
x = sess.run(W1)

# Transpose to match our model 
print(np.transpose(x))


[[[[0.100 0.100 0.200]
   [0.100 0.100 0.200]
   [0.200 0.200 0.200]]]


 [[[0.900 0.500 0.900]
   [0.500 0.300 0.500]
   [0.900 0.500 0.900]]]]

In [13]:
# Transpose to match our model 
feed_dict = {X: input_x}
Y1 = activation_1.eval(session=sess, feed_dict=feed_dict)

print(np.round_(np.transpose(Y1), 1))


[[[[0.200]
   [0.300]
   [0.400]
   [0.300]]

  [[0.300]
   [0.400]
   [0.600]
   [0.400]]

  [[0.300]
   [0.400]
   [0.600]
   [0.400]]

  [[0.200]
   [0.300]
   [0.400]
   [0.300]]]


 [[[0.500]
   [0.900]
   [1.200]
   [0.900]]

  [[0.800]
   [1.400]
   [2.000]
   [1.400]]

  [[0.800]
   [1.500]
   [2.000]
   [1.400]]

  [[0.500]
   [0.900]
   [1.300]
   [0.900]]]]

Activation2 Shape: 2 x 2 x 4

  • dimension_1 = d1 / stride
  • dimension_2 = d2 / stride
  • dimension_3 = output_channel

In [14]:
init_2 = tf.truncated_normal([4, 4, 2, 4], stddev=0.1)
W2 = tf.Variable(init_2)
B2 = tf.Variable(tf.ones([4])/10)

stride_2 = 2

In [18]:
strides = [1, stride_2, stride_2, 1]
preactivate = tf.nn.conv2d(activation_1, W2, strides=strides, padding='SAME') + B2
activation_2 = tf.nn.relu(preactivate)

print(activation_2.shape)


(?, 2, 2, 4)

Fully Connected Layer

The output of a Convolutional layer must flattened to a single layer

  • Reshape: [2, 2, 4] --> [16]
  • Select a number of nodes to output like a tradional ann layer. (200)

In [19]:
# reshape the output from the third convolution for the fully connected layer
reduced = int(np.multiply.reduce(list(activation_2.shape[1:])))
re_shape = [-1, reduced]

fully_connected_input = tf.reshape(activation_2, shape=re_shape)
print(fully_connected_input.shape)


(?, 16)

In [20]:
fully_connected_nodes = 6

fc_w_init = tf.truncated_normal([reduced, fully_connected_nodes], stddev=0.1)
fully_connected_weights = tf.Variable(fc_w_init)

fc_b_init = tf.ones([fully_connected_nodes])/10
fully_connected_biases = tf.Variable(fc_b_init)

In [21]:
preactivate = tf.matmul(fully_connected_input, fully_connected_weights) + fully_connected_biases
fully_connected_activate = tf.nn.relu(preactivate)

print(fully_connected_activate.shape)


(?, 6)

In [ ]: