Введение в архитектуры нейронных сетей

МЕНЮ


Искусственный интеллект. Новости
Поиск

ТЕМЫ


Внедрение ИИНовости ИИРобототехника, БПЛАТрансгуманизмЛингвистика, обработка текстаБиология, теория эволюцииВиртулаьная и дополненная реальностьЖелезоКиберугрозыНаучный мирИТ индустрияРазработка ПОТеория информации

RSS


RSS новости

Авторизация


логин:

пароль:


регистрация
восстановить пароль

Новостная лента форума ailab.ru


Григорий Сапунов (Intento)

Меня зовут Григорий Сапунов, я СТО компании Intento. Занимаюсь я нейросетями довольно давно и machine learning’ом, в частности, занимался построением нейросетевых распознавателей дорожных знаков и номеров. Участвую в проекте по нейросетевой стилизации изображений, помогаю многим компаниям.

Давайте перейдем сразу к делу. Моя цель — дать вам базовую терминологию и понимание, что к чему в этой области, из каких кирпичиков собираются нейросети, и как это использовать.

План доклада такой. Сначала небольшое введение про то, что такое нейрон, нейросеть, глубокая нейросеть, чтобы мы с вами общались на одном языке.

Дальше я расскажу про важные тренды, что происходит в этой области. Затем мы углубимся в архитектуру нейросетей, рассмотрим 3 основных их класса. Это будет самая содержательная часть.

После этого рассмотрим 2 сравнительно продвинутых темы и закончим небольшим обзором фреймворков и библиотек для работы с нейросетями.

На конференции Наталья Ефремова из компании NTechLab рассказывала о практических кейсах. Я же расскажу, как нейросети устроены внутри, из каких кирпичиков они внутри состоят.

Краткое содержание


Recap: нейрон, нейросеть, глубокая нейросеть

Краткое напоминание

Искусственный нейрон — это очень отдаленное подобие биологического нейрона.

Что такое искусственный нейрон? Это простая функция на самом деле. У нее есть входы. Каждый вход умножается на некие веса, дальше все суммируется, прогоняется через какую-то нелинейную функцию, результат выдается на выход — все, это один нейрон.

Если вы знакомы с логистической регрессией, под которой понимаем нелинейную функцию SIGMOID, то один нейрон — это полный аналог логистической регрессии, простого линейного классификатора.

На самом деле существует много разных функций активации, в том числе приведенные на рисунке гиперболический тангенс (TANH), SIGMOID, RELU.

В реальности все сильно сложнее. Этой темы касаться не будем.

Я привел совсем базовое представление искусственного нейрона, как некое подобие биологического нейрона.

Искусственная нейросеть — это способ собрать нейроны в сеть, чтобы она решала определенную задачу, например, задачу классификации. Нейроны собираются по слоям. Есть входной слой, куда подается входной сигнал, есть выходной слой, откуда снимается результат работы нейросети, и между ними есть скрытые слои. Их может быть 1, 2, 3, много. Если скрытых слоев больше, чем 1, нейросеть считается глубокой, если 1, то неглубокой.


Существует огромное разнообразие различных архитектур, основные из которых мы рассмотрим. Но имейте в виду, что их очень много. Если интересно, перейдите потом по ссылке – посмотрите, почитайте.

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

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

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

Recap: важные тренды

Что сейчас происходит с качеством и сложностью моделей

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

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

Другая важная веха — то, что мы начинаем обгонять по качеству человека. На соревновании ImageNet это впервые произошло в 2015 году. Но на самом деле нейросетевые системы, которые по качеству превосходят человека, появились раньше. Первый задокументированный внятный случай — это 2011 год, когда была построена система, которая распознавала немецкие дорожные знаки и делала это в 2 раза лучше человека.

Второй важный тренд — сложность нейросетей растет. В терминах глубины растет глубина. Если победитель 2012 года на ImageNet — сеть AlexNet — там было меньше 10 слоев, то в 2014 году их было уже больше 20, в 2015 — под 150. В этом году, кажется, уже за 200. Что будет дальше — непонятно, возможно, будет еще больше.


http://cs.unc.edu/~wliu/papers/GoogLeNet.pdf

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


https://culurciello.github.io/tech/2016/06/04/nets.html

Это график точности различных нейросетей. Здесь указано время, которое требуется на выполнение, на просчет этой сети, то есть некая вычислительная нагрузка. Размер кружка — это количество параметров, которые описываются нейросетью. Интересно сравнить классическую сеть AlexNet — победителя 2012 года и более поздние сети. Они лучше по точности, но, как правило, содержат меньше параметров. Это тоже важный тренд, что нейросети усложняются очень умно. То есть архитектура изменяется так, что даже несмотря на то, что число слоев 150, общее количество параметров оказывается меньше, чем в 6-7-слойной сети, которая в 2012 году была. Архитектура как-то усложняется очень интересным способом.

Еще один тренд — рост объемов данных. В 1998 году для обучения сверточной
нейросети, которая распознавала рукописные чеки, было использовано 10 7 пикселей, в 2012 году (IMAGENET) — 10 14.

7 порядков за 14 лет — это безумная разница и огромный сдвиг!

При этом количество транзитов на процессоре тоже растет, растут вычислительные мощности — закон Мура действует. За эти 14 лет процессоры стали условно в 1000 раз быстрее. Это видно на примере GPUs, которые сейчас доминируют в области Deep Learning. Практически все считается на графических ускорителях.

Компания NVIDIA перепрофилировалась из игровой фактически в компанию для искусственного интеллекта. Ее экспоненты оставили далеко позади экспоненты Intel, которые на этом фоне вообще не смотрятся.

Это картинка 2013 года, когда топовая видеокарта была 4,5 TFLOPS. Сейчас новый TITAN X — это уже 11 TFLOPS. В общем, экспонента продолжается!

На самом деле можно ожидать, что в ближайшее время появится FPGA’сики, которые частично потеснят GPU, и, может быть, со временем появятся даже нейроморфные процессоры. Следите за этим — там тоже много интересного происходит.

Архитектуры нейросетей. Нейросети прямого распространения

Fully Connected Feed-Forward Neural Networks, FNN

Первая классическая архитектура — полносвязные нейросети прямого распространения, или Fully Connected Feed-Forward Neural Network, FNN.

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

Однако у нее есть 2 проблемы:

  • Много параметров

Например, если взять нейросеть из 3 скрытых слоев, которой нужно обрабатывать картинки 100*100 ps, это значит, что на входе будет 10 000 ps, и они заводятся на 3 слоя. В общем, если честно посчитать все параметры, у такой сети их будет порядка миллиона. Это на самом деле много. Чтобы обучить нейросеть с миллионом параметров, нужно очень много обучающих примеров, которые не всегда есть. На самом деле сейчас примеры есть, а раньше их не было — поэтому, в частности, сети не могли обучать, как следует.

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

Плюс есть другая проблема под названием:

  • Затухающие градиенты

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

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

Есть различные вариации FNN-сетей. Например, очень интересная вариация Автоэнкодер. Это сеть прямого распространения с так называемым бутылочным горлышком в середине. Это очень маленький слой, допустим, всего на 10 нейронов.

В чем преимущества такой нейросети?

Цель этой нейросети взять какой-то вход, прогнать через себя и на выходе сгенерировать тот же самый вход, то есть чтобы они совпадали. В чем смысл? Если мы сможем обучить такую сеть, которая берет вход, прогоняет через себя и генерирует точно такой же выход, это значит, что этих 10 нейронов в середине достаточно для описания этого входа. То есть можно очень сильно уменьшить пространство, сократить объём данных, экономно закодировать любые входные данные в новых терминах 10 векторов.

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

Есть еще интересная модель RBM. Я ее написал в вариации FNN, но на самом деле это не правда. Во-первых, она не глубокая, во-вторых, она не Feed-Forward. Но она часто связана с FNN-сетями.

Что это такое?

Это неглубокая модель (на слайде она в уголке нарисована), у которой есть вход и есть какой-то скрытый слой. Вы подаете сигнал на вход и пытаетесь обучить скрытый слой так, чтобы он генерил этот вход.

Это генеративная модель. Если вы ее обучили, то потом можете генерить аналоги ваших входных сигналов, но чуть-чуть другие. Она стохастическая, то есть каждый раз она будет генерить что-то чуть другое. Если вы, например, обучили такую модель на генерацию рукописных единичек, она потом их нагенерит какое-то количество немножко разных.

Чем хороши RBM — тем, что их можно использовать для обучения глубоких сетей. Есть такой термин — Deep Belief Networks (DBN) — фактически это способ обучения глубоких сетей, когда берутся отдельно 2 нижних слоя глубокой сети, подается вход и RBM обучается на этих первых двух слоях. После этого фиксируются эти веса. Далее берется второй слой, рассматривается как отдельная RBM и точно также обучается. И так по всей сети. Потом эти RBM стыкуются, объединяются в одну нейросеть. Получается глубокая нейросеть, какая и должна была бы быть.

Но теперь есть огромное преимущество — если бы раньше вы ее обучали просто с какого-то рандомного (случайного) состояния, то теперь оно не рандомное – сеть обучена восстанавливать или генерить данные предыдущего слоя. То есть у нее веса разумные, и на практике это приводит к тому, что такие нейросети действительно уже довольно неплохо обучены. Их потом можно слегка дообучить какими-то примерами, и качество такой сети будет хорошим.

Плюс есть дополнительное преимущество. Когда вы используете RBM, вы, по сути, работаете на неразмеченных данных, что называется Un supervised learning. У вас есть просто картинки, вы не знаете их классов. Вы прогнали миллионы, миллиарды картинок, которые вы скачали с Flickr’а или еще откуда-то, и у вас есть какая-то структура в самой сети, которая описывает эти картинки.

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

Дальше вы увидите, что вся эта история на самом деле — про Lego. То есть у вас есть отдельные сети — рекуррентные нейросети, еще какие-то сети — это все блоки, которые можно совмещать. Они хорошо совмещаются на разных задачах.

Это были классические нейросети прямого распространения. Далее перейдем к сверточным нейросетям.

Архитектуры нейросетей: Сверточные нейросети

Convolutional Neural Networks, CNN


https://research.facebook.com/blog/learning-to-segment/

Сверточные нейросети решают 3 основные задачи:

  1. Классификация. Вы подаете картинку, и нейросеть просто говорит — у вас картинка про собаку, про лошадь, еще про что-то, и выдает класс.
  2. Детекция – это более продвинутая задачка, когда нейросеть не просто говорит, что на картинке есть собака или лошадь, но находит еще Bounding box — где это находится на картинке.
  3. Сегментация. На мой взгляд, это самая крутая задача. По сути, это попиксельная классификация. Здесь мы говорим про каждый пиксель изображения: этот пиксель относится к собаке, этот — к лошади, а этот еще к чему-то. На самом деле, если вы умеете решать задачу сегментации, то остальные 2 задачи уже автоматически даны.


Что такое сверточная нейросеть? На самом деле сверточная нейросеть — это обычная Feed-Forward сеть, просто она немножко специального вида. Вот уже начинается Lego.

Что есть в сверточной сети? У нее есть:

  • Сверточные слои — я дальше расскажу, что это такое;
  • Subsampling, или Pooling-слои, которые уменьшают размер изображения;
  • Обычные полносвязные слои, тот самый многослойный персептрон, который просто сверху навешен на эти первые 2 хитрых слоя.

Немного более подробно про все эти слои.


  • Сверточные слои обычно рисуются в виде набора плоскостей или объемов. Каждая плоскость на таком рисунке или каждый срез в этом объеме — это, по сути, один нейрон, который реализует операцию свертки. Опять же, дальше я расскажу, что это такое. По сути, это матричный фильтр, который трансформирует исходное изображение в какое-то другое, и это можно делать много раз.
  • Слои субдискретизации (буду называть Subsampling, так проще) просто уменьшают размер изображения: было 200*200 ps, после Subsampling стало 100*100 ps. По сути, усреднение, чуть более хитрое.
  • Полносвязные слои обычно персептрон использует для классификации. Ничего специального в них нет.


http://intellabs.github.io/RiverTrail/tutorial/

Что такое операция свертки? Это всех пугает, но на самом деле это очень простая вещь. Если вы работали в Photoshop и делали Gaussian Blur, Emboss, Sharpen и кучу других фильтров, это все матричные фильтры. Матричные фильтры — это на самом деле и есть операция свертки.

Как она реализована? Есть матрица, которая называется ядром фильтра (на рисунке kernel). Для Blur это будут все единицы. Есть изображение. Эта матрица накладывается на кусочек изображения, соответствующие элементы просто перемножаются, результаты складываются и записываются в центральную точку.


http://intellabs.github.io/RiverTrail/tutorial/

Так это выглядит более наглядно. Есть изображение Input, есть фильтр. Вы пробегаете фильтром по всему изображению, честно перемножаете соответствующие элементы, складываете, записываете в центр. Пробегаете, пробегаете — построили новое изображение. Все, это операция свертки.

То есть, по сути, свертка в сверточных нейросетях — это хитрый цифровой фильтр (Blur, Emboss, что угодно еще), который сам обучается.


http://cs231n.github.io/convolutional-networks/

На самом деле сверточные слои все работают на объемах. То есть если даже взять обычное изображение RGB, там уже 3 канала — это, по сути, не плоскость, а объем из 3-х, условно, кубиков.

Свертка в этом случае уже представляется не матрицей, а тензором — кубиком на самом деле.

У вас есть фильтр, вы пробегаете по всему изображению, он сразу смотрит на все 3 цветовых слоя и генерит одну новую точку для одного этого объема. Пробегаете по всему изображению — построили один канал, одну плоскость нового изображения. Если у вас 5 нейронов — вы построили 5 плоскостей.

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

Что делают такие нейроны? Они фактически учатся искать какие-то фичи, какие-то локальные признаки в той небольшой части, которую они видят — и все. Прогон одного такого фильтра — это построение некой карты нахождения этих признаков в изображении.

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


http://vaaaaaanquish.hatenablog.com/entry/2015/01/26/060622

Операция Pooling — еще более простая операция. Это просто усреднение либо взятие максимума. Она тоже работает на каких-то небольших квадратиках, например, 2*2. Вы накладываете на изображение и, например, выбираете максимальный элемент из этого квадратика 2*2, отправляете на выход.

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


http://cs231n.github.io/convolutional-networks/

Так работает Pooling-слой. Есть кубик какого-то объема — 3 канала, 10, или 100 каналов, которые вы насчитали свертками. Он просто уменьшает его по ширине и по высоте, остальные размерности не трогает. Все — примитивная вещь.

Чем хороши сверточные сети?

Они хороши тем, что у них сильно меньше параметров, чем у обычной полносвязной сети. Вспомните пример с полносвязной сетью, который мы рассматривали, где получился миллион весов. Если взять аналогичную, точнее, похожую — аналогичной ее нельзя назвать, но близкую сверточную нейросеть, у которой будет такой же вход, такой же выход, тоже будет один полносвязный слой на выходе и еще 2 сверточных слоя, где тоже будет по 100 нейронов, как в базовой сети, то выяснится, что число параметров в такой нейросети уменьшилось больше, чем на порядок.

Это здорово, если параметров настолько меньше — сеть проще обучать. Мы это видим, ее действительно проще обучать.

Что делает сверточная нейросеть?

По сути, она автоматически учит какие-то иерархические признаки для изображений: сначала базовые детекторы, линии разного наклона, градиенты и т.д. Из них она собирает какие-то более сложные объекты, потом еще более сложные.

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

Современные архитектуры сверточных нейросетей сильно усложнились. Те нейросети, которые побеждали на последних соревнованиях ImageNet — это уже не просто какие-то сверточные слои, Pooling-слои. Это прямо законченные блоки. На рисунке приведены примеры из сети Inception (Google) и ResNet (Microsoft).

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

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


https://arxiv.org/abs/1411.4038

Например, есть такая разновидность сверточных нейросетей, называется Fully-convolutional networks (FCN). Про них редко говорят, но это классная вещь. Можно взять и оторвать последний многослойный персептрон, он не нужен — и выкинуть его. И тогда нейросеть магическим образом может работать на изображениях произвольного размера.

То есть она научилась, допустим, определять 1000 классов в изображениях кошечек, собачек, чего-то еще, а потом мы последний слой взяли и не оторвали, но трансформировали в сверточный слой. Там нет проблем — можно веса пересчитать. Тогда выясняется, что эта нейросеть как бы работает тем же самым окном, на которое она была обучена, 100*100 ps, но теперь она может пробежаться этим окном по всему изображению и построить как бы тепловую карту на выходе — где в этом конкретном изображении находится конкретный класс.

Вы можете построить, например, 1000 этих Heatmap для всех своих классов и потом использовать это для определения места нахождения объекта на картинке.

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


http://cvlab.postech.ac.kr/research/deconvnet/

Более продвинутый пример — Deconvolution networks. Про них тоже редко говорят, но это еще более классная штука.

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

Что это такое? По сути, это обучаемый Upsampling. То есть вы уменьшили в какой-то момент ваше изображение до какого-то небольшого размера, может, даже до 1 ps. Скорее, не до пикселя, а до какого-то небольшого вектора. Потом можно взять этот вектор и раскрыть.

Или, если в какой-то момент получилось изображение 10*10 ps, теперь можно делать Upsampling этого изображения, но каким-то хитрым способом, в котором веса Upsampling также обучаются.

Это — не магия, это работает, и фактически это позволяет обучать нейросети, которые из входной картинки получают какую-то выходную картинку. То есть вы можете подавать образцы входа/выхода, а то, что посередине, обучится само. Это интересно.

На самом деле много задач можно свести к генерации картинок. Классификация — классная задача, но она все-таки не всеобъемлющая. Есть много задач, где надо картинки генерить. Сегментация — это в принципе классическая задача, где надо на выходе картинку иметь.

Более того, если вы научились делать так, то можно сделать еще по-другому, более интересно.


https://arxiv.org/abs/1411.5928

Можно первую часть, например, оторвать, а прикрутить какую-то опять полносвязную сеть, которую обучим — то, что ей на вход подается, например, номер класса: сгенери мне стул под таким-то углом и в таком-то виде. Эти слои генерят дальше какое-то внутреннее представление этого стула, а потом оно разворачивается в картинку.

Этот пример взят из работы, где действительно научили нейросеть генерить разные стулья и другие объекты. Это тоже работает, и это прикольно. Это собрано, в принципе, из тех же базовых блоков, но их по-другому завернули.


https://arxiv.org/abs/1508.06576

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


https://arxiv.org/abs/1508.06576

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

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

Единственная проблема этого метода в том, что он долгий. Этот итеративный прогон картинки туда-сюда — это долго. Кто игрался с этим кодом по генерации стиля, знает, что классический код долгий, и надо помучиться. Все сервисы типа Призмы и так далее, которые генерят более-менее быстро, работают по-другому.


https://arxiv.org/abs/1603.03417

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

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

Это такие хакерские методы использования нейросетей, но оказалось, что они работают, и это приводит к классным результатам.

Далее перейдем к рекуррентным нейросетям.

Архитектуры нейросетей: Рекуррентные нейросети

Recurrent Neural Networks, RNN

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

Про обычную нейросеть Feed-Forward известно, что это универсальный аппроксиматор. Они могут аппроксимировать более-менее любую непрерывную функцию (есть такая теорема Цыбенко). Это здорово, но рекуррентные нейросети — тьюринг полный. Они могут вычислить любое вычислимое.

По сути рекуррентные нейросети — это обычный компьютер. Задача — его правильно обучить. Потенциально он может считать любой алгоритм. Другое дело, что научить его сложно.

Кроме того, обычные Feed-Forward-нейросети никакой возможности не имеют учесть порядок во времени — нет в них этого, не представлено. Рекуррентные сети это делают явным образом, в них зашито понятие времени.

Обычные Feed-Forward сети не обладают никакой памятью, кроме той, которая была получена на этапе обучения, а рекуррентные обладают. За счет того, что содержимое слоя передается нейросети обратно, это как бы ее память. Она хранится во время работы нейросети. Это тоже очень многое добавляет.


http://colah.github.io/posts/2015-08-Understanding-LSTMs/

Как обучаются рекуррентные нейросети? На самом деле почти так же. Кроме Backpropagation, конечно, существует много других алгоритмов, но в данный момент Backpropagation работает лучше всего.

Для рекуррентных нейросетей есть вариация этого алгоритма — Backpropagation through time. Идея очень простая — вы берете рекуррентную нейросеть и цикл просто разворачиваете на сколько-то шагов, например, на 10, 20 или 100, и получается обычная глубокая нейросеть, которую после этого вы обучаете обычным Backpropagation.

Но есть проблема. Как только мы начинаем говорить про глубокие нейросети – где 10, 20, 100 слоев — от градиентов, которые с конца должны пройти в самое начало, за 100 слоев ничего не остается. С этим надо что-то делать. В этом месте придумали некий хак, красивое инженерное решение под названием LSTM или GRU- это ячейки памяти.


https://deeplearning4j.org/lstm

Их идея заключается в том, что визуализация обычного нейрона заменяется на некую хитрую штуку, у которой есть память и есть gate, которые контролируют то, когда эту память нужно сбросить, перезаписать или сохранить и т.д. Эти gate тоже обучаются так же, как и все остальное. Фактически эта ячейка, когда она обучилась, может сказать нейросети, что сейчас мы держим это внутреннее состояние долго, например, 100 шагов. Потом, когда нейросеть это состояние для чего-то использовала, его можно обнулить. Оно стало не нужно, мы пошли новое считать.

Эти нейросети на всех более-менее серьезных тестах сильно по качеству уделывают обычные классические рекуррентные, которые просто на нейронах. Почти все рекуррентные сети в данный момент построены либо на LSTM, либо на GRU.


http://kvitajakub.github.io/2016/04/14/rnn-diagrams

Не буду углубляться, что это такое внутри, но это такие хитрые блоки, сильно сложнее, чем обычные нейроны, но, по сути, они похожи. Там есть некие gate, которые контролируют это самое «запомнить — не запомнить», «передать дальше — не передать дальше».

Это были классические рекуррентные нейросети. Дальше начинается тема, о которой часто умалчивается, но она тоже важная.

Когда мы работаем с последовательностью в рекуррентной сети, мы обычно подаем один элемент, потом следующий, и заводим предыдущее состояние сети на вход, возникает такое естественное направление — слева направо. Но оно же не единственное! Если у нас есть, например, предложение, мы начинаем подавать его слова в обычном порядке в нейросеть — да, это нормальный способ, но почему бы с конца не подать?

То есть во многих случаях последовательность дана уже целиком с самого начала. У нас есть это предложение, и нет смысла как-то выделять одно направление относительно другого. Мы можем прогнать нейросеть с одной стороны, с другой стороны, фактически имея 2 нейросети, а потом их результат скомбинировать.

Это и называется Bidirectional — двунаправленная рекуррентная нейросеть. Их качество еще выше, чем обычных рекуррентных сетей, потому что появляется больше контекста: для каждой точки теперь есть 2 контекста — что было до, и что будет после. Для многих задач это добавляет качества, особенно для задач, связанных с языком.

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

Более того, мы рассматривали одномерные случаи — например, предложения. Но есть же многомерные последовательности — то же изображение тоже можно рассмотреть как последовательность. Тогда у него вообще есть 4 направления, которые разумны по-своему. Для произвольной точки изображения есть, по сути, 4 контекста при таком обходе.

Есть интересные многомерные рекуррентные нейросети: они и многомерные, и многонаправленные. Сейчас они немножко подзабыты. Это, кстати, старая разработка, которой уже лет 10, наверное, но сейчас она начинает всплывать.

Вот свежие работы (2015 год). Это нейросеть — аналог классической нейросети LeNet, которая классифицировала рукописные цифры. Но теперь она ни разу не сверточная, а рекуррентная и многонаправленная. Там стрелочки есть, которые по разным направлениям проходят по изображению.

Второй пример — хитрая нейросеть, которая использовалась для сегментации мозговых срезов. Она тоже ни разу не сверточная, а рекуррентная, и она победила в каком-то очередном конкурсе.

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


https://arxiv.org/abs/1507.01526

А еще есть совсем свежая разработка Grid LSTM, которая пока еще не очень осмыслена и осознана. На самом деле идея простая — взяли рекуррентную сеть, в какой-то момент заменили нейроны на какие-то хитрые ячейки, чтобы по времени можно было хранить состояние долго. Если наша сеть глубокая в этом направлении, то там нет никаких gate, градиенты также теряются. Что, если в этом направлении тоже что-то такое добавить? Да, добавили, оказалось круто!

Просто проблема — сейчас почти нет готовых программных библиотек, где это реализовано. Есть 1-2 кусочка кода, которые можно попытаться использовать. Надеюсь, что в ближайший год появятся общедоступные эти вещи, и будет совсем круто.

Это замечательная вещь, смотрите, что с ней будет, она хорошая.

Теперь начинаются продвинутые темы.

Мультимодальное обучение (Multimodal Learning)

Смешивание различных модальностей в одной нейросети, например, изображение и текст

Мультимодальное обучение — это идейно тоже простая штука, когда мы берем и в нейросети смешиваем 2 модальности, например, картинки и текст. До этого мы рассматривали случаи работы на 1 модальности — только на картинках, только на звуке, только на тексте. Но можно и смешать!


http://arxiv.org/abs/1411.4555

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

Кстати, мы выложили в открытый доступ видеозаписи последних пяти лет конференции разработчиков высоконагруженных систем HighLoad++. Смотрите, изучайте, делитесь и подписывайтесь на канал YouTube.

Внутри все устроено просто. Есть сверточная нейросеть, которая обрабатывает изображение, выделяет из него какие-то признаки и записывает его в каком-то хитром векторе состояния. Есть рекуррентная сеть, которая научена из этого состояния генерить и разворачивать текст.

Это совмещение 2-х модальностей очень продуктивно. Таких примеров много.


https://www.cs.utexas.edu/~vsub/

Есть, например, интересная задача аннотирования видео. По сути, к предыдущей задаче просто добавляется еще одно измерение — время.

Например:

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

Это интересно!

Чуть более детально, как мультмодальное обучение выглядит внутри.


http://arxiv.org/abs/1411.2539

Есть какое-то хитрое пространство, которое мы никак не видим, но оно внутри нейросети существует в виде этих весов, которые она для себя считает. Получается так, что в процессе обучения мы учим как бы 2 разные нейросети: сверточную и рекуррентную для текста, который описывает картинку и для самой картинки генерировать вектора в этом хитром пространстве в одном месте. То есть сводить 2 модальности в одну.

Если мы это научились делать, то дальше там до некоторой степени не важно: подаем картинку — генерируем текст, подаем текст — находим картинку. Можно играться с разными штуками и строить интересные вещи.

Кстати, уже есть попытки строить сети, которые по тексту генерят картинки. Это интересно, это тоже работает. Пока еще не очень хорошо, но потенциал огромен.

Sequence Learning и парадигма seq2seq

Когда надо работать с последовательностями произвольной длины на входе и/или выходе

Вторая интересная тема — Sequence Learning или парадигма seq2seq. Я даже не буду это переводить. Идея в том, что много ваших задач сводится к тому, что у вас есть последовательности. То есть не просто картинка, которую нужно классифицировать, выдать одно число, а есть одна последовательность, а на выходе нужна другая последовательность.

Например, перевод — классическая задача Sequence 2 Sequence Learning: задали текст на английском, хотите получить на французском.

Таких задач много на самом деле. Это кейс описания картинки.


http://karpathy.github.io/2015/05/21/rnn-effectiveness/

Обычные нейросети, которые мы рассматривали — что-то загнали, прогнали через сеть, сняли на выходе — не интересно.

Есть вариант под названием One to many. Загнали картинку в сеть, а дальше она пошла работать, работать и сгенерила описание этой картинки. Здорово.

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

Есть история про перевод. Вы долго загоняли последовательность на одном языке. Дальше сеть поработала и начала генерить последовательность на другом языке. Это вообще самая общая постановка.

Есть еще одна интересная постановка, когда входы и выходы синхронизированы. Например, если нужно аннотировать каждый кадр изображения — есть на нем что-то или нет.

На рисунке представлены все варианты Sequence 2 Sequence Learning, и это очень мощная парадигма. Она мощна тем, что если внутри нейросети все дифференцируемо — а нейросети, которые мы обсуждали, все внутри насквозь дифференцируемы, это значит, что вы можете обучать нейросеть, так сказать, end-to-end: подали на вход одни последовательности, на выход другие, а что происходит внутри, вам вообще не важно. Нейросеть сама справится — на вход куча примеров на английском, на выход — куча примеров на французском – отлично, она сама обучится переводу. Причем действительно с хорошим качеством, если у вас большая база данных и хорошие вычислительные мощности, чтобы все это прогнать.

Еще одна безумно важная вещь, про которую почти нигде не говорят, но без которой не работает ни распознавание речи Google, ни Baidu, ни Microsoft – CTC.


https://github.com/baidu-research/warp-ctc

CTC — это такой хитрый выходной слой. Что он делает? Есть много задач, в которых на самом деле не важно выравнивание внутри этой последовательности. Есть задача распознавания речи. Вы взяли звук, порезали на короткие фреймы по 50 мс, например, а дальше на выходе нужно сгенерить, какое слово это было, последовательность фонем. По большому счету, вам не важно, в каком месте исходного сигнала была та или иная фонема. Важен только порядок между собой, чтобы просто слово на выходе получить.

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

Можно просто все взять и выкинуть — есть входные данные, есть выход — что должно получиться в терминах выходной последовательности — слово, есть этот хитрый CTC-слой, который сам сделает какое-то выравнивание внутри себя, и это позволит, опять же, end-to-end обучить такую хитрую сеть, для которой вы вообще ничего не размечали.

Это мощнейшая вещь, она тоже не во всех современных пакетах реализована. Но, например, год назад Baidu выложил свою реализацию слоя CTC — это здорово.

Еще пару слов про разные архитектуры.


https://github.com/farizrahman4u/seq2seq

Есть классическая архитектура Encoder-Decoder. Пример с переводом, про который я говорил, практически целиком сводится к этой архитектуре.

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

Это работает. Многие системы перевода работают так.

Но у этой архитектуры есть одна проблема — тоже бутылочное горлышко. Вектор состояния (размер скрытого слоя), который передается, ограничен и фиксирован. То есть получается, что он одинаковый и для короткого предложения, и для безумно длинного — это не очень хорошо. Может оказаться, что длинное предложение не впишется в этот объем.


https://research.googleblog.com/2016/09/a-neural-network-for-machine.html

Появились архитектуры, что называется, с вниманием.

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

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

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


http://kelvinxu.github.io/projects/capgen.html

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

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


http://kelvinxu.github.io/projects/capgen.html

CNN + RNN с вниманием = красивые картинки.

Когда нейросеть генерит текст про знак СТОП, она действительно как бы смотрит на этот знак — его вес, его вклад в генерацию конкретного слова СТОП очень высокий, а все остальные пиксели играют мало роли.

Это интересная концепция, за ней тоже следите. Она тоже будет много где использоваться.

Фреймворки и библиотеки для работы с нейросетями

Очень краткий обзор

На самом деле про это можно говорить часами. У меня нет цели вам сказать – да, используйте вот эту библиотеку или вот эту — потому, что это все не так. Библиотек есть огромное количество. Приведу более-менее актуальный список разных библиотек.


Подробный список: http://deeplearning.net/software_links/

Универсальные библиотеки и сервисы:



Во-первых, есть универсальные библиотеки, про многие из которых вы слышали.

Например, TensorFlow (Google) — наверное, одна из самых популярных, хотя довольно свежая. Ее можно использовать на Python и C++.

Есть библиотека Torch, которая активно поддерживает Facebook в данный момент. Это язык Lua. Но не надо его пугаться, на самом деле это классный язык. На этой библиотеке очень много, чего реализовано, там много свежих исследований прямо в виде кода на Lua выходят. Это здорово.

Есть библиотека Theano — ее сейчас немножко потеснил TensorFlow, но вокруг Theano построено много разных классных высокоуровневых оберток — нейросеть можно написать в несколько строчек. Это прямо очень здорово!

Некоторые из этих оберток, например, Keras, могут работать с TensorFlow, как backend, что называется. То есть TensorFlow — это довольно низкоуровневый код в терминах нейросетей, Keras — высокоуровневый код, или слой одной строчкой — это удобно.

Microsoft что-то опубликовал, есть Neon, Deeplearning4j — редкий случай – библиотека Java для Deeplearning. Их мало на Java. Много на Python и C++. На остальных языках меньше.

Кроме того, есть специальные средства для обработки видео.

Обработка изображений и видео:


Я сюда OpenCV включил. Это конечно ни разу не Deeplearning-библиотека, но она хорошо интегрируется с другими библиотеками.

Caffe — отличная библиотека, мы ее использовали в Production. Это плюсовая библиотека, она очень быстрая, быстрее нее мало, что есть. Она до сих пор крута, хотя те, кто сейчас осваивает нейросети, почему-то думают только о TensorFlow. Но имейте в виду, что есть куча других прекрасных решений, в том числе Caffe — очень крутая вещь.

Кроме того, есть какое-то количество различных API, которые в WEB можно использовать.

Распознавание речи. Тут на самом деле все хуже.

Распознавание речи:


Есть одна классная библиотека KALDI для распознавания речи, она плюсовая. Но в целом распознавание речи более-менее замкнуто внутри крупных корпораций потому, что нет ни у кого больших Data Set про речь и звук. Зато есть большое количество API у Яндекса, Google, Baidu, у Microsoft, кажется, тоже есть.

Обработка текстов:


Для текстов вообще ничего специально особо нет, зато все универсальные библиотеки прекрасно подходят. Берете Keras (или любую другую, не принципиально), в несколько строчек что-нибудь пишете — у вас нейросеть для работы с текстом готова. Или любую другую библиотеку — не принципиально.

На этом все, спасибо. Нет универсального ответа на вопрос, какую универсальную библиотеку нужно брать. Смотрите на вашу задачу. Есть много тонкостей — и какая у вас технология, что в нее встраивается, и какой код готовый уже есть в природе — н http://github.com/ реально много кодов, которые можно использовать. Это инженерная задача, к которой нужно подходить вдумчиво. Одного универсального ответа нет и быть не может.

Вопросы-ответы

Вопрос: Можете Вы посоветовать какую-то литературу для начинающего — что бы было лучше почитать, посмотреть, чтобы более глубоко понимать, как программировать нейронные сети?

Ответ: Тут очень много зависит от Вашего текущего уровня, от того, насколько глубоко Вы хотите получить понимание. На самом деле есть огромное количество блогов. Во-первых, забудьте про русский язык — на нем практически ничего нет. Есть какие-то переводы на Хабре, но это не серьёзно на фоне того массива, который в природе существует.

На английском есть огромное количество классных блогов, где разные примеры разбираются. Их правда много, просто загуглите и на конкретную тему что-то найдете. Есть разные туториалы, опять же на английском, более-менее маленькие. Есть книжка Deeplearning на 800 страниц, которая в AMT-Press выходит на бумаге сейчас, а в PDF она доступна уже давно.

В общем, литература есть. Есть какие-то курсы онлайн, например, на Coursera, есть попытки запустить курс офлайн. В частности, в одном из таких курсов я буду скоро участвовать.

На самом деле есть довольно много разных вариантов. Посмотрите в Интернете — правда, возможностей много. Большинство из них — это все-таки чтение различной иностранной литературы, но она действительно хороша и всеобъемлюща.

Но при этом код на GitHub тоже хорош. Публикуется очень много кода, который можно, как минимум, посмотреть. Часто его можно почитать, он не очень страшный. И часто с этим кодом идут какие-то внятные комментарии про то, как это все работает. Просто идите в Интернет — там очень много всего есть.

Вопрос: Какие, вообще, существуют подходы по обучению нейронных сетей? Можно ли просто нагуглить кучу картинок из интернета, либо можно брать какие-то нейронные сети, которые обучают другие нейронные сети?

Ответ: Да, это классный вопрос. В обучении нейронных сетей, я думаю, в ближайшие годы тоже будет много прогресса. Есть разные подходы. Во-первых, да — когда вы набрали Data Set и на нем обучаете — это классический подход. Он есть, от него никуда не деться, он базовый во многих случаях.

Но сейчас, кстати, базовым часто становится другой подход под названием Transfer learning. Есть какое-то количество уже опубликованный нейросетей, которые обучены на разных задачах — на том же ImageNet. Можно взять себе готовую нейросеть ImageNet на 1000 классов и дообучить ее на какие-то свои специальные классы. Так может оказаться проще потому, что у вас есть, скажем, всего 1000 картинок ваших классов, и вы хорошую нейросеть с нуля не обучите на таком объеме. Для того, чтобы обучить глубокую нейросеть, реально нужно много данных. Речь идет о сотнях тысяч и миллионы объектов. Зато, если у вас есть готовая сетка, вы ее взяли, чуть-чуть дообучили, и у вас уже есть вменяемый результат. Transfer learning — это хороший подход. Он работает.

Вариант, когда нейросети учат другие нейросети — тоже есть такие варианты. Они больше research, чем production. Это очень классная тема, за ней здорово следить. Совсем хороших production-решений я не знаю, но если вам интересна научная сторона, то да, почитайте, есть прямо классные статьи, где нейросеть-учитель, которая в себе содержит модель как бы какого-то мира, обучает другую нейросеть, и это работает.

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

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

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

Вопрос: Вы рассказали про достаточно много разных архитектур рекуррентных
нейросетей. А что конкретно вы использовали и для каких задач

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

Здорово было бы начинать со всяких крутых вариантов с вниманием и так далее, но просто с них трудно начать потому, что их трудно с нуля запрограммировать. Там не тривиально все-таки. А таких хороших кусков кода, который взял и используешь, не очень много. Для меня пока Base line — это LSTM-сети — однонаправленные или двунаправленные. Я их применял для классификации текстов и изображений (распознавание номеров).

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

Ответ: Про это я особо много сказать не могу. Я недостаточно в этой области, так скажем, компетентен. Я не занимаюсь работой на стыке с такой безопасностью криптографии. Я видел какую-то свежую работу Google, где одну нейросеть учили генерить шифр, а другую взламывать. Но мне кажется все-таки этим примерам далеко до хороших криптоустойчивых алгоритмов. Мне кажется, это пока research на уровне из серии «Интересно посмотреть, что из этого выйдет». Я не слышал про крутые работы про взлом серьезных шифров.

Этот доклад — расшифровка одного из лучших выступлений на конференции разработчиков высоконагруженных систем HighLoad++. До конференции HighLoad++ 2017 осталось меньше месяца.

У нас уже готова Программа конференции, сейчас активно формируется расписание.

В этом году продолжаем исследовать тему нейронных сетей:


Также некоторые из этих материалов используются нами в обучающем онлайн-курсе по разработке высоконагруженных систем HighLoad.Guide — это цепочка специально подобранных писем, статей, материалов, видео. Уже сейчас в нашем учебнике более 30 уникальных материалов. Подключайтесь!


Источник: habrahabr.ru