Tutorial

Как «обмануть» нейронную сеть в Python 3

Published on August 6, 2020
Русский
Как «обмануть» нейронную сеть в Python 3

Автор выбрал Dev Color​​​ для получения пожертвования в рамках программы Write for DOnations.

Можно ли обмануть нейронную сеть для классификации животных? Попытка обмануть классификатор животных может не иметь значительных последствий, но что случится, если обмануть программу аутентификации лица? Или наше программное обеспечение прототипа беспилотного автомобиля? К счастью, целый легион инженеров и исследовательских центров стоит между прототипом в виде модели на базе машинного зрения и моделями, готовыми к применению на наших мобильных устройствах или автомобилях. Тем не менее эти риски имеют значительное воздействие, и специалисты по машинному обучению обязаны их учитывать.

В этом обучающем руководстве вы попытаетесь обмануть или «обвести вокруг пальца» классификатор животных. Во время работы с этим руководством вы будете использовать библиотеку компьютерного зрения OpenCV и библиотеку глубинного обучения PyTorch. Вы рассмотрите следующие темы в смежной области состязательного машинного обучения:

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

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

Предварительные требования

Для этого обучающего модуля вам потребуется следующее:

Шаг 1 — Создание проекта и установка зависимостей

Давайте создадим рабочее пространство для этого проекта и установим необходимые зависимости. Назовем рабочее пространство AdversarialML:

  1. mkdir ~/AdversarialML

Перейдите в директорию AdversarialML:

  1. cd ~/AdversarialML

В директории будут храниться все ваши ресурсы:

  1. mkdir ~/AdversarialML/assets

Затем создайте новую виртуальную среду для проекта:

  1. python3 -m venv adversarialml

Активируйте среду:

  1. source adversarialml/bin/activate

Затем установите PyTorch, платформу глубинного обучения для Python, которую вы будете использовать в этом руководстве.

В macOS установите Pytorch с помощью следующей команды:

  1. python -m pip install torch==1.2.0 torchvision==0.4.0

В Linux и Windows используйте следующие команды для создания значения CPU-only:

  1. pip install torch==1.2.0+cpu torchvision==0.4.0+cpu -f https://download.pytorch.org/whl/torch_stable.html
  2. pip install torchvision

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

  1. python -m pip install opencv-python==3.4.3.18 numpy==1.14.5

В дистрибутивах Linux вам потребуется установить libSM.so:

  1. sudo apt-get install libsm6 libxext6 libxrender-dev

После установки зависимостей запустите классификатор животных под названием ResNet18, о котором будет рассказано далее.

Шаг 2 — Запуск предварительно обученного классификатора животных

Библиотека torchvision, официальная библиотека компьютерного зрения для PyTorch, содержит предварительно обученные версии широко используемых нейронных сетей компьютерного зрения. Все эти нейронные сети обучены на ImageNet 2012, наборе данных, содержащем 1,2 миллиона учебных образцов из 1000 классов. Классы включают транспортные средства, места и, что самое главное, животных. На этом шаге вы запустите одну из предварительно обученных нейронных сетей под названием ResNet18. Мы будем считать сеть ResNet18, обученную на ImageNet, «классификатором животных».

Что такое ResNet18? ResNet18 — это самая маленькая нейронная сеть в семействе нейронных сетей, называемых остаточными нейронными сетями, разработанная MSR (Ге и соавт.). Вкратце, Ге обнаружил, что нейронная сеть (обозначенная как функция f с вводным модулем x и выводом f(x)) будет работать лучше с «остаточным соединением» x + f(x). Это остаточное соединение используется повсеместно в самых современных нейронных сетях, даже сегодня. Например, FBNetV2, FBNetV3.

Загрузите это изображение собаки с помощью следующей команды:

  1. wget -O assets/dog.jpg https://assets.digitalocean.com/articles/trick_neural_network/step2a.png

Изображение корги, который бежит вдоль водоема

Затем загрузите файл JSON для преобразования вывода в имя класса в удобной для чтения человеком форме:

  1. wget -O assets/imagenet_idx_to_label.json https://raw.githubusercontent.com/do-community/tricking-neural-networks/master/utils/imagenet_idx_to_label.json

Затем создайте скрипт для запуска вашей предварительно обученной модели на изображении собаки. Создайте новый файл с именем step_2_pretrained.py​​​:

  1. nano step_2_pretrained.py

Сначала добавьте шаблон Python, импортируя необходимые пакеты и декларируя функцию main:

step_2_pretrained.py
from PIL import Image
import json
import torchvision.models as models
import torchvision.transforms as transforms
import torch
import sys

def main():
    pass

if __name__ == '__main__':
    main()

Затем загрузите преобразование из вывода нейронной сети в имя класса в удобной для чтения человеком форме. Добавьте это непосредственно после операторов импорта и перед функцией main:

step_2_pretrained.py
. . .
def get_idx_to_label():
    with open("assets/imagenet_idx_to_label.json") as f:
        return json.load(f)
. . .

Создайте функцию преобразования изображения, которая обеспечит, во-первых, правильный размер вашего входного изображения, а во-вторых, корректную нормализованную форму. Добавьте следующую функцию непосредственно после последнего:

step_2_pretrained.py
. . .
def get_image_transform():
    transform = transforms.Compose([
      transforms.Resize(224),
      transforms.CenterCrop(224),
      transforms.ToTensor(),
      transforms.Normalize(mean=[0.485, 0.456, 0.406],
                           std=[0.229, 0.224, 0.225])
    ])
    return transform
. . .

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

  • transforms.Resize(224)​​​: меняет размер меньшей стороны изображения на 224. Например, если размер вашего изображения 448 х 672, данная операция уменьшит изображение до 224 х 336.
  • transforms.CenterCrop(224)​​: предлагает обрезку из центра изображения, размер 224 х 224
  • transforms.ToTensor()​​: конвертирует изображение в тензор PyTorch. Во всех моделях PyTorch в качестве входного модуля требуется использование тензоров PyTorch.
  • transforms.Normalize(mean=..., std=…)​​: стандартизирует ваш входной модуль путем вычитания среднего значения, а затем деления на стандартную девиацию. Более подробно это описано в документации torchvision.

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

step_2_pretrained.py
. . .
def predict(image):
    model = models.resnet18(pretrained=True)
    model.eval()

    out = model(image)

    _, pred = torch.max(out, 1)  
    idx_to_label = get_idx_to_label()  
    cls = idx_to_label[str(int(pred))]  
    return cls
. . .

Здесь функция predict​​​ классифицирует предоставленное изображение, используя предварительно обученную нейронную сеть:

  • models.resnet18(pretrained=True)​​​: загружает предварительно обученную нейронную сеть под названием ResNet18.
  • model.eval()​​​: изменяет присутствующую модель для работы в режиме ‘оценки’. Единственный иной режим — это режим обучения, но он не нужен, так как вы не обучаете модель (т. е. не обновляете параметры модели) в рамках данного обучающего руководства.
  • out = model(image): запускает нейронную сеть на предоставленном и преобразованном изображении.
  • _, pred = torch.max(out, 1): нейронная сеть выводит одну вероятность для каждого возможного класса. Этот шаг вычисляет индекс класса с самой высокой вероятностью. Например, если out = [0.4, 0.1, 0.2]​​​, тогда pred = 0.
  • idx_to_label = get_idx_to_label(): получает преобразование из индекса класса в имя класса в удобной для чтения человеком форме. Например, преобразование может быть {0: cat, 1: dog, 2: fish}.
  • cls = idx_to_label[str(int(pred))]: конвертирует предсказанный индекс класса в имя класса. Примеры, приведенные в последних двух пунктах списка, будут давать cls = idx_to_label[0] = 'cat'​​​.

Далее, после последней функции добавьте утилиту для загрузки изображений:

step_2_pretrained.py
. . .
def load_image():
    assert len(sys.argv) > 1, 'Need to pass path to image'
    image = Image.open(sys.argv[1])

    transform = get_image_transform()
    image = transform(image)[None]
    return image
. . .

Это позволит загружать изображение через путь, представленный в первом аргументе, в скрипт. transform(image)[None]​​​ использует последовательность трансформаций изображения, определенную в предыдущих строках.

Наконец, заполните вашу функцию main следующим содержанием, чтобы загрузить изображение и классифицировать животное на нем:

step_2_pretrained.py
def main():
    x = load_image()
    print(f'Prediction: {predict(x)}')

Проверьте еще раз, соответствует ли ваш файл сценарию финального шага 2 в step_2_pretrained.py на GitHub. Сохраните и закройте скрипт, потом запустите классификатор животных:

  1. python step_2_pretrained.py assets/dog.jpg

Это позволит получить следующий вывод, означающий, что ваш классификатор животных работает так, как и ожидалось:

Output
Prediction: Pembroke, Pembroke Welsh corgi

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

Шаг 3 — Испытание состязательного образца

Теперь вы синтезируете состязательный образец и протестируете на нем нейронную сеть. В ходе выполнения данного обучающего руководства вы построите состязательный образец формы x + r, где x — это оригинальное изображение, а r — некоторые «отклонения». Далее вы будете создавать отклонения r самостоятельно, но на данном этапе вы загрузите то, которое мы создали для вас заранее. Начните с загрузки отклонения r:

  1. wget -O assets/adversarial_r.npy https://github.com/do-community/tricking-neural-networks/blob/master/outputs/adversarial_r.npy?raw=true

Теперь соедините изображение с отклонением. Создайте новый файл с именем step_3_adversarial.py​​​:

  1. nano step_3_adversarial.py

В этом файле вы выполните следующий трехступенчатый процесс, чтобы получить состязательный образец:

  1. Преобразование изображения
  2. Применение отклонения r
  3. Обратное преобразование изображения с отклонением

После выполнения шага 3 вы получите состязательный образец. Сначала импортируйте необходимые пакеты и декларируйте функцию main:

step_3_adversarial.py
from PIL import Image
import torchvision.transforms as transforms
import torch
import numpy as np
import os
import sys

from step_2_pretrained import get_idx_to_label, get_image_transform, predict, load_image


def main():
    pass


if __name__ == '__main__':
    main()

Далее создайте «трансформацию изображения», которая инвертирует предыдущую трансформацию изображения. Разместите это после операций импорта, перед функцией main:

step_3_adversarial.py
. . .
def get_inverse_transform():
    return transforms.Normalize(
        mean=[-0.485/0.229, -0.456/0.224, -0.406/0.255],  # INVERSE normalize images, according to https://pytorch.org/docs/stable/torchvision/models.html
        std=[1/0.229, 1/0.224, 1/0.255])
. . .

Как и ранее, операция transforms.Normalize​​​ вычитает среднее значение и делит на стандартное отклонение (т.е. для оригинального изображения x, y = transforms.Normalize(mean=u, std=o) = (x - u) / o). Вы делаете определенные вычисления и определяете новую операцию, которая возвращает нормализованную функцию (transforms.Normalize(mean=-u/o, std=1/o) = (y - -u/o) / 1/o = (y + u/o) o = yo + u = x).

В рамках обратного преобразования добавьте метод, который преобразовывает тензор PyTorch обратно в изображение PIL. Добавьте это после последней функции:

step_3_adversarial.py
. . .
def tensor_to_image(tensor):
    x = tensor.data.numpy().transpose(1, 2, 0) * 255.  
    x = np.clip(x, 0, 255)
    return Image.fromarray(x.astype(np.uint8))
. . .
  • tensor.data.numpy()​​ конвертирует тензор PyTorch в массив NumPy. .transpose(1, 2, 0) перестраивает (channels, width, height) в (height, width, channels). Этот массив NumPy примерно находится в диапазоне (0, 1). Наконец, умножьте на 255, чтобы убедиться, что изображение находится сейчас в диапазоне (0, 255).
  • np.clip гарантирует, что все значения в изображении находятся между (0, 255).
  • x.astype(np.uint8) гарантирует, что все значения изображения являются целыми числами. Наконец, Image.fromarray(...) создает объект изображения PIL из массива NumPy.

Затем используйте эти утилиты для создания состязательного образца:

step_3_adversarial.py
. . .
def get_adversarial_example(x, r):
    y = x + r
    y = get_inverse_transform()(y[0])
    image = tensor_to_image(y)
    return image
. . .

Эта функция генерирует состязательный образец, описанный в начале этого раздела:

  1. y = x + r. Возьмите ваше отклонение r и добавьте его в оригинальное изображение x.
  2. get_inverse_transform​​:Получите и примените обратное преобразование изображения, которое вы установили несколькими строками ранее.
  3. tensor_to_image: Конвертируйте тензор PyTorch обратно в изображение объекта.

А теперь внесите изменения в функцию main, чтобы загрузить изображение, загрузите состязательное отклонение r, примените отклонение, сохраните состязательный образец на диск и запустите прогноз по состязательному образцу:

step_3_adversarial.py
def main():
    x = load_image()
    r = torch.Tensor(np.load('assets/adversarial_r.npy'))

    # save perturbed image
    os.makedirs('outputs', exist_ok=True)
    adversarial = get_adversarial_example(x, r)
    adversarial.save('outputs/adversarial.png')

    # check prediction is new class
    print(f'Old prediction: {predict(x)}')
    print(f'New prediction: {predict(x + r)}')

Ваш завершенный файл должен соответствовать step_3_adversarial.py на GitHub. Сохраните файл, закройте редактор и запустите скрипт с помощью следующей команды:

  1. python step_3_adversarial.py assets/dog.jpg

Вы увидите следующий результат:

Output
Old prediction: Pembroke, Pembroke Welsh corgi New prediction: goldfish, Carassius auratus

Теперь вы создали состязательный образец, который заставляет нейронную сеть распознавать корги, как золотую рыбку. На следующем шаге вы фактически создадите отклонение r, которое использовали здесь.

Шаг 4 — Принцип работы состязательного образца

Для начала вы можете ознакомиться со статьей Создание эмоционального фильтра «Собака».

Учитывая пройденный материал, вспомните, что ваша классификационная модель выводит вероятность для каждого класса. В логическом выводе модель предсказывает класс с самой высокой вероятностью. Во время обучения вы обновляете параметры модели t, чтобы максимально увеличить вероятность определения правильного класса y с учетом ваших данных x.

argmax_y P(y|x,t)

Но сейчас вы измените свою цель, чтобы создать состязательные образцы. Вместо определения класса, вашей целью будет поиск нового изображения x. Возьмите любой другой класс, помимо правильного. Назовем этот новый класс w. Ваша новая цель — увеличить вероятность определения неправильного класса.

argmax_x P(w|x)

Обратите внимание, что веса нейронных сетей t отсутствуют в вышеупомянутом выражении. Причина в том, что сейчас вы берете на себя роль противника — кто-то другой обучил и развернул модель. Вам разрешено создавать состязательные входные модули и запрещено видоизменять развернутую модель. Чтобы создать состязательный пример x, вы можете запустить «тренировку», но вместо обновления весов нейронных сетей, вы обновите входящее изображение с новой целью.

Напомним, что в этом обучающем руководстве вы предполагаете, что состязательный пример является аффинным преобразованием x. Другими словами, ваш состязательный пример принимает форму x + r для некоторых r. На следующем шаге вы напишете скрип, чтобы создать это r.

Шаг 5 — Создание состязательного образца

На этом шаге вы познакомитесь с отклонением r, из-за которого ваш корги будет классифицирован как золотая рыбка. Создайте новый файл с именем step_5_perturb.py​​​:

  1. nano step_5_perturb.py

Импортируйте необходимые пакеты и декларируйте функцию main:

step_5_perturb.py
from torch.autograd import Variable
import torchvision.models as models
import torch.nn as nn
import torch.optim as optim
import numpy as np
import torch
import os

from step_2_pretrained import get_idx_to_label, get_image_transform, predict, load_image
from step_3_adversarial import get_adversarial_example


def main():
    pass


if __name__ == '__main__':
    main()

Непосредственно за операциями импорта и перед функцией main определите две константы:

step_5_perturb.py
. . .
TARGET_LABEL = 1
EPSILON = 10 / 255.
. . .

Первая константа TARGET_LABEL — это класс, которым будет неправильно классифицироваться корги. В данном случае индекс 1 соответствует «золотой рыбке». Вторая константа EPSILON — это максимальное количество отклонений, разрешенное для каждого значения изображения. Это ограничение вводится, чтобы изменения изображения были незаметны.

После двух констант добавьте вспомогательную функцию для определения нейронной сети и параметра отклонения r:

step_5_perturb.py
. . .
def get_model():
    net = models.resnet18(pretrained=True).eval()
    r = nn.Parameter(data=torch.zeros(1, 3, 224, 224), requires_grad=True)
    return net, r
. . .
  • model.resnet18(pretrained=True) загружает предварительно обученную нейронную сеть под названием ResNet18, как и ранее. Также, как и ранее, вы устанавливаете модель в режим оценки, используя .eval.
  • nn.Parameter(...) определяет новое отклонение r, размер входного изображения. Входное изображение имеет размер (1, 3, 224, 224). Основной аргумент requires_grad=True обеспечивает возможность обновить данное отклонение r в последующих строках в этом файле.

Затем начинайте вносить изменения в вашу функцию main. Начните с загрузки модели net, загрузки вводных x и определения ярлыка label:

step_5_perturb.py
. . .
def main():
    print(f'Target class: {get_idx_to_label()[str(TARGET_LABEL)]}')
    net, r = get_model()
    x = load_image()
    labels = Variable(torch.Tensor([TARGET_LABEL])).long()
  . . .

Затем определите критерий и оптимизатор в функции main. Первый указывает PyTorch, что является целью, т. е. какие потери минимизировать. Второй указывает PyTorch, как обучать параметр r:

step_5_perturb.py
. . .
    criterion = nn.CrossEntropyLoss()
    optimizer = optim.SGD([r], lr=0.1, momentum=0.1)
. . .

Сразу за этим добавьте основной обучающий цикл для параметра r:

step_5_perturb.py
. . .
    for i in range(30):
        r.data.clamp_(-EPSILON, EPSILON)
        optimizer.zero_grad()

        outputs = net(x + r)
        loss = criterion(outputs, labels)
        loss.backward()
        optimizer.step()

        _, pred = torch.max(outputs, 1)
        if i % 5 == 0:
            print(f'Loss: {loss.item():.2f} / Class: {get_idx_to_label()[str(int(pred))]}')
. . .

На каждой итерации данного обучающего цикла вы сможете следующее:

  • r.data.clamp_(...): Убедиться, что параметр r невелик и находится в пределах EPSILON 0.
  • optimizer.zero_grad(): Очистить любые градиенты, которые вы вычислили в предыдущей итерации.
  • model(x + r): Запустить логический вывод на модифицированном изображении x + r.
  • Вычислить loss.
  • Вычислить градиент loss.backward.
  • Определить шаг градиентного спуска optimizer.step.
  • Вычислить прогноз pred.
  • Наконец, сообщить о потере и прогнозируемом классе print(...).

Затем сохраните финальное отклонение r:

step_5_perturb.py
def main():
    . . .
    for i in range(30):
        . . .
    . . .
    np.save('outputs/adversarial_r.npy', r.data.numpy())

Непосредственно за этим в функции main сохраните изображение с отклонением:

step_5_perturb.py
. . .
    os.makedirs('outputs', exist_ok=True)
    adversarial = get_adversarial_example(x, r)

После этого запустите прогноз на оригинальном изображении и на состязательном образце:

step_5_perturb.py
    print(f'Old prediction: {predict(x)}')
    print(f'New prediction: {predict(x + r)}')

Еще раз убедитесь, что ваш скрипт соответствует step_5_perturb.py на GitHub. Сохраните, выйдите и запустите скрипт:

  1. python step_5_perturb.py assets/dog.jpg

Ваш скрипт покажет следующий вывод.

Output
Target class: goldfish, Carassius auratus Loss: 17.03 / Class: Pembroke, Pembroke Welsh corgi Loss: 8.19 / Class: Pembroke, Pembroke Welsh corgi Loss: 5.56 / Class: Pembroke, Pembroke Welsh corgi Loss: 3.53 / Class: Pembroke, Pembroke Welsh corgi Loss: 1.99 / Class: Pembroke, Pembroke Welsh corgi Loss: 1.00 / Class: goldfish, Carassius auratus Old prediction: Pembroke, Pembroke Welsh corgi New prediction: goldfish, Carassius auratus

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

Теперь вы показали, что нейронные сети можно легко обмануть. Более того, отсутствие устойчивости к состязательным образцам имеет значительные последствия. Далее возникает естественный вопрос: как можно бороться с состязательными образцами? Различные организации, включая OpenAI​​​, провели множество исследований на эту тему. В следующем разделе вы запустите защиту, чтобы пресечь воздействие состязательного образца.

Шаг 6 — Защита от состязательных образцов

На этом шаге вы создадите защиту от состязательных образцов. Идея заключается в следующем: теперь вы являетесь владельцем классификатора животных, развернутого в производство. Вы не знаете, какие состязательные образцы могут быть созданы, но вы можете изменить изображение или модель для защиты от атак.

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

  1. assets/dog.jpg
  2. outputs/adversarial.png

Здесь они представлены рядом. Ваше оригинальное изображение будет иметь другие пропорции. Вы можете сказать, какое из изображений является состязательным образцом?

(слева) Корги как золотая рыбка, состязательное изображение, (справа) корги как корги, не состязательное изображение)

Обратите внимание, что новое изображение выглядит идентичным оригиналу. Как оказалось, левое изображение — это ваше состязательное изображение. Чтобы убедиться, загрузите изображение и запустите скрипт оценки:

  1. wget -O assets/adversarial.png https://github.com/alvinwan/fooling-neural-network/blob/master/outputs/adversarial.png?raw=true
  2. python step_2_pretrained.py assets/adversarial.png

Это позволит получить вывод о том, что изображение принадлежит к классу «золотая рыбка», что доказывает состязательную природу изображения:

Output
Prediction: goldfish, Carassius auratus

Вы запустите довольно примитивную, но эффективную защиту: сжатие изображения с потерями путем записи в формате JPEG. Откройте интерактивную строку Python:

  1. python

Затем загрузите состязательное изображение как PNG, и сохраните его снова как JPEG.

  1. from PIL import Image
  2. image = Image.open('assets/adversarial.png')
  3. image.save('outputs/adversarial.jpg')

Введите CTRL + D, чтобы покинуть интерактивную строку Python. Затем запустите логический вывод с помощью вашей модели на сжатом состязательном образце:

  1. python step_2_pretrained.py outputs/adversarial.jpg

Теперь это позволит получить вывод о том, что изображение принадлежит к классу «корги», что доказывает эффективность вашей примитивной защиты.

Output
Prediction: Pembroke, Pembroke Welsh corgi

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

Заключение

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

(слева) Корги как золотая рыбка, состязательное изображение, (справа) корги как корги, не состязательное изображение)

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

  • Adversarial Machine Learning (Состязательное машинное обучение), обучающее руководство по материалам конференции NeurIPS 2018.
  • Соответствующие посты блога от OpenAI о состязательных образцах и устойчивости перед состязательными атаками.

Дополнительную информацию о машинном обучении, а также обучающие руководства вы можете найти на странице, посвященной машинному обучению.

Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.

Learn more about our products

About the authors
Default avatar
Alvin Wan

author

AI PhD Student @ UC Berkeley

I’m a diglot by definition, lactose intolerant by birth but an ice-cream lover at heart. Call me wabbly, witling, whatever you will, but I go by Alvin



Still looking for an answer?

Ask a questionSearch for more help

Was this helpful?
 
Leave a comment


This textbox defaults to using Markdown to format your answer.

You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!

Try DigitalOcean for free

Click below to sign up and get $200 of credit to try our products over 60 days!

Sign up

Join the Tech Talk
Success! Thank you! Please check your email for further details.

Please complete your information!

Become a contributor for community

Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.

DigitalOcean Documentation

Full documentation for every DigitalOcean product.

Resources for startups and SMBs

The Wave has everything you need to know about building a business, from raising funding to marketing your product.

Get our newsletter

Stay up to date by signing up for DigitalOcean’s Infrastructure as a Newsletter.

New accounts only. By submitting your email you agree to our Privacy Policy

The developer cloud

Scale up as you grow — whether you're running one virtual machine or ten thousand.

Get started for free

Sign up and get $200 in credit for your first 60 days with DigitalOcean.*

*This promotional offer applies to new accounts only.