def MIMNativePytorch(device, dataLoader, model, decayFactor, epsilonMax, epsilonStep, numSteps, clipMin, clipMax, targeted): model.eval() #Change model to evaluation mode for the attack #Generate variables for storing the adversarial examples numSamples = len( dataLoader.dataset) #Get the total number of samples to attack xShape = DMP.GetOutputShape( dataLoader ) #Get the shape of the input (there may be easier way to do this) xAdv = torch.zeros(numSamples, xShape[0], xShape[1], xShape[2]) yClean = torch.zeros(numSamples) advSampleIndex = 0 batchSize = 0 #just do dummy initalization, will be filled in later loss = torch.nn.CrossEntropyLoss() tracker = 0 #Go through each sample for xData, yData in dataLoader: batchSize = xData.shape[ 0] #Get the batch size so we know indexing for saving later tracker = tracker + batchSize print("Processing up to sample=", tracker) #Put the data from the batch onto the device xAdvCurrent = xData.to(device) yCurrent = yData.type(torch.LongTensor).to(device) # Set requires_grad attribute of tensor. Important for attack. (Pytorch comment, not mine) #Initalize memory for the gradient momentum gMomentum = torch.zeros(batchSize, xShape[0], xShape[1], xShape[2]) #Do the attack for a number of steps for attackStep in range(0, numSteps): xAdvCurrent.requires_grad = True outputs = model(xAdvCurrent) model.zero_grad() cost = loss(outputs, yCurrent).to(device) cost.backward() #Update momentum term gMomentum = decayFactor * gMomentum + GradientNormalizedByL1( xAdvCurrent.grad) #Update the adversarial sample if targeted == True: advTemp = xAdvCurrent - (epsilonStep * torch.sign(gMomentum)).to(device) else: advTemp = xAdvCurrent + (epsilonStep * torch.sign(gMomentum)).to(device) #Adding clipping to maintain the range xAdvCurrent = torch.clamp(advTemp, min=clipMin, max=clipMax).detach_() #Save the adversarial images from the batch for j in range(0, batchSize): xAdv[advSampleIndex] = xAdvCurrent[j] yClean[advSampleIndex] = yData[j] advSampleIndex = advSampleIndex + 1 #increment the sample index #All samples processed, now time to save in a dataloader and return advLoader = DMP.TensorToDataLoader( xAdv, yClean, transforms=None, batchSize=dataLoader.batch_size, randomizer=None) #use the same batch size as the original loader return advLoader
def predictD(self, dataLoader, numClasses): #Basic variable setup numSamples = len(dataLoader.dataset) xTest, yTest = DMP.DataLoaderToTensor(dataLoader) #Randomly select which samples are predicted by which model sampleAssignments = numpy.random.randint(0, self.numModels, (numSamples, )) #memory for the solution yPred = torch.zeros(numSamples, numClasses) #Go through the models, get the sample subset they need to predict on, then do the prediction for modelIndex in range(0, self.numModels): currentModelPlus = self.modelPlusList[modelIndex] #Filter the data to get the samples only the currrent model should predict on dataLoaderSubset = self.filterSamplesIntoDataLoader( modelIndex, sampleAssignments, xTest, yTest, currentModelPlus.batchSize) #Get the array of correct predictions yPredCurrent = currentModelPlus.predictD(dataLoaderSubset, numClasses) currentIndex = 0 #Go through every sample for i in range(0, numSamples): #Check if the current sample was predicted using the current model if sampleAssignments[i] == modelIndex: yPred[i] = yPredCurrent[currentIndex] currentIndex = currentIndex + 1 return yPred
def filterSamplesIntoDataLoader(self, modelIndex, sampleAssignments, xTest, yTest, batchSize): numSamples = xTest.shape[0] count = 0 #First determine how many samples the model needs to evaluate for i in range(0, numSamples): if sampleAssignments[i] == modelIndex: count = count + 1 #We now know how many samples we need to evalute on, time to save them xSubset = torch.zeros( (count, xTest.shape[1], xTest.shape[2], xTest.shape[3])) ySubset = torch.zeros((count)) #Go through and get the samples currentIndex = 0 for i in range(0, numSamples): if sampleAssignments[i] == modelIndex: xSubset[currentIndex] = xTest[i] ySubset[currentIndex] = yTest[i] currentIndex = currentIndex + 1 #Do some basic error checkings if currentIndex != count: raise ValueError( "Something went wrong in the indexing, expected count did not match actual count." ) #Put the data into a dataloader and return dataLoaderSubset = DMP.TensorToDataLoader(xSubset, ySubset, transforms=None, batchSize=batchSize, randomizer=None) return dataLoaderSubset
def SelfAttentionGradientAttack(device, epsMax, numSteps, modelListPlus, coefficientArray, dataLoader, clipMin, clipMax): #Basic graident variable setup xClean, yClean = DMP.DataLoaderToTensor(dataLoader) xAdv = xClean #Set the initial adversarial samples numSamples = len( dataLoader.dataset) #Get the total number of samples to attack xShape = DMP.GetOutputShape( dataLoader ) #Get the shape of the input (there may be easier way to do this) #Compute eps step epsStep = epsMax / numSteps dataLoaderCurrent = dataLoader for i in range(0, numSteps): print("Running Step=", i) xGradientCumulative = torch.zeros(numSamples, xShape[0], xShape[1], xShape[2]) for m in range(0, len(modelListPlus)): currentModelPlus = modelListPlus[m] #First get the gradient from the model xGradientCurrent = FGSMNativeGradient(device, dataLoaderCurrent, currentModelPlus) #Resize the graident to be the correct size xGradientCurrent = torch.nn.functional.interpolate( xGradientCurrent, size=(xShape[1], xShape[2])) #Add the current computed gradient to the result if currentModelPlus.modelName.find("ViT") >= 0: attmap = GetAttention(dataLoaderCurrent, currentModelPlus) xGradientCumulative = xGradientCumulative + coefficientArray[ m] * xGradientCurrent * attmap else: xGradientCumulative = xGradientCumulative + coefficientArray[ m] * xGradientCurrent #Compute the sign of the graident and create the adversarial example xAdv = xAdv + epsStep * xGradientCumulative.sign() #Do the clipping xAdv = torch.clamp(xAdv, clipMin, clipMax) #Convert the result to dataloader dataLoaderCurrent = DMP.TensorToDataLoader( xAdv, yClean, transforms=None, batchSize=dataLoader.batch_size, randomizer=None) return dataLoaderCurrent
def AdaptiveAttackShuffleDefense(): #Corresponding tag for saving files #First part indicates the type of defense, second part indidcates the synthetic model and last part indicates the strenght of the attack (100%) saveTag = "ViT-L-16, ViT-32(ImageNet21K), p100" device = torch.device("cuda") #Attack parameters numAttackSamples = 1000 epsForAttacks = 0.031 clipMin = 0.0 clipMax = 1.0 #Parameters of training the synthetic model imgSize = 224 batchSize = 32 numClasses = 10 numIterations = 4 epochsPerIteration = 10 epsForAug = 0.1 #when generating synthetic data, this value is eps for FGSM used to generate synthetic data learningRate = (3e-2) / 2 #Learning rate of the synthetic model #Load the training dataset, validation dataset and the defense valLoader, defense = LoadShuffleDefenseAndCIFAR10() trainLoader = DMP.GetCIFAR10Training(imgSize, batchSize) #Get the clean data xTest, yTest = DMP.DataLoaderToTensor(valLoader) cleanLoader = DMP.GetCorrectlyIdentifiedSamplesBalancedDefense( defense, numAttackSamples, valLoader, numClasses) #Create the synthetic model syntheticDir = "Models//imagenet21k_ViT-B_32.npz" config = CONFIGS["ViT-B_32"] syntheticModel = VisionTransformer(config, imgSize, zero_head=True, num_classes=numClasses) syntheticModel.load_from(numpy.load(syntheticDir)) syntheticModel.to(device) #Do the attack oracle = defense dataLoaderForTraining = trainLoader optimizerName = "sgd" #Last line does the attack AttackWrappersAdaptiveBlackBox.AdaptiveAttack( saveTag, device, oracle, syntheticModel, numIterations, epochsPerIteration, epsForAug, learningRate, optimizerName, dataLoaderForTraining, cleanLoader, numClasses, epsForAttacks, clipMin, clipMax)
def LoadShuffleDefenseAndCIFAR10(vis=False): modelPlusList = [] #Basic variable and data setup device = torch.device("cuda") numClasses = 10 imgSize = 224 batchSize = 8 #Load the CIFAR-10 data valLoader = DMP.GetCIFAR10Validation(imgSize, batchSize) #Load ViT-L-16 config = CONFIGS["ViT-L_16"] model = VisionTransformer(config, imgSize, zero_head=True, num_classes=numClasses, vis=vis) dir = "Models/ViT-L_16,cifar10,run0_15K_checkpoint.bin" dict = torch.load(dir) model.load_state_dict(dict) model.eval() #Wrap the model in the ModelPlus class modelPlusV = ModelPlus("ViT-L_16", model, device, imgSizeH=imgSize, imgSizeW=imgSize, batchSize=batchSize) modelPlusList.append(modelPlusV) #Load the BiT-M-R101x3 dirB = "Models/BiT-M-R101x3-Run0.tar" modelB = BigTransferModels.KNOWN_MODELS["BiT-M-R101x3"]( head_size=numClasses, zero_head=False) #Get the checkpoint checkpoint = torch.load(dirB, map_location="cpu") #Remove module so that it will load properly new_state_dict = OrderedDict() for k, v in checkpoint["model"].items(): name = k[7:] # remove `module.` new_state_dict[name] = v #Load the dictionary modelB.load_state_dict(new_state_dict) modelB.eval() #Wrap the model in the ModelPlus class #Here we hard code the Big Transfer Model Plus class input size to 160x128 (what it was trained on) modelBig101Plus = ModelPlus("BiT-M-R101x3", modelB, device, imgSizeH=160, imgSizeW=128, batchSize=batchSize) modelPlusList.append(modelBig101Plus) #Now time to build the defense defense = ShuffleDefense.ShuffleDefense(modelPlusList, numClasses) return valLoader, defense
def predictD(self, dataLoader, numClasses): #Put the images in the right size if they are not already dataLoaderFinal = self.formatDataLoader(dataLoader) #Make a copy of the model and put it on the GPU currentModel = self.model currentModel.to(self.device) #Get the accuracy yPred = DMP.predictD(dataLoaderFinal, numClasses, currentModel) #Clean up the GPU memory del currentModel torch.cuda.empty_cache() return yPred
def validateDA(self, dataLoader): #Put the images in the right size if they are not already dataLoaderFinal = self.formatDataLoader(dataLoader) #Make a copy of the model and put it on the GPU currentModel = self.model currentModel.to(self.device) #Get the accuracy accArray = DMP.validateDA(dataLoaderFinal, currentModel, self.device) #Clean up the GPU memory del currentModel torch.cuda.empty_cache() return accArray
def formatDataLoader(self, dataLoader): sampleShape = DMP.GetOutputShape(dataLoader) #Check if we need to do resizing, if not just return the original loader if sampleShape[1] == self.imgSizeH and sampleShape[2] == self.imgSizeW: return dataLoader else: #We need to do resizing print("Resize required. Processing now.") p = torchvision.transforms.ToPILImage() t = torchvision.transforms.ToTensor() numSamples = len(dataLoader.dataset) sampleShape = DMP.GetOutputShape( dataLoader) #Get the output shape from the dataloader sampleIndex = 0 batchTracker = 0 xData = torch.zeros(numSamples, sampleShape[0], self.imgSizeH, self.imgSizeW) yData = torch.zeros(numSamples) #Go through and process the data in batches...kind of for i, (input, target) in enumerate(dataLoader): batchSize = input.shape[ 0] #Get the number of samples used in each batch #print("Resize processing up to=", batchTracker) batchTracker = batchTracker + batchSize #Save the samples from the batch in a separate tensor for batchIndex in range(0, batchSize): #Convert to pil image, resize, convert back to tensor xData[sampleIndex] = t( self.resizeTransform(p(input[batchIndex]))) yData[sampleIndex] = target[batchIndex] sampleIndex = sampleIndex + 1 #increment the sample index #All the data has been resized, time to put in the dataloader newDataLoader = DMP.TensorToDataLoader(xData, yData, transforms=None, batchSize=self.batchSize, randomizer=None) #Note we don't use the original batch size because the image may have become larger #i.e. to large to fit in GPU memory so we use the batch specified in the ModelPlus constructor return newDataLoader
def RaySAttack(model, epsMax, queryLimit, cleanLoader): xClean, yClean = DMP.DataLoaderToTensor(cleanLoader) rayS = RayS(model, epsilon=epsMax, order = np.inf) xAdv = torch.zeros((xClean.shape[0], xClean.shape[1], xClean.shape[2], xClean.shape[3])) #Go through and attack the samples for i in range(0, xClean.shape[0]): print(i) start = time.time() #yCurrent = torch.zeros((1,)) #yCurrent[0] = xAdvCurrent, stop_queries, dist, isLessDist = rayS.attack_hard_label(xClean[i].cuda(), yClean[i].cuda(), target=None, query_limit=queryLimit, seed=None) xAdvCurrent = xAdvCurrent.cpu().detach() dist = torch.dist(xAdvCurrent, xClean[i], np.inf) if dist>epsMax: print("Attack failed, returning clean sample instead.") xAdv[i] = xClean[i] else: xAdv[i] = xAdvCurrent end = time.time() print("Time Elapsed:", end-start) #Put solution in dataloader and return advLoader = DMP.TensorToDataLoader(xAdv, yClean, transforms = None, batchSize = cleanLoader.batch_size, randomizer = None) return advLoader
def FGSMNativeGradient(device, dataLoader, modelPlus): #Basic variable setup model = modelPlus.model model.eval() #Change model to evaluation mode for the attack model.to(device) sizeCorrectedLoader = modelPlus.formatDataLoader(dataLoader) #Generate variables for storing the adversarial examples numSamples = len(sizeCorrectedLoader.dataset ) #Get the total number of samples to attack xShape = DMP.GetOutputShape( sizeCorrectedLoader ) #Get the shape of the input (there may be easier way to do this) xGradient = torch.zeros(numSamples, xShape[0], xShape[1], xShape[2]) yClean = torch.zeros(numSamples) advSampleIndex = 0 batchSize = 0 #just do dummy initalization, will be filled in later #Go through each sample tracker = 0 for xData, yData in sizeCorrectedLoader: batchSize = xData.shape[ 0] #Get the batch size so we know indexing for saving later tracker = tracker + batchSize #print("Processing up to sample=", tracker) #Put the data from the batch onto the device xDataTemp = torch.from_numpy(xData.cpu().detach().numpy()).to(device) yData = yData.type(torch.LongTensor).to(device) # Set requires_grad attribute of tensor. Important for attack. (Pytorch comment, not mine) xDataTemp.requires_grad = True # Forward pass the data through the model output = model(xDataTemp) # Calculate the loss loss = torch.nn.CrossEntropyLoss() # Zero all existing gradients model.zero_grad() # Calculate gradients of model in backward pass cost = loss(output, yData).to(device) cost.backward() xDataTempGrad = xDataTemp.grad.data #Save the adversarial images from the batch for j in range(0, batchSize): xGradient[advSampleIndex] = xDataTempGrad[j] yClean[advSampleIndex] = yData[j] advSampleIndex = advSampleIndex + 1 #increment the sample index #Not sure if we need this but do some memory clean up del xDataTemp torch.cuda.empty_cache() #Memory management del model torch.cuda.empty_cache() return xGradient
def GetLoaderAtIndex(self, index): currentDataLoaderDir = self.homeDir + self.dataLoaderDirList[index] #First load the numpy arrays xData = numpy.load(currentDataLoaderDir + "XData.npy") yData = numpy.load(currentDataLoaderDir + "YData.npy") #Create a dataloader currentDataLoader = DMP.TensorToDataLoader(torch.from_numpy(xData), torch.from_numpy(yData), transforms=None, batchSize=self.batchSize, randomizer=None) #currentDataLoader = torch.load(currentDataLoaderDir) #Do some memory clean up del xData del yData return currentDataLoader
def AddLoader(self, dataLoaderName, dataLoader): #Torch limits the amount of data we can save to disk so we must use numpy to save #torch.save(dataLoader, self.homeDir+dataLoaderName) #First convert the tensor to a dataloader xDataPytorch, yDataPytorch = DMP.DataLoaderToTensor(dataLoader) #Second conver the pytorch arrays to numpy arrays for saving xDataNumpy = xDataPytorch.cpu().detach().numpy() yDataNumpy = yDataPytorch.cpu().detach().numpy() #Save the data using numpy numpy.save(self.homeDir + dataLoaderName + "XData", xDataNumpy) numpy.save(self.homeDir + dataLoaderName + "YData", yDataNumpy) #Save the file location string so we can re-load later self.dataLoaderDirList.append(dataLoaderName) #Delete the dataloader and associated variables from memory del dataLoader del xDataPytorch del yDataPytorch del xDataNumpy del yDataNumpy
def RaySAttackShuffleDefense(): #Load the model and dataset valLoader, defense = LoadShuffleDefenseAndCIFAR10() #Get the clean samples numClasses = 10 attackSampleNum = 1000 cleanLoader = DMP.GetCorrectlyIdentifiedSamplesBalancedDefense( defense, attackSampleNum, valLoader, numClasses) #Set the attack parameters epsMax = 0.031 queryLimit = 10000 #The next line does the actual attack on the defense advLoader = AttackWrappersRayS.RaySAttack(defense, epsMax, queryLimit, cleanLoader) #Check the results robustAcc = defense.validateD(advLoader) cleanAcc = defense.validateD(valLoader) #Print the results print("Queries used:", queryLimit) print("Robust acc:", robustAcc) print("Clean acc:", cleanAcc)
def validateD(self, dataLoader): #Basic variable setup numSamples = len(dataLoader.dataset) xTest, yTest = DMP.DataLoaderToTensor(dataLoader) #Randomly select which samples are predicted by which model sampleAssignments = numpy.random.randint(0, self.numModels, (numSamples, )) acc = 0 #Go through the models, get the sample subset they need to predict on, then do the prediction for modelIndex in range(0, self.numModels): currentModelPlus = self.modelPlusList[modelIndex] #Filter the data to get the samples only the currrent model should predict on dataLoaderSubset = self.filterSamplesIntoDataLoader( modelIndex, sampleAssignments, xTest, yTest, currentModelPlus.batchSize) #Get the array of correct predictions currentAccArray = currentModelPlus.validateDA(dataLoaderSubset) acc = acc + currentAccArray.sum() #We have all the correcly predicted samples, now compute the final accuracy acc = acc / float(numSamples) return acc
def LoadViTLAndCIFAR10(): class Arguments(): def __init__(self): self.cuda = "True" self.cnn = "E:\Projects\CPSC-597\AdversarialDetection\State\cifar10cnn.model" self.recon = "E:\Projects\CPSC-597\AdversarialDetection\State\cifar10recon.model" self.detect = "E:\Projects\CPSC-597\AdversarialDetection\State\cifar10detect.model" args = Arguments() metaCNN = MetaCNN(3, args) # metaCNN = ResNet18() # stateDict = torch.load( "E:\Projects\CPSC-597\AdversarialDetection\State\cifar10resnet.model" ) # metaCNN.load_state_dict( stateDict['model'] ) #Basic variable and data setup device = torch.device("cuda") numClasses = 10 imgSize = 32 batchSize = 128 #Load the CIFAR-10 data valLoader = DMP.GetCIFAR10Validation(imgSize, batchSize) #Load ViT-L-16 config = CONFIGS["ViT-L_16"] #model = VisionTransformer(config, imgSize, zero_head=True, num_classes=numClasses) #dir = "Models/ViT-L_16,cifar10,run0_15K_checkpoint.bin" #dict = torch.load(dir) #model.load_state_dict(dict) #model.eval() model = metaCNN #Wrap the model in the ModelPlus class modelPlus = ModelPlus("ViT-L_16", model, device, imgSizeH=imgSize, imgSizeW=imgSize, batchSize=batchSize) return valLoader, modelPlus
def GetFirstCorrectlyOverlappingSamplesBalanced(device, sampleNum, numClasses, dataLoader, modelPlusList): numModels = len(modelPlusList) totalSampleNum = len(dataLoader.dataset) #First check if modelA needs resize xTestOrig, yTestOrig = DMP.DataLoaderToTensor(dataLoader) #We need to resize first if modelPlusList[0].imgSizeH != xTestOrig.shape[2] or modelPlusList[ 0].imgSizeW != xTestOrig.shape[3]: xTestOrigResize = torch.zeros(xTestOrig.shape[0], 3, modelPlusList[0].imgSizeH, modelPlusList[0].imgSizeW) rs = torchvision.transforms.Resize( (modelPlusList[0].imgSizeH, modelPlusList[0].imgSizeW)) #resize the samples for model A #Go through every sample for i in range(0, xTestOrig.shape[0]): xTestOrigResize[i] = rs( xTestOrig[i]) #resize to match dimensions required by modelA #Make a new dataloader dataLoader = DMP.TensorToDataLoader(xTestOrigResize, yTestOrig, transforms=None, batchSize=dataLoader.batch_size, randomizer=None) #Get accuracy array for each model accArrayCumulative = torch.zeros( totalSampleNum ) #Create an array with one entry for ever sample in the dataset for i in range(0, numModels): accArray = modelPlusList[i].validateDA(dataLoader) accArrayCumulative = accArrayCumulative + accArray #Do some basic error checking if sampleNum % numClasses != 0: raise ValueError( "Number of samples not divisable by the number of classes") #Basic variable setup samplePerClassCount = torch.zeros( numClasses) #keep track of samples per class maxRequireSamplesPerClass = int( sampleNum / numClasses) #Max number of samples we need per class xTest, yTest = DMP.DataLoaderToTensor( dataLoader) #Get all the data as tensors #Memory for the solution xClean = torch.zeros(sampleNum, 3, modelPlusList[0].imgSizeH, modelPlusList[0].imgSizeW) yClean = torch.zeros(sampleNum) sampleIndexer = 0 #Go through all the samples for i in range(0, totalSampleNum): currentClass = int(yTest[i]) #Check to make sure all classifiers identify the sample correctly AND we don't have enough of this class yet if accArrayCumulative[i] == numModels and samplePerClassCount[ currentClass] < maxRequireSamplesPerClass: #xClean[sampleIndexer] = rs(xTest[i]) #resize to match dimensions required by modelA xClean[sampleIndexer] = xTest[i] yClean[sampleIndexer] = yTest[i] sampleIndexer = sampleIndexer + 1 #update the indexer samplePerClassCount[currentClass] = samplePerClassCount[ currentClass] + 1 #Update the number of samples for this class #Check the over all number of samples as well if sampleIndexer != sampleNum: print("Not enough clean samples found.") #Do some error checking on the classes for i in range(0, numClasses): if samplePerClassCount[i] != maxRequireSamplesPerClass: print(samplePerClassCount[i]) raise ValueError("We didn't find enough of class: " + str(i)) #Conver the solution into a dataloader cleanDataLoader = DMP.TensorToDataLoader( xClean, yClean, transforms=None, batchSize=modelPlusList[0].batchSize, randomizer=None) #Do one last check to make sure all samples identify the clean loader correctly for i in range(0, numModels): cleanAcc = modelPlusList[i].validateD(cleanDataLoader) if cleanAcc != 1.0: print("Clean Acc " + modelPlusList[i].modelName + ":", cleanAcc) raise ValueError("The clean accuracy is not 1.0") #All error checking done, return the clean balanced loader return cleanDataLoader
def FGSMNativePytorch(device, dataLoader, model, epsilonMax, clipMin, clipMax, targeted): model.eval() #Change model to evaluation mode for the attack #Generate variables for storing the adversarial examples numSamples = len( dataLoader.dataset) #Get the total number of samples to attack xShape = DMP.GetOutputShape( dataLoader ) #Get the shape of the input (there may be easier way to do this) xAdv = torch.zeros(numSamples, xShape[0], xShape[1], xShape[2]) yClean = torch.zeros(numSamples) advSampleIndex = 0 batchSize = 0 #just do dummy initalization, will be filled in later #Go through each sample tracker = 0 for xData, yData in dataLoader: batchSize = xData.shape[ 0] #Get the batch size so we know indexing for saving later tracker = tracker + batchSize #print("Processing up to sample=", tracker) #Put the data from the batch onto the device xDataTemp = torch.from_numpy(xData.cpu().detach().numpy()).to(device) yData = yData.type(torch.LongTensor).to(device) # Set requires_grad attribute of tensor. Important for attack. (Pytorch comment, not mine) xDataTemp.requires_grad = True # Forward pass the data through the model output = model(xDataTemp) # Calculate the loss loss = torch.nn.CrossEntropyLoss(ignore_index=10, size_average=True, reduce=True) # Zero all existing gradients model.zero_grad() # Calculate gradients of model in backward pass cost = loss(output, yData).to(device) cost.backward() # Collect datagrad #xDataGrad = xDataTemp.grad.data ###Here we actual compute the adversarial sample # Collect the element-wise sign of the data gradient signDataGrad = xDataTemp.grad.data.sign() # Create the perturbed image by adjusting each pixel of the input image #print("xData:", xData.is_cuda) #print("SignGrad:", signDataGrad.is_cuda) if targeted == True: perturbedImage = xData - epsilonMax * signDataGrad.cpu().detach( ) #Go negative of gradient else: perturbedImage = xData + epsilonMax * signDataGrad.cpu().detach() # Adding clipping to maintain the range perturbedImage = torch.clamp(perturbedImage, clipMin, clipMax) #Save the adversarial images from the batch for j in range(0, batchSize): xAdv[advSampleIndex] = perturbedImage[j] yClean[advSampleIndex] = yData[j] advSampleIndex = advSampleIndex + 1 #increment the sample index #Not sure if we need this but do some memory clean up del xDataTemp del signDataGrad torch.cuda.empty_cache() #All samples processed, now time to save in a dataloader and return advLoader = DMP.TensorToDataLoader( xAdv, yClean, transforms=None, batchSize=dataLoader.batch_size, randomizer=None) #use the same batch size as the original loader return advLoader