def test_solid_harmonic_scattering(): # Compare value to analytical formula in the case of a single Gaussian centers = torch.FloatTensor(1, 1, 3).fill_(0) weights = torch.FloatTensor(1, 1).fill_(1) sigma_gaussian = 3. sigma_0_wavelet = 3. M, N, O, J, L = 128, 128, 128, 1, 3 grid = torch.from_numpy( np.fft.ifftshift(np.mgrid[-M//2:-M//2+M, -N//2:-N//2+N, -O//2:-O//2+O].astype('float32'), axes=(1,2,3))) x = generate_weighted_sum_of_gaussians(grid, centers, weights, sigma_gaussian) scattering = HarmonicScattering3D(J=J, shape=(M, N, O), L=L, sigma_0=sigma_0_wavelet) scattering.max_order = 1 scattering.method = 'integral' scattering.integral_powers = [1] for device in devices: if device == 'cpu': x = x.cpu() scattering.cpu() else: x = x.cuda() scattering.cuda() s = scattering(x) for j in range(J+1): sigma_wavelet = sigma_0_wavelet*2**j k = sigma_wavelet / np.sqrt(sigma_wavelet**2 + sigma_gaussian**2) for l in range(1, L+1): err = torch.abs(s[0, j, l, 0] - k ** l).sum()/(1e-6+s[0, j, l, 0].abs().sum()) assert err<1e-4
def test_scattering_methods(): shape = (32, 32, 32) J = 4 L = 3 sigma_0 = 1 x = torch.randn((1,) + shape) scattering = HarmonicScattering3D(J=J, shape=shape, L=L, sigma_0=sigma_0) if not 'cpu' in devices: x = x.cuda() scattering.cuda() scattering.method = 'standard' Sx = scattering(x) scattering.rotation_covariant = False Sx = scattering(x) points = torch.zeros(1, 1, 3) points[0,0,:] = torch.tensor(shape)/2 scattering.method = 'local' scattering.points = points Sx = scattering(x) scattering.rotation_covariant = False Sx = scattering(x)
def test_scattering_batch_shape_agnostic(): J = 2 shape = (16, 16, 16) S = HarmonicScattering3D(J=J, shape=shape, frontend='tensorflow') for k in range(3): with pytest.raises(RuntimeError) as ve: S(np.zeros(shape[:k])) assert 'at least three' in ve.value.args[0] x = np.zeros(shape) Sx = S(x) assert len(Sx.shape) == 3 coeffs_shape = Sx.shape[-3:] test_shapes = ((1,) + shape, (2,) + shape, (2, 2) + shape, (2, 2, 2) + shape) for test_shape in test_shapes: x = np.zeros(test_shape) Sx = S(x) assert len(Sx.shape) == len(test_shape) assert Sx.shape[-3:] == coeffs_shape assert Sx.shape[:-3] == test_shape[:-3]
def test_against_standard_computations(device, backend): if backend.name.endswith('_skcuda') and device == "cpu": pytest.skip("The skcuda backend does not support CPU tensors.") file_path = os.path.abspath(os.path.dirname(__file__)) with open(os.path.join(file_path, 'test_data_3d.npz'), 'rb') as f: buffer = io.BytesIO(f.read()) data = np.load(buffer) x = torch.from_numpy(data['x']) scattering_ref = torch.from_numpy(data['Sx']) J = data['J'] L = data['L'] integral_powers = data['integral_powers'] M = x.shape[1] batch_size = x.shape[0] N, O = M, M sigma = 1 scattering = HarmonicScattering3D(J=J, shape=(M, N, O), L=L, sigma_0=sigma, method='integral', integral_powers=integral_powers, max_order=2, backend=backend, frontend='torch') scattering.to(device) x = x.to(device) order_0 = backend.compute_integrals(x, integral_powers) scattering.max_order = 2 scattering.method = 'integral' scattering.integral_powers = integral_powers orders_1_and_2 = scattering(x) order_0 = order_0.cpu().numpy().reshape((batch_size, -1)) start = 0 end = order_0.shape[1] order_0_ref = scattering_ref[:, start:end].cpu().numpy() orders_1_and_2 = orders_1_and_2.cpu().numpy().reshape((batch_size, -1)) start = end end += orders_1_and_2.shape[1] orders_1_and_2_ref = scattering_ref[:, start:end].cpu().numpy() order_0_diff_cpu = relative_difference(order_0_ref, order_0) orders_1_and_2_diff_cpu = relative_difference(orders_1_and_2_ref, orders_1_and_2) assert order_0_diff_cpu < 1e-6, "CPU : order 0 do not match, diff={}".format( order_0_diff_cpu) assert orders_1_and_2_diff_cpu < 1e-6, "CPU : orders 1 and 2 do not match, diff={}".format( orders_1_and_2_diff_cpu)
def setup(self, sc_params, batch_size): scattering = HarmonicScattering3D(**sc_params) scattering.cpu() x = torch.randn( batch_size, sc_params["shape"][0], sc_params["shape"][1], sc_params["shape"][2], dtype=torch.float32) x.cpu() self.scattering = scattering self.x = x
def test_against_standard_computations(backend): file_path = os.path.abspath(os.path.dirname(__file__)) with open(os.path.join(file_path, 'test_data_3d.npz'), 'rb') as f: buffer = io.BytesIO(f.read()) data = np.load(buffer) x = data['x'] scattering_ref = data['Sx'] J = data['J'] L = data['L'] integral_powers = data['integral_powers'] M = x.shape[1] batch_size = x.shape[0] N, O = M, M sigma = 1 scattering = HarmonicScattering3D(J=J, shape=(M, N, O), L=L, sigma_0=sigma, method='integral', integral_powers=integral_powers, max_order=2, backend=backend, frontend='numpy') order_0 = backend.compute_integrals(x, integral_powers) scattering.max_order = 2 scattering.method = 'integral' scattering.integral_powers = integral_powers orders_1_and_2 = scattering(x) order_0 = order_0.reshape((batch_size, -1)) start = 0 end = order_0.shape[1] order_0_ref = scattering_ref[:, start:end] orders_1_and_2 = orders_1_and_2.reshape((batch_size, -1)) start = end end += orders_1_and_2.shape[1] orders_1_and_2_ref = scattering_ref[:, start:end] order_0_diff_cpu = relative_difference(order_0_ref, order_0) print(orders_1_and_2_ref.shape) print(orders_1_and_2.shape) orders_1_and_2_diff_cpu = relative_difference(orders_1_and_2_ref, orders_1_and_2) assert order_0_diff_cpu < 1e-6, "CPU : order 0 do not match, diff={}".format( order_0_diff_cpu) assert orders_1_and_2_diff_cpu < 1e-6, "CPU : orders 1 and 2 do not match, diff={}".format( orders_1_and_2_diff_cpu)
def test_larger_scales(): shape = (32, 32, 32) L = 3 sigma_0 = 1 x = torch.randn((1,) + shape) for J in range(3, 4+1): scattering = HarmonicScattering3D(J=J, shape=shape, L=L, sigma_0=sigma_0) if not 'cpu' in devices: x = x.cuda() scattering.cuda() scattering.method = 'integral' Sx = scattering(x)
def test_larger_scales(device, backend): if backend.name.endswith('_skcuda') and device == "cpu": pytest.skip("The skcuda backend does not support CPU tensors.") shape = (32, 32, 32) L = 3 sigma_0 = 1 x = torch.randn((1, ) + shape).to(device) for J in range(3, 4 + 1): scattering = HarmonicScattering3D(J=J, shape=shape, L=L, sigma_0=sigma_0, frontend='torch', backend=backend).to(device) scattering.method = 'integral' Sx = scattering(x)
def test_solid_harmonic_scattering(device, backend): if backend.name.endswith('_skcuda') and device == "cpu": pytest.skip("The skcuda backend does not support CPU tensors.") # Compare value to analytical formula in the case of a single Gaussian centers = np.zeros((1, 1, 3)) weights = np.ones((1, 1)) sigma_gaussian = 3. sigma_0_wavelet = 3. M, N, O, J, L = 128, 128, 128, 1, 3 grid = np.mgrid[-M // 2:-M // 2 + M, -N // 2:-N // 2 + N, -O // 2:-O // 2 + O] grid = grid.astype('float32') grid = np.fft.ifftshift(grid, axes=(1, 2, 3)) x = torch.from_numpy( generate_weighted_sum_of_gaussians(grid, centers, weights, sigma_gaussian)).to(device).float() scattering = HarmonicScattering3D(J=J, shape=(M, N, O), L=L, sigma_0=sigma_0_wavelet, max_order=1, method='integral', integral_powers=[1], frontend='torch', backend=backend).to(device) scattering.max_order = 1 scattering.method = 'integral' scattering.integral_powers = [1] s = scattering(x) for j in range(J + 1): sigma_wavelet = sigma_0_wavelet * 2**j k = sigma_wavelet / np.sqrt(sigma_wavelet**2 + sigma_gaussian**2) for l in range(1, L + 1): err = torch.abs(s[0, j, l, 0] - k**l).sum() / (1e-6 + s[0, j, l, 0].abs().sum()) assert err < 1e-4
def test_scattering_batch_shape_agnostic(device, backend): if backend.name.endswith('_skcuda') and device == "cpu": pytest.skip("The skcuda backend does not support CPU tensors.") J = 2 shape = (16, 16, 16) S = HarmonicScattering3D(J=J, shape=shape) for k in range(3): with pytest.raises(RuntimeError) as ve: S(torch.zeros(shape[:k])) assert 'at least three' in ve.value.args[0] x = torch.zeros(shape) x = x.to(device) S.to(device) Sx = S(x) assert len(Sx.shape) == 3 coeffs_shape = Sx.shape[-3:] test_shapes = ((1, ) + shape, (2, ) + shape, (2, 2) + shape, (2, 2, 2) + shape) for test_shape in test_shapes: x = torch.zeros(test_shape) x = x.to(device) Sx = S(x) assert len(Sx.shape) == len(test_shape) assert Sx.shape[-3:] == coeffs_shape assert Sx.shape[:-3] == test_shape[:-3]
def test_cpu_cuda(): shape = (32, 32, 32) J = 4 L = 3 sigma_0 = 1 x = torch.randn((1,) + shape) S = HarmonicScattering3D(J=J, shape=shape, L=L, sigma_0=sigma_0) assert not S.is_cuda if 'cpu' in devices: Sx = S(x) if 'gpu' in devices: x_gpu = x.cuda() with pytest.raises(TypeError) as record: Sx_gpu = S(x_gpu) assert "is in CPU mode" in record.value.args[0] S.cuda() assert S.is_cuda Sx_gpu = S(x_gpu) assert Sx_gpu.is_cuda with pytest.raises(TypeError) as record: Sx = S(x) assert "is in GPU mode" in record.value.args[0] S.cpu() assert not S.is_cuda
hist[4][1].pop('_metrics') trsfm_hist, seeds_hist = tio.compose_from_history(history=hist) trsfm_hist[0].get_inverse = True colin_back = trsfm_hist[0](transformed, seed=seeds_hist[0]) data = ssynth.t1.data data_shape = data.shape[1:] M, N, O = 128, 128, 128 J = 2 L = 2 integral_powers = [1., 2.] sigma_0 = 1 scattering = HarmonicScattering3D(J, shape=data_shape, L=L, sigma_0=sigma_0) scattering.method = 'integral' scattering.integral_powers = integral_powers s=time.time() res = scattering(data) s=time.time()-s ldata = ssynth.label.data ind = ldata>0.5 #ldata[ind]=1;ldata[~ind]=0 data = ssynth.t1.data meanlab = [data[li].mean() for li in ind] stdlab = [data[li].std() for li in ind] data = ssynth.t1.data[0] datas = smot.t1.data[0]
def time_constructor(self, sc_params, batch_size): HarmonicScattering3D(**sc_params)
def _grad_ratio(input, target, do_scat=False, do_nmi=True, do_entropy=True, do_autocorr=True, do_histo=True, mask_keys=None): #print(f' i shape {input.shape}') #not sure how to handel batch size (first dim) TODO input = input[0] target = target[0] grad_i = np.gradient(input) grad_t = np.gradient(target) grad_sum_i = np.zeros_like(grad_i[0]) for gg in grad_i: grad_sum_i += np.abs(gg) grad_sum_t = np.zeros_like(grad_t[0]) for gg in grad_t: grad_sum_t += np.abs(gg) #grad_sum_i = np.sum([np.sum(np.abs(gg)) for gg in grad_i]) #grad_sum_t = np.sum([np.sum(np.abs(gg)) for gg in grad_t]) grad_mean_i = np.mean(grad_sum_i) grad_mean_t = np.mean(grad_sum_t) #mean only on edge ... (like AES metric) grad_mean_edge_i = np.mean(grad_sum_i[grad_sum_i > 0.01]) grad_mean_edge_t = np.mean(grad_sum_t[grad_sum_t > 0.01]) res_dict = dict() res_dict['ratio'] = grad_mean_i / grad_mean_t res_dict['ratio_bin'] = grad_mean_edge_i / grad_mean_edge_t #print(f'do_scat is {do_scat}') if do_scat: #print('DO SCATTERING') from kymatio import HarmonicScattering3D import time data = dd = torch.stack([input, target]) data_shape = data.shape[1:] print(data_shape) J = 2 L = 2 integral_powers = [1., 2.] sigma_0 = 1 scattering = HarmonicScattering3D(J, shape=data_shape, L=L, sigma_0=sigma_0) scattering.method = 'integral' scattering.integral_powers = integral_powers s = time.time() res = scattering(data) s = time.time() - s print(f'scat in {s}') res_dict['scat'] = torch.norm(res[0] - res[1]) if do_nmi: res_dict['nMI1'] = nmi(input.numpy(), target.numpy()) res_dict['nMI2'] = mutual_information_2d(input.numpy(), target.numpy()) if do_entropy: res_dict['Eorig'] = _entropy(input.numpy()) res_dict['Emot'] = _entropy(target.numpy()) # res_dict['Emot2'] = nmi(target.numpy(), target.numpy()) #faudrait une version non normalise ... res_dict['Eratio'] = res_dict['Eorig'] / res_dict['Emot'] entro_grad1 = np.sum([_entropy(gg) for gg in grad_i]) entro_grad2 = np.sum([_entropy(gg) for gg in grad_t]) res_dict['EGorig'] = entro_grad1 res_dict['EGratio'] = entro_grad1 / entro_grad2 if do_autocorr: c1, c2, c3, cdiff = _get_autocor(input, nb_off_center=3) c1m, c2m, c3m, cdiffm = _get_autocor(target, nb_off_center=3) res_dict['cor1_ratio'] = c1 / c1m res_dict['cor2_ratio'] = c2 / c2m res_dict['cor3_ratio'] = c3 / c3m res_dict['cor_diff_ratio'] = cdiffm / cdiff res_dict['cor1_orig'] = c1 res_dict['cor2_orig'] = c2 res_dict['cor3_orig'] = c3 res_dict['cor_diff_orig'] = cdiff if do_histo: histo_metric = get_histogram_metrics(input, target, mask_keys=mask_keys) #print(f"histo is {histo_metric}") res_dict = dict(res_dict, **histo_metric) return res_dict
# restore training set import numpy as np temp = np.load('../Zeldovich_Approximation.npz') sim_z0 = temp["sim_z0"] sim_z50 = temp["sim_z50"] #------------------------------------------------------------------------------------- # import packages from kymatio import HarmonicScattering3D # make scattering coefficients J_choice = 6 L_choice = 5 max_order_choice = 2 scattering = HarmonicScattering3D(J=J_choice, shape=(64,64,64),\ L=L_choice, max_order=max_order_choice) scattering.cuda() import torch x_image = torch.from_numpy(sim_z0).type(torch.cuda.FloatTensor) scatter_coeff = scattering(x_image).view(x_image.shape[0], -1).cpu().detach().numpy() print(scatter_coeff.shape) # save results np.save("scatter_coeff_3D_max_order=" + str(max_order_choice) + ".npy", scatter_coeff)
def test_against_standard_computations(): file_path = os.path.abspath(os.path.dirname(__file__)) data = torch.load(os.path.join(file_path, 'test_data_3d.pt')) x = data['x'] scattering_ref = data['Sx'] J = data['J'] L = data['L'] integral_powers = data['integral_powers'] M = x.shape[1] batch_size = x.shape[0] N, O = M, M sigma = 1 scattering = HarmonicScattering3D(J=J, shape=(M, N, O), L=L, sigma_0=sigma) for device in devices: if device == 'cpu': x = x.cpu() scattering.cpu() else: x = x.cuda() scattering.cuda() order_0 = compute_integrals(x, integral_powers) scattering.max_order = 2 scattering.method = 'integral' scattering.integral_powers = integral_powers orders_1_and_2 = scattering(x) # WARNING: These are hard-coded values for the setting J = 2. n_order_1 = 3 n_order_2 = 3 # Extract orders and make order axis the slowest in accordance with # the stored reference scattering transform. order_1 = orders_1_and_2[:,0:n_order_1,...] order_2 = orders_1_and_2[:,n_order_1:n_order_1+n_order_2,...] # Permute the axes since reference has (batch index, integral power, j, # ell) while the computed transform has (batch index, j, ell, integral # power). order_1 = order_1.permute(0, 3, 1, 2) order_2 = order_2.permute(0, 3, 1, 2) order_1 = order_1.reshape((batch_size, -1)) order_2 = order_2.reshape((batch_size, -1)) orders_1_and_2 = torch.cat((order_1, order_2), 1) order_0 = order_0.cpu().numpy().reshape((batch_size, -1)) start = 0 end = order_0.shape[1] order_0_ref = scattering_ref[:,start:end].numpy() orders_1_and_2 = orders_1_and_2.cpu().numpy().reshape((batch_size, -1)) start = end end += orders_1_and_2.shape[1] orders_1_and_2_ref = scattering_ref[:, start:end].numpy() order_0_diff_cpu = relative_difference(order_0_ref, order_0) orders_1_and_2_diff_cpu = relative_difference( orders_1_and_2_ref, orders_1_and_2) assert order_0_diff_cpu < 1e-6, "CPU : order 0 do not match, diff={}".format(order_0_diff_cpu) assert orders_1_and_2_diff_cpu < 1e-6, "CPU : orders 1 and 2 do not match, diff={}".format(orders_1_and_2_diff_cpu)
# backend. if backend.NAME == 'torch': devices = ['cpu', 'gpu'] elif backend.NAME == 'skcuda': devices = ['gpu'] ############################################################################### # Set up the scattering object and the test data # ---------------------------------------------- ############################################################################### # Create the `HarmonicScattering3D` object using the given parameters and generate # some compatible test data with the specified batch size. scattering = HarmonicScattering3D(J, shape=(M, N, O), L=L, sigma_0=sigma_0) x = torch.randn(batch_size, M, N, O, dtype=torch.float32) ############################################################################### # Run the benchmark # ----------------- # For each device, we need to convert the Tensor `x` to the appropriate type, # invoke `times` calls to `scattering.forward` and print the running times. # Before the timer starts, we add an extra `scattering.forward` call to ensure # any first-time overhead, such as memory allocation and CUDA kernel # compilation, is not counted. If the benchmark is running on the GPU, we also # need to call `torch.cuda.synchronize()` before and after the benchmark to # make sure that all CUDA kernels have finished executing. for device in devices: