Spaces:
Running
Running
# Copyright 2017 The TensorFlow Authors All Rights Reserved. | |
# | |
# Licensed under the Apache License, Version 2.0 (the "License"); | |
# you may not use this file except in compliance with the License. | |
# You may obtain a copy of the License at | |
# | |
# http://www.apache.org/licenses/LICENSE-2.0 | |
# | |
# Unless required by applicable law or agreed to in writing, software | |
# distributed under the License is distributed on an "AS IS" BASIS, | |
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
# See the License for the specific language governing permissions and | |
# limitations under the License. | |
# ============================================================================== | |
"""Tests for basic tensorflow blocks_std.""" | |
from __future__ import division | |
from __future__ import unicode_literals | |
import math | |
import os | |
import numpy as np | |
from six.moves import xrange | |
import tensorflow as tf | |
import blocks_std | |
def _NumpyConv2D(x, f, strides, padding, rate=1): | |
assert strides[0] == 1 and strides[3] == 1, strides | |
if rate > 1: | |
f_shape = f.shape | |
expand_f = np.zeros([f_shape[0], ((f_shape[1] - 1) * rate + 1), | |
f_shape[2], f_shape[3]]) | |
expand_f[:, [y * rate for y in range(f_shape[1])], :, :] = f | |
f = np.zeros([((f_shape[0] - 1) * rate + 1), expand_f.shape[1], | |
f_shape[2], f_shape[3]]) | |
f[[y * rate for y in range(f_shape[0])], :, :, :] = expand_f | |
if padding != 'VALID': | |
assert x.shape[1] > 0 and x.shape[2] > 0, x.shape | |
# Compute the number of padded rows and cols. | |
# See Conv2D block comments for a math explanation. | |
remainder = ((x.shape[1] - 1) % strides[1], (x.shape[2] - 1) % strides[2]) | |
pad_rows = f.shape[0] - remainder[0] - 1 | |
pad_cols = f.shape[1] - remainder[1] - 1 | |
pad = ((0, 0), | |
(pad_rows // 2, (pad_rows + 1) // 2), | |
(pad_cols // 2, (pad_cols + 1) // 2), | |
(0, 0)) | |
# Pad the input using numpy.pad(). | |
mode = None | |
if padding == 'SAME': | |
mode = str('constant') | |
if padding == 'REFLECT': | |
mode = str('reflect') | |
if padding == 'SYMMETRIC': | |
mode = str('symmetric') | |
x = np.pad(x, pad, mode=mode) | |
# Since x is now properly padded, proceed as if padding mode is VALID. | |
x_window = np.empty( | |
(x.shape[0], | |
int(math.ceil((x.shape[1] - f.shape[0] + 1) / strides[1])), | |
int(math.ceil((x.shape[2] - f.shape[1] + 1) / strides[2])), | |
np.prod(f.shape[:3]))) | |
# The output at pixel location (i, j) is the result of linear transformation | |
# applied to the window whose top-left corner is at | |
# (i * row_stride, j * col_stride). | |
for i in xrange(x_window.shape[1]): | |
k = i * strides[1] | |
for j in xrange(x_window.shape[2]): | |
l = j * strides[2] | |
x_window[:, i, j, :] = x[:, | |
k:(k + f.shape[0]), | |
l:(l + f.shape[1]), | |
:].reshape((x_window.shape[0], -1)) | |
y = np.tensordot(x_window, f.reshape((-1, f.shape[3])), axes=1) | |
return y | |
class BlocksStdTest(tf.test.TestCase): | |
def CheckUnary(self, y, op_type): | |
self.assertEqual(op_type, y.op.type) | |
self.assertEqual(1, len(y.op.inputs)) | |
return y.op.inputs[0] | |
def CheckBinary(self, y, op_type): | |
self.assertEqual(op_type, y.op.type) | |
self.assertEqual(2, len(y.op.inputs)) | |
return y.op.inputs | |
def testPassThrough(self): | |
p = blocks_std.PassThrough() | |
x = tf.placeholder(dtype=tf.float32, shape=[1]) | |
self.assertIs(p(x), x) | |
def CheckBiasAdd(self, y, b): | |
x, u = self.CheckBinary(y, 'BiasAdd') | |
self.assertIs(u, b._bias.value()) | |
self.assertEqual(x.dtype, u.dtype.base_dtype) | |
return x | |
def testBiasAdd(self): | |
b = blocks_std.BiasAdd() | |
x = tf.placeholder(dtype=tf.float32, shape=[4, 8]) | |
y = b(x) | |
self.assertEqual(b._bias.get_shape(), x.get_shape()[-1:]) | |
self.assertIs(x, self.CheckBiasAdd(y, b)) | |
def testBiasRankTest(self): | |
b = blocks_std.BiasAdd() | |
x = tf.placeholder(dtype=tf.float32, shape=[10]) | |
with self.assertRaises(ValueError): | |
b(x) | |
def CheckLinear(self, y, m): | |
x, w = self.CheckBinary(y, 'MatMul') | |
self.assertIs(w, m._matrix.value()) | |
self.assertEqual(x.dtype, w.dtype.base_dtype) | |
return x | |
def testLinear(self): | |
m = blocks_std.Linear(10) | |
x = tf.placeholder(dtype=tf.float32, shape=[8, 9]) | |
y = m(x) | |
self.assertEqual(m._matrix.get_shape(), [9, 10]) | |
self.assertIs(x, self.CheckLinear(y, m)) | |
def testLinearShared(self): | |
# Create a linear map which is applied twice on different inputs | |
# (i.e. the weights of the map are shared). | |
linear_map = blocks_std.Linear(6) | |
x1 = tf.random_normal(shape=[1, 5]) | |
x2 = tf.random_normal(shape=[1, 5]) | |
xs = x1 + x2 | |
# Apply the transform with the same weights. | |
y1 = linear_map(x1) | |
y2 = linear_map(x2) | |
ys = linear_map(xs) | |
with self.test_session() as sess: | |
# Initialize all the variables of the graph. | |
tf.global_variables_initializer().run() | |
y1_res, y2_res, ys_res = sess.run([y1, y2, ys]) | |
self.assertAllClose(y1_res + y2_res, ys_res) | |
def CheckNN(self, y, nn, act=None): | |
if act: | |
pre_act = self.CheckUnary(y, act) | |
else: | |
pre_act = y | |
if not isinstance(nn._bias, blocks_std.PassThrough): | |
pre_bias = self.CheckBiasAdd(pre_act, nn._bias) | |
else: | |
pre_bias = pre_act | |
if len(nn._matrices) > 1: | |
self.assertEqual('AddN', pre_bias.op.type) | |
pre_bias = pre_bias.op.inputs | |
else: | |
pre_bias = [pre_bias] | |
self.assertEqual(len(pre_bias), len(nn._matrices)) | |
return [self.CheckLinear(u, m) for u, m in zip(pre_bias, nn._matrices)] | |
def testNNWithoutActWithoutBias(self): | |
nn = blocks_std.NN(10, act=None, bias=None) | |
x = tf.placeholder(dtype=tf.float32, shape=[5, 7]) | |
y = nn(x) | |
self.assertIs(x, self.CheckNN(y, nn)[0]) | |
def testNNWithoutBiasWithAct(self): | |
nn = blocks_std.NN(10, act=tf.nn.relu, bias=None) | |
x = tf.placeholder(dtype=tf.float32, shape=[5, 7]) | |
y = nn(x) | |
self.assertIs(x, self.CheckNN(y, nn, 'Relu')[0]) | |
def testNNWithBiasWithoutAct(self): | |
nn = blocks_std.NN(10, bias=blocks_std.Bias(0), act=None) | |
x = tf.placeholder(dtype=tf.float32, shape=[5, 7]) | |
y = nn(x) | |
self.assertIs(x, self.CheckNN(y, nn)[0]) | |
def testNNWithBiasWithAct(self): | |
nn = blocks_std.NN(10, bias=blocks_std.Bias(0), act=tf.square) | |
x = tf.placeholder(dtype=tf.float32, shape=[5, 7]) | |
y = nn(x) | |
self.assertIs(x, self.CheckNN(y, nn, 'Square')[0]) | |
def testNNMultipleInputs(self): | |
nn = blocks_std.NN(10, bias=blocks_std.Bias(0), act=tf.tanh) | |
x = [tf.placeholder(dtype=tf.float32, shape=[5, 7]), | |
tf.placeholder(dtype=tf.float32, shape=[5, 3]), | |
tf.placeholder(dtype=tf.float32, shape=[5, 5])] | |
y = nn(*x) | |
xs = self.CheckNN(y, nn, 'Tanh') | |
self.assertEqual(len(x), len(xs)) | |
for u, v in zip(x, xs): | |
self.assertIs(u, v) | |
def testConv2DSAME(self): | |
np.random.seed(142536) | |
x_shape = [4, 16, 11, 5] | |
f_shape = [4, 3, 5, 6] | |
strides = [1, 2, 2, 1] | |
padding = 'SAME' | |
conv = blocks_std.Conv2D(depth=f_shape[-1], | |
filter_size=f_shape[0:2], | |
strides=strides[1:3], | |
padding=padding, | |
act=None, | |
bias=None) | |
x_value = np.random.normal(size=x_shape) | |
x = tf.convert_to_tensor(x_value, dtype=tf.float32) | |
y = conv(x) | |
with self.test_session(): | |
tf.global_variables_initializer().run() | |
f_value = conv._kernel.eval() | |
y_value = y.eval() | |
y_expected = _NumpyConv2D(x_value, f_value, | |
strides=strides, padding=padding) | |
self.assertAllClose(y_expected, y_value) | |
def testConv2DValid(self): | |
np.random.seed(253647) | |
x_shape = [4, 11, 12, 5] | |
f_shape = [5, 2, 5, 5] | |
strides = [1, 2, 2, 1] | |
padding = 'VALID' | |
conv = blocks_std.Conv2D(depth=f_shape[-1], | |
filter_size=f_shape[0:2], | |
strides=strides[1:3], | |
padding=padding, | |
act=None, | |
bias=None) | |
x_value = np.random.normal(size=x_shape) | |
x = tf.convert_to_tensor(x_value, dtype=tf.float32) | |
y = conv(x) | |
with self.test_session(): | |
tf.global_variables_initializer().run() | |
f_value = conv._kernel.eval() | |
y_value = y.eval() | |
y_expected = _NumpyConv2D(x_value, f_value, | |
strides=strides, padding=padding) | |
self.assertAllClose(y_expected, y_value) | |
def testConv2DSymmetric(self): | |
np.random.seed(364758) | |
x_shape = [4, 10, 12, 6] | |
f_shape = [3, 4, 6, 5] | |
strides = [1, 1, 1, 1] | |
padding = 'SYMMETRIC' | |
conv = blocks_std.Conv2D(depth=f_shape[-1], | |
filter_size=f_shape[0:2], | |
strides=strides[1:3], | |
padding=padding, | |
act=None, | |
bias=None) | |
x_value = np.random.normal(size=x_shape) | |
x = tf.convert_to_tensor(x_value, dtype=tf.float32) | |
y = conv(x) | |
with self.test_session(): | |
tf.global_variables_initializer().run() | |
f_value = conv._kernel.eval() | |
y_value = y.eval() | |
y_expected = _NumpyConv2D(x_value, f_value, | |
strides=strides, padding=padding) | |
self.assertAllClose(y_expected, y_value) | |
def testConv2DReflect(self): | |
np.random.seed(768798) | |
x_shape = [4, 10, 12, 6] | |
f_shape = [3, 4, 6, 5] | |
strides = [1, 2, 2, 1] | |
padding = 'REFLECT' | |
conv = blocks_std.Conv2D(depth=f_shape[-1], | |
filter_size=f_shape[0:2], | |
strides=strides[1:3], | |
padding=padding, | |
act=None, | |
bias=None) | |
x_value = np.random.normal(size=x_shape) | |
x = tf.convert_to_tensor(x_value, dtype=tf.float32) | |
y = conv(x) | |
with self.test_session(): | |
tf.global_variables_initializer().run() | |
f_value = conv._kernel.eval() | |
y_value = y.eval() | |
y_expected = _NumpyConv2D(x_value, f_value, | |
strides=strides, padding=padding) | |
self.assertAllClose(y_expected, y_value) | |
def testConv2DBias(self): | |
input_shape = [19, 14, 14, 64] | |
filter_shape = [3, 7, 64, 128] | |
strides = [1, 2, 2, 1] | |
output_shape = [19, 6, 4, 128] | |
conv = blocks_std.Conv2D(depth=filter_shape[-1], | |
filter_size=filter_shape[0:2], | |
strides=strides[1:3], | |
padding='VALID', | |
act=None, | |
bias=blocks_std.Bias(1)) | |
x = tf.placeholder(dtype=tf.float32, shape=input_shape) | |
y = conv(x) | |
self.CheckBiasAdd(y, conv._bias) | |
self.assertEqual(output_shape, y.get_shape().as_list()) | |
if __name__ == '__main__': | |
tf.test.main() | |