def _operator_and_matrix(self, build_info, dtype, use_placeholder): shape = build_info.shape # For this test class, we are creating Hermitian spectrums. # We also want the spectrum to have eigenvalues bounded away from zero. # # pre_spectrum is bounded away from zero. pre_spectrum = linear_operator_test_util.random_uniform( shape=self._shape_to_spectrum_shape(shape), minval=1., maxval=2.) pre_spectrum_c = _to_complex(pre_spectrum) # Real{IFFT[pre_spectrum]} # = IFFT[EvenPartOf[pre_spectrum]] # is the IFFT of something that is also bounded away from zero. # Therefore, FFT[pre_h] would be a well-conditioned spectrum. pre_h = math_ops.ifft(pre_spectrum_c) # A spectrum is Hermitian iff it is the DFT of a real convolution kernel. # So we will make spectrum = FFT[h], for real valued h. h = math_ops.real(pre_h) h_c = _to_complex(h) spectrum = math_ops.fft(h_c) lin_op_spectrum = spectrum if use_placeholder: lin_op_spectrum = array_ops.placeholder_with_default(spectrum, shape=None) operator = linalg.LinearOperatorCirculant(lin_op_spectrum, input_output_dtype=dtype) mat = self._spectrum_to_circulant_1d(spectrum, shape, dtype=dtype) return operator, mat
def _spectrum_to_circulant_1d(self, spectrum, shape, dtype): """Creates a circulant matrix from a spectrum. Intentionally done in an explicit yet inefficient way. This provides a cross check to the main code that uses fancy reshapes. Args: spectrum: Float or complex `Tensor`. shape: Python list. Desired shape of returned matrix. dtype: Type to cast the returned matrix to. Returns: Circulant (batch) matrix of desired `dtype`. """ spectrum = _to_complex(spectrum) spectrum_shape = self._shape_to_spectrum_shape(shape) domain_dimension = spectrum_shape[-1] if not domain_dimension: return array_ops.zeros(shape, dtype) # Explicitly compute the action of spectrum on basis vectors. matrix_rows = [] for m in range(domain_dimension): x = np.zeros([domain_dimension]) # x is a basis vector. x[m] = 1.0 fft_x = math_ops.fft(x.astype(np.complex64)) h_convolve_x = math_ops.ifft(spectrum * fft_x) matrix_rows.append(h_convolve_x) matrix = array_ops.stack(matrix_rows, axis=-1) return math_ops.cast(matrix, dtype)
def _operator_and_matrix(self, build_info, dtype, use_placeholder): shape = build_info.shape # For this test class, we are creating Hermitian spectrums. # We also want the spectrum to have eigenvalues bounded away from zero. # # pre_spectrum is bounded away from zero. pre_spectrum = linear_operator_test_util.random_uniform( shape=self._shape_to_spectrum_shape(shape), minval=1., maxval=2.) pre_spectrum_c = _to_complex(pre_spectrum) # Real{IFFT[pre_spectrum]} # = IFFT[EvenPartOf[pre_spectrum]] # is the IFFT of something that is also bounded away from zero. # Therefore, FFT[pre_h] would be a well-conditioned spectrum. pre_h = math_ops.ifft(pre_spectrum_c) # A spectrum is Hermitian iff it is the DFT of a real convolution kernel. # So we will make spectrum = FFT[h], for real valued h. h = math_ops.real(pre_h) h_c = _to_complex(h) spectrum = math_ops.fft(h_c) lin_op_spectrum = spectrum if use_placeholder: lin_op_spectrum = array_ops.placeholder_with_default(spectrum, shape=None) operator = linalg.LinearOperatorCirculant( lin_op_spectrum, input_output_dtype=dtype) mat = self._spectrum_to_circulant_1d(spectrum, shape, dtype=dtype) return operator, mat
def test_hermitian_spectrum_gives_operator_with_zero_imag_part(self): with self.test_session(): # Make spectrum the FFT of a real convolution kernel h. This ensures that # spectrum is Hermitian. h = linear_operator_test_util.random_normal(shape=(3, 4)) spectrum = math_ops.fft(math_ops.cast(h, dtypes.complex64)) operator = linalg.LinearOperatorCirculant( spectrum, input_output_dtype=dtypes.complex64) matrix = operator.to_dense() imag_matrix = math_ops.imag(matrix) eps = np.finfo(np.float32).eps np.testing.assert_allclose( 0, imag_matrix.eval(), rtol=0, atol=eps * 3 * 4)
def test_hermitian_spectrum_gives_operator_with_zero_imag_part(self): with self.cached_session(): # Make spectrum the FFT of a real convolution kernel h. This ensures that # spectrum is Hermitian. h = linear_operator_test_util.random_normal(shape=(3, 4)) spectrum = math_ops.fft(math_ops.cast(h, dtypes.complex64)) operator = linalg.LinearOperatorCirculant( spectrum, input_output_dtype=dtypes.complex64) matrix = operator.to_dense() imag_matrix = math_ops.imag(matrix) eps = np.finfo(np.float32).eps np.testing.assert_allclose(0, imag_matrix.eval(), rtol=0, atol=eps * 3 * 4)
def test_defining_operator_using_real_convolution_kernel(self): with self.cached_session(): convolution_kernel = [1., 2., 1.] spectrum = math_ops.fft( math_ops.cast(convolution_kernel, dtypes.complex64)) # spectrum is shape [3] ==> operator is shape [3, 3] # spectrum is Hermitian ==> operator is real. operator = linalg.LinearOperatorCirculant(spectrum) # Allow for complex output so we can make sure it has zero imag part. self.assertEqual(operator.dtype, dtypes.complex64) matrix = operator.to_dense().eval() np.testing.assert_allclose(0, np.imag(matrix), atol=1e-6)
def test_defining_operator_using_real_convolution_kernel(self): with self.test_session(): convolution_kernel = [1., 2., 1.] spectrum = math_ops.fft( math_ops.cast(convolution_kernel, dtypes.complex64)) # spectrum is shape [3] ==> operator is shape [3, 3] # spectrum is Hermitian ==> operator is real. operator = linalg.LinearOperatorCirculant(spectrum) # Allow for complex output so we can make sure it has zero imag part. self.assertEqual(operator.dtype, dtypes.complex64) matrix = operator.to_dense().eval() np.testing.assert_allclose(0, np.imag(matrix), atol=1e-6)
def _operator_and_mat_and_feed_dict(self, build_info, dtype, use_placeholder): shape = build_info.shape # For this test class, we are creating Hermitian spectrums. # We also want the spectrum to have eigenvalues bounded away from zero. # # pre_spectrum is bounded away from zero. pre_spectrum = linear_operator_test_util.random_uniform( shape=self._shape_to_spectrum_shape(shape), minval=1., maxval=2.) pre_spectrum_c = _to_complex(pre_spectrum) # Real{IFFT[pre_spectrum]} # = IFFT[EvenPartOf[pre_spectrum]] # is the IFFT of something that is also bounded away from zero. # Therefore, FFT[pre_h] would be a well-conditioned spectrum. pre_h = math_ops.ifft(pre_spectrum_c) # A spectrum is Hermitian iff it is the DFT of a real convolution kernel. # So we will make spectrum = FFT[h], for real valued h. h = math_ops.real(pre_h) h_c = _to_complex(h) spectrum = math_ops.fft(h_c) if use_placeholder: spectrum_ph = array_ops.placeholder(dtypes.complex64) # Evaluate here because (i) you cannot feed a tensor, and (ii) # it is random and we want the same value used for both mat and feed_dict. spectrum = spectrum.eval() operator = linalg.LinearOperatorCirculant(spectrum_ph, input_output_dtype=dtype) feed_dict = {spectrum_ph: spectrum} else: operator = linalg.LinearOperatorCirculant(spectrum, input_output_dtype=dtype) feed_dict = None mat = self._spectrum_to_circulant_1d(spectrum, shape, dtype=dtype) return operator, mat, feed_dict
def _operator_and_mat_and_feed_dict(self, build_info, dtype, use_placeholder): shape = build_info.shape # For this test class, we are creating Hermitian spectrums. # We also want the spectrum to have eigenvalues bounded away from zero. # # pre_spectrum is bounded away from zero. pre_spectrum = linear_operator_test_util.random_uniform( shape=self._shape_to_spectrum_shape(shape), minval=1., maxval=2.) pre_spectrum_c = _to_complex(pre_spectrum) # Real{IFFT[pre_spectrum]} # = IFFT[EvenPartOf[pre_spectrum]] # is the IFFT of something that is also bounded away from zero. # Therefore, FFT[pre_h] would be a well-conditioned spectrum. pre_h = math_ops.ifft(pre_spectrum_c) # A spectrum is Hermitian iff it is the DFT of a real convolution kernel. # So we will make spectrum = FFT[h], for real valued h. h = math_ops.real(pre_h) h_c = _to_complex(h) spectrum = math_ops.fft(h_c) if use_placeholder: spectrum_ph = array_ops.placeholder(dtypes.complex64) # Evaluate here because (i) you cannot feed a tensor, and (ii) # it is random and we want the same value used for both mat and feed_dict. spectrum = spectrum.eval() operator = linalg.LinearOperatorCirculant( spectrum_ph, input_output_dtype=dtype) feed_dict = {spectrum_ph: spectrum} else: operator = linalg.LinearOperatorCirculant( spectrum, input_output_dtype=dtype) feed_dict = None mat = self._spectrum_to_circulant_1d(spectrum, shape, dtype=dtype) return operator, mat, feed_dict
def _IFFTGrad(_, grad): rsize = 1. / math_ops.cast(array_ops.size(grad), dtypes.float32) return math_ops.fft(grad) * math_ops.complex(rsize, 0.)
def _IFFTGrad(_, grad): rsize = 1. / math_ops.cast(_FFTSizeForGrad(grad, 1), dtypes.float32) return math_ops.fft(grad) * math_ops.complex(rsize, 0.)