Category: it

Category was added automatically. Read all entries about "it".

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

Ещё пример.

Рассматривая инструмент (язык программирования), можно смотреть на квадрат "(не) позволяет (не) делать".

Позволяет ли инструмент делать полезное? Позволяет ли инструмент не делать вредное или бесполезное? С отрицанием перед глаголом "позволять" труднее, поэтому сменю вид вопроса. Инструмент не позволяет делать бесполезное или бесполезное - насколько это правда? Инструмент не позволяет не делать нужное и/или важное - насколько это правда?

Между "позволяет не делать" и "не позволяет делать" есть разница. Первое это вероятная экономия усилий, второе - прямой запрет. Первое это "позволяет не делать лишних движений, на которые тратится время". Второе это "не сможете потратить лишнее время".
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

Сложение-Вращение-ИсключающееИЛИ

или Add-Rotate-Xor - базовые блоки построения криптографических функций, от поточного шифрования до криптосумм (пример SipHash).

Я тут с этим экспериментирую, пока болею.

Пока вывод один - любая константа важна. Вроде бы, вращать на 17 позиций должно быть неважно, в какую сторону, однако практика показывает, что это не так.
with Cat The Cat

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

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

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

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

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

w=w0+at

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

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

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

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

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

Статистика

Я как-то экспериментировал с упаковкой данных и обнаружил, что для текстовых данных знание полной статистики пар букв для, примерно, 8-16 букв, часто даёт возможность восстановить эти 16 букв по менее, чем двум битам дополнительной информации.

(я смотрел на байты, но для букв тоже более-менее справедливо)

" бит дополнитель" - 16 букв. Пары букв: "\0 " (буквы перед началом кодируем симолов с кодом 0), " б", "би", "ит" и так далее до пары "ль". Префиксов с выбором у нас два - пробел и буква "о". Выбор после пробела требует один бит, после "о" - один бит. Поскольку статистика у нас полная, мы можем удалять увиденные пары, поэтому после первого пробела у нас нет выбора при его втором появлении, то же справедливо и для пар, начинающихся с буквы "о".

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

Увеличение длины побуквенной послледовательности с 2 до 3 ещё сильнее уменьшает необходимость в дополнительной информации для выбора.

Это объясняет неплохие результаты фейсбучного fasttext (вычисление словарных вложений, как суммы вложений для отдельных частей слова) и последнего достижения Kaldi, где рекуррентная сеть с входом в 10 тысяч наиболее частых слов и несколькими тысячами буквенных N-ок позволила получить уменьшение ошибок распознавания (обычно на входе и выходе несколько сотен тысяч слов, закодированных как 1-из-N (one hot)).
with Cat The Cat

Make

Пользуясь случаем, хочу порекомендовать The Good Fight. Это как "Хорошая Жена", только лучше.

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

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

Поправлю я количество читаемых строк с 100 тысяч на 200 тысяч и жду, пока обработается. Всё заново, всегда.

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

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

Гуглевская система контроля версий и сборки это наклон в правильном направлении - даже не шаг, всего лишь наклон.

Пока всё. Вернусь к The Good Fight. Может, чуть позже вернусь ещё к этой теме.
with Cat The Cat

Снова про оптимизацию.

Итак, при оптимизации сложных функций наподобие современных сетей есть проблема исчезающе малого изменения (vanishing gradient problem). Современные методы градиентного спуска справляются с ней путём изменения весов при коэффициентах - после вычисления вектора градиента он поэлементно домножается на вектор весов, который в разных вариантах считается по-разному, но назначение у него всегда одно, это понижение изменений в сильно меняющихся переменных.

В предыдущей серии я поборол эту проблему, введя массы частиц - вектор параметров интерпретируется, как вектор одномерных координат частиц, - чем дальше от выхода параметр, тем меньше масса частицы, связанной с параметром. В результате я получил приятное ускорение процесса оптимизации. заветные 94% точности на PenDigits процесс начал достигать за 80 итераций, против 130-150 без масс частиц.

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

Поэтому я взял финт ушами из природы - я ввёл скорость света, как предельную скорость изменений.

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

Плюс, множитель Лоренца включает в себя корень квадратный, а он определён для положительных подкоренных выражений. И если у меня из-за неточности вычислений подкоренное выражение становится отрицательным, то могут возникнуть ошибки, корректировка которых также может привести к ошибкам точности. Такое ещё возможно для 1/f(t) - надо смотреть, чтобы делитель не пересёк 0.

В общем, прогресс есть, и довольно интересный.

А ещё у меня возникает вопрос - не меняется ли у нас скорость света в нашем физическом мире? ;)

Если я правильно все понимаю, она должна уменьшаться. ;)
with Cat The Cat

Про успех.

К моему предыдущему посту.

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

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

Сейчас думаю, как ещё подойти к этой проблеме, чтобы не задавать массы изначально, ведь формула может быть произвольно сложной.