Category: технологии

Category was added automatically. Read all entries about "технологии".

with Cat The Cat

Секретные материалы

5-й сезон, 11 серия.

Про искусственный интеллект, что убил своего создателя.

На 21-й минуте явное напоминание о ещё не существующем ИИ сериала В Поле Зрения - самое его завершение, когда выяснилось, что он прячется в узлах системы электроснабжения США.

Я до этого (в седьмой серии) опознал серию будущего сериала Агентов Щита, про планету, где прятался умеющий управлять мутантами мутант.

Право слово, плохо иметь хорошую память. Помнишь время, когда ничего не болело и ничего нового не происходит.
with Cat The Cat

Про word2vec.

Word2vec это способ вычисления "вложений" (embeddings) для слов, основываясь на их окружении в тех местах, где они встречаются.

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

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

Есть два режима использования word2vec - предсказание непрерывного словесного окружения по слову (continuous skipgram) и предсказание слова по непрерывному словесному окружению (continuous bag of words, CBOW). В первом случае мы по слову предсказываем несколько слов из его окружения, во втором случае мы предсказываем слово по нескольким словам из окружения.

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

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

(интересно здесь то, что "начало фразы" и "конец фразы" могут быть словами словаря и для них также может быть вычислены вложения)

Что интересного в этих вложениях?

Если использовать расстояние по косинусу угла между вложениями, то сходные слова будут расположены близко друг от друга. В частности, кластеризация через k-means (которая в исходном пакете word2vec есть из коробки) для предсказания окружения по слову давала интересные классы слов - в одном были прилагательные одного склонения, в другом - другого, и кластера слов ещё и делились по смыслу - вот в этих классах про положение на карте, а вот в этих про бытовую и электронную технику. Что интересно, разные режимы тренировок давали разные кластера и, по словам статьи, отличаются точностью решения языковых задач.

В исходной статье про word2vec давался алгоритм решения простых аналогий: чтобы вычислить "А относится к Б, как В относится к Х", надо было решить простую задачу Х=БлижайшееПоКосинусу(Вложение(Б)-Вложение(А)+Вложение(В)).

Товарищи из Фейсбука пошли чуть дальше (fasttext). В их работе слова разбиваются на части и вложения вычисляются не для слов, а для частей (n-grams - слово "будда" может быть разбито на триграммы "^бу", "удд", "дда" и "да$"). Вложение слова вычисляется простой суммой вложений частей. Таким образом, если для редко (менее 5 раз, обычно это в районе половины процента корпуса, опечатки и тому подобное) встречающихся слов word2vec не мог определить вложения, то фейсбучный подход позволяет и вложения определить, и сами слова использовать для вложений.

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

Можно сделать извлечение смысла, вычисляя вложение текста (например, сверточными сетями) и вычисляя из вложения текста краткое его содержание (encoder-decoder). На входе много слов текста, на выходе вектор размера M (вложение текста), из которого как-то (хоть простым полностью связным слоем) вычисляется несколько векторов-вложений слов смысла текста (см. выше про вложения для "конца фразы").
with Cat The Cat

Тренировка нейросетй без распространения ошибок.

Раз: https://arxiv.org/pdf/1908.01580.pdf
Два: http://proceedings.mlr.press/v48/taylor16.pdf
Три: https://arxiv.org/pdf/1910.01526.pdf

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

Вторая статья использует, можно сказать, распространение ошибок, но в режиме оптимизации по всему объёму данных - по всему объёму тренировочных данных, не на очередной выборке (batch) из тренировочного объёма.

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

Самое интересное во второй статье на странице 8: метод обратного распространения ошибок (backpropagation) заканчивает там, где метод второй статьи (ADMM) начинает работу. Да и сопряжённый градиент не отстал.

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

Вдогонку: https://arxiv.org/pdf/1409.5827.pdf - как вместо сложных статистических вычислений использовать невероятно параллельные.
with Cat The Cat

Управление версиями.

Дерево слияний в git представляет собой граф, который эквивалентен графу зависимостей возможностей ПО.

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

Получается, что управление требованиями и планирование можно вести в ветках git/mercurial.
with Cat The Cat

Поржать.

https://matloff.wordpress.com/2018/06/20/neural-networks-are-essentially-polynomial-regression/ - нейронки смело уподоблены полиномам, причём полиномы добиваются схожей точности при степени полинома 2. По мнению авторов, поскольку на каждом следующем слое степень полинома перемножаются, это приводит к переобучению.

https://arxiv.org/abs/1611.03530 - современные нейронки свободно учатся на случайных метках в тренировочных данных, достигая нулевой ошибки предсказания на них.
with Cat The Cat

Эксперимент.

А что будет, если мы попробуем приблизить градиент случайными векторами?

(проверяю идеи)

Collapse )

Предел получается в районе обратного корня из 2. Это разумно ожидать. До косинуса, равного половине, мы добираемся за выборку, равную трети от размерности вектора. Четверть - где-то в районе 7%, пятая часть - 4,7%. Снижая скорость приближения, мы можем уменьшить количество вычислений.

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

Мне не нравится градиентный спуск, как его применяют сейчас. Он был придуман, в его современной форме, из-за ограниченности ресурсов (особенно learning rate) и уже довольно давно. У него есть проблемы со значениями и он плохо применим в новых системах (то самое обучение подкреплением). Поэтому я и пытаюсь получить что-то другое. Две вещи, которые мне очень не нравятся, это скорость обучения (learning rate) и обратное распространение ошибок (backpropagation). Обе они подозрительны мне из-за связанной с ними магии - для скорости обучения придумывают вычурные "расписания" (learning rate cosine schedule, например), обратное распространение ошибок требует хитрых приведений (batch normalization, ADAM и тп), чтобы оно обучало более-менее быстро на современных данных.
with Cat The Cat

Случайный поиск.

https://thegradient.pub/why-rl-is-flawed/

Там про "обучение подкреплением", и в процессе рассматриваются методы, отличные от градиентного спуска. Вкратце, случайный поиск вполне себе сравним с градиентным спуском и даже превосходит его.
with Cat The Cat

Про тренировку нейросетей

Итак, у нас есть обычный стохастический спуск по градиенту (ССГ). Это мы вычисляем градиент, сглаженный по порции из нескольких, случайно выбранных, обучающих отсчётов, а потом смещаем наши веса по вычисленному направлению, умноженному на текущий множитель обучения.

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

Для ССГ необходимо несколько проходов по обучающему набору, со случайной выборкой обучающих примеров. Во время прохода множитель обучения меняется от начального относительного большого значения до конечного относительно малого. Выбор множителя и способа его убывания является ремеслом (тут, с картинками, может работать, а вот тут, со словами - может, но много хуже; cosine learning rate schedule - это вот что такое? кому в голову пришло? и почему cosine, а не tangent или hyperbolic?..).

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

Критикуя, предлагай.

Предложение - тренировать нейросети на всём тренировочном наборе сразу и всегда.

Первое, самое интересное: http://proceedings.mlr.press/v48/taylor16.pdf Смотрите сразу на страницу 8, рисунок 2, правая часть. На нём показаны результаты тренировки на ЦЕРНовском наборе из области физики элементарных частиц высоких энергий для ССГ, который тренируется по части набора, для метода в статье и для метода сопряжённых градиентов. Последние два работают с полным тренировочным набором. Важно в картинке то, что ССГ после полного цикла тренировки с многочисленными проходами по всему набору остановился там, где методы, работающие с полным тренировочным набором, начали.

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

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

Собственно, моя попытка что-то сделать со случайными направлениями это как раз оно - как научиться работать с большими наборами в памяти наилучшим образом и убрать из машинного обучения как можно больше ремесла (нет множителя обучения, нет обусловливания промежуточных слоёв и тп).
with Cat The Cat

Нейросетки - случайные направления.

Возьмём нейросеть с какими-то весами и выберем случайное направление изменения весов.

w=w0+at

Вход функции активации будет иметь вид x=x0+bt, а выход, в общем случае, для дважды дифференцируемых функций активации (ReLU, выйди вон), будет иметь вид y=y0+ct+dt^2.

Для некоторого набора данных можно вычислить функцию потерь, которая также будет полиномом второй степени. Если коэффициент при t положительный, то это означает лишь необходимость изменения нашего направления a на противоположное. Таким образом мы всегда можем получить направление в сторону убывания, а из коэффициентов полинома можно получить приближение размера шага, который приблизит нас к минимуму. Если мы проведём аналогичные вычисления для нескольких случайных направлений, то можно выбрать наиболее улучшающее. Также можно использовать метод сопряжённых направлений (не градиентов, направлений). И даже методы второго порядка не выглядят неподъёмными.

Чем меня привлекает эта идея - нет градиента вообще. Задал направление, прошёлся по корпусу, получил полином, вычислил шаг и выполнил обновление. В рекуррентных автокодерах, например, расстояние между входами и выходами (по которым, обычно, считается градиент) велико, и для кодирующей части его легко потерять.

Вот это я сейчас и пытаюсь состряпать.

PS
ReLU тоже можно прикрутить. Как мне кажется.