Привет! Я Пшемыслав из Profil Software, компании, занимающейся разработкой программного обеспечения, расположенной в Северной Польше, где я работаю разработчиком Python. Мой интерес к ИИ возник во время изучения темы обучения с подкреплением и компьютерного зрения. У меня есть сильная внутренняя потребность увидеть, как все делается под капотом, поэтому я хотел проверить, могу ли я возиться с некоторыми хорошо известными моделями классификации объектов, такими как CNN (сверточные нейронные сети). Это просто набор чисел и математических операций, так что давайте посмотрим, сможем ли мы с этим поиграться!

Классификация изображений

Классификация изображений относится к процессу компьютерного зрения, который может классифицировать изображение в соответствии с его визуальным содержанием. Не следует путать с другими аналогичными операциями, такими как локализация, обнаружение объекта или сегментация. На изображении
ниже показана разница, чтобы убедиться, что все ясно:

Описание экспериментов

Для этой статьи я выбрал два алгоритма. Первый - это генетический алгоритм, используемый для атаки на один пиксель, который, как следует из названия, изменяет только значение одного пикселя, чтобы обмануть модель классификации. Второй - FGSM (метод быстрого градиентного знака), который изменяет изображение с небольшим шумом, который практически не виден людям, но может влиять на предсказание модели.

Атака одним пикселем

Когда я искал в сети способы обмануть модели DNN (Deep Neural Network), я натолкнулся на очень интересную концепцию One Pixel Attack, и я знал Мне нужно было это проверить. Моя интуиция подсказывала мне, что изменения только одного пикселя в исходном изображении будет недостаточно, чтобы сломать все концепции фильтров и сверточных слоев, используемых в нейронных сетях, которые отлично справляются с классификацией объектов.

Единственной информацией, которая использовалась для управления входным изображением, была вероятность классификации (процентные значения для каждой метки). Я хотел добиться этого без метода грубой силы с помощью GA (генетического алгоритма). Идея была проста:

  1. Получите истинную метку для данного изображения.
  2. Нарисуйте базовую совокупность измененных пикселей (закодированную как xyrgb), где x и y - это положение пиксель, а r, g и b - его цветовые компоненты.
  3. Делайте GA магию (скрещивание, мутацию, отбор) с учетом разнообразия популяции.
  4. Завершите вычисления, когда вероятность упадет ниже 20% или после определенного количества шагов без заметных результатов.

Для экспериментов я использовал модель на основе архитектуры VGG16 для набора данных cifar10 с предварительно обученными весами (https://github.com/geifmany/cifar-vgg). Это было сделано так, чтобы исключить влияние потенциально плохо обученной модели. Приведенный ниже пример кода представлен, чтобы начать обучение ваших собственных моделей на этом наборе данных:

# cifar10 dataset preparation
from keras.datasets import cifar10
from keras.utils import to_categorical
cifar_10_categories = {
    0: 'airplane',
    1: 'automobile',
    2: 'bird',
    3: 'cat',
    4: 'deer',
    5: 'dog',
    6: 'frog',
    7: 'horse',
    8: 'ship',
    9: 'truck',
}
(X_train, y_train), (X_test, y_test) = cifar10.load_data()
X_train = X_train.astype('float32')
X_test = X_test.astype('float32')
y_train = to_categorical(y_train, 10)
y_test = to_categorical(y_test, 10)
# training and evaluation goes here
...

Результаты, полученные в результате атаки, были действительно хорошими, потому что почти для 20% изображений изменение только одного пикселя привело к ошибочной классификации.

ФГСМ

Еще один метод, который я нашел, - это FGSM (Метод быстрого градиентного знака), который чрезвычайно прост по своей концепции, но также дает отличные результаты. Не вдаваясь слишком глубоко во все технические вопросы, этот метод основан на вычислении градиента (между входом и выходом нейронной сети) для данного изображения, который повысит классификацию истинной метки.

Для нецелевого подхода следующий шаг - просто добавить к изображению знаковое значение градиента (-1, 0 или 1 для каждого пиксельного компонента), чтобы избежать хорошего прогноза. В некоторых исследованиях также используется параметр под названием epsilon, который является множителем для значения знака, но в этом эксперименте мы рассматривали изображения, представленные целыми значениями rgb. Этот шаг можно повторить несколько раз, чтобы получить удовлетворительные результаты.

Другой подход - это целевая атака, которая отличается способом вычисления градиента. Для этого типа атаки он берется между входным изображением и целевой меткой (не истинной меткой). Затем он вычитается из изображения, чтобы приблизить классификацию к цели. Легко, не правда ли? Я вставил пример кода ниже, чтобы его было легче понять.

# sample code that calculates the gradients and updates an image
import keras.backend as K
sess = K.get_session()
...
target = K.one_hot(target_class if target_class is not None else       base_class, num_classes)
def get_image_update_function(target_class):
    def target(img, delta):
        return img - epsilon * delta
        
    def non_target(img, delta):
        return img + epsilon * delta
        
    if target_class is not None:
        return target
    return non_target
update_fun = get_image_update_function(target_class)
# calculate delta - difference noise
loss = losses.categorical_crossentropy(target, model.output)
grads = K.gradients(loss, evaluated_model.input)
delta = K.sign(grads[0])
delta = sess.run(delta, feed_dict={model.input: image})
# update image
image = update_fun(image, delta)

В этом эксперименте использовалась модель resnet18 с imagenet w восьмерками. Пример кода, который разрешает его загрузку (с использованием image-classifiers == 0.2.2), вставлен ниже:

# loading resnet pretrained models (224x224px, 1000 classes)
from classification_models import Classifiers
ResNet18, preprocess_input = Classifiers.get('resnet18')
resnet_dim = (224, 224)
model = ResNet18(input_shape=(*resnet_dim, 3), weights='imagenet', classes=1000)

На изображении ниже представлен оригинальный и состязательный пример, сгенерированный с использованием шума, сгенерированного FGSM +, после 2 шагов алгоритма:

Черный ящик FGSM

Предыдущий метод был простым случаем, когда у нас есть полная информация об атакуемой модели, но что делать, если она недоступна? Вот исследование, которое оценивает градиент с помощью большого количества запросов к целевой модели. Я пытался обмануть целевую модель, используя мою собственную модель, которая имела другую архитектуру, но выполняла аналогичные задачи. Модифицированные изображения были подготовлены на основе моей модели (потребовалось 7 шагов, чтобы уменьшить прогноз истинной метки ниже 1%) и проверены целевой моделью (модель vgg16 cifar10, использованная на предыдущих шагах). Результаты этого эксперимента показаны ниже:

Эти результаты выглядят многообещающими, но мы должны учитывать, что это относительно простые задачи (классификация изображений размером 32x32 пикселя), и сложность обмана других моделей, вероятно, будет расти с увеличением сложности используемых структур.

Заключение

Представленные подходы показывают, что мы можем изменять изображения, манипулируя результатами классификации. Это легко, когда у нас есть полная информация о структуре модели. В противном случае трудно оценить возмущенные образцы с ограниченным доступом к целевой модели.

Знания, полученные в результате этих экспериментов, могут помочь защититься от таких атак, расширив обучающую выборку слегка измененными изображениями.

Ресурсы

опубликовано на

ResearchGate: Обман нейронных сетей
Разработчик: Обман нейронных сетей