<jupyter_start><jupyter_text>Table of Contents 1&nbsp;&nbsp;Create the two ScatterNets2&nbsp;&nbsp;Stability to noise3&nbsp;&nbsp;Stability to Shifts4&nbsp;&nbsp;Stability to Deformations This notebook quantifies how stable the DTCWT and Morlet based scatternets are to noise, shifts, and deformation<jupyter_code>from kymatio import Scattering2D
import torch
from pytorch_wavelets import ScatLayer, ScatLayerj2
import numpy, elasticdeform
%matplotlib notebook
import matplotlib.pyplot as plt
import numpy as np
import dtcwt_gainlayer.data.tiny_imagenet as ti
trainloader, testloader = ti.get_data(64, data_dir='/scratch/share/Tiny_ImageNet/', val_only=True)
# Get some image data. Let us use some tiny_imagenet images
data = []
for i, x in enumerate(testloader):
    if i == 10:
        break
    data.append(x[0])
data = torch.cat(data, dim=0)
print(data.shape)
class Scat2D(torch.nn.Module):
    """ A wrapper around KyMatIO's ScatterNet"""
    def __init__(self):
        super().__init__()
        self.scat = Scattering2D(J=2, shape=(64, 64), L=6).cuda()
        
    def forward(self, x):
        x = self.scat(x)
        return x.view(x.shape[0], -1, x.shape[3], x.shape[4])<jupyter_output><empty_output><jupyter_text>Create the two ScatterNetsFor the DTCWT, we test over some of the options<jupyter_code>scat_morlet = Scat2D()
scatA = torch.nn.Sequential(ScatLayer(magbias=0.0, biort='near_sym_b', mode='symmetric'), ScatLayer(magbias=0.0, biort='near_sym_b', mode='symmetric')).cuda()
scatB = torch.nn.Sequential(ScatLayer(magbias=0.0, biort='near_sym_a', mode='zero'), ScatLayer(magbias=0.0, biort='near_sym_a', mode='zero')).cuda()
scatC = ScatLayerj2(biort='near_sym_b', qshift='qshift_b').cuda()
x = data
Sx = scat_morlet(x.cuda())
Dax = scatA(x.cuda())
Dbx = scatB(x.cuda())
Dcx = scatC(x.cuda())<jupyter_output><empty_output><jupyter_text>Stability to noise<jupyter_code>n = 0.7*torch.randn_like(x)
Sxn = scat_morlet((x+n).cuda())
Daxn = scatA((x+n).cuda())
Dbxn = scatB((x+n).cuda())
Dcxn = scatC((x+n).cuda())
print('For an additive noise with σ=0.7 ({:.0f}% the input energy), we have:'.format(100*(n**2).sum()/(x**2).sum()))
print("|x-x'|^2 is {:.3f}".format(torch.mean((n**2))))
print("|Sx-Sx'|^2 for Morlet Scat is {:.3f}".format(torch.mean((Sx-Sxn)**2)))
print("|Sx-Sx'|^2 for DTCWT Scat A is {:.3f}".format(torch.mean((Dax-Daxn)**2)))
print("|Sx-Sx'|^2 for DTCWT Scat B is {:.3f}".format(torch.mean((Dbx-Dbxn)**2)))
print("|Sx-Sx'|^2 for DTCWT Scat C is {:.3f}".format(torch.mean((Dcx-Dcxn)**2)))<jupyter_output>For an additive noise with σ=0.7 (38% the input energy), we have:
|x-x'|^2 is 0.490
|Sx-Sx'|^2 for Morlet Scat is 0.003
|Sx-Sx'|^2 for DTCWT Scat A is 0.030
|Sx-Sx'|^2 for DTCWT Scat B is 0.029
|Sx-Sx'|^2 for DTCWT Scat C is 0.046<jupyter_text>Stability to Shifts<jupyter_code>y = torch.roll(x, (2, 2), dims=(2,3))
Sy = scat_morlet(y.cuda())
Day = scatA(y.cuda())
Dby = scatB(y.cuda())
Dcy = scatC(y.cuda())
print('For a shift of 2 pixels right and 2 down, we have:')
print("|x-x'|^2 is {:.3f}".format(torch.mean((y-x)**2)))
print("|Sx-Sx'|^2 for Morlet Scat is {:.3f}".format(torch.mean((Sx-Sy)**2)))
print("|Sx-Sx'|^2 for DTCWT Scat A is {:.3f}".format(torch.mean((Dax-Day)**2)))
print("|Sx-Sx'|^2 for DTCWT Scat B is {:.3f}".format(torch.mean((Dbx-Dby)**2)))
print("|Sx-Sx'|^2 for DTCWT Scat C is {:.3f}".format(torch.mean((Dcx-Dcy)**2)))<jupyter_output>For a shift of 2 pixels right and 2 down, we have:
|x-x'|^2 is 0.740
|Sx-Sx'|^2 for Morlet Scat is 0.004
|Sx-Sx'|^2 for DTCWT Scat A is 0.009
|Sx-Sx'|^2 for DTCWT Scat B is 0.009
|Sx-Sx'|^2 for DTCWT Scat C is 0.030<jupyter_text>Stability to Deformations<jupyter_code>σ = 3
z = torch.tensor(elasticdeform.deform_random_grid(x.numpy(), sigma=σ, axis=(2,3)))
Sz = scat_morlet(z.cuda())
Daz = scatA(z.cuda())
Dbz = scatB(z.cuda())
Dcz = scatC(z.cuda())
print('For a random deformation with σ=5 we have:')
print("|x-x'|^2 is {:.3f}".format(torch.mean((z-x)**2)))
print("|Sx-Sx'|^2 for Morlet Scat is {:.3f}".format(torch.mean((Sz-Sx)[:, :, 2*σ:-2*σ]**2)))
print("|Sx-Sx'|^2 for DTCWT Scat A is {:.3f}".format(torch.mean((Daz-Dax)[:, :, 2*σ:-2*σ]**2)))
print("|Sx-Sx'|^2 for DTCWT Scat B is {:.3f}".format(torch.mean((Dbz-Dbx)[:, :, 2*σ:-2*σ]**2)))
print("|Sx-Sx'|^2 for DTCWT Scat C is {:.3f}".format(torch.mean((Dcz-Dcx)[:, :, 2*σ:-2*σ]**2)))
import plotters  # https://github.com/fbcotter/plotters
fig, ax = plt.subplots(2,2, gridspec_kw=dict(hspace=0.1, wspace=0.1, left=0., right=1, top=1,bottom=0), 
                       subplot_kw=dict(xticks=[], yticks=[]))
ax[0,0].imshow(plotters.normalize(x[0, :, 2*σ:-2*σ].numpy().transpose(1,2,0)))
ax[0,1].imshow(plotters.normalize(z[0, :, 2*σ:-2*σ].numpy().transpose(1,2,0)))
ax[1,0].imshow(plotters.normalize(x[1, :, 2*σ:-2*σ].numpy().transpose(1,2,0)))
ax[1,1].imshow(plotters.normalize(z[1, :, 2*σ:-2*σ].numpy().transpose(1,2,0)))<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.21444603142215873, 'fraction_numerical': 0.04182819832687207, 'mean_word_length': 5.544726301735648, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 19, 'https://': 1, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '5', 'dir': 'jupyter-structured-clean-dedup', 'id': '109757', 'license': 'MIT', 'n_tokens_mistral': 2285, 'n_tokens_neox': 2209, 'n_words': 421, 'path': 'tests/Measure of Stability.ipynb', 'repo_name': 'voletiv/pytorch_wavelets', 'size': '4901'}