def check_results_versus_brute_force( self, x, axis, max_lags, center, normalize): """Compute auto-correlation by brute force, then compare to tf result.""" # Brute for auto-corr -- avoiding fft and transpositions. axis_len = x.shape[axis] if max_lags is None: max_lags = axis_len - 1 else: max_lags = min(axis_len - 1, max_lags) auto_corr_at_lag = [] if center: x -= x.mean(axis=axis, keepdims=True) for m in range(max_lags + 1): auto_corr_at_lag.append(( np.take(x, indices=range(0, axis_len - m), axis=axis) * np.conj(np.take(x, indices=range(m, axis_len), axis=axis)) ).mean(axis=axis, keepdims=True)) rxx = np.concatenate(auto_corr_at_lag, axis=axis) if normalize: rxx /= np.take(rxx, [0], axis=axis) x_ph = array_ops.placeholder_with_default( x, shape=x.shape if self.use_static_shape else None) with spectral_ops_test_util.fft_kernel_label_map(): with self.cached_session(): auto_corr = sample_stats.auto_correlation( x_ph, axis=axis, max_lags=max_lags, center=center, normalize=normalize) if self.use_static_shape: output_shape = list(x.shape) output_shape[axis] = max_lags + 1 self.assertAllEqual(output_shape, auto_corr.shape) self.assertAllClose(rxx, auto_corr.eval(), rtol=1e-5, atol=1e-5)
def check_results_versus_brute_force(self, x, axis, max_lags, center, normalize): """Compute auto-correlation by brute force, then compare to tf result.""" # Brute for auto-corr -- avoiding fft and transpositions. axis_len = x.shape[axis] if max_lags is None: max_lags = axis_len - 1 else: max_lags = min(axis_len - 1, max_lags) auto_corr_at_lag = [] if center: x -= x.mean(axis=axis, keepdims=True) for m in range(max_lags + 1): auto_corr_at_lag.append( (np.take(x, indices=range(0, axis_len - m), axis=axis) * np.conj(np.take(x, indices=range(m, axis_len), axis=axis))).mean(axis=axis, keepdims=True)) rxx = np.concatenate(auto_corr_at_lag, axis=axis) if normalize: rxx /= np.take(rxx, [0], axis=axis) x_ph = array_ops.placeholder_with_default( x, shape=x.shape if self.use_static_shape else None) with self.cached_session(): auto_corr = sample_stats.auto_correlation(x_ph, axis=axis, max_lags=max_lags, center=center, normalize=normalize) if self.use_static_shape: output_shape = list(x.shape) output_shape[axis] = max_lags + 1 self.assertAllEqual(output_shape, auto_corr.shape) self.assertAllClose(rxx, auto_corr.eval(), rtol=1e-5, atol=1e-5)
def _effective_sample_size_single_state(states, filter_beyond_lag, filter_threshold): """ESS computation for one single Tensor argument.""" with ops.name_scope( "effective_sample_size_single_state", values=[states, filter_beyond_lag, filter_threshold]): states = ops.convert_to_tensor(states, name="states") dt = states.dtype # filter_beyond_lag == None ==> auto_corr is the full sequence. auto_corr = sample_stats.auto_correlation( states, axis=0, max_lags=filter_beyond_lag) if filter_threshold is not None: filter_threshold = ops.convert_to_tensor( filter_threshold, dtype=dt, name="filter_threshold") # Get a binary mask to zero out values of auto_corr below the threshold. # mask[i, ...] = 1 if auto_corr[j, ...] > threshold for all j <= i, # mask[i, ...] = 0, otherwise. # So, along dimension zero, the mask will look like [1, 1, ..., 0, 0,...] # Building step by step, # Assume auto_corr = [1, 0.5, 0.0, 0.3], and filter_threshold = 0.2. # Step 1: mask = [False, False, True, False] mask = auto_corr < filter_threshold # Step 2: mask = [0, 0, 1, 1] mask = math_ops.cast(mask, dtype=dt) # Step 3: mask = [0, 0, 1, 2] mask = math_ops.cumsum(mask, axis=0) # Step 4: mask = [1, 1, 0, 0] mask = math_ops.maximum(1. - mask, 0.) auto_corr *= mask # With R[k] := auto_corr[k, ...], # ESS = N / {1 + 2 * Sum_{k=1}^N (N - k) / N * R[k]} # = N / {-1 + 2 * Sum_{k=0}^N (N - k) / N * R[k]} (since R[0] = 1) # approx N / {-1 + 2 * Sum_{k=0}^M (N - k) / N * R[k]} # where M is the filter_beyond_lag truncation point chosen above. # Get the factor (N - k) / N, and give it shape [M, 1,...,1], having total # ndims the same as auto_corr n = _axis_size(states, axis=0) k = math_ops.range(0., _axis_size(auto_corr, axis=0)) nk_factor = (n - k) / n if auto_corr.shape.ndims is not None: new_shape = [-1] + [1] * (auto_corr.shape.ndims - 1) else: new_shape = array_ops.concat( ([-1], array_ops.ones([array_ops.rank(auto_corr) - 1], dtype=dtypes.int32)), axis=0) nk_factor = array_ops.reshape(nk_factor, new_shape) return n / (-1 + 2 * math_ops.reduce_sum(nk_factor * auto_corr, axis=0))
def test_constant_sequence_axis_0_max_lags_none_center_true(self): x_ = np.array([[0., 0., 0.], [1., 1., 1.]]).astype(self.dtype) x_ph = array_ops.placeholder_with_default( input=x_, shape=x_.shape if self.use_static_shape else None) with self.cached_session() as sess: # Setting normalize = True means we divide by zero. auto_corr = sample_stats.auto_correlation(x_ph, axis=1, normalize=False, center=True) if self.use_static_shape: self.assertEqual((2, 3), auto_corr.shape) auto_corr_ = sess.run(auto_corr) self.assertAllClose([[0., 0., 0.], [0., 0., 0.]], auto_corr_)
def test_constant_sequence_axis_0_max_lags_none_center_true(self): x_ = np.array([[0., 0., 0.], [1., 1., 1.]]).astype(self.dtype) x_ph = array_ops.placeholder_with_default( input=x_, shape=x_.shape if self.use_static_shape else None) with spectral_ops_test_util.fft_kernel_label_map(): with self.cached_session() as sess: # Setting normalize = True means we divide by zero. auto_corr = sample_stats.auto_correlation( x_ph, axis=1, normalize=False, center=True) if self.use_static_shape: self.assertEqual((2, 3), auto_corr.shape) auto_corr_ = sess.run(auto_corr) self.assertAllClose( [[0., 0., 0.], [0., 0., 0.]], auto_corr_)
def test_long_orthonormal_sequence_has_corr_length_0(self): l = 10000 x = rng.randn(l).astype(self.dtype) x_ph = array_ops.placeholder_with_default( x, shape=(l, ) if self.use_static_shape else None) with self.cached_session(): rxx = sample_stats.auto_correlation(x_ph, max_lags=l // 2, center=True, normalize=False) if self.use_static_shape: self.assertAllEqual((l // 2 + 1, ), rxx.shape) rxx_ = rxx.eval() # OSS CPU FFT has some accuracy issues, so this tolerance is a bit bad. self.assertAllClose(1., rxx_[0], rtol=0.05) # The maximal error in the rest of the sequence is not great. self.assertAllClose(np.zeros(l // 2), rxx_[1:], atol=0.1) # The mean error in the rest is ok, actually 0.008 when I tested it. self.assertLess(np.abs(rxx_[1:]).mean(), 0.02)
def test_long_orthonormal_sequence_has_corr_length_0(self): l = 10000 x = rng.randn(l).astype(self.dtype) x_ph = array_ops.placeholder_with_default( x, shape=(l,) if self.use_static_shape else None) with spectral_ops_test_util.fft_kernel_label_map(): with self.cached_session(): rxx = sample_stats.auto_correlation( x_ph, max_lags=l // 2, center=True, normalize=False) if self.use_static_shape: self.assertAllEqual((l // 2 + 1,), rxx.shape) rxx_ = rxx.eval() # OSS CPU FFT has some accuracy issues is not the most accurate. # So this tolerance is a bit bad. self.assertAllClose(1., rxx_[0], rtol=0.05) # The maximal error in the rest of the sequence is not great. self.assertAllClose(np.zeros(l // 2), rxx_[1:], atol=0.1) # The mean error in the rest is ok, actually 0.008 when I tested it. self.assertLess(np.abs(rxx_[1:]).mean(), 0.02)
def test_step_function_sequence(self): # x jumps to new random value every 10 steps. So correlation length = 10. x = (rng.randint(-10, 10, size=(1000, 1)) * np.ones((1, 10))).ravel().astype(self.dtype) x_ph = array_ops.placeholder_with_default( x, shape=(1000 * 10,) if self.use_static_shape else None) with spectral_ops_test_util.fft_kernel_label_map(): with self.cached_session(): rxx = sample_stats.auto_correlation( x_ph, max_lags=1000 * 10 // 2, center=True, normalize=False) if self.use_static_shape: self.assertAllEqual((1000 * 10 // 2 + 1,), rxx.shape) rxx_ = rxx.eval() rxx_ /= rxx_[0] # Expect positive correlation for the first 10 lags, then significantly # smaller negative. self.assertGreater(rxx_[:10].min(), 0) self.assertGreater(rxx_[9], 5 * rxx_[10:20].mean()) # RXX should be decreasing for the first 10 lags. diff = np.diff(rxx_) self.assertLess(diff[:10].max(), 0)
def test_normalization(self): l = 10000 x = 3 * rng.randn(l).astype(self.dtype) x_ph = array_ops.placeholder_with_default( x, shape=(l,) if self.use_static_shape else None) with spectral_ops_test_util.fft_kernel_label_map(): with self.test_session(): rxx = sample_stats.auto_correlation( x_ph, max_lags=l // 2, center=True, normalize=True) if self.use_static_shape: self.assertAllEqual((l // 2 + 1,), rxx.shape) rxx_ = rxx.eval() # Note that RXX[0] = 1, despite the fact that E[X^2] = 9, and this is # due to normalize=True. # OSS CPU FFT has some accuracy issues is not the most accurate. # So this tolerance is a bit bad. self.assertAllClose(1., rxx_[0], rtol=0.05) # The maximal error in the rest of the sequence is not great. self.assertAllClose(np.zeros(l // 2), rxx_[1:], atol=0.1) # The mean error in the rest is ok, actually 0.008 when I tested it. self.assertLess(np.abs(rxx_[1:]).mean(), 0.02)
def test_step_function_sequence(self): # x jumps to new random value every 10 steps. So correlation length = 10. x = (rng.randint(-10, 10, size=(1000, 1)) * np.ones((1, 10))).ravel().astype(self.dtype) x_ph = array_ops.placeholder_with_default( x, shape=(1000 * 10,) if self.use_static_shape else None) with spectral_ops_test_util.fft_kernel_label_map(): with self.test_session(): rxx = sample_stats.auto_correlation( x_ph, max_lags=1000 * 10 // 2, center=True, normalize=False) if self.use_static_shape: self.assertAllEqual((1000 * 10 // 2 + 1,), rxx.shape) rxx_ = rxx.eval() rxx_ /= rxx_[0] # Expect positive correlation for the first 10 lags, then significantly # smaller negative. self.assertGreater(rxx_[:10].min(), 0) self.assertGreater(rxx_[9], 5 * rxx_[10:20].mean()) # RXX should be decreasing for the first 10 lags. diff = np.diff(rxx_) self.assertLess(diff[:10].max(), 0)
def _effective_sample_size_single_state(states, max_lags, max_lags_threshold): """ESS computation for one single Tensor argument.""" if max_lags is not None and max_lags_threshold is not None: raise ValueError( "Expected at most one of max_lags, max_lags_threshold to be provided. " "Found: {}, {}".format(max_lags, max_lags_threshold)) if max_lags_threshold is None: max_lags_threshold = 0. with ops.name_scope("effective_sample_size_single_state", values=[states, max_lags, max_lags_threshold]): states = ops.convert_to_tensor(states, name="states") dt = states.dtype if max_lags is not None: auto_corr = sample_stats.auto_correlation(states, axis=0, max_lags=max_lags) elif max_lags_threshold is not None: max_lags_threshold = ops.convert_to_tensor( max_lags_threshold, dtype=dt, name="max_lags_threshold") auto_corr = sample_stats.auto_correlation(states, axis=0) # Get a binary mask to zero out values of auto_corr below the threshold. # mask[i, ...] = 1 if auto_corr[j, ...] > threshold for all j <= i, # mask[i, ...] = 0, otherwise. # So, along dimension zero, the mask will look like [1, 1, ..., 0, 0,...] # Building step by step, # Assume auto_corr = [1, 0.5, 0.0, 0.3], and max_lags_threshold = 0.2. # Step 1: mask = [False, False, True, False] mask = auto_corr < max_lags_threshold # Step 2: mask = [0, 0, 1, 1] mask = math_ops.cast(mask, dtype=dt) # Step 3: mask = [0, 0, 1, 2] mask = math_ops.cumsum(mask, axis=0) # Step 4: mask = [1, 1, 0, 0] mask = math_ops.maximum(1. - mask, 0.) auto_corr *= mask else: auto_corr = sample_stats.auto_correlation(states, axis=0) # With R[k] := auto_corr[k, ...], # ESS = N / {1 + 2 * Sum_{k=1}^N (N - k) / N * R[k]} # = N / {-1 + 2 * Sum_{k=0}^N (N - k) / N * R[k]} (since R[0] = 1) # approx N / {-1 + 2 * Sum_{k=0}^M (N - k) / N * R[k]} #, where M is the max_lags truncation point chosen above. # Get the factor (N - k) / N, and give it shape [M, 1,...,1], having total # ndims the same as auto_corr n = _axis_size(states, axis=0) k = math_ops.range(0., _axis_size(auto_corr, axis=0)) nk_factor = (n - k) / n if auto_corr.shape.ndims is not None: new_shape = [-1] + [1] * (auto_corr.shape.ndims - 1) else: new_shape = array_ops.concat( ([-1], array_ops.ones([array_ops.rank(auto_corr) - 1], dtype=dtypes.int32)), axis=0) nk_factor = array_ops.reshape(nk_factor, new_shape) return n / (-1 + 2 * math_ops.reduce_sum(nk_factor * auto_corr, axis=0))