Дипфейки ставят под сомнение само наличие реальных фото или видео, подрывая доверие между социальными институтами и ставя реальность любого события или происшествия под сомнение; документальные съемки или кадры с мест событий больше не могут служить доказательством - ни в суде, ни в СМИ. Особенно уязвимы авторитарные общества, где дипфейки будут распространяться в социальных сетях и мессенджерах. Такие государства, по мнению Тома Ван де Веге, и так обладают дефицитом доверия к власти и их граждане "особенно восприимчивы к теориям заговора" Там же.
В статье "How can journalists help solve the global problem of deepfakes?" также поднимается вопрос доверия к журналистскому контенту. Распространение дипфейков, которые становится все труднее отличить от реальности, становится проблемой: "Без доверия к журналистике (которое уже очень шатко) дипфейки могут просто дестабилизировать ситуацию с реальным контентом" How can journalists help solve the global problem of deepfakes? // WNIP URL: https://whatsnewinpublishing.com/how-can-journalists-help-solve-the-global-problem-of-deepfakes/ (дата обращения: 20.04.2020)..
Хао Ли, еще до дипфейков создававший технологии для замены лиц для киноиндустрии, задумался о возможных последствиях дипфейков и попытался донести эту проблему до политиков и лидеров технологических компаний оригинальным способом. На Всемирном экономическом форуме Ли предлагал участникам по одному пройти в кабинку, где в режиме реального времени их лица на экране заменялись на лица актеров и известных деятелей. Хао Ли создал свой дипфейк не для развлечения, а чтобы донести до влиятельных людей, какие последствия ожидают мир с распространением этой технологии. Ли беспокоится, что мы приближаемся к эпохе, когда не можем доверять своим глазам и медиа, которые уже сейчас имеют все инструменты для того, чтобы транслировать неправду. "Эта проблема уже стоит перед нами" The world's top deepfake artist is wrestling with the monster he created // MIT Technology Review URL: https://www.technologyreview.com/s/614083/the-worlds-top-deepfake-artist-is-wrestling-with-the-monster-he-created/?fbclid=IwAR2Vp_eBCwv5ZHL8-tulfBmH_KSjunMQ2MG4uhbBeibY83jZ55x-_DzydIg (дата обращения: 20.04.2020)., - говорит он в интервью Technology Review.
Глава 2. Влияние дипфейков на журналистику и способы их обнаружения
2.1 Последовательные шаги для создания дипфейка
Современные дипфейки создаются на основе GAN - генеративно-состязательных нейронных сетей. GAN - это "тип архитектуры глубоких нейронных сетей, использующий для генерации данных обучение без учителя" Ахирвар К. Состязательные сети. Проекты. - М.: ДМК Пресс, 2020. - С. 16.. Обучение без учителя означает, что для обучения нейросети не требуются размеченные данные извне, она сама способна отличать их друг от друга и разделять на кластеры по принципу схожести. Архитектура GAN содержит внутри себя две сети - сеть генератора и сеть дискриминатора. Сеть генератора способна создавать новые данные на основе существующих - это могут быть изображения, текст, видео, аудио, то есть "генеративные модели моделируют распределение отдельных классов" Генеративно-состязательная нейросеть (GAN). Руководство для новичков // Neurohive URL: https://neurohive.io/ru/osnovy-data-science/gan-rukovodstvo-dlja-novichkov/ (дата обращения: 10.04.2020).. Например, генератор, обученный на пейзажах известных художников, будет стараться создать свои картины на их основе. Дискриминатор работает по принципам бинарной классификации, то есть разбивает поступающую от генератора информацию на две категории. "Математически категории обозначают y, а образы обозначают x. Запись p(y|x) используется для обозначения "вероятности y при заданном x" Там же". Роль дискриминатора в процессе генерации контента - отличить сгенерированный контент от реального. Отсюда возникает состязательный элемент нейросети: генератор на каждой итерации создает все более реалистичный контент, чтобы обмануть дискриминатор, а дискриминатор учится находить самые незначительные неточности в работе генератора. Так продолжается до тех пор, пока дискриминатор не перестанет отличать сгенерированный контент от реального - это состояние нейросети называется равновесием Нэша. Термин пришел из теории игр, где под равновесием Нэша понимается такая ситуация, при которой стратегия каждого игрока - это лучшая реакция на стратегии других игроков. При этом ни одному игроку в отдельности не выгодно менять стратегию, чтобы не ухудшить свое положение. В контексте генеративно-состязательных нейросетей "игроками" выступают генератор и дискриминатор, которые достигли той точки, когда генератор не может больше улучшать качество, а дискриминатор не отличает сгенерированное от реального.
С помощью GAN можно создавать не только дипфейки. Например, разновидность GAN, 3D-GAN, способна визуализировать 3D модели, воспроизводить промежуточные результаты на этапах проектирования (например, при строительстве зданий), а также отрисовывать за нас модели, которые можно использовать в 3D печати. Сеть StackGAN способна переводить текстовые описания в изображения, что дает возможность создавать наброски для фильмов по сценарию, помогает в создании комиксов, облегчает работу художников. Сеть ArtGAN способна самостоятельно создавать картины.
На сайте neurohive Там же выложен пример кода, который позволяет создать собственную нейросеть GAN (код представлен в Приложении 1) и генерировать рукописные цифры на основе обучающих данных MNIST. Код написан на языке Python, как и большинство продуктов для машинного обучения (самый популярный инструмент для замены лиц в видео, DeepFaceLab, также интегрирован с Python). Для создания нейросетей в Python существует несколько библиотек, наиболее популярные из них - Keras и Pytorch. Эти библиотеки схожи по функционалу, но Keras имеет более низкий порог входа для начинающих специалистов. Keras - библиотека, созданная специалистом из Google Франсуа Шолле. Библиотека содержит простой, интуитивно понятный интерфейс, а ее создатель выпустил книгу "Глубокое обучение на Python", в которой раскрываются все тонкости работы с Keras. Pytorch - библиотека Facebook, изначально написанная на Lua, но затем интегрированная в Python, с помощью которой можно обучить модель быстро и эффективно.
Код, который мы будем разбирать в примере, написан на Keras. Рассмотрим функционал основных понятий, пользуясь определениями из книги Франсуа Шолле "Глубокое обучение на Python". Одно из основных понятий в нейронных сетях, которое является главным строительным блоком моделей глубокого обучения - это слой. Слои принимают на вход некоторые данные и выводят их в другой форме. Данные для слоев подаются в числовом формате и могут быть различными в зависимости от задач, которые стоят перед программистом. Эти данные называются тензорами, их вид указывает на то, какую информацию мы обрабатываем. Например, векторные данные или временные ряды представляются двумерными и трехмерными тензорами, изображения - четырехмерными тензорами, где измерениями являются образцы, высота, ширина и цвет, а видео - пятимерными тензорами, где пятым измерением становятся кадры.
Создание моделей глубокого обучения в Keras осуществляется путем объединения слоев в последовательности. Это прописывается с помощью импортируемого модуля models: models.тип_модели.add(…). В примере используется последовательная модель с одним слоем. Слой принимает на вход двумерные тензоры, первое измерение которого равно 786. Получается полносвязный слой с 32 выходными нейронами:
from keras import models
from keras import layers
model = models.Sequential()
model.add(layers.Dense(32, activation='relu', input_shape=(784,))) Шолле Ф. Глубокое обучение на Python. - СПб.: Питер, 2018. - С. 88.
Теперь мы можем создавать новые слои, при этом входные нейроны будут поданы автоматически из выхода предыдущего слоя, а выходные нейроны необходимо прописать в круглых скобках. Пусть их значение снова равняется 10:
model.add(layers.Dense(10, activation='softmax'))
В примере присутствует функция активации ("activation"), которая определяет выходной сигнал нейрона. В примере промежуточная функция активации - relu, которая используется для преобразования отрицательных значений в ноль. В последнем, выходном слое применяется сигмоидальная функция активации, которая выводит вероятность в интервале от 0 до 1, что образец данных принадлежит к заданному классу.
После того, как мы задали параметры модели, необходимо настроить процесс обучения, который начинается на этапе компиляции:
from keras import optimizers
model.compile(optimizer=optimizers.RMSprop(lr=0.001),
loss='mse',
metrics=['accuracy']) Там же
На этом этапе задается оптимизатор ("optimizer"), функция потерь ("loss") и метрики для мониторинга во время обучения ("metrics"). Оптимизатор определяет, "как будет изменяться сеть под воздействием функции потерь" Шолле Ф. Глубокое обучение на Python. - СПб.: Питер, 2018. - С. 84.. Функция потерь определяет "количественную оценку, которая будет минимизироваться в процессе обучения. Представляет собой меру успеха в решении стоящей задачи" Там же. Метрики качества позволяют понять, как обучалась модель в течение каждой эпохи (каждой итерации) и отследить, с какой эпохи началось переобучение модели.
Непосредственно процесс обучения содержится в следующем шаге - применении функции fit() на целевые данные. Внутри нее задается количество эпох, в течение которых будет обучаться модель. Так как одна эпоха слишком велика для обучения, принято делить весь датасет, который проходит сквозь нейросеть в течение одной эпохи, на батчи. Таким образом, размер батча - это число итераций, которые нужно пройти алгоритму для одной эпохи. Чем меньше размер батча, тем больше итераций потребуется:
model.fit(input_tensor, target_tensor, batch_size=128, epochs=10) Шолле Ф. Глубокое обучение на Python. - СПб.: Питер, 2018. - С. 89.
Теперь, когда у нас есть обученная модель, можно делать предсказание для тестовой выборки с помощью функции predict():
model.predict(test_data)
После разбора основных функций, необходимых для построения нейросетей, вернемся к разбору кода для GAN, который имеет некоторые особенности. В представленном коде из Приложения 1 создание GAN начинается с инициализации класса:
class GAN():
Внутри класса создано несколько методов, которые отвечают за работу модели. Метод __init__() задает параметры будущей нейросети. Внутри него выбирается тип оптимизатора, задается метрика качества, функция потерь. На этом этапе в качестве атрибутов экземпляра класса прописывается сборка и компиляция для дискриминатора и генератора, схожие с тем примером, что мы рассмотрели выше. В методе build_generator() описываются слои нейросети генератора. Аналогичное происходит в методе build_discriminator() для дискриминатора. В методе train() происходит отдельное обучение генератора и дискриминатора и их состязание. В случае, если сгенерированная цифра окажется похожа на реальную, она будет сохранена на следующем шаге - в методе save_imgs().
Мы рассмотрели принцип работы GAN и можем оценить сложность подобной модели для создания дипфейка. Несмотря на то, что шаги, описанные выше, выглядят понятно, о написании дипфейков с нуля непрофессионалами говорить сложно. Оговоримся, что мы не рассматриваем дипфейки, которые создаются по заданному шаблону с помощью программ Doublicat, DeepNude и других. Мы преимущественно говорим о дипфейках, которые обладают высоким качеством и, что важно, работают с пользовательским датасетом для обучения.
Для создания дипфейка требуется умение писать код, опыт в машинном обучении, в работе с нейронными сетями и мощный компьютер с поддержкой OpenCL видеокарт. Решения, предоставляющие вычислительные мощности (например, GoogleColab), не подходят из-за ограничений по времени сеанса. Можно арендовать вычислительные мощности на виртуальных серверах, но это не бесплатно, поэтому собственный компьютер с одной или несколькими мощными видеокартами выглядит оптимальным решением. Почему, несмотря на такую сложную реализацию, количество дипфейков все растет? Неужели в мире такое большое количество специалистов по машинному обучению?
В настоящее время для создания даже такого качественного дипфейка необязательно писать код с нуля: существует несколько решений, которые позволяют создать дипфейк, запуская последовательность команд в командной строке. Для того, чтобы разобраться с готовым решением, требуется гораздо меньше времени, чем на то, чтобы выучить основы машинного обучения. Одно из таких публичных доступных решений - репозиторий DeepFaceLab, опубликованный на гитхабе. Попытаемся создать собственный дипфейк, чтобы проверить, может ли это осуществить человек, который никогда не выполнял подобные задачи. В качестве инструкции мы взяли комментарий, который был опубликован на сайте proglib.io DeepFake-туториал: создаем собственный дипфейк в DeepFaceLab // proglib URL: https://proglib.io/p/deepfake-tutorial-sozdaem-sobstvennyy-dipfeyk-v-deepfacelab-2019-11-16#comments (дата обращения: 12.04.2020)..
Для начала необходимо установить DeepFaceLab на компьютер. Так как в эксперименте мы пользуемся AMD видеокартой, скачиваем с гугл-диска файл DeepFaceLabOpenCLSSE. После разархивирования папки в заданную директорию необходимо загрузить в папку workspace ролики, на которых мы будем обучаться. Затем мы переходим в командную строку и выполняем последовательность команд для извлечения кадров видео. После этого запускаем код, который находит во всех указанных кадрах лицо и заменяет его. На следующем шаге нам вручную предстоит очистить группы неудачных кадров: нечетких или таких, которые не содержат лицо. После этого происходит обучение и склейка кадров, на выходе мы получаем дипфейк-видео.
На обучение было потрачено несколько суток, включая подготовку: устранение ошибок, общение с пользователями данной библиотеки на форуме для уточнения непонятных деталей. В процессе обучения сложнее всего было подготовить данные и разобраться в форматах экспортируемых видео. У многих пользователей возникала ошибка с воспроизведением в формате mp4. Экспорт в формате AVI частично решал ошибку, но в экспортируемом видео возникали проблемы со звуком.
Таким образом, у нас получилось создать дипфейк, который на данный момент не обладает высоким уровнем достоверности. Это случилось из-за малого времени обучения, а также из-за неудачного подбора исходного датасета изображений и того видео, на которое они должны были накладываться. При большем времени обучения и при более аккуратном подборе исходных данных дипфейк мог бы получиться более качественным. Этим экспериментом мы смогли показать, что в настоящее время создание дипфейков - задача, доступная даже начинающим программистам при наличии ресурсов и достаточного времени на подготовку. Это и объясняет не только интерес к дипфейкам, но и то, что их количество постоянно растет. Несмотря на то, что на данный момент создателей дипфейков в основном интересует создание пародийных и порнографических роликов, ситуация может измениться. Например, может возникнуть интерес к созданию общественно-политических видео. Публикация такого дипфейка через каналы медиа может стать причиной серьезного конфликта, виновной в котором останется само средство массовой информации. Именно поэтому СМИ уже сейчас важно учиться отличать дипфейки от реальных фото, видео или аудио. В следующей части мы рассмотрим код, предложенный участниками соревнования Kaggle для обнаружения дипфейков, анализ которого поможет нам сформировать универсальные рекомендации по обнаружению дипфейков сотрудниками СМИ в условиях отсутствия технических средств.