def testUpsampleAndDownsampleAreTransposes(self): """Tests that _downsample() is the transpose of _upsample().""" n = 8 x = np.random.uniform(size=(1, n, 1)) for f_len in range(1, 5): f = np.random.uniform(size=f_len) for shift in [0, 1]: # We're only testing the resampling operators away from the boundaries, # as this test appears to fail in the presences of boundary conditions. # TODO(barron): Figure out what's happening and make this test more # thorough, and then set range1 = range(d), range2 = range(d//2) and # have this code depend on util.compute_jacobian(). range1 = np.arange(f_len // 2 + 1, n - (f_len // 2 + 1)) range2 = np.arange(f_len // 4, n // 2 - (f_len // 4)) y = wavelet._downsample(x, f, 0, shift) # Construct the jacobian of _downsample(). x_ph = tf.placeholder(tf.float32, x.shape) jacobian_down = [] vec = lambda x: tf.reshape(x, [-1]) for d in range2: jacobian_down.append( vec( tf.gradients( vec(wavelet._downsample(x_ph, f, 0, shift))[d], x_ph)[0])) jacobian_down = tf.stack(jacobian_down, 1) with tf.Session() as sess: jacobian_down, y = sess.run([jacobian_down, y], {x_ph: x}) # Construct the jacobian of _upsample(). y_ph = tf.placeholder(tf.float32, y.shape) jacobian_up = [] vec = lambda x: tf.reshape(x, [-1]) for d in range1: jacobian_up.append( vec( tf.gradients( vec( wavelet._upsample(y_ph, x.shape[1:], f, 0, shift))[d], y_ph)[0])) jacobian_up = tf.stack(jacobian_up, 1) with tf.Session() as sess: jacobian_up = sess.run(jacobian_up, {y_ph: y}) # Test that the jacobian of _downsample() is close to the transpose of # the jacobian of _upsample(). self.assertAllClose(jacobian_down[range1, :], np.transpose(jacobian_up[range2, :]), atol=1e-6, rtol=1e-6)
def testUpsampleAndDownsampleAreTransposes(self): """Tests that _downsample() is the transpose of _upsample().""" n = 8 x = tf.convert_to_tensor(np.random.uniform(size=(1, n, 1))) for f_len in range(1, 5): f = np.random.uniform(size=f_len) for shift in [0, 1]: # We're only testing the resampling operators away from the boundaries, # as this test appears to fail in the presences of boundary conditions. # TODO(barron): Figure out what's happening and make this test more # thorough, and then set range1 = range(d), range2 = range(d//2) and # have this code depend on util.compute_jacobian(). range1 = np.arange(f_len // 2 + 1, n - (f_len // 2 + 1)) range2 = np.arange(f_len // 4, n // 2 - (f_len // 4)) y = wavelet._downsample(x, f, 0, shift) vec = lambda z: tf.reshape(z, [-1]) jacobian_down = [] with tf.GradientTape(persistent=True) as tape: tape.watch(x) for d in range2: yd = vec(wavelet._downsample(x, f, 0, shift))[d] jacobian_down.append(vec(tape.gradient(yd, x))) jacobian_down = tf.stack(jacobian_down, 1).numpy() jacobian_up = [] with tf.GradientTape(persistent=True) as tape: tape.watch(y) for d in range1: xd = vec(wavelet._upsample(y, x.shape[1:], f, 0, shift))[d] jacobian_up.append(vec(tape.gradient(xd, y))) jacobian_up = tf.stack(jacobian_up, 1).numpy() # Test that the jacobian of _downsample() is close to the transpose of # the jacobian of _upsample(). self.assertAllClose( jacobian_down[range1, :], np.transpose(jacobian_up[range2, :]), atol=1e-6, rtol=1e-6)