В мае 2015 года стало известно, что актер озвучивания мультсериала Симпсоны Гарри Ширер, чьим голосом говорят несколько ключевых персонажей, например, мистер Бернс и его ассистент Смитерс, покидает проект.
Причин тому сразу несколько. Во-первых, на тот момент сериал продолжался уже более 25 лет. Гонорары актеров все эти годы росли с 30 000 долларов за серию в 1998 году до 400 000 долларов с 2008 года. Однако такой расклад не устроил студию Fox: она пригрозила отменить подшефный сериал, если продюсеры не сократят оплату актеров хотя бы на 30%.
Почти все согласились с таким положением дел и продолжили работу. Однако Гарри Ширер, ранее уже критиковавший качество новых серий, отказался продлевать контракт. Двадцать лет в этой золотой клетке практически не оставляли ему свободного времени на собственные проекты. По словам шоураннера Эла Джина, на место Ширера планировалось нанять других актеров. На минуточку: рекасту могли подвергнуться в том числе директор Скиннер, Нед Фландерс и Отто Манн.
Но нельзя просто так взять и уйти из Симпсонов. Несколько месяцев спустя Ширер уступил студии и подписал новый контракт. Сериал и без того периодически ломает четвертую стену, а с экрана летят гэги о замене голосов озвучки. Но шутки шутками, а Симпсонам уже 32 года. Срок немалый, большая часть актеров уже перешагнула рубеж пенсионного возраста: большинству из них уже минуло 60, а то и 70 лет. Самому Ширеру уже 77. Есть вероятность, что в ближайшие годы он окончательно покинет проект уже по состоянию здоровья. То же самое может произойти и с другими голосами героев. Деньгами их не удержать: благодаря отчислениям за трансляции старых серий и озвучивание новых каждый из них сколотил состояние в десятки миллионов долларов.
Но может статься, что необходимость в содержании большого числа живых актеров вскоре отпадет сама собой. Не так давно персонаж Эдна Крабаппл (учительница Барта, была выведена из шоу после кончины актрисы Марсии Уоллес в 2013 году), снова появилась в сериале, на сей раз, чтобы окончательно проститься со зрителями. Для озвучки персонажа были использованы реплики, записанные при создании прошлых эпизодов.
Вычислительные мощности постоянно растут, на рынок регулярно выходят новые, улучшенные технологии. В частности, постоянно развиваются и совершенствуются инструменты создания дипфейков. Возможно ли, что скоро любого персонажа можно будет сымитировать компьютерным образом?
Дипфейк можно создать даже на основе небольшого количества обучающих данных. А в распоряжении Fox находится запас озвучек за целых 32 года. Давайте разберемся, стоит ли ждать выхода на экран Симпсонов, в озвучивании которых не были задействованы реальные актеры.
Безусловно создать эпизод Симпсонов, правдоподобно озвученный при помощи ИИ, возможно говорит Тим МакСмитурс, исследователь ИИ и медиа-продюсер, построивший речевую модель, которую можно обучить имитировать любой голос. Но будет ли интересно его смотреть это уже другой вопрос.
На своем YouTube-канале, Speaking of AI, МакСмитурс переделал культовую сцену из фильма Ноттинг-Хилл: в роли героини Джулии Робертс выступает Гомер.
В другом видео на канале МакСмитурса голосом Дональда Трампа говорит глуповатый Ральф Виггам.
МакСмитурс построил ИИ-модель, способную превращать любой письменный текст в речь на английском языке. Чтобы создать новый голос, достаточно обучить модель на двух-трех часах записей реального человека, снабженных письменной расшифровкой. По словам МакСмитурса, ИИ фокусируется на речевых особенностях персонажа: на том, что делает Гомера Гомером.
После обучения модель может сгенерировать несколько дублей одной и той же сцены, и каждый из них будет немного отличаться от предыдущего. Остается выбрать один наиболее удачный и использовать его в своих целях.
Синтезированный голос персонажа звучит ясно и узнаваемо, хотя и несколько плоско. Он лишен характерных эмоций, которые актер озвучивания может добавить герою от себя. Создается ощущение, что знакомый голос зачитывает текст с бумажки, не понимая, о чем именно говорит.
Всё зависит от набора обучающих данных говорит МакСмитурс. Если в модель не заложен широкий спектр эмоций, она не сможет их произвести из ничего. Так что искусственный Гомер звучит гораздо менее энергично, чем настоящий.
Задачу придания искусственному голосу эмоций решает британский стартап Sonantic. Специалистам удалось создать собственную методику создания эмоций в голосах, сгенерированных ИИ. Чтобы получить как можно больше интонированных обучающих данных, программисты привлекают настоящих актеров озвучки. За одну сессию актер проходит один и тот же текст несколько раз, произнося его с разной эмоциональной окраской.
Мы знаем, в чем заключается разница между сарказмом и искренним участием, умеем обрабатывать крошечные нюансы звука говорит Джон Флинн, соучредитель и технический директор Sonantic. Мы научились качественно считывать и масштабировать естественные особенности и акценты живой речи. По словам Флинна, количество данных, необходимых для обучения, удалось сократить с 30-50 часов до 10-20 минут на человека.
Видео от Sonantic с демонстрацией возможностей технологии искусственного интеллекта по имитации человеческих эмоций:
Компании Replica Studios из Брисбена удалось построить модель для воссоздания голоса, которую можно обучить на 20 записях конкретных предложений. Чем больше исходных данных, тем качественнее результат. Но кое-что интересное можно сделать и за пару-тройку минут говорит Шреяс Нивас, соучредитель и генеральный директор Replica.
Слова состоят из слогов, они, в свою очередь, из фонем, отдельных звуков, которые можно издавать с помощью речевого аппарата. Теоретически, необходимые для обучения данные реально получить и из одного единственного предложения, известного как фонетическая панграмма. Такие предложения содержат все фонемы, свойственные языку, а их итоговое произношение будет зависеть от акцента и особенностей произносящего.
Распространенная панграмма для английского языка выглядит следующим образом: The beige hue on the waters of the loch impressed all, including the French queen, before she heard that symphony again, just as young Arthur wanted.
Такой же (во всяком случае, сходный) пример для русского языка: Всё ускоряющаяся эволюция компьютерных технологий предъявила жесткие требования к производителям как собственно вычислительной техники, так и периферийных устройств.
Технология генерации голоса из текста кое-где уже применяется. Хороший пример видеоигры. Sonantic сотрудничает с компанией Obsidian, создателем некоторых игр серии Fallout и The Outer Worlds, а к услугам Replica прибегают и AAA-студии, и инди-разработчики. В частности, синтезированные фоновые диалоги позволяют наполнить открытый игровой мир гораздо большим количеством контента и сделать его живее. Подобный объем живых записей с участием актеров озвучивания стоил бы непомерно дорого и замедлил бы процесс производства игры.
Технология особенно полезна на ранних стадиях разработки: ИИ-голос можно использовать в качестве плейсхолдера и обкатать на нем различные варианты сценария. Когда всё будет готово, можно пригласить профессионального актера и записать реплики, не прерываясь на изменения и исправления.
В спортивных играх ИИ-голоса часто отдаются комментаторам (например, такой подход используется в FIFA для живого комментирования матчей). Существует также модификация для Cyberpunk 2077, которая позволяет изменить имя главного героя и заставить ключевых персонажей, которые обращаются к игроку, произносить его.
Если студия Fox решится делегировать ИИ работу над озвучкой тех же Симсонов, все эти навороты вряд ли пригодятся: диалоги заранее прописаны, а времени на качественную генерацию речи предостаточно. Но куда более вероятен сценарий, при котором место классических актеров займут люди с похожим тембром и сходными голосовыми возможностями. Если цель состоит в том, чтобы снять еще один эпизод шоу, ничего лучше, чем собрать актеров, вручить им сценарий и попросить прочитать реплики, не найдется. Они этим занимаются уже не один десяток лет, им под силу воплотить своих персонажей на высочайшем уровне говорит Нивас. Использование ИИ-актера потребует приложить гораздо больше усилий.
Помимо сугубо технических проблем, авторы шоу могут столкнуться с массой юридических проблем и нюансов.
При отсутствии каких-либо договорных отношений в игру вступает закон об авторском праве. Тот, кто владеет авторскими правами на Симпсонов, будет обладать всеми правами на воспроизведение готовых работ, включая записи актеров, а также правом на создание производных работ говорит Дженнифер Ротман, специалист по авторскому праву из Университета Пенсильвании.
Но это противоречит набору законов, регулирующих право свободы голоса. Актеры и исполнители могут контролировать несанкционированное использование своих имен, образов и, в том числе, записей своих голосов.
Например, создатель Family Guy (Гриффины) Сет МакФарлейн озвучил и Брайана, и Стьюи. Притом своим естественным голосом он говорит от имени пса. Голос младенца Стьюи же был придуман им специально для этого образа. Так что технически прав на Брайана у актера несколько больше. Тем не менее, поскольку МакФарлейн также является создателем сериала, очень сомнительно, что его голос кто-то может заменить на искусственный без согласия автора.
Еще один сходный прецедент имел место в 1993 году. Два актера из сериала Cheers, Джордж Вендт и Джон Ратценбергер, подали в суд на Paramount за использование своих образов в качестве промо в барах аэропортов. Актеры утверждали, что право на публичность дает им контроль над собственным имиджем, Студия же утверждала, что закон об авторском праве позволяет создавать и эксплуатировать производные работы на основе ситкома. Дело рассматривалось в суде восемь лет, и студия в конечном итоге согласилась выплатить актерам гонорар за несанкционированную рекламу. Сумма не раскрывается.
Но актерам озвучивания, вероятно, пока не требуется искать адвоката по авторскому праву. Ни один инструмент генерации голоса не разрабатывается с целью полностью заменить реальных актёров на дешевые ИИ-копии. И Sonantic, и Replica стремятся подчеркнуть, что они работают с живыми актерами и, согласно внутренней модели распределения доходов, люди, чьи голоса используются для синтеза в видеоиграх, получают регулярные отчисления.
Зина Куреши, генеральный директор и соучредитель Sonantic, сравнивает нынешние технологии генерации голоса с первыми днями CGI: Возможно воспроизвести голос реального актера, но не заменить его в фильме или сериале. CGI не лишил работы операторов, актеров, эта технология лишь помогает им работать лично и виртуально. Даже если человек уйдет на пенсию, его голос сможет работать за него.
МакСмитурс также проводит параллели с компьютерной графикой. По его словам, уже на данный момент возможно снять и озвучить эпизод Симпсонов без участия актеров озвучивания. Это будет долго, сложно, понадобится не одна сотня дублей. Тем не менее, вряд ли полученный результат выдержит испытание временем. Компьютерная графика начала 1990-х кажется современному зрителю неубедительной, устаревшей. То же самое произойдет с голосами. Тем не менее, можно использовать эту технологию во благо: например, для создания коротких фрагментов, призванных ненадолго вернуть умершего актера, чтобы он мог попрощаться со зрителем.
Актеры привносят в своих персонажей гораздо больше, нежели просто голос. Они дарят свои эмоции, чувства говорит МакСмитурс. Дэн Кастелланета наполняет двумерного Гомера своей теплотой, глубиной и прочими жизненно важными качествами, за которые мы его так любим. Настоящие люди очень хорошо умеют быть людьми.
Даны описание процедуры и её начальные входные данные. Требуется определить: завершится ли когда-либо выполнение процедуры с этими данными; либо, что процедура всё время будет работать без остановки.
ALGORITHM 1: Harm(R;D)Input: program R; input to the program Dif R(D) is harmful to humans thenreturn TRUEelsereturn FALSEend
Вы такой знаменитый ученый и получили Нобелевскую премию! Пожалуйста, расскажите в двух словах, что же изучает квантовая физика?
Фейнман задумался, а потом ответил:
Знаете что?.. Наверное я не могу этого сделать, потому что у вас не хватит знания терминологии для понимания того, что я вам расскажу. Возможно это неправильно и я подумаю над этой проблемой, как без специфических терминов, понимание которых требует длительного обучения рассказать о квантовой физике, но сейчас я к этому не готов.
>Это вы хорошо сравнили меня, вроде пока в гражданских человеческих правах никто не поражал, с насекомым
Вы, безграмотные обыватели, сомневающиеся трусы и прочие свободные граждане, имеющие мнение, поражаете меня в своих человеческих правах. Из-за ваших идиотских страхов, например, я вынужден был оставить идею сделать карьеру в сельхоз-биотехе, так как занимался именно ГМ культурами.
Именно из-за вас наша прикладная биотехнология отброшена на десятилетия по сравнению с передовыми странами.
Можете продолжать тешить себя правом называться человеком с большой буквы. Лично я имею право относиться к вам так, как написал.
Да, у исламистов, громящих древние статуи, небось тоже есть право на свое мнение. Будем толерантны и все такое.
Я люблю ввязываться в авантюры, и за последний месяц об одной из них я пару раз рассказывал друзьям, что вызывало восторг, поэтому решил поделиться с хабравчанами! Эта история про отважные пет-проекты, мощь опен-сорса и саморазвитие, а также основные технические детали. Надеюсь, вас это вдохновит :)
В первой половине 2016-го в свет вышел нашумевший FindFace, позволяющий загрузить фото человеческого лица и находить соответствующий профиль Вк. Он вызвал большой общественный резонанс, привёл как к поиску девушек по скрытым фоткам на эскалаторах в метро и к обнародованию порноактрис с неприятными последствиями для их близких, так и к находкам потерянных близких, к нереально быстрому поиску преступников по случайным кадрам с камер, прям как в американских фильмах, только наяву.
В то время мне об этом сервисе говорили и ленты новостей, и друзья, я отвечал "ну да, прикольно", и только. Но спустя пару лет, в начале октябре 2018 на каком-то айтишном форуме я захотел связаться с одним пользователем по специфическому вопросу, вот только он туда уже давно не заходил. Зато там было его хорошее фото, и тут-то я вспомнил про крутой сервис! Побежал на их сайт и разочаровался в сентябре 2018, буквально за месяц, они перестали предоставлять свои услуги физ.лицам, и бесплатно, и даже за деньги, перейдя в сегмент b2b и b2g. Оно и понятно, пиар уже сработал, а этических вопросов так возникает куда меньше. Но меня, законопослушного гражданина, это огорчило. И не только меня: фан-группы ФайндФейса пестрили сообщениями о том, что люди готовы заплатить в 10 раз больше, лишь бы им помогли найти нужного человека.
Я стал искать аналоги, но они все были либо точным поиском, но по крайне ограниченной выборке вроде нескольких сотен знаменитостей из Википедии, либо обширным, но почти бесполезным по точности поиском через Гугл/Яндекс.
Пару рабочих дней я размышлял, что же сложного в создании такого сервиса, который бы и точно искал людей, и по всему Вк? Решил, что ничего, ведь у меня тогда уже были базовые познания в data science, разработке и администрировании. Поэтому в пятницу, приехав с работы домой, я взялся за дело. За вечер я накидал скрипт, который парсит профили Вк, находит фото, индексирует по ним лица и сохраняет в БД. Потом просидел ещё пару суток почти без сна, заставил это дело безостановочно работать на своём сервере. Началась новая трудовая неделя, я был очень уставший, но ещё больше довольный и полный энтузиазма! Ведь мой скрипт медленно, но безостановочно бежал по всему Вк.
Как вы считаете, что происходит после того, как вы отправляете запрос в любую крупную поисковую систему? Не важно, поиск текста в Яндексе, Google или поиск лиц в FindFace или моём сервисе. Многие, особенно не-айтишники, с трудном представляют внутренние механики технических процессов, а они бывают нетривиальны даже казалось бы в простых задачах. В случае поисковых систем магия заключается в том, что при получении запроса они не начинают обегать все страницы в интернете, ища там ваш текст, или весь Вк, сравнивая вашу фотку со всеми подряд, это бы занимало астрономические объёмы времени. Вместо этого, поисковые системы сперва индексируют нужные данные. В случае текста (и подобных тексту данных вроде ДНК) в ближайшем приближении могут использоваться хэш-таблицы или префиксные деревья. В случае фоток тоже нужны индексы, которые сильно сократят время поиска. Для этого я использовал библиотеку face_recognition, которая позволяет преобразовать фото лица, если правильно помню, в 128-мерный вектор признаков со значениями от -1 до 1 (далее буду называть его просто хэш). Для поиска человека по фото, нам нужно просто пробежаться по всем фото из коллекции, считая евклидово расстояние между векторами-хэшами из запроса и набора подобный пример, реализованный на Питоне, доступен на сайте упомянутой библиотеки. Да, такая операция поиска тоже не дешёвая, но об этом позже.
В ближайшие недели я стал прикидывать темпы роста и понимать, что надо масштабироваться. API Вк работает на токенах доступа, и каждый токен имеет ограничения по числу запросов на единицу времени. Чтобы увеличить их число, я создал несколько приложений Вк с формами получения токенов и попросил пару десятков друзей выполнить там простой клик, что в итоге дало мне сотню токенов, которые я бережно сложил в файлик.
Конечно, не только лимиты АПИ повышать надо, но и объёмы CPU. Изначально я развернул скрипт на маленьком VPS, который создавался для простого личного сайта. В подмогу ему, я взял ещё один VPS, в несколько раз мощнее. Потом я решил, что и этого мало, взял ещё и целый выделенный сервер, который сильнее моего собственного рабочего компьютера :D Не энтерпрайз-левел, но производительность стала меня устраивать, хотя расходы и выросли до 15 тысяч руб/месяц, что для меня тогда было весьма ощутимой тратой.
Если у вас есть опыт в бэкэнд разработке, то сразу встаёт вопрос, как я заставил несколько серверов работать в тандеме, а не независимо, дублируя одну и ту же работу? На самом деле, решение классическое: один микросервис брал на себя роль ведущего, мастера, хранил состояние всей системы, и выдавал задания объёмом в тысячу профилей Вк воркерам, которые быстрее или медленнее их индексировали, а результаты, в том числе промежуточные, возвращали мастеру; если же мастер за определённый промежуток времени не получал ответа от воркера, он давал это задание другому, с учётом промежуточного прогресса.
Кстати, воркеры работали в несколько потоков. Да, Питон, благодаря Global Interpreter Lock, не умеет в полный параллелизм, но много времени уходило на выгрузку фоток, а IO-операции хорошо параллелятся. Вдобавок, это позволило легко назначить каждому потоку свой токен доступа и гибко настраивать загруженность каждой машины.
Для автоматизации настройки окружения, токенов и т.п были написаны скрипты на Питоне, которые подключались к целевой машине по SSH и ставили всё что нужно. Позже я узнал, что у меня костыльный велосипед, есть качественные решения, но всё равно было интересно посмотреть подноготные детали. Из прикольного, пришлось также разобраться, что есть разные ВМ и средства виртуализации, что некоторое ПО не работает в определённых конфигурациях, благодаря чему виртуалки на Xen и OpenVZ с казалось бы одинаковыми ресурсами могут отличаться в цене на 40%.
Помимо ролей мастера и воркера, есть роль поискового микросервиса. Проиндексированные фото Вк и айдишники их профилей сохраняются в БД, точнее, MySQL v5.7 и алгоритм поиска я переписал с Python на SQL, что позволило сильно ускорить вычисления и выйти на больший масштаб. Но с ростом данных этого всё равно было очень мало, я думал над оптимизациями, старался переиспользовать свой опыт big data аналитики с работы, экспериментировал с разными структурами запросов и генерацией SQL-запросов Питоном, это позволило ускорить вычисления в несколько раз, что мило, но всё равно мало.
Потом я решил сделать поиск двух-этапным: преобразовывать хэши-дробные-векторы в небольшой массив байт, сохраняя каждый признак в два бита: v>0.1 и v<-0.1 (здесь), затем сравнивая число совпавших бит такого хэша у целевого лица и всех лиц в БД, а потом фильтруя записи в БД по какому-то трешхолду, отправляя на более точное и медленное сравнение только потенциальных кандидатов. Пришлось повозиться и переехать на MySQL v8, т.к в 5.7 бинарных операций нет. Но это позволило ускорить поиск ещё почти в 30 раз а это уже клёво ^_^
Вообще, поиск можно было бы улучшать и дальше возможно подобрав более эффективные коэффициенты в операции выше, или переделав этот хэш, ещё было бы круто добавить параллелизм, которого в MySQL из коробки нет, партицирование, шардирование, и искать многопоточно; для этого в планах был переезд на PostgreSQL.
Когда у меня накопился большой объём данных, и мой сервис научился находить некоторую долю людей по случайным фоткам за приемлемое время, я стал мечтать дальше и задумываться о развитии функционала.
Ускорять время поиска можно не только ускорением самого поискового алгоритма, но и снижением выборки, например, ища профили только среди участников каких-то групп Вк. Ясное дело, здесь встаёт вопрос ограничения размера этой выборки, т.к делать запрос с "ISIN (десятки тысяч айдишников)" такое себе, а вот на паре сотен и даже тысяч работает в разы быстрее, чем полный проход БД.
Помимо прочего, я немного помешан на математике, множествах графах, а соц.сети это прекрасные данные и множеств, и графов! Я подумал, что можно двигаться в этом направлении, позволяя задавать сложные запросы с И-ИЛИ-деревьями. Притом, искать можно не только по фото, но и по ник-неймам или ссылкам на профили в других соц.сетях к сожалению, поисковики интернета и Вк эту инфу не очень индексируют, и я попробовал делать это сам.
Если идти ещё дальше, то можно индексировать не только Вк, но и ВотсАп, Тг перебрав все русские номера, возможно частично FB, Twi, Ig. Но это уже совсем будущее, я решил двигаться в сторону скорейшей апробации и монетизации того, что есть уже.
Перед разработкой ЛК, интеграции платежей и т.п декора, я решил больше разобраться в общественных настроениях, т.к некоторые мои знакомые выражали сомнения, что им было быы приятно пользоваться, а ещё серьёзнее быть доступными в таком сервисе. Помимо этого, примерно тогда же Вк ввёл закрытые профили, чтобы переживающее о своей безопасности люди могли спокойно скрываться, и анализируя статистику своих воркеров я видел, что число таких профилей всё растёт.
Я написал в тех поддержку Вк (тогда они ещё отвечали, ахах), аккуратно представился студентом, что хочу проводить социологические исследования скандируя большие объёмы данных Вк, в т.ч фото, ФИО и описание. Что на самом деле было правдой, с учётом моего интереса к аналитике и психологии. Они ответили, что ради статистики и небольших выборок в целом не против, но точно против какой-либо идентификации. А ещё "порадовали" тем, что будут и палки в колёса АПИ вставлять таким сервисам, и участвовать в разработке/внедрению законов, регулирующих эту деятельность. А недавно, уже в наше время, вышел законопроект, запрещающий автоматизированную обработку данных с сайтов, что по сути полностью блокирует подобные сервисы с парсингом.
В связи с этим, я принял решение о закрытии проекта, хоть это и было печально: в феврале 2019 у меня уже было проиндексировано 25% всего Вк в гигабайтах БД, притом не за бесплатно. Но у меня уже тогда был опыт различных проектов, поэтому я не жил розовыми мечтами об успешном успехе, а старался извлечь другую пользу и просто фан (:
Кстати, только в процессе написания этой статьи я понял, что принявшись за эту работу, я совсем забыл про исходный мотив, про того человека с какого-то сайта и свой вопрос к нему xD
После завершения описанной истории, я решил опубликовать
исходники, но т.к там в истории коммитов засветились токены, то
перезалил в новый репозиторий. Но код действительно такой, что мне
самому туда страшно заглядывать :D
https://github.com/AivanF/ID-Detective-public
Здесь, как и в других своих пет-проектах и стартапах, я набрался много опыта:
Разобрался с многопоточностью в Питоне.
Покопался в специфических вопросах оптимизации MySQL запросов.
Научился строить организацию приложений, файлов и комментов на будущее, чтобы оно не превращалось в спагетти.
Освоил работу из кода с SSH для настройки окружения, понял, насколько чудесен Ansible.
Разработал микросервисную архитектуру из клея и палок, что затем позволило легко понять концепции Kubernetes.
И всё это мне очень пригодилось в последующих работах и проектах.
Выводы каждый сделает свои, но главное не бойтесь пробовать, учиться и искать себя! Надеюсь, вам было интересно :)
Управляемые складки одежды и морщины, фотореалистичные симуляции вождения, естественное освещение объектов при смене фона, китайский аналог DALL-E и многое другое: встречайте подборку самых интересных исследований и нейросетевых моделей, которые появились в прошедшем месяце.
Доступность: страница проекта / статья / репозиторий
Современные методы монокулярной трехмерной реконструкции создают лица, которые невозможно реалистично анимировать, поскольку они не моделируют изменение морщин в зависимости от выражения. Также модели, обученные на высококачественных сканированных изображениях, плохо работают на фото, сделанных в естественных условиях.
Данный подход регрессирует трехмерную форму лица и анимируемые черты лица, которые меняются в зависимости от артикуляции. Модель обучена создавать карту UV-смещений из низкоразмерного скрытого представления, которое состоит из специфичных для человека параметров, а регрессор обучен предсказывать параметры формы, позы и освещения из одного изображения. Для этого авторы создали функцию потерь, которая отделяет индивидуальные особенности лица от морщин, которые зависят от артикуляции. Такое разделение позволяет синтезировать реалистичные морщины, характерные для конкретного человека, и управлять параметрами выражения лица, сохраняя при этом индивидуальные особенности человека.
Доступность: страница проекта / статья
Симуляция деформации и движения одежды на человеке часто приводит к тому, что текстура одежды проникает внутрь модели тела. Существующие методы виртуальной примерки требуют этап постобработки, чтобы устранить этот нежелательный эффект. Данный подход напрямую выводит трехмерные конфигурации одежды, которые не пересекаются с телом.
Модель симулирует деформацию одежды и реалистичное движение складок в зависимости от изменения позы. Достигается это с помощью новогоканонического пространства для одежды, которое устраняет зафиксированные диффузной моделью человеческого тела деформации позы и формы, которая и экстраполирует свойства поверхности тела, такие как скиннинг и блендшейп, на любую трехмерную точку.
Доступность: страница проекта / статья
Для автопилотов и реалистичных тренажеров нужны данные, которые приходится собирать вручную, а это очень долгий и трудоемкий процесс. Можно использовать машинное обучение, чтобы стимулировать ответную реакцию среды на действия непосредственно из данных. Исследователи из NVIDIA и MIT обучили нейросеть на сотнях часов дорожных видео, чтобы моделировать динамическую среду непосредственно в пиксельном пространстве на основе неразмеченных последовательностей кадров и связанных с ними действий.
В получающихся синтезируемых дорожных путешествиях можно моделировать погодные условия, время суток и расположение объектов. Симуляцией можно управлять через графический интерфейс с помощью поворотов руля и изменения скорости.
Доступность: страница проекта / статья / репозиторий
Пока приходится ждать симулятор езды от NVIDIA, можно развлечь себя с помощью разработок от исследователей из Intel. Они представили подход к повышению реалистичности синтетических изображений. Сверточная нейросеть использует промежуточные представления, созданные обычными пайплайнами рендеринга, что позволяет добиться фотореалистичной картинки в GTA V.
Доступность: онлайн-демо / статья / репозиторий
Новая нейросеть для перевода текста в изображение. В основе модели трансформер на 4 миллиарда параметров и токенизатор VQ-VAE. Создатели утверждают, что их модель работает лучше DALL-E от OpenAI, и в статье также делятся подходом к файнтюнингу модели для решения других задач вроде обучения стилю, улучшению разрешения, а также стабилизации предварительного обучения.
Попробовать модель можно уже сейчас, правда онлайн-демо пока понимает только текст на китайском.
Доступность: публикация в блоге / статья / репозиторий
В отличие от человеческой памяти, большинство нейронных сетей обрабатывают информацию целиком, без разбора. При небольших масштабах это не вызывает проблем. Но современные крупные модели, которые на вход принимают полноценные книги или десятки часов видеозаписей, требуют все больше вычислительные мощностей.
Исследователи из FAIR решили научить модели забывать информацию, чтобы фокусироваться только на том, что имеет значение. Сначала модель предугадывает информацию, которая наиболее актуальна для поставленной задачи. В зависимости от контекста, данным присваивается дата истечения срока действия, с наступлением которой информация выбрасывается моделью.
Доступность: публикация в блоге / статья / репозиторий
Есть много моделей распознавания речи, которые превосходно справляются с распространенными языками. Но множество диалектов все еще не поддерживаются этими технологиями. Это связано с тем, что высококачественные системы необходимо обучать с использованием большого количества размещенных аудиозаписей. Исследователи FAIR представили версию модели wav2vec-U, которая обучается без учителя и вообще не требуют размеченных данных.
Доступность: страница проекта / статья / репозиторий
Существует много качественных моделей для переноса стиля. В большинстве из них процесс стилизации ограничен оптимизацией пикселей. Это не совсем естественно, так как картины состоят из мазков кисти, а не пикселей. Данный метод предлагает стилизовать изображения путем оптимизации параметризованных мазков кисти и дифференцируемого рендеринга. Этот подход улучшает визуальное качество и обеспечивает дополнительный контроль над процессом стилизации пользователь может управлять потоком мазков.
Доступность: страница проекта / статья
Когда вы сидите перед телевизором или монитором, ваше лицо активно освещается изменяющимся потоком света с экрана. Исследователи обучили нейронную сеть, которая принимает на вход фото лица и текущую картинку на мониторе и предсказывает, как будет выглядеть лицо в таком освещении с монитора. Таким образом, можно контролировать виртуальное освещение лица для видео с вебкамеры. Можно предстать перед коллегами в выгодном свете при очередном видеосозвоне.
Доступность: страница проекта / статья
Исследователи из GoogleAI пошли дальше и представили систему, которая способна заменить фон фотографии и скорректировать освещение человека на ней, сохраняя четкими границы объектов. На вход подаются две фотографии портретный снимок и картинка с новым окружением. Исследователи отмечают, что пока модель плохо справляется с альбедо, из-за чего некоторые типы одежды и глаза могут выглядеть неестественно.
Доступность: страница проекта / статья
Работа со светом и тенью также нужна для качественного удаления объектов с изображений. Новая нейросеть от исследователей Google может автоматически связывать предметы в видео и вызванные ими эффекты в сцене. Это могут быть тени и отражения, а также рябь от объектов в воде или вообще посторонние объекты, движущиеся рядом, например, собака на поводке. На вход подается грубая маска объектов, а на выходе отдается два видео с фоном и с отдельно вырезанным объектом.
Доступность: страница проекта / репозиторий
Создатели объединили подход с преобразованием фото в карандашный набросок с возможностями управления скрытым пространством GAN для сохранения эффектов освещения, реалистичности текстур и т.д. Таким образом для редактирования на вход подается оригинальное фото лица человека, оно преобразуется в скетч, который можно изменять штрихами.
Доступность: репозиторий
Новый нейросетевой фотошоп, на этот раз от исследователей из корейской компании Naver. Метод позволяет редактировать отдельные области изображений. Как и у решений, которые мы рассматривали в апреле, здесь та же задача управление скрытыми векторами генеративно-состязательной сети. В их подходе промежуточное скрытое пространство имеет пространственные измерения, и пространственно изменяющаяся модуляция заменяет адаптивную раздельную нормализацию. Таким образом кодировщик более точно создает вектора чем методы, основанные на оптимизации с сохранением свойств GAN.
Доступность: онлайн-демо / статья / репозиторий
Китайские исследователи из Alibaba представили модель для реставрации размытых фото низкого качества, который в отличие от методов на основе GAN, создает не чрезмерно сглаженные изображения. Для этого модель использует GAN, чтобы сгенерировать высококачественное изображения лица, которое предварительно декодируется с помощью U-образной DNN.
Доступность: репозиторий
Исследователи из IBM представили крупнейший открытый датасет для проведения бенчмарков с участием программного кода. Набор данных содержит 500 миллионов строк кода на 55 языках программирования, включая C ++, Java, Python, Go, COBOL, Pascal и FORTRAN. CodeNet фокусируется на обнаружении сходств и отличий кода, чтобы продвигать разработку систем, которые смогут автоматически переводить код с одного языка программирования на другой.
Доступность: страница проекта / статья
Современные глубокие сети чрезвычайно требовательны к данным, поэтому обучение на крупномасштабных наборах данных требует много времени на разметку. NVIDIA представили генератор синтетических аннотированных датасетов для создания массивных наборов данных, который требует минимальных человеческих усилий. Метод основан на современных GAN и предлагает способ декодирования скрытого пространства для семантической сегментации изображений. Код обещают скоро опубликовать.
Доступность: репозиторий
Исследователи из Сбера опубликовали датасет с русским корпусом, подходящий для исследования речи. Набор данных в основном состоит из записанных и вручную размеченных аудиофайлов. Общая продолжительность аудиозаписи около 1240 часов.
исходный код и онлайн-демо BlazePose от Mediapipe. Технология позволяет распознавать позы человека в реальном времени даже на маломощных устройствах.
На этом все, спасибо за внимание и до встречи в следующем месяце!
Писать игровой AI очень интересно и увлекательно - не раз убеждался в этом на личном опыте. Недавно, случайно наткнувшись на код своего старого проекта шахматной программы, решил его немного доработать и выложить на GitHub. А заодно рассказать о том, как он создавался и какие уроки преподал мне в процессе работы.
Это случилось в 2009 году: я решил написать простую шахматную программу, чтобы попрактиковаться в разработке игрового AI. Сам я не шахматист и даже не сказать что любитель шахмат. Но задача для тренировки вполне подходящая и интересная. Кроме того, играя в шахматы на доске или в программе, мне всегда было любопытно, почему тот или иной ход сильнее другого. Хотелось возможности наглядно видеть всё дерево развития шахматной позиций. Такой фичи в других программах я не встречал - так почему бы не написать самому? Ну а раз уж это тренировка - то придумывать и писать нужно с нуля, а не изучать другие алгоритмы и писать их собственную реализацию. В общем, думаю, дня за три можно управиться и сделать какой-то рабочий вариант :-)
Обычно шахматные движки используют поиск в глубину с алгоритмом "ветвей и границ" для сужения поиска. Но это не очень-то наглядно, поэтому решено: мы пойдём своим путём - пусть это будет поиск в ширину на фиксированную глубину. Тогда в памяти будет полное дерево поиска, которое можно как-то визуализировать. А также выяснить: а) на какую глубину можно просчитать шахматную игру в рамках имеющихся ресурсов CPU и памяти, б) насколько хорошо или плохо будет играть такой алгоритм?
Надо сказать, что на тот момент у меня был 2-ядерный процессор с 2 или 4 Гб памяти (точно уже не помню), 32-битная винда и 32-битный компилятор Turbo Delphi Explorer. Так что если временем работы ещё можно было как-то пожертвовать, то доступная процессу память была ограничена 2Gb. Про PE flag, расширяющий user memory до 3Gb я тогда не знал. Впрочем, поскольку память кушают и система, и Delphi и другие программы - для шахмат, чтобы не уходить в своп, доступно менее гигабайта.
В результате получилась первая версия игры, состоящая из таких модулей:
UI - основное окно, отрисовка доски с фигурами.
Игровая логика - составление списка возможных ходов, выполнение хода, детекция завершения игры.
AI:оценка - оценочная функция позиции.
AI:перебор - поиск в ширину через очередь.
UI:браузер - окно визуализации дерева поиска, в котором можно наглядно изучать как всё работает.
Выяснилось что:
Поиск на глубину 3 полухода работает быстро - меньше секунды, и расходует немного памяти - 5-15 Мб. А вот поиск на глубину 4 полухода работает уже довольно долго и расходует большую часть доступной памяти. В отдельных ситуациях памяти и вовсе не хватает.
При глубине поиска в 3 полухода уровень сложности - "младшая школа": компьютер вроде как-то играет, не позволяет "зевнуть" фигуру, не упускает возможность поставить "вилку". Но в то же время допускает грубые ошибки и легко попадается в ловушки. В общем, очень слабый соперник.
При любой глубине поиска, компьютер совершенно не умеет играть в эндшпиле и не понимает что делать, если у противника остался один король.
Таким образом, вырисовались направления дальнейшей работы: углубить поиск, научить позиционной игре а также научить играть в эндшпиле. И многие проблемы можно решить за счёт оценочной функции.
Функция оценки позиции - важнейший компонент любого шахматного движка. Где-то она предельно простая и быстрая - учитывает лишь количество фигур и их стоимость, а где-то - сложная и учитывает множество факторов. Поскольку в моём случае количество оцениваемых позиций ограничено объемом памяти, имеет смысл использовать сложную оценочную функцию и заложить в неё как можно больше факторов.
В итоге пришел к примерно такому алгоритму:
Для каждого игрока:
Подсчитать стоимость фигур: конь - 3, ладья - 5 и т.д. Начальная стоимость пешки - 1, но она растёт по мере её продвижения.
Бонус за сделанную рокировку, штраф за потерю возможности рокировки, штраф в миттельшпиле за невыведенные фигуры (коней и ладьи в углах). Штраф за сдвоенные пешки и бонус за захваченные открытые линии.
Определение какие поля находятся под боем и кем. Это медленная операция - основная часть времени выполнения оценочной функции тратится именно здесь. Зато польза от неё колоссальная! Незащищённая фигура под боем на ходу противника - минус фигура. Защищённая - минус разность стоимости фигур. Это позволяет получить эффект углубления поиска на 1-2 уровня.
Если остался один король: штраф за расстояние от центра доски и штраф за расстояние до короля противника. Такая формула в эндшпиле заставляет AI стремиться прижать короля противника к краю доски, т.е. получить позицию, из которой можно найти возможность поставить мат.
Итоговая оценка = (white_rate - black_rate) * (1 + 10 / (white_rate + black_rate)). Эта формула делает разницу более значимой в эндшпиле, заставляя отстающего игрока избегать размена фигур, а ведущего - наоборот, стремиться к размену.
Прежде всего, несмотря на доработку оценочной функции, углубление поиска необходимо для ходов со взятием а также шахов. Для этого добавлен новый атрибут узла - вес, который используется вместо глубины. Если дочерний узел порождается обычным ходом - его вес уменьшается на 1, если ходом со взятием - на 0.4, если ходом с шахом - не уменьшается вовсе. Узлы с положительным весом возвращаются в очередь поиска и получают продолжение.
Кроме того, нужно развивать наиболее перспективные направления - ветки с наибольшей оценкой.
В итоге алгоритм получился такой:
На первой стадии строится дерево с базовой глубиной 3 (при этом ветки со взятиями и шахами могут достигать заметно большей глубины).
Оценка дерева алгоритмом минимакс.
Если выполнены критерии принятия решения - выбирается ветка с наилучшей оценкой и алгоритм завершается.
Обрезка дерева: последовательно удаляются ветки с наихудшей оценкой пока не будет свободно достаточно памяти для продолжения поиска.
Переход к следующей стадии: добавляем вес всем листьям дерева и продолжаем поиск. После завершения переходим к п 2.
Критерии принятия решения:
Осталась единственная ветка - выбора нет.
Одна из веток имеет оценку существенно более высокую чем у остальных - выбираем её.
Истекло время на ход - выбираем ветку с наилучшей оценкой.
В процессе работы больше всего времени тратится на оценочную функцию. Но бывает, что в ходе поиска одни и те же позиции встречаются несколько раз: в одно и то же состояние можно прийти различными путями. Возникает мысль: почему бы не кэшировать результат оценочной функции?
Всё просто: нужно вычислить хэш от позиции и если в кэше уже есть оценка с таким хэшем - использовать её вместо вычисления. А если нет - вычислить и сохранить в кэше оценок. Основная проблема - нужна достаточно качественная и быстрая хэш-функция. После множества экспериментов получилось написать приемлемую функцию, вычисляющую 64-битный хэш. Общее количество возможных шахматных позиций значительно больше 264, но количество позиций, оцениваемых в ходе партии значительно меньше 232, поэтому более-менее качественная хэш-функция должна свести вероятность хэш-коллизий к минимуму.
Процент "попаданий" в кэш в ходе игры получился в районе 30-45%, но в эндшпиле достигает 80-90%, что даёт ускорение почти в 5-10 раз, а следовательно позволяет увеличить глубину поиска. Неплохой выигрыш!
Я добавил библиотеку дебютов, и в таком состоянии программа играла уже довольно неплохо - примерно на уровне 2-го разряда, а может и чуть сильнее. Результат, в принципе, достойный - можно остановиться. Хотя были вполне очевидны недостатки и направления развития:
AI работает в один поток - ресурс CPU задействован не полностью.
А что если предоставить больше памяти?
AI думает только во время своего хода. Почему бы не использовать время соперника для просчёта наиболее вероятных продолжений?
Главная слабость: детерминированность. Каждый ход рассматривается как отдельная задача, каждая позиция приводит к детерминированному решению. Достаточно выиграть один раз, чтобы запомнить последовательность ходов, которая всегда приведёт к победе. А играть с таким соперником неинтересно.
Однако, к этому времени код проекта уже достаточно "замусорился" и требовал рефакторинга. Поскольку на него и так уже было потрачено много времени, я решил его забросить.
Недавно наткнувшись на этот заброшенный проект, решил всё-таки привести его код в порядок и доработать. Доработки сделал такие:
Многопоточность: сейчас у меня уже 8-поточный, а не 2-поточный CPU, поэтому многопоточный вариант даёт серьёзную прибавку в скорости.
64-битный режим: кроме возможности использовать больше памяти, было любопытно, будет ли алгоритм работать быстрее на архитектуре x64. Как ни странно, оказалось что нет! Хотя отдельные функции на x64 работают быстрее, в целом версия x86 оказалась на 5-10% быстрее. Возможно 64-битный компилятор Delphi не очень хорош, не знаю.
Больше памяти: даже в 32-битном режиме за счёт PE-флага расширения адресного пространства доступной памяти стало больше. Однако практика показала, что больше 1 Гб памяти все-равно не нужно - разве что для хранения "обрезанных" ветвей дерева. К усилению игры увеличение памяти не приводит.
Непрерывность поиска: теперь дерево поиска не создаётся с нуля каждый ход, а создаётся лишь в начале партии. Когда делается ход - неактуальные ветви дерева обрезаются а поиск продолжается с того состояния, которое было. В том числе и во время хода соперника - идёт проработка перспективных продолжений, поэтому когда соперник сделает ход, поиск продолжится не с нуля. Быть может и вовсе получится сразу же сделать ход. Момент времени, когда игрок сделает ход - это фактор случайности, который делает игру недетерминированной. Теперь уже нельзя запомнить выигрышную последовательность ходов.
Оценка дерева. Ввёл новый атрибут узла - качество оценки. Качество равно сумме качества всех прямых потомков, умноженное на коэффициент затухания. Т.е. качество оценки показывает проработанность ветки.
Углубление поиска. Качество оценки вместе с самой оценкой учитывается при выборе веток для углубления поиска. Чем выше оценка и чем ниже её качество - тем выше приоритет такой ветки для её развития. Потому что мало смысла до посинения развивать и так хорошо проработанную ветку с максимальной оценкой, которая уже вряд ли существенно изменится, когда она сравнивается со слабо проработанными ветками, чья оценка может значительно измениться.
База оценок и самообучение. В процессе игры какие-то позиции детально прорабатываются и получают оценку с высоким качеством. Почему бы не сохранять такие оценки для использования в других партиях? Это ещё одна фича, которая делает игру недетерминированной.
В результате этих доработок AI стал сильнее, и вполне уверенно обыгрывает старую версию игры. Я провел несколько партий против AI на chess.com и выяснил, что уровень моей программы примерно соответствует рейтингу 1800-1900. Прогресс есть, и это хорошо!
Программирование игрового AI - занятие чертовски затягивающее: всегда хочется добиться большего. И хотя у меня по прежнему есть масса идей для дальнейшего развития, наступает момент, когда надо остановиться. Думаю, он наступил. Однако если кто-либо желает - может взять мой код, побаловаться, поэкспериментировать, что-нибудь реализовать. Благо, сейчас Delphi доступен каждому благодаря бесплатной Community Edition, не говоря уже про бесплатный Free Pascal и Lazarus. Код проекта (а также скомпилированный exe-шник) можно взять тут: https://github.com/Cooler2/chess (для компиляции понадобится также кое что из https://github.com/Cooler2/ApusGameEngine). Спасибо всем, кто дочитал :-)
В последние годы мы наблюдаем взрывной рост популярности многопользовательских онлайн-игр, которые покоряют сердца миллионов игроков во всем мире. В результате этого многократно растут требования к гейм-дизайнерам, потому что игроки хотят видеть продуманную механику и баланс. Ведь нет никакого интереса, если одна стратегия заметно превосходит все остальные.
При разработке игрового процесса баланс обычно настраивается по следующей схеме:
Проводятся тысячи игровых партий с участием тестировщиков.
Собираются отзывы и на их основании в игру вносятся корректировки.
Шаги 1и2 повторяются, пока результат не устроит и тестировщиков, и гейм-дизайнеров.
Этот процесс не только времязатратный, но и несовершенный. Чем сложнее игра, тем вероятнее, что незначительные недостатки останутся незамеченными. Когда в играх много разных ролей с десятками взаимосвязанных навыков, добиться правильного баланса оказывается очень сложно.
Сегодня мы представляем механизм на базе машинного обучения, который помогаетадаптировать игровой балансза счет обучения моделей, выступающих в роли тестировщиков. Мы продемонстрируем подход на примере экспериментальной компьютерной карточной игрыChimera. Мы уже показывали ее в качестве опытной системы дляграфики, сгенерированной алгоритмом машинного обучения. При таком тестировании обученные программные агенты проводят между собой миллионы партий. Из их результатов собирается статистика, которая помогает гейм-дизайнерам улучшать баланс, совершенствовать игру и приближать ее к первоначальному замыслу.
Мы задумывалиChimeraкак экспериментальную игру, при разработке которой будет активно использоваться машинное обучение. Для нее мы сознательно предложили такие правила, которые расширяют возможности и серьезно усложняют создание традиционных игровых ИИ-алгоритмов.
В Chimera игроки из других существ создаютхимер, которых нужно развивать и делать сильнее. Цель игры победить химеру противника. Игровой процесс включает в себя основные моменты, описанные ниже.
Игроки могут использовать:
существ, которые атакуют (урон зависит от показателяатаки)или защищаются (теряя показательздоровья);
заклинания, которые дают особые эффекты.
Существа вызываются вбиомыограниченной вместимости, которые размещаются на игровом поле. У каждого существа есть предпочтительный биом, и оно получает постоянный урон, если окажется в неподходящем или перенаселенном биоме.
В самом начале игрок получает зародыш химеры, который нужно развивать и делать сильнее, добавляя фрагменты других существ. Для этого игрок должен набрать достаточное количествоэнергии связииз разных источников.
Игра заканчивается, когда игрок доводит здоровье химеры противника до нуля.
Chimera это карточная играс неполной информациейи большим пространством состояний, поэтому мы думали, что модели будет сложно научиться в нее играть. Особенно учитывая то, что мы собирались применять относительно простую модель. На вооружение был взят подход, использовавшийся в ранних игровых агентах, таких какAlphaGo, когдасверточную нейронную сеть(CNN) обучают предсказывать вероятность выигрыша по произвольному игровому состоянию. Первую модель мы обучили на играх с произвольными ходами, а затем заставили агента играть против самого себя, собирая данные для обучения последующих его итераций. С каждым разом качество данных повышалось, как и игровые навыки агента.
Результаты игры агента против лучшего написанного вручную ИИ-алгоритма по мере обучения. Исходная нулевая версия агента делала ходы случайно.В качестве игрового состояния, которое подается на вход CNN, мы выбрали кодированное изображение. Такой подход оказался эффективнее всех процедурных агентов и нейронных сетей других типов (например, полносвязных). Выбранная архитектура модели достаточно компактная, чтобы ее можно было выполнять на ЦП за разумное время. Поэтому мы загрузили веса модели и запускали агент в реальном времени в клиенте игры Chimera на платформеUnity Barracuda.
Пример кодированного игрового состояния, на котором обучалась нейронная сеть.Помимо принятия игровых решений модель использовалась, чтобы показывать приблизительную вероятность выигрыша игрока во время игры.Наш подход помог смоделировать на много миллионов больше матчей, чем живые игроки смогли бы сыграть за тот же период времени. Собрав данные из игр самых успешных агентов, мы проанализировали результаты и нашли дисбаланс между двумя придуманными нами игровыми колодами.
Первая,Evasion Link Gen,состояла из заклинаний и существ со способностями, которые давали дополнительную энергию связи, необходимую для развития химеры. В ней также были заклинания, позволявшие существам уклоняться от атак. В колодеDamage-Healнаходились существа с разными показателями силы и заклинаний, лечившие и наносившие незначительный урон. Мы думали, что эти колоды будут примерно равносильны, однакоEvasion Link Genпобеждала в 60 % случаев при игре противDamage-Heal.
Собрав разные показатели по биомам, существам, заклинаниям и развитию химер, мы сразу увидели две вещи:
Развитие химеры давало явное преимущество агент, развивший свою химеру больше своего оппонента, побеждал в большинстве игр. При этом среднее число эволюционных этапов на игру не соответствовало нашим ожиданиям. Мы хотели сделать развитие ключевой составляющей игровой механики и увеличить общее среднее количество эволюционных этапов.
Существо Тирекс оказалось чересчур сильным. Его появление в игре тесно коррелировало с победами, и модель всегда старалась играть с Тирексом, невзирая на штрафы за его вызов в неподходящий или перенаселенный биом.
На основании этих наблюдений мы внесли в игру некоторые изменения. Чтобы поощрять развитие химеры, мы сократили количество энергии связи, необходимой для эволюции, с трех до единицы. Мы также добавили период восстановления для Тирекса: теперь после любого действия ему приходилось ждать в два раза дольше, чтобы выполнить следующее действие.
Повторив игру модели против самой себя с обновленными правилами, мы заметили, что игра изменилась в нужном направлении среднее число эволюционных этапов увеличилось, а Тирекс перестал доминировать.
Сравнение влияния Тирекса до и после корректировки баланса. На диаграммах показано количество выигранных (или проигранных) игр, когда в колоде используется определенное заклинание (например, заклинание для уклонения, повышающее характеристики Тирекса). Слева: до изменений Тирекс оказывал серьезное влияние по всем оцениваемым показателям самый высокий коэффициент выживаемости, наибольшая вероятность вызова даже при штрафах, самое часто поглощаемое существо при победах. Справа: после изменений Тирекс стал гораздо менее мощным.Ослабив Тирекса, мы снизили зависимость колодыEvasion Link Genот чрезмерно сильного существа. Но даже при этом соотношение побед сохранилось на уровне 60/40 вместо 50/50. При детальном рассмотрении журналов отдельных игр стало видно, что они часто велись без продуманной стратегии. Проанализировав данные снова, мы обнаружили ряд других областей, где можно было внести изменения.
Мы увеличили начальный уровень здоровья обоих игроков, а также эффективность лечащих заклинаний. Это помогло увеличить продолжительность игр и разнообразить стратегии. В частности, это позволило игроку с колодойDamage-Healдержаться достаточно долго, чтобы получить преимущество от своей стратегии лечения. Чтобы игроки с умом подходили к вызову существ и их размещению, мы увеличили штрафы за использование существ в неподходящих или перенаселенных биомах. Наконец, мы сократили разрыв между самыми сильными и слабыми существами, немного изменив атрибуты.
С новыми корректировками мы получили итоговые сбалансированные показатели для двух колод:
Обычно на поиск дисбаланса в новых играх могут уходить месяцы тестирования. Рассмотренный здесь подход помог нам не только выявить возможные недостатки баланса, но и внести корректировки для их устранения за считаные дни. Мы выяснили, что относительно простая нейронная сеть способна обеспечить высокую эффективность при игре против человека и традиционного ИИ. Такие агенты можно использовать и в других целях, например при обучении новых игроков и поиске неочевидных стратегий. Мы надеемся, что эта работа вдохновит на дальнейшее изучение возможностей машинного обучения в разработке игр.
Этот проект был реализован при поддержке множества людей. Мы благодарим Райана Поплина, Максвелла Ханнамана, Тейлора Стейла, Адама Принса, Михала Тодоровича, Сюэфан Чжоу, Аарона Каммарата, Эндипа Тура, Транга Ле, Эрин Хоффман-Джон и Колина Бозвела. Спасибо всем, кто участвовал в игровом тестировании, давал советы по игровому дизайну и оставлял ценные отзывы.
Некоторое время назад мы искали оптимальное аппаратное и программное обеспечение для исполнения нейронных сетей в ЦОД и "на краю" (edge computing). В рамках нашего исследования мы протестировали множество устройств, от процессоров до встроенной графики iGPU и GPGPU различных производителей. С результатами исследования можно ознакомиться по ссылке.
В рамках этого исследования нас заинтересовал VPU Intel Movidius (MyriadX). При вычислениях "на краю" и использовании фреймворка Intel OpenVINO он позволял нам увеличивать число потоков или каналов путем дооснащения существующих устройств без какой-либо модификации аппаратной и программной базы. По умолчанию мы использовали встроенную графику, например, Intel HD или Iris Plus 655, но если FPS и число потоков необходимо было увеличивать, то промышленные ПК можно было дооснастить VPU. Это давало возможность сохранить единообразие множества устройств при изменяемом числе потоков. В качестве примера можно привести транспортную отрасль и подсчет пассажиров на борту автобусов. Автобусы бывают с 2, 3 и 4 дверьми. И если для двух дверей достаточно встроенной графики, то для четырех необходимо увеличение FPS, что достигалось расширением готового решения при помощи VPU формата M.2.
Вот так выглядело наше устройство для исполнения нейронных сетей "на краю" с Intel Movidius:
ComBox Outdoor Box SquaredСегодня для инференса "на краю" интерес представляют решения от компании AAEON, в частности VPC-3350S, VPC-3350AI:
AAEON VPC-3350SОни отличаются расширенным температурным диапазоном эксплуатации -20+70 градусов, наличием возможности расширения двумя VPU Movidius, широкой линейкой поддерживаемых процессоров от Intel Atom x5 E3940 до Pentium N4200 или Atom x7 E3950, а также наличием 4 PoE Ethernet портов для подключения камер или иного оборудования.
С использованием Movidius в IoT все было более или менее понятно, но нас заинтересовала хотя бы теоретическая возможность масштабирования и применения этих компактных энергоэффективных чипов в ЦОД в виде ускорителей инференса PCIe формата.
Суммарный объем рынка публичных и частных облаков в России по данным IDC с 2019 года растет минимум на 25% в год, что на 2019 год составляло $1,72 млрд., а на 2020 год увеличилось до $2,2 млрд. Доля публичных облаков в общем объеме рынка в 2019 году 84,6%. Несмотря на то, что облачный рынок претерпел ряд структурных изменений в 2020 году, рост продолжается с частичным, но постоянным увеличением объемов облачных вычислений в системах искусственного интеллекта прикладного уровня, например, видеоаналитике для обработки ранее сформированных видеоархивов.
После предварительной оценки рынка мы провели поиск имеющихся решений в формате PCIe. Все найденные на тот момент устройства содержали 4 или 8 Movidius на одну плату. Например, решения от AAEON:
AAEON AI CORE XP4/ XP8Общее назначение имеющихся устройств - инференса "на краю". И вот здесь родилась идея реализации собственного ускорителя инференса нейронных сетей для ЦОД с чипами Movidius высокой плотности.
Сейчас в этой сфере используются два основных устройства: GPGPU nVidia Tesla T4 и ускорители инференса Huawei Atlas 300. Альтернатив по производительности от компании Intel для дооснащения существующих систем или внедрения новых серверных решений нет. Возможное решение, сопоставимое по производительности и стоимости - это ускоритель на основе VPU Movidius (MyriadX) высокой плотности в форм-факторе PCIe с плотностью не менее 64 Movidius на каждой несущей плате.
Требования:
плотность чипов Movidius не менее 64 штук на каждую плату
наличие возможности изменения числа VPU на плате
минимально возможное энергопотребление
форм-фактор PCIe x4/x8
работа конечного устройства под управлением фреймворка Intel OpenVINO без каких-либо значимых доработок
исполнение под использование в серверных платформах
Концепт не заставил себя долго ждать:
ComBox x64 Movidius Blade BoardComBox x64 Movidius Blade BoardРезультатом проектирования платы получилось устройство PCIe с размещенными на несущей плате кастомными разъемами для подключения дочерних плат с нанесенными на них VPU. Таким образом конечную плату можно использовать с числом VPU до 64 штук, кратно 8. На каждый разъем отведена 1 линия PCIe, а в рамках каждой дочерней платы устройства подключены через USB хаб.
Охлаждение - пассивные радиаторы вдоль каждой дочерней платы, которые продуваются мощными вентиляторами серверных платформ.
Первые образцы прототипа:
ComBox x64 Movidius Blade BoardДочерние платы (по 8 Movidius на каждой):
x8 Movidius blades for ComBox x64 Movidius boardДля тестирования и отладки мы использовали платформу Supermicro SYS-1029TRT и рекомендуем ее по следующим причинам:
хорошее соотношения цена/качество
форм-фактора 1U (занимает 1 место в стойке)
наличие 4 портов PCIe x8/x16
Про 1U отдельно отмечу, что при высоком энергопотреблении платформы и установленных ускорителей это не важно из-за наличия лимитов энергопотребления на шкаф, в целом. Но так как мы говорим о чипах, изначально предназначенных для использования в IoT, вся плата отличается низким энергопотреблением, что позволяет повышать плотность количества серверов в стойках.
Supermicro SYS-1029TRT с установленной платой ComBox x64 Movidius Blade BoardНа картинке выше у нас установлено 4 дочерних платы с 32 Movidius, что отображается на обратной стороне ускорителя 4 зелеными диодами.
Вид готового изделия:
ComBox x64 Movidius Blade BoardИ первые первые промышленные образцы платы:
Каких итогов мы добились:
Максимальная плотность VPU Movidius на одной плате в мире.
Показатель в инференсе сверточных нейронных сетей (на примере Mobilenet v.2 SSD) - 2800 FPS.
Энергопотребление платы не более 120 Вт при полной загрузке.
Возможность использовать произвольное число дочерних плат и устанавливать по 8, 16, 24 и т.д. VPU в рамках одной несущей платы.
Возможность запуска инференса под управлением фреймворка Intel OpenVINO с использованием MDL и HDDL плагинов.
Следующие планируемые шаги:
Выпуск несущих плат с интегрируемым аппаратным ключом Senselock для защиты моделей нейронных сетей в процессе их исполнения.
Предоставление облачных мощностей для инференса в аренду на базе ComBox x64 Movidius Blade board.
Откройте для себя решения, которые можно создавать с помощью ИИ, и сервисы Azure, помогающие в разработке этих решений. Присоединяйтесь к нам на бесплатном мероприятии Microsoft Azure Virtual Training Day: основы ИИ, чтобы получить общее представление о том, что такое ИИ, и узнать, как начать работу с ИИ в Azure.
Посетите виртуальное обучающее мероприятие, чтобы:
Изучить основные концепции и области применения ИИ.
Создать прогнозные модели, не требующие написания программного кода, с помощью сервиса машинного обучения Azure.
Подробнее узнать о разговорном ИИ, обработке естественного языка и компьютерном зрении в Microsoft Azure.
После завершения этого бесплатного обучающего курса вы сможете сдатьсертификационный экзамен по основам Microsoft Azure AIбесплатно.
Вот, что мы вам предлагаем:
Введение
Введение в ИИ
Машинное обучение
Перерыв 10минут
Компьютерное зрение
Перерыв 10минут
Обработка естественного языка
Виртуальный собеседник
Завершающий сеанс вопросов и ответов
$$display$$\begin{aligned} {\large f(\vec{x}) \rightarrow \underset{\vec{x} \in X}{\min} },\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\; \\ X = \left\{\vec{x} \; | \; g_{i}(\vec{x}) \leq 0, \; h_{k}(\vec{x}) = 0, \;\\ i = 1, \ldots, m, \;k=1\ldots,p \right\} \subset R^n.\end{aligned} \;\;\; (1)$$display$$
import pandas as pdfrom mip import Model, MAXIMIZE, CBC, BINARY, OptimizationStatusframe = pd.read_csv('table_for_optimization.csv')frame.head()
def optimize(frame: pd.DataFrame, channel_limits: dict) -> list: """ Возвращает массив оптимальных предложений """ df = frame.copy() #создание модели model = Model(sense=MAXIMIZE, solver_name=CBC) #вектор бинарных переменных задачи x = [model.add_var(var_type=BINARY) for i in range(df.shape[0])] df['x'] = x #целевая функция model.objective = sum(df.score * df.x) #ограничения на количество коммуникаций в каждом канале for channel in df.channel.unique(): model += (sum(df[df.channel==channel]['x']) <= channel_limits[channel]) #ограничения на количество продуктов для каждого клиента for client in df.client_id.unique(): model += (sum(df[df['client_id']==client]['x']) <= 1) status = model.optimize(max_seconds=300) del df if status == OptimizationStatus.OPTIMAL or status == OptimizationStatus.FEASIBLE: return [var.x for var in model.vars] elif status == OptimizationStatus.NO_SOLUTION_FOUND: print('No feasible solution found')
#объем доступных коммуникаций в каналахCHANNELS_LIMITS = { 'call': 200, 'sms': 500}optimal_decisions = optimize(frame=frame, channel_limits=CHANNELS_LIMITS)frame['optimal_decision'] = optimal_decisions#распределение продуктов в каналахframe[frame['optimal_decision']==1].groupby(['channel', 'product']).\ agg({'client_id': 'count'}).\ rename(columns={'client_id': 'client_cnt'})
Уже февраль 2021 года, а значит пришло время подводить итоги! В это время, 3 года назад, состоялся первый альфа релиз библиотеки. Библиотека DeepPavlov v0.0.1 содержала несколько предварительно обученных моделей и конфигураций JSON. А сегодня у нас есть несколько продуктов, множество пользователей и сценариев использования, достижения на всемирно известных конкурсах и конференциях, и всего через несколько месяцев библиотека DeepPavlov совершит скачок до версии v1.
И несмотря на обстоятельства пандемии, в 2020 году у нас было много задач и поводов для гордости. Как минимум, мы обновили наш веб-сайт, выпустили новый продукт DP Dream, выиграли Про/Чтение, а также повторно участвуем в Alexa Prize Challenge. Об этих и других достижениях мы рады поделиться с вами в обзоре нашего 2020 года.
P.S. 5 марта в честь 3х летия состоится встреча пользователей и разработчиков открытой библиотеки DeepPavlov. Посмотреть детали и зарегистрироваться можно на сайте.
Прежде чем мы перейдем к деталям, давайте вспомним о тех огромных скачках, которые мы сделали за этот год:
Скачивания DeepPavlov Library возросли на 40% по сравнению с прошлым годом. Сейчас всего более 200 тысяч pip установок и более полумиллиона установок контейнеров. Наши технологии используют в 80 странах!
DeepPavlov Library достигла 5 тысяч звезд на Github.
Выпустили 7 релизов DeepPavlov Library, с которыми выкатили новые модели и стали писать release notes о них.
Первый релиз DP Dream и нашего открытого multiskill AI Assistant-а Deepy.
Количество активных участников сообщества возросло в 5 раз. Сотрудниками проводятся ежемесячные звонки DeepPavlov Community Calls, в рамках которых разбираются основы использования компонент библиотеки DeepPavlov, проводятся обучающие туториалы, а также приглашаются внешние спикеры для проведения мастер-классов.
Наша команда студентов и аспирантов дошла до полуфинала конкурса Alexa Prize Socialbot Grand Challenge 3 by Amazon.
Наша команда студентов и аспирантов была повторно отобрана для участия в Alexa Prize Socialbot Grand Challenge 4 by Amazon.
Команда DeepPavlov заняла 1 место в номинации Грамматика.Eng в рамках первого этапа конкурса по разработке системы искусственного интеллекта для выявления смысловых, логических и фактических ошибок в текстах Up Great ПРО//ЧТЕНИЕ.
Сотрудниками было опубликовано 12 научных публикаций.
Три наших аспиранта успешно защитили диссертации на соискание ученой степени кандидата наук.
Мы провели более 20 лекций и воркшопов на таких конференциях, как: NVIDIA GTC Fall 2020, ODSC WEST 2020, MLConf EU 2020, Conversations AI, AI Journey 2020, Innopolis NLP MeetUp.
Выпустили 10 постов-туториалов по использованию компонент библиотеки DeepPavlov.
Приняли 10 студентов-стажеров в команду по направлениям NLP и Conversational AI.
Мы провели 2 учебных курса в весеннем семестре: Глубокое обучение в обработке естественного языка и Advanced Topics in Deep Reinforcement learning.
1 место на либерборде DialoGLUE.
На сегодняшний день, DeepPavlov это не только одна библиотека, это целая экосистема продуктов и проектов. К основным направлениям можно отнести:
Развитие открытой библиотеки DeepPavlov Library, которая поставляется с набором предобученных компонентов для решения задач, связанных с обработкой естественного языка, и предоставляет разработчикам возможность автоматизации разговорных интерфейсов.
Развитие открытой платформы DeepPavlov Agent, которая представляет собой многофункциональный оркестратор, использующий декларативный подход для формирования конвейеров и построения диалогового ИИ в виде модульной системы.
Развитие открытой платформы DeepPavlov Dream, необходимой для разработки масштабируемых и многофункциональных виртуальных помощников, и опирающейся на технологии DP Library и Agent.
Развитие репозитория открытого multiskill AI Assistant-а Deepy, в настоящее время представляющего собой очень простую демонстрацию многофункционального AI Assistant, обладающего всего двумя навыками (целенаправленным и болталкой), а также несколькими аннотаторами. Это фундамент, который позволит любому желающему создать своего ассистента.
Расширение функционала демо-версии работы компонент библиотеки и открытой версии ИИ ассистента на базе Deepy.
Развитие NLP сообщества и контрибьюторов, а также участие в конкурсах для преодоления технологических барьеров.
Вместе с продуктами DeepPavlov, мы обновили наш сайт. Пройдемся детальнее по основному функционалу, о котором вы могли не знать:
Появился свой собственный блог как на русском, так и на английском языке, где мы делимся новостями.
Появился раздел Challenges, где мы рассказываем о конкурсах, в которых участвуем или проводим сами.
Для раздела DeepPavlov Library появилась вкладка Releases, где подробно описаны изменения в библиотеке.
Теперь вы можете узнать о наших научных проектах, а также про текущие стажировки в разделе Research.
Другие улучшения разделов: о проекте, о команде, о выпускниках, и т.д.
У нас отличные новости начиная с v0.12.0 релиза DeepPavlov Library поддерживает и TensorFlow, и PyTorch. В дополнение к этому DP поддерживает Трансформеры от Hugging Face, позволяющие разработчикам использовать широкий выбор моделей на основе Трансформеров и сотни датасетов для ваших моделей.
В 2020 году в DeepPavlov Library также появились следующие модели:
Speech recognition and synthesis (ASR and TTS)
Knowledge Base Question Answering model for WikiData
Entity Linking
Intent Catcher
Обновления Go-Bot
С 2021 мы начали преобразование нашей библиотеки DeepPavlov до версии v1.0. Этот процесс потребует значительной реструктуризации и рефакторинга, которые, в свою очередь, приведут к значительным изменениям. Вот некоторые из ожидаемых обновлений:
Переход на PyTorch всех моделей
Изменение документации
Прекращение поддержки старых моделей и кода
Контроль версий моделей
Обновления конфигураций
Вы можете заполнить эту форму, чтобы сообщить нам, как вы используете DeepPavlov Library, и что бы вы предложили добавить или улучшить!
В 2020 DeepPavlov стал партнёром программы NVIDIA GPU Cloud (NGC) контейнерного реестра для работы с искусственным интеллектом, машинным обучением, нейронными сетями и высокопроизводительными вычислениями. Теперь контейнеры библиотеки DeepPavlov доступны в облаке NGC.
Контейнеры DeepPavlov состоят из предварительно обученных моделей, которые используют современные модели глубокого обучения типа BERT для задач классификации, распознавания именованных сущностей, вопросов-ответов и других задач области NLP. Использование GPU позволяет ускорить работу библиотеки DeepPavlov до 20 раз (для примера был взят запуск конвейеров модуля ASR / TTS на V100 GPU в сравнении с CPU).
Представьте, что в будущем ИИ-помощники будут понимать нас и разговаривать с нами на одном языке. Представьте, что они будут учиться и учить нас. Представьте, что они станут нашими верными друзьями. Они будут делать все, что мы захотим
Для достижения этой цели мы создали целое семейство ИИ-помощников и сейчас подробнее о них расскажем.
DeepPavlov Dream это ИИ-помощник, основанный на социальном боте, созданном командой лаборатории для участия в конкурсе Alexa Prize Socialbot Grand Challenge 3 от Amazon. Подробнее о нем мы недавно писали в статье.
Но что важно знать, сейчас этот помощник отключен от каналов и не работает. По причине того, что организаторы Alexa Prize попросили выключить его на время нашего участия в конкурсе. Сейчас доступны мини-версии под названием Deepy.
Deepy это репозиторий нашего простого многофункционального ИИ-помощника, обладающего всего двумя навыками (целенаправленным, написанным с использованием нашей инфраструктуры Go-Bot, и болталкой, написанной с использованием AIML), а также несколькими аннотаторами.
Архитектура Deepy та же, что и у DeepPavlov Dream: мы используем тот же DeepPavlov Agent в качестве механизма для оркестрации и тот же конвейер. Однако количество используемых компонентов значительно сокращено по сравнению Dream.
В настоящий момент доступны 3 конфигурации дистрибутивов:
deepy_base базовый дистрибутив Deepy, состоящий из двух навыков: простого целенаправленного навыка и навыка общения в чате, а также классификаций эмоций и аннотаторов проверки орфографии,
deepy_gobot_base дистрибутив Deepy на основе Go-Bot, состоящий также из двух навыков: целенаправленного на основе Go-Bot и болталки, а также классификаций эмоций и аннотаторов проверки орфографии,
deepy_adv более продвинутый дистрибутив Deepy, который в дополнение к компонентам deepy_gobot_base также включает еще несколько аннотаторов, включая Entity Linking, Intent Catcher и Sentence Segmentation.
Третий дистрибутив, deepy_adv, в настоящее время работает на нашем демо.
Почитать подробнее про DeepPavlov Deepy можно в статье.
Мы не только проводим конкурсы, но и сами участвуем в них.
Так, в марте 2020 наш исследователь и преподаватель курса по NLP Алексей Сорокин занял второе место на конкурсе GramEval-2020. Он разработал модель для автоматического определения морфологических и синтаксических характеристик слов в предложениях на русском языке.
А в декабре 2020 исследователь проекта DeepPavlov и капитан команды Dream Alexa Prize Диляра Баймурзина взяла третье место на конкурсе AI 4 Humanities: ruGPT-3 от AIJourney. Она разработала модель AI CopyWriter для перефразирования и/или распространения текста на основе ruGPT3Large.
Каждый год американская компания Amazon проводит конкурс на создание разговорного искусственного интеллекта для своего голосового помощника Alexa Prize Socialbot Grand Challenge. Задача научить Alexa поддерживать естественный диалог с пользователем на свободные темы. 10 командам выдают грант на разработку в $250 тыс. В 2019 году в эту десятку впервые попала наша команда DREAM DeepPavlov. Команда год работала над проектом и достигла полуфинала конкурса. Узнать подробности созданной архитектуры DREAM socialbot можно ознакомившись с техническим отчетом команды DREAM для конкурса Alexa Prize 3 .
В 2020 команда проекта повторно прошла отбор на участие в конкурсе Alexa Prize Socialbot Grand Challenge 4. На данный момент команда активно работает над созданием бота и проходит необходимые стадии тестирования системы на ресурсах Amazon. Всю актуальную информацию можно найти на официальной странице проекта.
В декабре 2020 года завершился первый цикл конкурса Up Great ПРО//ЧТЕНИЕ по созданию ИИ-системы для проверки сочинений школьников. В соревновании приняли участие более 180 команд, из которых до испытаний были допущены 11 коллективов разработчиков, показавших эффективные решения. В рамках испытаний ИИ-ассистенты проверили по 500 эссе и сочинений ЕГЭ на русском языке и столько же на английском. Автоматизированная платформа сопоставила тексты, проверенные ИИ-ассистентами и реальными педагогами, и выявила наиболее качественные решения.
Наша команда НейроЧтение заняла первое место в номинации Грамматика.Eng. В работе над решением сложной составной задачи по проверке эссе на английском языке мы использовали фреймворк DeepPavlov Agent.
Наша команда на удаленке!Для удобства общения с пользователями ранее был создан форум разработчиков, позволяющий найти и задать вопросы по теме фреймворка. Так что если у вас есть вопросы, то сразу пишите туда. А для тех, кто использует DeepPavlov Dream, дополнительно создана группа в Telegram.
С сентября прошлого года у нас появилась хорошая традиция для наших пользователей и разработчиков мы проводим ежемесячные звонки DeepPavlov Community Calls, в рамках которых разбираем основы использования компонент библиотеки DeepPavlov, проводим обучающие туториалы, а также приглашаем внешних спикеров для проведения мастер-классов.
А если вы просто хотите быть на волне DeepPavlov, то подключайтесь к каналу новостей в Telegram.
На 2х летии библиотеки мы обещали вам больше туториалов и воркшопов. За прошедший год мы постарались исполнить обещание, и по итогу мы участвовали:
На конференции NVIDIA GTC Fall 2020 с докладом: Multiskill Conversational AI innovations
На конференции ODSC WEST 2020 с докладом: Conversational AI with DeepPavlov
В обучающем вебинаре, в рамках ODSC: BERT-based Open Domain Question Answering using DeepPavlov Library on Azure Machine Learning
На конференции MLConf EU 2020 с воркшопом: DeepPavlov Open-source Framework for Multiskill Conversational AI
На конференции AI Journey 2020 с докладом: От NLP к AGI Многофункциональный ИИ
И это только часть, но самая весомая.
Немаловажную часть нашего Community занимают образовательные программы. Так в весеннем семестре 2020 года мы организовали курс Глубокое обучение в обработке естественного языка. Темами занятий являлись построение диалоговых систем, способы оценки диалоговой системы с возможностью генерации ответа, различные фреймворки диалоговых систем и др. В курсе суммарно приняли участие более 800 человек с разных регионов России, а защитили успешно проекты порядка 100 (самый масштабный для нас курс выдался). Кстати, подробную информацию об итоговых проектах можно найти в статье на Хабр.
Также в весеннем семестре совместно с АНО ВО Школа анализа данных был проведен курс Advanced Topics in Deep Reinforcement learning, проходивший в формате reading group. В рамках курса было проведено 13 занятий, где исследовались и анализировались современные подходы по теме обучения с подкреплением. Для успешного завершения курса участникам также необходимо было выполнить итоговый проект. Если вам интересна тема RL, обязательно посмотрите запись курса.
Также мы хотели бы поблагодарить всех контрибьюторов за ценный вклад в код в этом году. В 2020 году более 20 человек впервые добавили код в DeepPavlov. Большое спасибо всем вам!
Ну а если вы ML/NLP инженер и разделяете нашу внутреннюю страсть к расширению границ разговорного ИИ или просто хотите упростить использование инструментов NLP/NLU сообществом, мы приглашаем присоединиться к нашему Open Source Community.
Узнать больше про community можно в статье блога, а если хочется внести свой вклад прямо сейчас, то вам сюда.
Какой день рождения без праздника? По нашей сложившейся традиции, в честь дня рождения DeepPavlov мы проводим встречу пользователей и разработчиков. В этом году, к сожалению, она пройдет в онлайн формате 5 марта. Чтобы попасть на мероприятие, необходимо зарегистрироваться на сайте.
В программе вечера 10 крутых докладов от сотрудников проекта DeepPavlov и приглашенные специалисты:
Булат Замалиев, Уполномоченный по технологиям ИИ в Татарстане расскажет, как DeepPavlov помогает в решении государственных задач
Диляра Баймурзина, исследователь и капитан Dream Team Alexa, расскажет как русской команде участвовать в международном конкурсе Alexa Prize Socialbot Grand Challenge
Дмитрий Сошников, Microsoft, поделится туториалом о том, как адаптировать DeepPavlov отвечать на вопросы по COVID-19
Роман Смирнов, Системный архитектор DeepPavlov, поделится, как можно организовать свою личную жизнь с помощью ИИ
Щекин Роман и Тедеев Алан, исследователи НКО АО НРД, в своем докладе расскажут о том, как им удалось свести обработку новостей о корпоративных действиях к очень специфичному NER'у с помощью DeepPavlov
Фёдор Игнатов, старший инженер-разработчик, расскажет о том, какой станет версия 1.0 библиотеки DeepPavlov Library.
В докладе Александра Янчина, CTO в Leroma B2B-Platform, речь пойдет об использовании библиотеки DeepPavlov для определения сущностей из текста, и дальнейшей структуризации этой информации.
Данила Корнев, CPO проекта DeepPavlov, расскажет о том, как и почему лаборатория DeepPavlov пришла к открытому решению для создания Multiskill AI Assistants.
Татьяна Шаврина, AGI NLP Team lead в управлении экспериментальных систем машинного обучения в Sberdevices, поговорит с вами на Всю эту BERTологию
Ну и герой вечера Михаил Бурцев, руководитель проекта, держит в секрете тему выступления, чтобы удивить вас!
Всех ждем! Присоединяйтесь!
Спасибо всем, кто дочитал этот текст. Мы ждем ваши комментарии и вопросы по продуктам, которые мы создаем в проекте. Ждем ваши пулреквесты и предложения. И конечно же, ждем на нашем праздновании!
Машинное обучение, компьютерное зрение, обработку естественного языка уже используют в разных городах мира. Искусственный интеллект помогает сократить загрязнение воздуха и оптимизировать для его снижения работу светофоров, подсчитывать деревья, ориентируясь на Google Street View, и даже делить имущество и детей при разводе.
В этом посте давайте обсудим несколько примеров использования таких технологий для предоставления государственных услуг и улучшения городской среды.
Развод обычно затягивается на недели или даже месяцы, особенно когда бывшим близки людям нужно многое делить. Процесс сильно усложняют споры о том, с кем останется ребёнок.
В Австралии попытались решить эту проблему с помощью искусственного интеллекта под названием Amica. На разработку онлайн-сервиса правительство выделило AU$3 млн.
Amica делит имущество и готовит соглашение о родительских правах, а затем регистрирует бракоразводный договор. ИИ должен быть непредвзятым, решение он должен принимать индивидуально для каждой пары, учитывая стоимость имущества и интересы бывших партнёров.
Сервис также позволяет общаться с бывшим партнёром в удобном режиме онлайн, чтобы избежать неудобство и эмоции, которые способно вызвать личное общение.
Эффект от этой услуги сокращение судебных издержек на разводы и снижение нагрузки на суды по семейным делам.
Зелёные насаждения в городах могут пострадать из-за изменения климата в будущем, а уже сейчас могут страдать из-за неправильного планирования застройки территорий и непродуманной посадки новых растений.
Чтобы сохранить природу в Екатеринбурге, волонтёры из Уральского федерального университета создают интерактивную карту на основе готовой архитектуры нейросети YOLO3. Нейросети, обученные на больших наборах данных, используются в проекте для учёта деревьев.
Нейросети должны распознавать деревья на фотографиях со Street View а для этого им нужно будет отличать их, например, от столбов. Обучение проходило с помощью существующей карты деревьев Нью-Йорка и фотографий Street View, об этом писали на Хабре.
Студенты университета помогают в разметке деревьев и указании их точного местонахождения, при этом собирается разметка с помощью телеграм-бота @helpwithtree_bot, который они сами написали.
В британском городе Вулверхэмптон тестируют https://cities-today.com/predictive-analytics-help-wolverhampton-to-manage-pollution/ систему, отслеживающую загрязнение воздуха. Ситуацию с экологией таким образом пытаются улучшить с помощью решения от компании Now Wireless https://www.nowwireless.com/traffic-lights.
В городе на существующей инфраструктуре а именно на светофорах уже установлены датчики загрязнения воздуха. Данные с них, поступающие в реальном времени, новое решение использует, чтобы алгоритм дал в реальном времени прогноз о повышении уровня загрязнения на следующий час.
Искусственный интеллект затем предлагает микрокорректировки работы светофоров: например, дольше удерживать автомобили в конкретных местах, перенаправлять трафик или поощрить водителей припарковаться, сократив длительность поездки
Вовлечение жителей города в планирование городской среды позволяет узнать, что именно хотят люди, и, соответственно, решить настоящие, а не вымышленные проблемы. Правительство может использовать для этого собрания, опросы, мониторинг социальных сетей или внедрение решений для прямого диалога между горожанами и властью.
В российском Кисловодске для этого запустили платформу Чего хочет Кисловодск?. Полученные с её помощью данные должны использовать как администрации города и региона, так и девелоперы и другие бизнесы, способные вносить изменения в город.
На платформе собирают идеи с помощью сайта, чат-ботов в соцсетях и мессенджерах, а затем обрабатывают их. Для обработки и нужен искусственный интеллект, а именно NLP технологии обработки естественного языка. Это позволяет выделять ключевые слова, распознавать сущности, классифицировать тексты по категориям тем и анализировать тональность сообщений.
В какой из трёх контейнеров в торговом центре или (у некоторых) в офисе нужно выкинуть пакетик для чая или упаковку от готовой еды? Ответы на вопросы по раздельному сбору мусора не всегда очевидны, а ведь именно сложности с сортировкой усложняют процесс переработки. И весь мусор отправляется, например, в океан.
С проблемой сортировки канадский стартап Intuitive AI решил помочь с помощью технологий компьютерного зрения. Они оснастили контейнер для мусора камерой, динамикой и дисплеем. А работает он на ИИ-платформе NVIDIA Jetson TX2.
Вы подходите к контейнеру, показываете камере мусор в ваших руках, нейромодуль анализирует изображение и сопоставляет его с собственной базой данных Wastenet. Затем система указывает, куда именно этот мусор нужно выкинуть.
Эффективность раздельного сбора мусора таким образом повышается на 300%.
А назвали этот алгоритм Oscar по имени одного из персонажей Улицы Сезам, который жил в мусорном баке.
Много лет назад я загорелась идеей научиться программированию, создав собственный сайт. Тогда я ничего не понимала в компьютерах и тем более в серверах. И только одна мысль о том, сколько же мне предстоит узнать нового, будила во мне необыкновенный интерес. Перед сном я обдумывала сотни вариантов своего сайта от параллакс-эффекта при прокручивании до шрифтов из Google Fonts и мечтала о будущих проектах.
Прошли годы, и теперь я профессиональный инженер и решаю серьезные технологические задачи они действительно гораздо сложнее, чем мой первый сайт! Тем не менее, я часто вспоминаю ощущения и эмоции, которые испытала тогда, делая первые шаги в программировании.
Один из веселых способов познакомиться с машинным обучением это создать что-то для себя. В этой статье я расскажу, как это сделать.
Работая в сфере технологий, вы посвящаете свою жизнь учебе. Глазом не успеешь моргнуть, как самое совершенное ПО моментально заменяется чем-то более продвинутым (хотя я все никак не могу отвыкнуть от старого доброго Vim).
Одно из интереснейших направлений в ИТ машинное обучение. Большинству из нас не рассказывали о нем в вузах (а у некоторых вообще не было уроков информатики), но скоро машинное обучение станет повсеместным, и оно изменит процесс разработки ПО во всех областях. Неудивительно, что меня часто спрашивают, с чего лучше начать изучение машинного обучения.
Обычно я советую обратиться к таким ресурсам, как курс компании Google под названиемMachine Learning Crash Course, а также книгаПрикладное машинное обучение с помощью Scikit-Learn, Keras и TensorFlowи курс на сайте CourseraМашинное обучение(автор: Andrew Ng), который нацелен не только на теоретические основы, но и на практику.
Но если вы, как и я, предпочитаете сразу переходить к делу, попробуйте познакомиться с машинным обучением, создав для себя программу. Собственные проекты это не только приятный и полезный способ знакомства с новыми технологиями. В отличие от идеальных условий, которые предлагаются в домашних заданиях, на практике вы столкнетесь с реальными трудностями при внедрении машинного обучения в ПО.
В начале пандемии я вдруг поняла, что у меня много свободного времени. И я поставила перед собой задачу узнать больше о машинном обучении, решая с его помощью повседневные задачи. С тех пор машинное обучение помогает мне искать семейные видео, улучшать подачу во время игры в теннис, переводить видео, создавать новые рецепты выпечки и многое другое.
Ниже вы найдете список и обзор всех этих проектов, а такжеисходный код, обучающиевидео на YouTubeи пошаговые инструкции вмоем блоге. Я расскажу обо всем процессе от работы с новыми технологиями и инструментами до создания приложения с их помощью. Надеюсь, эти проекты окажутся для вас не только веселыми, но и полезными. А если они вдохновят вас на собственные проекты с машинным обучением, я буду только рада. Не забудьтерассказать мнео своих свершениях в твиттере. Удачной работы!
Вы создадите: архив, который сможет предоставлять видео по фразе или объекту из записи (например, "день рождения", "велосипед" или "видеоигры").
Вы узнаете:
как применять машинное обучение в сортировке и поиске сложных типов данных;
как использовать Video Intelligence API;
как проектировать приложение, в основе которого лежит машинное обучение (в этом помогут инструментыFlutter для создания клиентской части,Firebase для написания кода без использования серверов, и поиск как сервис, предоставленныйAlgolia).
Вы создадите: бот для чат-платформыDiscord,который помогает находить оскорбительные и нецензурные сообщения, а также спам.
Вы узнаете:
как использоватьPerspective APIдля анализа текста;
как применять машинное обучение в приложениях для чата;
как выбирать, нужно ли машинное обучение в сложных и неоднозначных ситуациях.
Вы создадите: блокнот Jupyter, который отслеживает подачу и траекторию теннисного мяча (может также пригодиться в гольфе и баскетболе), а также анализирует данные, чтобы дать полезные советы. Для этого перейдите вQwiklabs.
Вы узнаете:
как выполнять сложное машинное обучение с помощью небольших наборов данных;
как комбинировать простые математические вычисления с распознаванием поз для понимания движений человека;
как использовать Video Intelligence API;
как работать c AutoML Vision.
илиСоздание приложений на основе языка с помощью семантического машинного обучения
Вы создадите:
простую систему на основе языка, с помощью которой можно взаимодействовать с игровым миром через ввод текста.
Вы узнаете:
как использовать одну из самых полезных методик обработки естественного языка встраивание предложений;
как реализовывать семантический поиск текста;
как разделять текст на кластеры;
как добавлять простые чат-боты;
как выполнять эти действия в Google Таблице.
Вы создадите: код, который преобразует PDF-файлы в аудиокниги формата MP3.
Вы узнаете:
как извлекать текст из PDF-файлов при помощи Vision API;
как озвучивать текст при помощи Text-to-Speech API;
как использовать математические вычисления для разделения макетов документа.
Вы создадите: код, который автоматически преобразовывает речь из видео в текст, а затем переводит и озвучивает его.
Вы узнаете:
как совмещать технологии распознавания, перевода и синтеза речи;
как улучшать качество перевода и преобразования речи в текст;
как работать с видео и аудио на языке Python.
Вы создадите: модель машинного обучения без единой строки кода, которая может классифицировать рецепты и генерировать новые.
Вы узнаете:
как создавать модели машинного обучения в AutoML Tables с помощью табличных данных без написания кода;
как определять причину решений модели с помощью функций.
Вы создадите: быструю модель машинного обучения, которая распознает позы, объекты и звуки.
Вы узнаете:
что нужно, чтобы создать простую модель машинного обучения без написания кода;
как с помощью инструмента "Обучаемая машина" создать быструю модель, которую можно запустить в браузере.
Вы создадите: приложение, которое будет рекомендовать образы на основе фотографий вашего гардероба и публикаций медийных персон в соцсетях.
Вы узнаете:
как использовать Product Search и Vision API;
как проектировать приложения на основе машинного обучения с помощью React и Firebase.
В последнее время все больше людей приходит к тому, чтобы не держать деньги под матрасом, а куда-то их инвестировать в надежде сохранить и преумножить свой капитал. Вариант с матрасом плох тем, что с повышением цен на товары и услуги (инфляция) покупательная способность денег падает и через какое-то время купить на них можно значительно меньше, чем раньше. Есть много вариантов, куда вложить деньги(недвижимость, банковский вклад, ценные металлы), но в последнее время популярным становится инвестирование в акции. Только у брокера Тинькофф Инвестиции за несколько лет число клиентов превысило 3.5 млн. В статье я постараюсь описать свой подход к выбору бумаг и поделюсь инструментами, которые для этого разрабатываю.
Дисклеймер: у автора нет экономического образования и все выводы и суждения в статье делаются на основе житейского опыта и здравого смысла.
Ниже приведены некоторые базовые моменты, на которые можно обращать внимание при формировании решения о покупке какой-либо акции.
Можно смотреть на то, чем занимается компания. Если есть вера в будущее электромобилей, то, например, можно посмотреть в сторону Tesla (далее из статьи будет понятно, что это может быть не самый лучший выбор). Если есть вера в биомед, то можно купить бумаги из соответствующего сектора. При этом, на мой взгляд, важно понимать, что конкретно делает компания, на чем основан ее бизнес. Например, если взять нефтяные компании, то они могут заниматься совершенно разными вещами - одни добывают сырье, другие его перерабатывают, третьи только транспортируют. Из-за этого некоторые события, происходящие в мире, сильно влияют на одних, но совсем не влияют на других. Условно, закрыли какой-то морской канал, и танкеру, чтобы доставить нефть, приходится делать крюк, следовательно лишние затраты для транспортной компании. При этом какому-нибудь переработчику нефти все равно.
Это все к тому, что зачастую популярный подход с выбором только известных брендов может работать не очень хорошо. Часто бывает полезно понять, что конкретно делает компания и тогда желание её купить может само отпасть (например, деятельность явно устаревающая/новые технологии могут заместить необходимость в такой деятельности и т.п.).
Но помимо этого было бы неплохо знать - а как конкретно зарабатывает фирма? Откуда у нее основные источники дохода и как они распределены? К счастью, каждая компания, торгующаяся на бирже, обязана раз в квартал (четверть года) раскрывать информацию о своих финансах (так называемые финансовые отчеты). Чтобы найти такие отчеты, достаточно вбить в любом поисковике "company_name investor relations" и перейти на соответствующий раздел сайта компании. На картинке показан кусок такого отчета компании Apple за 4 квартал:
Из него можно понять, что выручка компании (net sales,
часто её называют revenue) за квартал составила почти
111.5 миллиардов долларов, что больше, чем в аналогичном квартале
год назад (91.8 млрд). Кроме того, 95.7 млрд из них приходится на
продукцию компании (продажи iPhone, iPad и т.д.), а 15.7 - на
сервисы (Apple Music, App Store и т.д.). Так же можно увидеть, что
чистая прибыль компании составила 28.8 млрд, причем видно, как это
число получилось :
Из net sales вычли cost of sales
(непосредственные затраты на производство) и operating
expenses (побочные затраты), а так же учли налоги
(provision for income taxes).
111.4 - 67.1 - 10.8 - 4.8 = 28.7
Если покопаться в отчете глубже, то можно увидеть, как распределена выручка между продуктами, сколько денег было потрачено на исследования и разработку, сколько на продажи и много другой полезной информации, которую, безусловно, можно исользовать при принятии инвестиционных решений.
Часто бывает так, что нужно сравнить компании, понять, какая из них лучше. Например, было решено, что в портфель необходимо добавить компанию, производящую потребительские товары. Но таких компаний огромное количество, и все они разных размеров, демонстрируют совершенно разные revenue, net income и т.д. На помощь приходят мультпликаторы - производные величины, которые можно непосредственно сравнить.
P/E (price to earnings) - цена-прибыль. Вычисляется как отношение капитализации компании к её годовой прибыли. Другими словами, данный показатель говорит о том, сколько лет компания будет окупаться, если ее купить сейчас. Например, у Apple сейчас P/E~30. Значит, если (в теории) мы целиком купим эту компанию по текущей цене, то через 30 лет эта покупка себя отобьет. Итак, чем ниже P/E, тем "дешевле" компания, что, разумеется, хорошо (лучше я куплю бизнес, который окупится за 10 лет, чем за 20). При этом важно понимать, что для разных секторов средние P/E могут сильно разниться. Это объясняется тем, что от одних секторов ожидания выше, чем от других. Например, продуктовому ритейлеру почти нереально увеличить выручку в 10 раз, а поставщик какого-нибудь интернет-сервиса спокойно может кратно наращивать количество пользователей от года к году. Вот и выходит, что технологические компании по P/E стоят "дороже", чем, например, сырьевые.
D/E (Debt to Equity) - долг к собственному капиталу. Данный мультипликатор показывает, насколько высокая долговая нагрузка у компании. Понятно, что если долг слишком высокий, то выше риски банкротства компании и меньше у неё возможностей. Иногда компании со слишком высоким D/E называют "зомби", потому что результат их деятельности целиком идет на обслуживание долга.
ROE (Return On Equity) - рентабельность
собственного капитала. Вычисляется как отношение чистой прибыли к
собственному капиталу компании. Мультипликатор показывает, как
компания способна генерировать прибыль за счет собственных
средств.
Есть еще много других мультипликаторов, но я в основном пользуюсь
только этими.
По своему основному роду деятельности я - датасаентист, поэтому логично было бы использовать современные методы машинного обучения и анализа данных для оптимизации и упорядочивания процесса своих инвестиций. Стоит уточнить, что речь не идет про алгоритмический трейдинг, спекуляции и прочее. Я говорю лишь про инструменты, которые могут упростить инвестирование, сделать его более понятным и предсказуемым. Поскольку, думаю, что инвестировать я буду долгое время, то код решил писать чуть более аккуратно, чем обычно. Посмотреть все исходники можно тут. А если кому лень самостоятельно все запускать, то я сделал еще и веб-сервис с основными моделями (их цели и значение можно понять дальше в статье).
Понятно, что для написания нужных мне алгоритмов необходимы данные по фундаментальным показателям компаний за предыдущие кварталы (как в отчетах, только в одном месте и единообразно). Для американского рынка бесплатных источников я не нашел, но есть недорогой (около 30$) поставщик довольно качественных данных с удобным API. Кроме того, там же есть и посуточные базовые свечные данные.
После оформления подписки написал даунлоэдер, который позволяет скачать все данные и разложить по нужным папкам. Его можно использовать следующим образом:
downloader = QuandlDownloader(config, secrets, sleep_time=0.8) downloader.ticker_download('datatables/SHARADAR/SF1?ticker={ticker}', ticker_list, save_dirpath='data/core_fundamental', skip_exists=False, batch_size=10, n_jobs=2)downloader.ticker_download('datatables/SHARADAR/DAILY?ticker={ticker}', ticker_list, save_dirpath='data/daily', skip_exists=False, batch_size=5, n_jobs=2)
Все дальнейшие подсчеты фичей, таргетов, а так же построение пайплайнов будут производиться на основе данных, источник которых со временем может поменяться, поэтому было решено придерживаться следующего интерфейса для загрузки данных в память:
class DataLoader: def load_base_data(self) -> pd.DataFrame: # returned pd.DataFrame should have ["ticker"] column def load_quartely_data(self, tickers: List[str]) -> pd.DataFrame: # returned pd.DataFrame should have ["ticker", "date"] columns def load_daily_data(self, tickers: List[str]) -> pd.DataFrame: # returned pd.DataFrame should have ["ticker", "date"] columns
Соответственно, предполагается, что load_base_data
будет загружать основные данные про компании, которые не меняются
со временем, вроде сектора, индустрии и т.д.
load_quartely_data
будет загружать поквартальные
данные (revenue, netincome и т.д.), при этом каждая строчка -
отдельный квартал.
load_daily_data
грузит дневную дату (например,
ценовые свечи, дневную капитализацию). Для текущего поставщика
данных используется класс SF1Data
, реализующий данный
интерфейс.
Итак, первая задача, которая у меня постоянно возникала и которую я не знал как решить - оценка адекватной стоимости компании. То есть, часто можно слышать фразы "эта компания переоценена", "слишком дорогая" или наоборот "сильно недооцененная, дешевая". Но как численно понять, сколько по-хорошему должна стоить компания? Кто-то может сказать "а разве не для этого и существует мультипликатор P/E?" и будет отчасти прав. Но. Часть компаний (особенно на ранних этапах) являются убыточными и для них мультипликатор вообще не определен. Или для какой-то компании сейчас мультипликатор высокий, но это не значит, что компания плохая, просто на данном этапе она может вкладываться в рост. И для меня, как для инвестора, это хорошо - да, компания могла бы получить высокую прибыль (а, соответственно, низкий P/E), если бы сократила расходы на маркетинг, например. Но тогда она не заполучила бы новых клиентов, не открыла новые точки и т.д. В результате это привело бы к тому, что в будущем прибыль компании была бы не такая большая, как если бы сейчас полученная прибыль направилась в развитие.
Вернемся к определению адекватной стоимости компании. Известно, что часть торгующихся компаний имеют завышенную стоимость, а часть - заниженную. Из-за этого возникла мысль - что если обучить модель, которая чисто по показателям из отчетов компании будет предсказывать текущую капитализацию? Понятно, что модель не сможет учитывать какие-то настроения инвесторов и прочие спекулятивные моменты, а в качестве предсказания будет предлагаться что-то среднее. Но это среднее и можно интерпретировать как "честную стоимость", ведь алгоритм машинного обучения просмотрел все похожие по фундаментальным показателям компании и на основе их реальных рыночных капитализаций сделал оценку.
Первым делом нужно соорудить некоторое представление компании по ее фундаментальным показателям. Логично предположить, что если компания зарабатывает по 100 млрд последние 10 кварталов, то она никак не может стоить 1 млрд (должна стоить гораздо дороже).
Аналогичная интуиция и с остальными показателями - если долг
убывает со временем, значит дела в порядке (плюсик к
капитализации). Если выручка растет за последние кварталы - значит
компания развивается, это хорошо, и, соответственно, должно
закладываться в цену. Все эти признаки легко покрываются с помощью
подсчетов статистик вроде mean
max
min
std
и т.д. для последних, например,
2, 4, 10 кварталов. Кроме того, часто смотрят не только на то,
растет выручка или нет, но и на темпы роста. Поэтому можно добавить
статистики и по диффам - например, среднее значение того, на
сколько процентов росла выручка. При этом логично, что все эти
подсчеты можно делать для разных квартальных срезов компании:
считать признаковое представление не только для текущего квартала,
но и для предыдущих (параметр max_back_quarter
), тем
самым кратно увеличивая датасет. Ну и как результат, полученный
класс для подсчета квартальных фичей и его использование:
fc1 = QuarterlyFeatures(columns=['revenue', 'netinc', 'debt'], quarter_counts=[2, 4, 10], max_back_quarter=5)fc1.calculate(data_loader, ['AAPL', 'INTC', 'F'])
Кроме того, при оценке стоимости компании важны и ее базовые
характеристики. Например, как уже упоминал, технологические
компании обычно оцениваются дороже. Аналогично, из разных индустрий
средние оценки компаний тоже могут разниться. Поэтому был
реализовал класс BaseCompanyFeatures
, кодирующий
подобные признаки с помощью лэйбл-энкодинга:
fc2 = BaseCompanyFeatures(cat_columns=['sector', 'sicindustry'])fc2.calculate(data_loader, ['AAPL', 'INTC', 'F'])
Ещё одним моментом, который бы хотелось учитывать при оценке
компании, является подневная динамика движения цены акции компании
за последнее время. Интуиция в том, что если стоимость компании
стабильно растет, то инвесторы охотнее будут её покупать. При этом
динамика должна представляться в нормализованном виде, чтобы
избежать лика(нечестно определять стоимость компании, основываясь
на стоимости компании). Соответствующий класс
DailyAggQuarterFeatures
(так же работает с
квартальными слайсами компании и параметром
max_back_quarter
):
fc3 = DailyAggQuarterFeatures( columns=['marketcap'], agg_day_counts=[100, 200, 400, 800], max_back_quarter=5)fc3.calculate(data_loader, ['AAPL', 'INTC', 'F'])
Для удобства комбинирования признаков был реализован класс
FeatureMerger
:
feature = FeatureMerger(fc1, fc2, on='ticker')feature = FeatureMerger(feature, fc3, on=['ticker', 'date'])feature.calculate(data_loader, ['AAPL', 'INTC', 'F'])
С целевой переменной (той, что собираемся предсказывать) для этой модели более-менее понятно. Нужно просто взять капитализацию компании в момент отчета. Для согласования таргета и фичей было принято решение сделать следующий интерфейс подсчета таргета:
def calculate(self, data_loader, info_df: pd.DataFrame) -> pd.DataFrame: ''' info_df: pd.DataFrame containing information of tickers and dates to calculate targets for. Should have columns: ["ticker", "date"]. '''
Ну и ниже сам класс QuarterlyTarget
для подсчета
таких квартальных таргетов. Его функционал чуть шире - данный класс
позволяет брать значения переменных не только для нужного квартала,
но и для соседних (например, если вдруг захотим предсказывать не
текущую, а будущую капитализацию компании):
info_df = pd.DataFrame([{'ticker':'AAPL', 'date':'2020-10-30'}])target = QuarterlyTarget(col='marketcap', quarter_shift=0)target.calculate(data_loader, info_df)
На самом деле, тут можно было бы сделать и другой таргет -
сгладить капитализацию за будущие 30 дней, например. Интуиция в
том, что непосредственно в день отчета цена может сильно скакать, а
за месяц все более-менее устаканится и средняя капитализация будет
более стабильной. Как раз для таких целей у меня написан
DailyAggTarget
класс таргета:
target = DailyAggTarget( col='marketcap', horizon=30, foo=np.mean)target.calculate(data_loader, info_df)
С подобными признаками, как известно, хорошо работают градиентные бустинги. Их и будем использовать. Единственный момент, что распределение нашего таргета не очень хорошее - одни компании стоят сотни миллиардов долларов, другие миллионы. А модель должна уметь адекватно предсказывать для всех. Воспользуемся классической фишкой - логарифмированием таргета.
Теперь его распределение хоть как-то похоже на нормальное, что
является комфортным для модели. Для удобства логарифмирование
таргета и последующее возведение предсказаний в экспоненту были
инкапсулированы в классе LogExpModel
:
model = LogExpModel(lgbm.sklearn.LGBMRegressor())model.fit(X, y)model.predict(X)
Теперь главное - правильно построить валидацию. Дело в том, что
если обучить модель на одном квартале, а валидировать на следующем,
то модель просто запомнит эту компанию и возьмет капитализацию с
предыдущего квартала, что не очень правильно. Модель должна по
другим похожим компаниям понимать, сколько должна
стоить текущая. Соответственно, нужно делать группировку по
компаниям при валидации (разные квартальные срезы компании должны
быть строго в одном фолде, т.е. не использоваться одновременно и
для тренировки, и для валидации).
Для удобства процедура группировки по фолдам и предсказания была
инкапсулирована в классе GroupedOOFModel
. Т.е. можно
вызывать методы обучения и предикта, при этом внутри класс будет
хранить не одну модель, а целый набор и при предсказании для
очередной компании будет использовать ту модель, при обучении
которой данная компания не использовалась.
model = GroupedOOFModel(ansamble, group_column='ticker', fold_cnt=5)model.fit(X, y) # X should contain 'ticker' columnmodel.predict(X)
Кроме того, экспериментально было проверено, что одна модель ведет себя нестабильно при, например, дообучении на новых данных. Поэтому (и еще для увеличения итогового качества предсказаний) было решено использовать ансабль моделей. При этом в ансамбль входят как разные классы моделей, так и модели, обученные на разных сабсетах тренировочных данных (бэггинг). Во время инференса предсказания базовых моделей усредняются.
Данный ансамбль реализован с интерфейсом, типичным для всех моделей:
base_models = [lgbm.sklearn.LGBMRegressor(), ctb.CatBoostRegressor()]ansamble = EnsembleModel( base_models=base_models, bagging_fraction=0.7, model_cnt=20)ansamble.fit(X, y)ansamble.predict(X)
Итого, финальная модель, являющаяся комбинацией всех описанных выше классов:
base_models = [LogExpModel(lgbm.sklearn.LGBMRegressor()), LogExpModel(ctb.CatBoostRegressor())]ensemble = EnsembleModel( base_models=base_models, bagging_fraction=0.7, model_cnt=20)model = GroupedOOFModel(ensemble, group_column='ticker', fold_cnt=5)
Итак, почти все готово для обучения:
feature
- класс, реализующий подсчет фичей
target
- класс, реализующий вычисление таргета
model
- модель(в том числе инкапсулирующая в себе
разделение для валидации)
Осталось собрать все это воедино и обучить, используя наши
данные (а именно, класс SF1Data
). Для данных целей был
написан класс BasePipeline
. Он скрывает в себе всю
логику с расчетом фичей, таргетов, обучением модели и подсчетом
метрики (кроме того, поддерживается режим с мульти-таргетом и
мульти-метриками). При инференсе производит
pd.DataFrame
с результатом в колонке
out_name.
data_loader = SF1Data('path/to/data')pipeline = BasePipeline( feature=feature, target=target, model=model, metric=median_absolute_relative_error, out_name=['fair_marketcap'])pipeline.fit(data_loader, ticker_list)pipeline.execute(data_loader, ['INTC'])
Результат:
ticker |
date |
fair_marketcap |
---|---|---|
INTC |
2021-01-22 |
4.363793e+11 |
INTC |
2020-10-23 |
2.924576e+11 |
INTC |
2020-07-24 |
3.738603e+11 |
INTC |
2020-04-24 |
3.766202e+11 |
INTC |
2020-01-24 |
4.175332e+11 |
Еще раз код всего пайплайна целиком(он же на гитхабе
https://github.com/fartuk/ml_investment/blob/main/train/fair_marketcap.py):
SAVE_PATH = 'models_data/fair_marketcap'OUT_NAME = 'fair_marketcap'CURRENCY = 'USD'MAX_BACK_QUARTER = 10BAGGING_FRACTION = 0.7MODEL_CNT = 20FOLD_CNT = 5QUARTER_COUNTS = [2, 4, 10]AGG_DAY_COUNTS = [100, 200, 400, 800]SCALE_MARKETCAP = ["4 - Mid", "5 - Large", "6 - Mega"]DAILY_AGG_COLUMNS = ["marketcap", "pe"]CAT_COLUMNS = ["sector", "sicindustry"]QUARTER_COLUMNS = [ "revenue", "netinc", "ncf", "assets", "ebitda", "debt", "fcf", "gp", "workingcapital", "cashneq", "rnd", "sgna", "ncfx", "divyield", "currentratio", "netinccmn" ]data_loader = SF1Data('path/to/data')tickers_df = data_loader.load_base_data( currency=CURRENCY, scalemarketcap=SCALE_MARKETCAP)ticker_list = tickers_df['ticker'].unique().tolist()fc1 = QuarterlyFeatures( columns=QUARTER_COLUMNS, quarter_counts=QUARTER_COUNTS, max_back_quarter=MAX_BACK_QUARTER)fc2 = BaseCompanyFeatures(cat_columns=CAT_COLUMNS)# Daily agss on marketcap and pe is possible here because it # normalized and there are no leakage.fc3 = DailyAggQuarterFeatures( columns=DAILY_AGG_COLUMNS, agg_day_counts=AGG_DAY_COUNTS, max_back_quarter=MAX_BACK_QUARTER)feature = FeatureMerger(fc1, fc2, on='ticker')feature = FeatureMerger(feature, fc3, on=['ticker', 'date'])target = QuarterlyTarget(col='marketcap', quarter_shift=0)base_models = [LogExpModel(lgbm.sklearn.LGBMRegressor()), LogExpModel(ctb.CatBoostRegressor(verbose=False))]ensemble = EnsembleModel( base_models=base_models, bagging_fraction=BAGGING_FRACTION, model_cnt=MODEL_CNT)model = GroupedOOFModel(ensemble, group_column='ticker', fold_cnt=FOLD_CNT)pipeline = BasePipeline(feature=feature, target=target, model=model, metric=median_absolute_relative_error, out_name=OUT_NAME)result = pipeline.fit(data_loader, ticker_list)print(result)pipeline.export_core(SAVE_PATH)
Итак, удалось построить пайплайн, который выдает для квартальных срезов компаний оценки честной капитализации. Поиграться с результатами и посмотреть на fair marketcap для компаний американского рынка можно на странице http://fattakhov.site/company?ticker=AAPL . Для этого нужно ввести тикер интересующей компании и нажать кнопку Analyze. Ну и, собственно, как можно использовать полученный инструмент - смотреть на реальную капитализацию (синий график), на предсказанную честную капитализацию (оранжевый график) и считать компанию недооцененный, если оранжевый график лежит ниже синего и переоцененной в противном случае. Сами точки, соответственно, находятся на датах выходов квартальных отчетов. Проверим модельку на некоторых примерах:
С теслой, как и ожидалось, модель говорит о сильной переоценке. И действительно, если глазами смотреть на показатели компании, то в данный момент цена кажется не очень оправданной.
С интелом, наоборот, модель считает оценку рынка не очень справедливой. Возможно, подобные эффекты связаны с другими проблемами компании, которые модель пока не в состоянии учитывать (непонятно, как, например, обрабатывать новости про отсрочки выходов очередных продуктов, переходов на другие тех.процессы и т.д.).
Идея следующего пайплайна, который я попробовал, заключается в следующем: пусть модель для честного определения капитализации может не учитывать некоторые скрытые причны того, почему та или иная компания стот столько, сколько она стоит. Но можно ли научить модель после выхода очередного отчета предсказывать, насколько должна была измениться стоимость компании? Кажется, что такая задача проще, потому что часто бывает, скрытые моменты, объясняющие рыночную стоимость, переходят из квартала в квартал. Ну вот нравится инвесторам покупать Теслу и ничего с этим не поделаешь.
Итак, вышел отчет компании, ее фундаментальные показатели как-то изменились (например, выручка выросла на 30%, прибыль выросла на 40% и т.д.). И по таким изменениям хотим предсказывать, а как по-хорошему должна была измениться капитализация.
В принципе, все базовые фичи, которые были в первом пайплайне, можно оставить, они подходят и для текущей задачи. Но понятно, что нужно добавить и характеристики типа "изменение от квартала к кварталу". При этом стоит заметить, что важно сравнивать не только с предыдущим кварталом, но и кварталом год назад, потому что часто встречаются компании, например, с сезонными продажами. На графике ниже показана поквартальная выручка и прибыль компании Apple. Четко видны сезонные пики, связанные, думаю, с выходом новых моделей айфонов.
Реализовать подсчет нужных признаков можно с помощью класса
QuarterlyDiffFeatures
. В качестве параметра
compare_quarter_idxs
передаем [1, 4]
, так
как хотим сравнить показатели с предыдущим кварталом и кварталом
год назад. Класс посчитает относительные изменения показателей,
находящихся в колонках columns
:
fc = QuarterlyDiffFeatures( columns=['revenue', 'netinc'], compare_quarter_idxs=[1, 4], max_back_quarter=5)fc.calculate(data_loader, ['AAPL', 'INTC', 'F'])
С таргетом тут тоже вроде все понятно, просто берем и считаем, насколько изменилась рыночная капиталзизация и нормализуем для удобства:
target = QuarterlyDiffTarget(col='marketcap', norm=True)target.calculate(data_loader, info_df)
Навороты с ансамблем, разумеется, можно оставить, но нужно решить вопрос с валидацией. В данном случае совсем не обязательно группировать по компаниям, ведь предсказания относительные, а что будет с компанией в будущем по ее истории из прошлого - совсем непонятно. Однако тут есть другой момент - предсказывая изменение на текущий квартал, модель не должна знать про то, как в аналогичном квартале (и в будущем) изменились капитализации других компаний. Например, если вдруг случился мощный кризис, на фоне всеобщей паники капитализации всех компаний попадали даже при хороших отчетах. И модель по косвенным признакам поняла, что в данный момент кризис и занизила предсказания. Но во время инференса такой информации не будет, поэтому приходим к тому, что нужно делать time-series валидацию. А именно, сортируем все данные во времени, делим на N фолдов, обучаем модель на первом, предсказываем на второй. Обучаем модель на первых двух фолдах, предсказываем на третий. И так далее. Таким образом, делая предсказание на очередной квартал, мы не заглядываем в будущее.
Как и в случае с группировкой по фолдам, реализация time series
валидации скрыта в классе модели
TimeSeriesOOFModel
:
model = TimeSeriesOOFModel( base_model=lgbm.sklearn.LGBMRegressor(), time_column='date', fold_cnt=20)model.fit(X, y) # X should contain 'date' columnmodel.predict(X)
Пайплайн аналогичен тому, что был в прошлый раз. Посмотреть весь код можно на гитхабе.
код
SAVE_PATH = 'models_data/fair_marketcap_diff'OUT_NAME = 'fair_marketcap_diff'CURRENCY = 'USD'MAX_BACK_QUARTER = 10BAGGING_FRACTION = 0.7MODEL_CNT = 20FOLD_CNT = 5QUARTER_COUNTS = [2, 4, 10]COMPARE_QUARTER_IDXS = [1, 4]SCALE_MARKETCAP = ["4 - Mid", "5 - Large", "6 - Mega"]CAT_COLUMNS = ["sector", "sicindustry"]QUARTER_COLUMNS = [ "revenue", "netinc", "ncf", "assets", "ebitda", "debt", "fcf", "gp", "workingcapital", "cashneq", "rnd", "sgna", "ncfx", "divyield", "currentratio", "netinccmn" ]data_loader = SF1Data('path/to/data')tickers_df = data_loader.load_base_data( currency=CURRENCY, scalemarketcap=SCALE_MARKETCAP)ticker_list = tickers_df['ticker'].unique().tolist()fc1 = QuarterlyFeatures( columns=QUARTER_COLUMNS, quarter_counts=QUARTER_COUNTS, max_back_quarter=MAX_BACK_QUARTER)fc2 = BaseCompanyFeatures(cat_columns=CAT_COLUMNS)fc3 = QuarterlyDiffFeatures( columns=QUARTER_COLUMNS, compare_quarter_idxs=COMPARE_QUARTER_IDXS, max_back_quarter=MAX_BACK_QUARTER)feature = FeatureMerger(fc1, fc2, on='ticker')feature = FeatureMerger(feature, fc3, on=['ticker', 'date'])target = QuarterlyDiffTarget(col='marketcap')base_models = [lgbm.sklearn.LGBMRegressor(), ctb.CatBoostRegressor(verbose=False)]ensemble = EnsembleModel(base_models=base_models, bagging_fraction=BAGGING_FRACTION, model_cnt=MODEL_CNT)model = GroupedOOFModel(ensemble, group_column='ticker', fold_cnt=FOLD_CNT)pipeline = BasePipeline(feature=feature, target=target, model=model, metric=median_absolute_relative_error, out_name=OUT_NAME)result = pipeline.fit(data_loader, ticker_list)print(result)pipeline.export_core(SAVE_PATH)
Попробуем запустить полученный пайплайн на некоторых примерах. Опять же, посмотреть результат для других тикеров можно на странице http://fattakhov.site/company?ticker=AAPL (черный график). Итак, новый пайплайн выдет относительное предсказанное изменение для текущего квартала:
ticker |
date |
fair_marketcap_diff |
---|---|---|
INTC |
2021-01-22 |
0.283852 |
INTC |
2020-10-23 |
-0.021278 |
INTC |
2020-07-24 |
-0.035124 |
INTC |
2020-04-24 |
-0.098987 |
INTC |
2020-01-24 |
0.198822 |
Для удобства сделаем следующее: будем отображать посчитанное абсолютное изменение (беря информацию о реальной рыночной капитализации за предыдущий квартал). Т.е. новый график несет примерно такой же смысл, как и предыдущие - сколько по-хорошему должна стоить компания на текущий момент с учетом того, что известна стоимость за предыдущий квартал.
Видно, что получаются довольно точные предсказания (черный график), но расхождения все равно присутствуют, и как раз их и можно использовать при принятии решений о покупке/продажи очередной акции. То есть, например, вышел плохой отчет, компания сильно упала. Но модель говорит, что падение должно было быть не таким сильным -> потенциально хороший момент, чтобы купить.
С теслой, однако, даже такая модель не может объяснить столь стремительный рост :)
Может быть случай, что все предыдущие модели в один голос говорят: "покупай, дёшево!", но из истории понятно, что стоимость данной акции сильно скачет вверх-вниз, что не совсем приятно. Совершая сделку, хочется понимать, а какой есть риск? До каких пределов может опуститься цена и с какой вероятностью? Можно было бы из истории сделать статистические оценки, но у нас же ML-тулы :) Поэтому сделаем еще один машинно-обученный пайплайн (в этом подходе есть надежда, что модель сможет самостоятельно детектировать неблагоприятные/сильно рискованные моменты)
Не мелочимся и используем сразу все признаки, которые использовались ранее.
С выбором таргета тут сложнее. Основная идея в том, что он должен показывать, насколько вероятно падение в ближайшее время и каким оно может быть по величине. В голову приходит что-то вроде стандартного отклонения, std-вниз, максимальной просадки и т.п. за какой-то будущий промежуток времению. Пока для примера можно ограничиться std-вниз. Формула расчета представлена ниже (x_down - все x, меньшие среднего):
Класс таргета для таких целей уже описывался ранее:
target = DailyAggTarget( col='marketcap', horizon=90, foo=down_std_norm)
С моделью все понятно, берем максимальный ансамбль. При этом так же, как и в предыдущем примере, нужно использовать time-series валидацию (более того, это первая модель, которая должна оценивать будущее).
Все тот же класс BasePipeline
позволяет реализовать
данный пайплайн (гитхаб
версия).
SAVE_PATH = 'models_data/marketcap_down_std'OUT_NAME = 'marketcap_down_std'CURRENCY = 'USD'TARGET_HORIZON = 90MAX_BACK_QUARTER = 10BAGGING_FRACTION = 0.7MODEL_CNT = 20FOLD_CNT = 20QUARTER_COUNTS = [2, 4, 10]COMPARE_QUARTER_IDXS = [1, 4]AGG_DAY_COUNTS = [100, 200, 400, 800]SCALE_MARKETCAP = ["4 - Mid", "5 - Large", "6 - Mega"]DAILY_AGG_COLUMNS = ["marketcap", "pe"]CAT_COLUMNS = ["sector", "sicindustry"]QUARTER_COLUMNS = [ "revenue", "netinc", "ncf", "assets", "ebitda", "debt", "fcf", "gp", "workingcapital", "cashneq", "rnd", "sgna", "ncfx", "divyield", "currentratio", "netinccmn" ]data_loader = SF1Data(config['path/to/data'])tickers_df = data_loader.load_base_data( currency=CURRENCY, scalemarketcap=SCALE_MARKETCAP)ticker_list = tickers_df['ticker'].unique().tolist()fc1 = QuarterlyFeatures( columns=QUARTER_COLUMNS, quarter_counts=QUARTER_COUNTS, max_back_quarter=MAX_BACK_QUARTER)fc2 = BaseCompanyFeatures(cat_columns=CAT_COLUMNS)fc3 = QuarterlyDiffFeatures( columns=QUARTER_COLUMNS, compare_quarter_idxs=COMPARE_QUARTER_IDXS, max_back_quarter=MAX_BACK_QUARTER)fc4 = DailyAggQuarterFeatures( columns=DAILY_AGG_COLUMNS, agg_day_counts=AGG_DAY_COUNTS, max_back_quarter=MAX_BACK_QUARTER)feature = FeatureMerger(fc1, fc2, on='ticker')feature = FeatureMerger(feature, fc3, on=['ticker', 'date'])feature = FeatureMerger(feature, fc4, on=['ticker', 'date'])target = DailyAggTarget( col='marketcap', horizon=TARGET_HORIZON, foo=down_std_norm)base_models = [LogExpModel(lgbm.sklearn.LGBMRegressor()), LogExpModel(ctb.CatBoostRegressor(verbose=False))]ensemble = EnsembleModel(base_models=base_models, bagging_fraction=BAGGING_FRACTION, model_cnt=MODEL_CNT)model = TimeSeriesOOFModel(ensemble, time_column='date', fold_cnt=FOLD_CNT)pipeline = BasePipeline(feature=feature, target=target, model=model, metric=median_absolute_relative_error, out_name=OUT_NAME)result = pipeline.fit(data_loader, ticker_list)print(result)pipeline.export_core(SAVE_PATH)
Итак, пайплайн готов и выдает на выход предсказанные std-вниз (нормированные):
ticker |
date |
marketcap_down_std |
|
---|---|---|---|
INTC |
2021-01-22 |
0.043619 |
|
INTC |
2020-10-23 |
0.057673 |
|
INTC |
2020-07-24 |
0.061062 |
|
INTC |
2020-04-24 |
0.053481 |
|
INTC |
2020-01-24 |
0.039370 |
Если считать предсказанное std верным, то можно посчитать различные доверительные интервалы и отобразить их в виде ступенчатого графика. Для примера возьмём компанию Carnival, так как она известна своими скачками.
В глаза бросается мартовское падение 2020го года, но модель явно не могла предугадать кризисную историю, а с остальными кварталами вроде все более-менее в порядке и предсказание действительно лежит ниже графика капитализации. Тем не менее, с пайплайном для оценки рисков еще можно поработать и сделать что-то более точное и интерпретируемое.
В данной статье были описаны основные модели, которыми я пользуюсь при принятии своих инвестиционных решений. Понятно, что в таком виде - это всего лишь инструменты, которые могут как-то влиять на выбор той или иной акции, а не полноценные стратегии. Тем не менее, надеюсь, что основные идеи могли оказаться полезными для читателя, а так же жду советов/предложений по улучшению тулов.
Сам я завел отдельный портфель в котором совершаю сделки только на основании предсказаний от описанных выше моделей, за его результатами можно последить в Тинькофф Пульсе.
Возможно, напишу продолжение про то, как я конкретно составляю портфель, диверсифицирую по секторам, подбираю веса бумаг и т.д.