|
| 1 | +import time |
| 2 | +import torch |
| 3 | +from numpy import linspace as linspace |
| 4 | +import numpy.linalg as la |
| 5 | +import numpy as np |
| 6 | +from scipy.io import loadmat |
| 7 | +import LaFA.utils.file_name_gens as file_name_gens |
| 8 | +import pandas as pd |
| 9 | +import pickle |
| 10 | +import tqdm |
| 11 | +import os |
| 12 | +import glob |
| 13 | + |
| 14 | +# from grad_attacks_dev import * |
| 15 | +from LaFA.utils.grad_attacks import * |
| 16 | + |
| 17 | +if torch.cuda.is_available(): |
| 18 | + device=torch.device('cuda:0') |
| 19 | +else: |
| 20 | + device=torch.device('cpu') |
| 21 | + |
| 22 | +def read_pgm(pgmf): |
| 23 | + """Return a raster of integers from a PGM as a list of lists.""" |
| 24 | + header = pgmf.readline() |
| 25 | + header1 = pgmf.readline() |
| 26 | + header2 = pgmf.readline() |
| 27 | + assert header[:2] == b'P5' |
| 28 | + (width, height) = [int(i) for i in header1.split()[:2]] |
| 29 | + depth = int(header2) |
| 30 | + assert depth <= 65535 |
| 31 | + |
| 32 | + raster = [] |
| 33 | + for y in range(height): |
| 34 | + row = [] |
| 35 | + for y in range(width): |
| 36 | + row.append(ord(pgmf.read(1))) |
| 37 | + raster.append(row) |
| 38 | + return raster |
| 39 | + |
| 40 | +def experiment(args): |
| 41 | + print(args) |
| 42 | + print("FACE experiment") |
| 43 | + log_file = file_name_gens.log_name_gen(args) |
| 44 | + print("Log is saved to: ", log_file) |
| 45 | + if os.path.isfile(log_file): |
| 46 | + log = pd.read_pickle(log_file) |
| 47 | + else: |
| 48 | + log = pd.DataFrame() |
| 49 | + |
| 50 | + print("Load data") |
| 51 | + allFace = [] |
| 52 | + for curF in glob.glob('data/face/*.pgm'): |
| 53 | + file = open(curF, 'rb') |
| 54 | + im = np.array(read_pgm(file)) |
| 55 | + file.close() |
| 56 | + allFace.append(im.flatten()) |
| 57 | + allFace = np.array(allFace) |
| 58 | + X = allFace.astype(np.float32) |
| 59 | + X = X/np.max(X) |
| 60 | + |
| 61 | + XorigT = Tcons(X,device).float() |
| 62 | + print("-------------------------") |
| 63 | + print("* DATA STATS *") |
| 64 | + print("Min: ", torch.min(XorigT).cpu().detach().numpy()) |
| 65 | + print("Max: ", torch.max(XorigT).cpu().detach().numpy()) |
| 66 | + print("Shape: ", XorigT.shape) |
| 67 | + print("Data type: ", XorigT.dtype) |
| 68 | + print("-------------------------") |
| 69 | + |
| 70 | + np.random.seed(seed=args.seed) |
| 71 | + Winit = np.random.rand(X.shape[0],args.rank) |
| 72 | + Hinit = np.random.rand(args.rank,X.shape[1]) |
| 73 | + Winit = torch.Tensor(Winit) |
| 74 | + Hinit = torch.Tensor(Hinit) |
| 75 | + WinitT = Tcons(Winit,device).float() |
| 76 | + HinitT = Tcons(Hinit,device).float() |
| 77 | + |
| 78 | + Wstay,Hstay = NMFiter_KL(XorigT,args.base_iter,WinitT,HinitT) |
| 79 | + |
| 80 | + # Test stationary condition of base: |
| 81 | + Wnext,Hnext = NMFiter_KL(XorigT,100,Wstay,Hstay) |
| 82 | + X0 = Wstay@Hstay |
| 83 | + Xnext = Wnext@Hnext |
| 84 | + print("-------------------------") |
| 85 | + print("* SETUP STATIONARY BASE STATE *") |
| 86 | + print("Reconstruction error Linf: ", torch.max(torch.abs(X0-XorigT)).cpu().detach().numpy()) |
| 87 | + print("Reconstruction error L2: ", (torch.norm(X0-XorigT)/torch.norm(XorigT)).cpu().detach().numpy()) |
| 88 | + print("Recon base error: ", torch.max(torch.abs(X0-Xnext)).cpu().detach().numpy()) |
| 89 | + print("W stationary error: ", torch.max(torch.abs(Wstay-Wnext)).cpu().detach().numpy()) |
| 90 | + print("H stationary error: ", torch.max(torch.abs(Hstay-Hnext)).cpu().detach().numpy()) |
| 91 | + print("-------------------------") |
| 92 | + |
| 93 | + print("Generate attacker") |
| 94 | + |
| 95 | + min_eps = args.eps_min |
| 96 | + no_eps = args.no_eps |
| 97 | + max_eps = args.eps_max |
| 98 | + norm = args.norm |
| 99 | + eps_range = max_eps - min_eps |
| 100 | + nmf_rank = args.rank |
| 101 | + nmf_iter = args.nmf_iter |
| 102 | + |
| 103 | + attacker = Gradient_based_attack(XorigT, |
| 104 | + nmf_rank = nmf_rank, |
| 105 | + base_nmf_iters = nmf_iter, |
| 106 | + use_cuda = True, |
| 107 | + implicit_func = args.implicit, |
| 108 | + taylor = args.taylor, |
| 109 | + norm = norm, |
| 110 | + rec_loss = args.recloss, |
| 111 | + verbose = True) |
| 112 | + |
| 113 | + for step in tqdm.tqdm(range(no_eps)): |
| 114 | + |
| 115 | + eps = step/no_eps * (eps_range) + min_eps |
| 116 | + print("Generate attack for eps = ", eps) |
| 117 | + |
| 118 | + # Attack |
| 119 | + start_time = time.time() |
| 120 | + torch.cuda.reset_peak_memory_stats() |
| 121 | + start_mem_allocated = torch.cuda.memory_stats()['active_bytes.all.peak'] |
| 122 | + Xperturb = attacker.pgd_attack(eps=eps, alpha=args.alpha, iters= args.no_iter, record = False, average_grad = args.average) |
| 123 | + end_mem_allocated = torch.cuda.memory_stats()['active_bytes.all.peak'] |
| 124 | + duration = time.time()-start_time |
| 125 | + memory = end_mem_allocated |
| 126 | + memory_Mb_ifunc = memory/1000000 |
| 127 | + |
| 128 | + # Stats |
| 129 | + in_X_dist = (torch.norm(Xperturb - XorigT)/torch.norm(XorigT)).cpu().detach().numpy() |
| 130 | + Wp,Hp = NMFiter_KL(Xperturb,10000,WinitT,HinitT) |
| 131 | + out_X_dist = (torch.norm(Wp@Hp - XorigT)/torch.norm(XorigT)).cpu().detach().numpy() |
| 132 | + out_FE_dist = loss_wh(Wstay,Wp,Hstay,Hp).cpu().detach().numpy() |
| 133 | + Hstay = Hstay + 1e-10 |
| 134 | + Hp = Hp + 1e-10 |
| 135 | + Wstay = Wstay + 1e-10 |
| 136 | + Wp = Wp + 1e-10 |
| 137 | + out_W_dist = loss_w(Wstay,Wp).cpu().detach().numpy() |
| 138 | + out_H_dist = loss_w(Hstay,Hp).cpu().detach().numpy() |
| 139 | + |
| 140 | + # Log |
| 141 | + print("Input distortion: ", in_X_dist) |
| 142 | + print("FE distortion: ", out_FE_dist) |
| 143 | + print("W distortion: ", out_W_dist) |
| 144 | + print("H distortion: ", out_H_dist) |
| 145 | + print("Duration (sec): ", duration) |
| 146 | + print("Memory (Mb): ", memory_Mb_ifunc) |
| 147 | + print("----") |
| 148 | + |
| 149 | + result = { |
| 150 | + 'eps': eps, |
| 151 | + 'alpha': args.alpha, |
| 152 | + 'pgd iters': args.no_iter, |
| 153 | + 'in': in_X_dist, |
| 154 | + 'out rec': out_X_dist, |
| 155 | + 'out fe': out_FE_dist, |
| 156 | + 'out W': out_W_dist, |
| 157 | + 'out H': out_H_dist, |
| 158 | + 'duration': duration, |
| 159 | + 'memory': memory, |
| 160 | + 'Implicit gradient': args.implicit, |
| 161 | + 'norm': args.norm, |
| 162 | + 'NMF iters': args.nmf_iter, |
| 163 | + 'Seed': args.seed |
| 164 | + } |
| 165 | + log = pd.concat([log, pd.DataFrame.from_records([result])]) |
| 166 | + with open(log_file, 'wb') as logfile: |
| 167 | + pickle.dump(log, logfile) |
| 168 | + |
| 169 | + Hp_np = Hp.cpu().detach().numpy() |
| 170 | + FEATURE_FILES = file_name_gens.feature_name_gen(args, eps = eps) |
| 171 | + with open(FEATURE_FILES, 'wb') as f: |
| 172 | + np.save(f, Hp_np) |
| 173 | + |
| 174 | + return |
| 175 | + |
| 176 | + |
| 177 | + |
0 commit comments