| 105 | |
| 106 | |
| 107 | class Model(ModelDesc): |
| 108 | def inputs(self): |
| 109 | return [tf.TensorSpec((None, IMAGE_SIZE, IMAGE_SIZE, 2), tf.float32, 'input'), |
| 110 | tf.TensorSpec((None,), tf.int32, 'label')] |
| 111 | |
| 112 | def build_graph(self, image, label): |
| 113 | xys = np.array([(y, x, 1) for y in range(WARP_TARGET_SIZE) |
| 114 | for x in range(WARP_TARGET_SIZE)], dtype='float32') |
| 115 | xys = tf.constant(xys, dtype=tf.float32, name='xys') # p x 3 |
| 116 | |
| 117 | image = image / 255.0 - 0.5 # bhw2 |
| 118 | |
| 119 | def get_stn(image): |
| 120 | stn = (LinearWrap(image) |
| 121 | .AvgPooling('downsample', 2) |
| 122 | .Conv2D('conv0', 20, 5, padding='VALID') |
| 123 | .MaxPooling('pool0', 2) |
| 124 | .Conv2D('conv1', 20, 5, padding='VALID') |
| 125 | .FullyConnected('fc1', 32) |
| 126 | .FullyConnected('fct', 6, activation=tf.identity, |
| 127 | kernel_initializer=tf.constant_initializer(), |
| 128 | bias_initializer=tf.constant_initializer([1, 0, HALF_DIFF, 0, 1, HALF_DIFF]))()) |
| 129 | # output 6 parameters for affine transformation |
| 130 | stn = tf.reshape(stn, [-1, 2, 3], name='affine') # bx2x3 |
| 131 | stn = tf.reshape(tf.transpose(stn, [2, 0, 1]), [3, -1]) # 3 x (bx2) |
| 132 | coor = tf.reshape(tf.matmul(xys, stn), |
| 133 | [WARP_TARGET_SIZE, WARP_TARGET_SIZE, -1, 2]) |
| 134 | coor = tf.transpose(coor, [2, 0, 1, 3], 'sampled_coords') # b h w 2 |
| 135 | sampled = GridSample('warp', [image, coor], borderMode='constant') |
| 136 | return sampled |
| 137 | |
| 138 | with argscope([Conv2D, FullyConnected], activation=tf.nn.relu): |
| 139 | with tf.variable_scope('STN1'): |
| 140 | sampled1 = get_stn(image) |
| 141 | with tf.variable_scope('STN2'): |
| 142 | sampled2 = get_stn(image) |
| 143 | |
| 144 | # For visualization in tensorboard |
| 145 | with tf.name_scope('visualization'): |
| 146 | padded1 = tf.pad(sampled1, [[0, 0], [HALF_DIFF, HALF_DIFF], [HALF_DIFF, HALF_DIFF], [0, 0]]) |
| 147 | padded2 = tf.pad(sampled2, [[0, 0], [HALF_DIFF, HALF_DIFF], [HALF_DIFF, HALF_DIFF], [0, 0]]) |
| 148 | img_orig = tf.concat([image[:, :, :, 0], image[:, :, :, 1]], 1) # b x 2h x w |
| 149 | transform1 = tf.concat([padded1[:, :, :, 0], padded1[:, :, :, 1]], 1) |
| 150 | transform2 = tf.concat([padded2[:, :, :, 0], padded2[:, :, :, 1]], 1) |
| 151 | stacked = tf.concat([img_orig, transform1, transform2], 2, 'viz') |
| 152 | tf.summary.image('visualize', |
| 153 | tf.expand_dims(stacked, -1), max_outputs=30) |
| 154 | |
| 155 | sampled = tf.concat([sampled1, sampled2], 3, 'sampled_concat') |
| 156 | logits = (LinearWrap(sampled) |
| 157 | .FullyConnected('fc1', 256, activation=tf.nn.relu) |
| 158 | .FullyConnected('fc2', 128, activation=tf.nn.relu) |
| 159 | .FullyConnected('fct', 19, activation=tf.identity)()) |
| 160 | tf.nn.softmax(logits, name='prob') |
| 161 | |
| 162 | cost = tf.nn.sparse_softmax_cross_entropy_with_logits(logits=logits, labels=label) |
| 163 | cost = tf.reduce_mean(cost, name='cross_entropy_loss') |
| 164 |
no outgoing calls
no test coverage detected
searching dependent graphs…