Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
tensorflow
GitHub Repository: tensorflow/docs-l10n
Path: blob/master/site/pt-br/tutorials/generative/adversarial_fgsm.ipynb
25118 views
Kernel: Python 3

Licensed under the Apache License, Version 2.0 (the "License");

#@title Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License.

Este tutorial cria um exemplo adversário usando o ataque Método Rápido de Sinal de Gradiente (FGSM, na sigla em inglês), conforme descrito no artigo Explicação e Demonstração de Exemplos Adversários, por Goodfellow et al. Este foi um dos primeiros e mais populares ataques para enganar uma rede neural.

O que é um exemplo adversário?

Os exemplos adversários são entradas especializadas, criadas para confundir uma rede neural, resultando na classificação incorreta de uma determinada entrada. Essas entradas notórias são indistinguíveis a olho nu, mas fazem a rede não conseguir identificar o conteúdo da imagem. Existem diversos tipos desse ataque, porém o foco deste artigo é o ataque Método Rápido de Sinal de Gradiente, que é um ataque white-box, cujo objetivo é mensurar as classificações incorretas. Um ataque white-box ocorre quando o invasor tem acesso completo ao modelo que está sob ataque. Um dos exemplos mais famosos de uma imagem adversária exibida abaixo foi tirado do artigo mencionado acima.

Exemplo adversário

Começando com a imagem de um panda, o invasor adiciona pequenas perturbações (distorções) à imagem original, o que faz o modelo rotular esta imagem como um gibão com alta confiança. O processo de adicionar essas perturbações é explicado abaixo.

Método Rápido de Sinal de Gradiente

O Método Rápido de Sinal de Gradiente funciona usando-se os gradientes da rede neural para criar um exemplo adversário. Para uma imagem de entrada, o método usa os gradientes da perda em relação à imagem de entrada para criar uma nova imagem que maximiza a perda. Essa nova imagem é chamada de imagem adversária. A seguinte expressão pode resumir isso: advx=x+ϵsign(xJ(θ,x,y))adv_x = x + \epsilon*\text{sign}(\nabla_xJ(\theta, x, y))

em que

  • adv_x: imagem adversária.

  • x: imagem de entrada original.

  • y: rótulo da entrada original.

  • ϵ\epsilon: multiplicador para garantir que as perturbações sejam pequenas.

  • θ\theta: parâmetros do modelo.

  • JJ: perda.

Um aspecto intrigante é que os gradientes são obtidos em relação à imagem de entrada, pois o objetivo é criar uma imagem que maximize a perda. Um método para atingir essa objetivo é descobrir quanto cada pixel da imagem contribui para o valor de perda e adicionar uma perturbação com base nisso. Isso é muito rápido, pois é fácil descobrir quanto cada pixel da entrada contribui para a perda usando-se a regra da cadeia e encontrando-se os gradientes necessários. Por isso, os gradientes são obtidos em relação à imagem. Além disso, como o modelo não está mais sendo treinado (e, portanto, o gradiente não é obtido em relação às variáveis treinadas, isto é, os parâmetros do modelo), os parâmetros do modelo permanecem constantes. O único objetivo é enganar um modelo já treinado.

Então, vamos tentar enganar um modelo pré-treinado. Neste tutorial, o modelo é MobileNetV2, pré-treinado com o ImageNet.

import tensorflow as tf import matplotlib as mpl import matplotlib.pyplot as plt mpl.rcParams['figure.figsize'] = (8, 8) mpl.rcParams['axes.grid'] = False

Vamos carregar o modelo MobileNetV2 pré-treinado e os nomes da classe ImageNet.

pretrained_model = tf.keras.applications.MobileNetV2(include_top=True, weights='imagenet') pretrained_model.trainable = False # ImageNet labels decode_predictions = tf.keras.applications.mobilenet_v2.decode_predictions
# Helper function to preprocess the image so that it can be inputted in MobileNetV2 def preprocess(image): image = tf.cast(image, tf.float32) image = tf.image.resize(image, (224, 224)) image = tf.keras.applications.mobilenet_v2.preprocess_input(image) image = image[None, ...] return image # Helper function to extract labels from probability vector def get_imagenet_label(probs): return decode_predictions(probs, top=1)[0][0]

Imagem original

Vamos usar uma imagem de amostra de um labrador por Mirko (CC-BY-SA 3.0 do Wikimedia Common) e criar exemplos adversários a partir dela. O primeiro passo é pré-processá-la para que ela possa ser usada como entrada no modelo MobileNetV2.

image_path = tf.keras.utils.get_file('YellowLabradorLooking_new.jpg', 'https://storage.googleapis.com/download.tensorflow.org/example_images/YellowLabradorLooking_new.jpg') image_raw = tf.io.read_file(image_path) image = tf.image.decode_image(image_raw) image = preprocess(image) image_probs = pretrained_model.predict(image)

Vamos dar uma olhada na imagem.

plt.figure() plt.imshow(image[0] * 0.5 + 0.5) # To change [-1, 1] to [0,1] _, image_class, class_confidence = get_imagenet_label(image_probs) plt.title('{} : {:.2f}% Confidence'.format(image_class, class_confidence*100)) plt.show()

Criar a imagem adversária

Implementação do Método Rápido de Sinal de Gradiente

O primeiro passo é criar perturbações, que serão usadas para distorcer a imagem original, resultando em uma imagem adversária. Conforme mencionado, para esta tarefa, os gradientes são obtidos em relação à imagem.

loss_object = tf.keras.losses.CategoricalCrossentropy() def create_adversarial_pattern(input_image, input_label): with tf.GradientTape() as tape: tape.watch(input_image) prediction = pretrained_model(input_image) loss = loss_object(input_label, prediction) # Get the gradients of the loss w.r.t to the input image. gradient = tape.gradient(loss, input_image) # Get the sign of the gradients to create the perturbation signed_grad = tf.sign(gradient) return signed_grad

As perturbações resultantes também podem ser visualizadas.

# Get the input label of the image. labrador_retriever_index = 208 label = tf.one_hot(labrador_retriever_index, image_probs.shape[-1]) label = tf.reshape(label, (1, image_probs.shape[-1])) perturbations = create_adversarial_pattern(image, label) plt.imshow(perturbations[0] * 0.5 + 0.5); # To change [-1, 1] to [0,1]

Vamos tentar usar diferentes valores de épsilon e observar a imagem resultante. Você notará que, à medida que o valor de épsilon aumenta, fica mais fácil enganar a rede. Entretanto, em compensação, fica mais fácil identificar as perturbações.

def display_images(image, description): _, label, confidence = get_imagenet_label(pretrained_model.predict(image)) plt.figure() plt.imshow(image[0]*0.5+0.5) plt.title('{} \n {} : {:.2f}% Confidence'.format(description, label, confidence*100)) plt.show()
epsilons = [0, 0.01, 0.1, 0.15] descriptions = [('Epsilon = {:0.3f}'.format(eps) if eps else 'Input') for eps in epsilons] for i, eps in enumerate(epsilons): adv_x = image + eps*perturbations adv_x = tf.clip_by_value(adv_x, -1, 1) display_images(adv_x, descriptions[i])

Próximos passos

Agora que você sabe o que são ataques adversários, experimente esse método em diferentes datasets e diversas arquiteturas. Além disso, você pode criar e treinar seu próprio modelo, e depois pode tentar enganá-lo usando o mesmo método. E você pode tentar ver como a confiança das previsões variam à medida que você altera o épsilon.

Embora poderoso, o ataque mostrado neste tutorial foi apenas o começo das pesquisas sobre ataques adversários e, desde então, foram escritos diversos artigos sobre a criação de ataques mais poderosos. Além dos ataques adversários, as pesquisas também levaram à criação de defesas, que têm o objetivo de criar modelos de aprendizado de máquina mais robustos. Confira este artigo de pesquisa para ver uma lista abrangente de ataques e defesas adversários.

Se quiser ver mais implementações de ataques e defesas adversários, confira a biblioteca de exemplos adversários CleverHans.