Митасов Андрей Павлович : другие произведения.

Металоция неведомого. Модуль С. Структуры

Самиздат: [Регистрация] [Найти] [Рейтинги] [Обсуждения] [Новинки] [Обзоры] [Помощь|Техвопросы]
Ссылки:


 Ваша оценка:
  • Аннотация:
    Выжимка информации из Инета по структурам нейросетей.
    Предварительный анализ.
    Крайнее изменение 21.04.2024

  
  "Следует стремиться увидеть в каждой вещи то,
  чего еще никто не видел и над чем еще никто не думал."
  
  "Кто не понимает ничего, кроме химии, тот и её понимает недостаточно."
  
  "Изучай все не из тщеславия, а ради практической пользы."
  
  Георга Кристоф Лихтенберг.
  
  
  Оглавление:
   Вместо предисловия.
   Зоопарк нейронных сетей.
   Структуры нейросетей для задач компьютерного зрения.
   Структуры нейросетей для задач визуального детектирования.
   Структуры нейронок YOLO.
   Пошаговый разбор работы трансформера.
   Структура сети ViT.
   Структура сети Swin.
   Сверточная сеть "для чайников".
   И еще немного сверточных сетей.
   И снова трансформеры.
   Что общего между структурным мышлением и структурой нейросетей?
   Inductive bias в нейронных сетях.
   Двоичные нейронные сети "для чайников".
   Насколько реально обучение BNN методом сплошного перебора?
  
  Иллюстрации:
   Тральщик "Наставник" от "Модели Kandinsky 2.1".
   Тральщики "Наставник" от "Модели Kandinsky 3.0".
   Тральщик "Наставник" от "Модели Kandinsky 3.1".
  
  
  ==========
  
  17.02.2024 19:03
  
  Вместо предисловия.
  В оглавление.
  
  Этот модуль задуман как учебный и исследовательский материал
  по анализу предлагавшихся ранее и используемых в настоящее время
  структур нейросетей и Используемых в них архитектурных и композиционных решений.
  Безусловно, при чтении его предполагается какое-то минимальное представление/знание
  начальных азов "нейросетевых наук".
  Если с этим есть какие-то затруднения, то можно начать с материалов,
  расположенных в "Модуле Л. Ликбез.", например, см.:
  "Нейронная сеть простыми словами."
  "Структуры нейросетей простыми словами."
  "Трансформеры простыми словами."
  
  Цели этого модуля не совсем традиционные, предполагается,
  что основное внимание будет уделяться
  не столько особенностям конструирования/архитектуры нейросетей.
  Хотя сейчас это становится все более актуальным, так как в дополнение
  к "стандартным" нейронкам начинают разрабатываться и другие структуры,
  использующие эти стандартные модели уже как "строительные блоки"
  для создания специализированных систем, например, см.:
  "Режем, клеим, дообучаем - нейросеть собираем."
  
  Этому направлению, конечно, тоже будет уделено внимание,
  но все-таки основная цель модуля в другом.
  Хочется, анализируя различные архитектуры,
  попытаться понять внутреннюю механику работы нейросетей,
  возможности улучшения процессов/методов их обучения
  и, самое главное, с другой стороны попытаться подступиться
  к пониманию "внутреннего пространства эмбеддингов" нейросетей, подробнее см.:
  "Каково же оно "пространство эмбеддингов" нейронки?"
  
  Представляется, что понимание "пространства эмбеддингов" нейросетей
  будет более надежным ориентиром/инструментом в конструировании
  различных новых архитектур нейросетей,
  чем простое "полушаманское"/"полуэвристическое" манипулирование блоками и элементами,
  как это, большей частью, происходит сейчас.
  
  
  =========
  
  15.01.2024 8:58
  
  Зоопарк нейронных сетей.
  В оглавление.
  
  Погружение в структуры современных нейросетей, наверно,
  стоит начать с экскурса по своеобразной "кунсткамере",
  сравнительного обзора целых направлений нейросетей,
  которые предлагались в "дотрансформерную эпоху".
  Часть из этих конструкций достаточно активно используется и развивается,
  а часть уже "канула в Лету".
  Но какие-то идеи, лежащие в основание этих структур,
  наверно, все-таки еще проявятся в той или иной форме:
  
  "Зоопарк архитектур нейронных сетей. Часть 1"
  Автор: xopxe
  https://habr.com/ru/companies/wunderfund/articles/313696/.
  26 окт 2016 в 19:44
  
  Автор оригинала: FJODOR VAN VEEN
  http://www.asimovinstitute.org/neural-network-zoo/
  
  //// Начало цитирования.
  
  ......
  
  За всеми архитектурами нейронных сетей,
  которые то и дело возникают последнее время,
  уследить непросто.
  Даже понимание всех аббревиатур, которыми бросаются профессионалы,
  поначалу может показаться невыполнимой задачей.
  
  Поэтому я решил составить шпаргалку по таким архитектурам.
  Большинство из них - нейронные сети,
  но некоторые - звери иной породы.
  Хотя все эти архитектуры подаются как новейшие и уникальные,
  когда я изобразил их структуру,
  внутренние связи стали намного понятнее.
  
  У изображения нейросетей в виде графов есть один недостаток:
  граф не покажет, как сеть работает.
  Например, вариационный автоэнкодер (variational autoencoders, VAE)
  выглядит в точности как простой автоэнкодер (AE),
  в то время как процесс обучения у этих нейросетей совершенно разный.
  Сценарии использования различаются еще сильнее:
  в VAE на вход подается шум,
  из которого они получают новый вектор,
  в то время как AE просто находят для входных данных
  ближайший соответствующий вектор из тех,
  что они "помнят".
  Добавлю еще, что этот обзор не имеет цели объяснить
  работу каждой из топологий изнутри
  (но это будет темой одной из следующих статей).
  
  Следует отметить, что не все (хотя и большинство)
  из используемых здесь сокращений общеприняты.
  Под RNN иногда понимают рекурсивные нейронные сети
  (recursive neural networks),
  но обычно эта аббревиатура означает рекуррентную нейронную сеть
  (recurrent neural network).
  Но и это еще не все:
  во многих источниках вы встретите RNN как обозначение
  для любой рекуррентной архитектуры,
  включая LSTM, GRU и даже двунапраленные варианты.
  Иногда похожая путаница происходит с AE:
  VAE, DAE и им подобные могут называть просто AE.
  Многие сокращения содержат разное количество N в конце:
  можно сказать "сверточная нейронная сеть"
  - CNN (Convolutional Neural Network),
  а можно и просто "сверточная сеть" - CN.
  
  Составить полный список топологий практически невозможно,
  так как новые появляются постоянно.
  Даже если специально искать публикации,
  найти их может быть сложно,
  а некоторые можно просто упустить из виду.
  Поэтому, хотя этот список поможет вам создать представление
  о мире искусственного интеллекта,
  пожалуйста, не считайте его исчерпывающим,
  особенно, если читаете статью спустя долгое время после ее появления.
  
  Для каждой из архитектур, изображенной на схеме,
  я привел очень короткое описание.
  Некоторые из них будут полезны,
  если вы хорошо знакомы с несколькими архитектурами,
  но не знакомы конкретно с этой.
  
  Сети прямого распространения (Feed forward neural networks, FF or FFNN)
  и перцептроны (perceptrons, P) очень просты
  - они передают информацию от входа к выходу.
  Считается, что у нейронных сетей есть слои,
  каждый из которых состоит из входных, скрытых или выходных нейронов.
  Нейроны одного слоя между собой не связаны,
  при этом каждый нейрон этого слоя связан с каждым нейроном соседнего слоя.
  Простейшая мало-мальски рабочая сеть состоит из двух входных
  и одного выходного нейрона
  и может моделировать логический вентиль
  - базовый элемент цифровой схемы, выполняющий элементарную логическую операцию.
  FFNN обычно обучают методом обратного распространения ошибки,
  подавая модели на вход пары входных и ожидаемых выходных данных.
  Под ошибкой обычно понимаются различные степени отклонения выходных данных
  от исходных (например, среднеквадратичное отклонение
  или сумма модулей разностей).
  При условии, что сеть обладает достаточным количеством скрытых нейронов,
  теоретически она всегда сможет установить связь
  между входными и выходными данными.
  На практике использование сетей прямого распространения ограничено,
  и чаще они используются совместно с другими сетями.
  
  Rosenblatt, Frank. "The perceptron: a probabilistic model
  for information storage and organization in the brain."
  Psychological review 65.6 (1958): 386.
  
  > Original Paper PDF
  http://www.ling.upenn.edu/courses/cogs501/Rosenblatt1958.pdf
  
  Сети радиально-базисных функций (radial basis function, RBF)
  - это FFNN с радиально-базисной функцией в качестве функции активации.
  Больше здесь нечего добавить.
  Мы не хотим сказать, что она не используется,
  но большинство FFNN с другими функциями активации
  обычно не выделяют в отдельные группы.
  
  Broomhead, David S., and David Lowe. Radial basis functions,
  multi-variable functional interpolation and adaptive networks.
  No. RSRE-MEMO-4148. ROYAL SIGNALS AND RADAR ESTABLISHMENT MALVERN
  (UNITED KINGDOM), 1988.
  
  > Original Paper PDF
  http://www.dtic.mil/cgi-bin/GetTRDoc?AD=ADA196234
  
  Нейронная сеть Хопфилда - полносвязная сеть
  (каждый нейрон соединен с каждым),
  где каждый нейрон выступает во всех трех ипостасях.
  Каждый нейрон служит входным до обучения,
  скрытым во время него и выходным после.
  Матрица весов подбирается таким образом,
  чтобы все <запомненные> вектора являлись бы для нее собственными.
  Однажды обученная одному или нескольким образам
  система будет сходиться к одному из известных ей образов,
  потому что только одно из этих состояний является стационарным.
  Отметим, что это не обязательно соответствует желаемому состоянию
  (к сожалению, у нас не волшебный черный ящик).
  Система стабилизируется только частично из-за того,
  что общая "энергия" или "температура" сети во время обучения
  постепенно понижается.
  Каждый нейрон обладает порогом активации,
  соизмеримым с этой температурой,
  и если сумма входных данных превысит этот порог,
  нейрон может переходить в одно из двух состояний
  (обычно -1 или 1, иногда 0 или 1).
  Узлы сети могут обновляться параллельно,
  но чаще всего это происходит последовательно.
  В последнем случае генерируется случайная последовательность,
  которая определяет порядок,
  в котором нейроны будут обновлять свое состояние.
  Когда каждый из нейронов обновился и их состояние больше не изменяется,
  сеть приходит в стационарное состояние.
  Такие сети часто называют ассоциативной памятью,
  так как они сходятся с состоянию, наиболее близкому к заданному:
  как человек, видя половину картинки,
  может дорисовать недостающую половину,
  так и нейронная сеть, получая на входе наполовину зашумленную картинку,
  достраивает ее до целой.
  
  Hopfield, John J. "Neural networks and physical systems
  with emergent collective computational abilities."
  Proceedings of the national academy of sciences 79.8 (1982): 2554-2558.
  
  > Original Paper PDF
  https://bi.snu.ac.kr/Courses/g-ai09-2/hopfield82.pdf
  
  Цепи Маркова (Markov Chains, MC или discrete time Markov Chain, DTMC)
  - своего рода предшественники машин Больцмана (BM) и сетей Хопфилда (HN).
  В цепях Маркова мы задаем вероятности перехода из текущего состояния в соседние.
  Кроме того, это цепи не имеют памяти:
  последующее состояние зависит только от текущего
  и не зависит от всех прошлых состояний.
  Хотя цепь Маркова нельзя назвать нейронной сетью,
  она близка к ним и формирует теоретическую основу для BM и HN.
  Цепи Маркова также не всегда являются полносвязными.
  
  Hayes, Brian. "First links in the Markov chain."
  American Scientist 101.2 (2013): 252.
  
  > Original Paper PDF
  http://www.americanscientist.org/libraries/documents/201321152149545-2013-03Hayes.pdf
  
  Машины Больцмана (Boltzmann machines, BM) во многом похожи на сети Хопфилда,
  но в них некоторые нейроны помечены как входные, а некоторые остаются скрытыми.
  Входные нейроны становятся выходными,
  когда все нейроны в сети обновляют свои состояния.
  Сначала весовые коэффициенты присваиваются случайным образом,
  затем происходит обучение методом обратного распространения,
  или в последнее время все чаще с помощью алгоритма
  contrastive divergence
  (когда градиент вычисляется при помощи марковской цепи).
  BM - стохастическая нейронная сеть,
  так как в обучении задействована цепь Маркова.
  Процесс обучения и работы здесь почти такой же, как в сети Хопфилда:
  нейронам присваивают определенные начальные состояния,
  а затем цепь начинает свободно функционировать.
  В процессе работы нейроны могут принимать любое состояние,
  и мы постоянно перемещаемся между входными и скрытыми нейронами.
  Активация регулируется значением общей температуры,
  при понижении которой сокращается и энергия нейронов.
  Сокращение энергии вызывает стабилизацию нейронов.
  Таким образом, если температура задана верно,
  система достигает равновесия.
  
  Hinton, Geoffrey E., and Terrence J. Sejnowski.
  "Learning and releaming in Boltzmann machines."
  Parallel distributed processing:
  Explorations in the microstructure of cognition 1 (1986): 282-317.
  
  > Original Paper PDF
  https://www.researchgate.net/profile/Terrence_Sejnowski/publication/242509302_Learning_and_relearning_in_Boltzmann_machines/links/54a4b00f0cf256bf8bb327cc.pdf
  
  Ограниченная машина Больцмана (Restricted Boltzmann machine, RBM),
  как ни удивительно, очень похожа на обычную машину Больцмана.
  Основное отличие RBM от BM в том, что они ограничены,
  и следовательно, более удобны в использовании.
  В них каждый нейрон не связан с каждым,
  а только каждая группа нейронов соединена с другими группами.
  Входные нейроны не связаны между собой,
  нет соединений и между скрытыми нейронами.
  RBM можно обучать так же, как и FFPN,
  за небольшим отличием:
  вместо передачи данных вперед и последующего обратного распространения ошибки,
  данные передаются вперед и назад (к первому слою),
  а затем применяется прямое и обратное распространение
  (forward-and-back propagation).
  //// Нужно подумать. Может быть и прямое распространение использовать
  //// для обучения.
  
  Smolensky, Paul. Information processing in dynamical systems:
  Foundations of harmony theory.
  No. CU-CS-321-86. COLORADO UNIV AT BOULDER DEPT OF COMPUTER SCIENCE, 1986.
  
  > Original Paper PDF
  http://www.dtic.mil/cgi-bin/GetTRDoc?Location=U2&doc=GetTRDoc.pdf&AD=ADA620727
  
  Автоэнкодеры (Autoencoders, AE) - нечто подобное FFNN,
  это скорее другой способ использования FFNN,
  чем принципиально новая архитектура.
  Основная идея автоэнкодеров - автоматическое кодирование
  (как при сжатии, а не при шифровании) информации,
  отсюда и название.
  Сеть напоминает по форме песочные часы,
  так как скрытый слой меньше, чем входной и выходной;
  к тому же она симметрична относительно средних слоев
  (одного или двух, в зависимости от четности/нечетности общего количества слоев).
  Самый маленьких слой почти всегда средний,
  в нем информация максимально сжата.
  Все, что расположено до середины - кодирующая часть,
  выше середины - декодирующая,
  а в середине (вы не поверите) - код.
  AE обучают методом обратного распространения ошибки,
  подавая входные данные и задавая ошибку равной разницу между входом и выходом.
  AE можно построить симметричными и с точки зрения весов,
  выставляя кодирующие веса равными декодирующим.
  
  Bourlard, Herve, and Yves Kamp.
  "Auto-association by multilayer perceptrons and singular value decomposition."
  Biological cybernetics 59.4-5 (1988): 291-294.
  
  > Original Paper PDF
  https://pdfs.semanticscholar.org/f582/1548720901c89b3b7481f7500d7cd64e99bd.pdf
  
  Разреженный автоэнкодер (Sparse autoencoder, AE)
  - в некоторой степени антипод AE.
  Вместо того чтобы обучать сеть представлять блоки информации
  на меньшем "пространстве", мы кодируем информацию так,
  чтобы она занимала больше места.
  И вместо того чтобы заставлять систему сходиться в центре,
  а затем обратно расширяться до исходного размера,
  мы, наоборот, увеличиваем средние слои.
  Сети этого типа могут применяться для извлечения
  множества маленьких деталей из набора данных.
  Если бы мы стали обучать SAE тем же методом, что и AE,
  мы получили бы в большинстве случаев абсолютно бесполезную сеть,
  где на выходе получается ровно то же, что и на входе.
  Чтобы этого избежать,
  мы вместо входных данных выдаем на выходе входные данные
  плюс штраф за количество активированных нейронов в скрытом слое.
  //// Интересно. Стоит обдумать. Фактически прототип "наставника",
  //// только очень ограниченного. Скорее "надзирателя".
  Это в какой-то мере напоминает биологическую нейронную сеть
  (spiking neural network),
  в которой не все нейроны постоянно находятся в возбужденном состоянии.
  
  Marc'Aurelio Ranzato, Christopher Poultney, Sumit Chopra, and Yann LeCun.
  "Efficient learning of sparse representations with an energy-based model."
  Proceedings of NIPS. 2007.
  
  > Original Paper PDF
  https://papers.nips.cc/paper/3112-efficient-learning-of-sparse-representations-with-an-energy-based-model.pdf
  
  Архитектура вариационных автоэнкодеров (VAE) такая же, как и у обычных,
  но обучают их другому
  - приблизительному вероятностному распределению входных образцов.
  Это в какой-то степени возвращение к истокам,
  так как VAE немножко ближе к машинам Больцмана.
  Тем не менее, они опираются на Байесовскую математику
  касательно вероятностных суждений и независимости,
  которые интуитивно понятны,
  но требуют сложных вычислений.
  Базовый принцип можно сформулировать так:
  принимать в расчет степень влияния одного события на другое.
  Если в одном месте происходит определенное событие,
  а другое событие случается где-то еще,
  то эти события вовсе не обязательно связаны.
  Если они не связаны, то распространение ошибки должно это учитывать.
  Это полезный подход, так как нейронные сети
  - своего рода огромные графы,
  и иногда бывает полезно исключить влияние одних нейронов на другие,
  проваливаясь в нижние слои.
  //// Тоже можно и нужно использовать для "изоляции",
  //// точнее раздельного/ансамблевого обучения.
  
  Kingma, Diederik P., and Max Welling. "Auto-encoding variational bayes."
  arXiv preprint arXiv:1312.6114 (2013).
  
  > Original Paper PDF
  https://arxiv.org/pdf/1312.6114v10.pdf
  
  Шумоподавляющие (помехоустойчивые) автоэнкодеры (Denoising autoencoders, DAE)
  - это такое AE, которым на подаем на вход не просто данные,
  а данные с шумом (например, делая картинку более зернистой).
  Тем не менее, ошибку мы вычисляем прежним методом,
  сравнивая выходной образец с оригиналом без шума.
  Таким образом, сеть запоминает не мелкие детали,
  а крупные черты,
  так как запоминание небольших деталей, постоянно меняющихся из-за шума,
  часто не приводит никуда.
  
  Vincent, Pascal, et al. "Extracting and composing robust features
  with denoising autoencoders."
  Proceedings of the 25th international conference on Machine learning.
  ACM, 2008.
  
  > Original Paper PDF
  http://machinelearning.org/archive/icml2008/papers/592.pdf
  
  Глубокие сети доверия (Deep belief networks, DBN)
  - сети, представляющие собой композицию нескольких RBM или VAE.
  Такие сети показали себя эффективно обучаемыми одна за другой,
  когда каждая сеть должна научиться кодировать предыдущую.
  Этот метод также называют "жадное обучение",
  он заключается в принятии оптимального на данный момент решение,
  чтобы получить подходящий, но, возможно, не оптимальный результат.
  DBN могут обучаться методами contrastive divergence
  или обратным распространением ошибки
  и учатся представлять данные в виде вероятностной модели,
  в точности как RBM или VAE.
  Однажды обученную и приведенную к стационарному состоянию модель
  можно использовать для генерации новых данных.
  
  Bengio, Yoshua, et al. "Greedy layer-wise training of deep networks."
  Advances in neural information processing systems 19 (2007): 153.
  
  > Original Paper PDF
  https://papers.nips.cc/paper/3048-greedy-layer-wise-training-of-deep-networks.pdf
  
  Свёрточные нейронные сети (convolutional neural networks, CNN)
  и глубокие свёрточные нейронные сети (deep convolutional neural networks, DCNN)
  кардинально отличаются от других сетей.
  Они используются в основном для обработки изображений,
  иногда для аудио и других видов входных данных.
  Типичным способом применения CNN является классификация изображений:
  если на вход подается изображение кошки, сеть выдаст <кошка>,
  если картинка собаки - <собака>.
  Такие сети обычно используют <сканер>,
  не обрабатывающий все данные за один раз.
  Например, если у вас есть изображение 200х200,
  вы захотите строить слой сети из 40 тысяч узлов.
  Вместо это сеть считает квадрат размера 20х20
  (обычно из левого верхнего угла),
  затем сдвинется на 1 пиксель и считает новый квадрат, и т.д.
  Заметьте, что мы не разбиваем изображение на квадраты,
  а скорее ползем по нему.
  Эти входные данные затем передаются через свёрточные слои,
  в которых не все узлы соединены между собой.
  Вместо этого каждый узел соединен только со своими ближайшими соседями.
  Эти слои имеют свойство сжиматься с глубиной,
  причём обычно они уменьшаются на какой-нибудь из делителей
  количества входных данных
  (например, 20 узлов в следующем слое превратятся в 10, в следующем - в 5),
  часто используются степени двойки.
  Кроме сверточных слоев есть также так называемые слои объединения
  (pooling layers).
  Объединение - это способ уменьшить размерность получаемых данных,
  например, из квадрата 2х2 выбирается и передается наиболее красный пиксель.
  На практике к концу CNN прикрепляют FFNN
  для дальнейшей обработки данных.
  Такие сети называются глубокими (DCNN),
  но названия их обычно взаимозаменяемы.
  
  LeCun, Yann, et al. "Gradient-based learning applied to document recognition."
  Proceedings of the IEEE 86.11 (1998): 2278-2324.
  
  > Original Paper PDF
  http://yann.lecun.com/exdb/publis/pdf/lecun-98.pdf
  
  Развёртывающие нейронные сети (deconvolutional networks, DN),
  также называемые обратными графическими сетями,
  - это свёрточные нейронные сети наоборот.
  Представьте, что вы передаёте сети слово "кошка"
  и обучаете ее генерировать картинки кошек путем сравнения получаемых картинок
  с реальными изображениями кошек.
  DNN тоже можно объединять с FFNN.
  Стоит заметить, что в большинстве случаев сети передаётся не строка,
  а бинарный классифицирующий вектор:
  например, <0, 1> - это кошка, <1, 0> - собака, а <1, 1> - и кошка, и собака.
  Вместо слоев объединения, которые часто встречаются в CNN,
  здесь присутствуют аналогичные обратные операции,
  обычно интерполяцию или экстраполяцию.
  
  Zeiler, Matthew D., et al. "Deconvolutional networks."
  Computer Vision and Pattern Recognition (CVPR),
  2010 IEEE Conference on. IEEE, 2010.
  
  > Original Paper PDF
  http://www.matthewzeiler.com/pubs/cvpr2010/cvpr2010.pdf
  
  .......
  
  //// Из комментариев.
  
  .......
  
  kryvichh
  31 окт 2016 в 15:43
  
  Спасибо большое!
  
  Но вот как сейчас, глядя на это многообразие,
  выбирать сеть наиболее оптимальную для конкретной задачи?
  
  Например, мы хотим сделать спелл-чекер русских слов на основе нейронной сети.
  Скормить ей словарь русских слов,
  чтобы она затем по последовательности букв на входе
  выдавала вероятность того, что это - нормальное слово.
  А еще лучше - предлагало вариант слова с исправлением ошибки.
  Какая тут сеть лучше подойдет?
  0
  
  .......
  
  //// Конец цитирования.
  
  И сразу же вторая часть этого замечательного обзора.
  
  "Зоопарк архитектур нейронных сетей. Часть 2"
  Автор: xopxe
  .
  31 окт 2016 в 15:40
  
  Автор оригинала: FJODOR VAN VEEN
  http://www.asimovinstitute.org/neural-network-zoo/
  
  //// Начало цитирования.
  
  ......
  
  Название "Глубокие сверточные обратные глубинные сети
  (Deep convolutional inverse graphics networks, DCIGN)"
  может ввести в заблуждение,
  так как на самом деле это вариационные автоэнкодеры
  со сверточными и развертывающими сетями
  в качестве кодирующей и декодирующей частей соответственно.
  Такие сети представляют черты изображения в виде вероятностей
  и могут научиться строить изображение кошки и собаки вместе,
  взглянув лишь на картинки только с кошками и только с собаками.
  Кроме того, вы можете показать этой сети фотографию вашего кота
  с надоедливой соседской собакой
  и попросить ее вырезать собаку и изображения,
  и DCIGN справится с этой задачей,
  даже если никогда не делала ничего подобного.
  Разработчики также продемонстрировали,
  что DCIGN может моделировать различные сложные преобразования изображений,
  например, изменение источника света или поворот 3D объектов.
  Такие сети обычно обучают методом обратного распространения.
  
  Kulkarni, Tejas D., et al. "Deep convolutional inverse graphics network."
  Advances in Neural Information Processing Systems. 2015.
  
  Original Paper PDF
  https://arxiv.org/pdf/1503.03167v4.pdf
  
  Генеративные состязательные сети
  (Generative adversarial networks, GAN)
  принадлежат другому семейству нейросетей,
  это близнецы - две сети, работающие вместе.
  GAN состоит из любых двух сетей
  (но чаще это сети прямого распространения или сверточные),
  где одна из сетей генерирует данные ("генератор"),
  а вторая - анализирует ("дискриминатор").
  Дискриминатор получает на вход или обучающие данные,
  или сгенерированные первой сетью.
  То, насколько точно дискриминатор сможет определить источник данных,
  служит потом для оценки ошибок генератора.
  Таким образом, происходит своего рода соревнование,
  где дискриминатор учится лучше отличать реальные данные от сгенерированных,
  а генератор стремится стать менее предсказуемым для дискриминатора.
  Это работает отчасти потому,
  что даже сложные изображения с большим количеством шума
  в конце концов становятся предсказуемыми,
  но сгенерированные данные, мало отличающиеся от реальных,
  сложнее научиться отличать.
  GAN достаточно сложно обучить,
  так как задача здесь - не просто обучить две сети,
  но и соблюдать необходимый баланс между ними.
  Если одна из частей (генератор или дискриминатор) станет намного лучше другой,
  то GAN никогда не будет сходиться.
  
  Goodfellow, Ian, et al. "Generative adversarial nets."
  Advances in Neural Information Processing Systems. 2014.
  
  Original Paper PDF
  https://arxiv.org/pdf/1406.2661v1.pdf
  
  Рекуррентные нейронные сети (Recurrent neural networks, RNN)
  - это те же сети прямого распространения,
  но со смещением во времени:
  нейроны получают информацию не только от предыдущего слоя,
  но и от самих себя в результате предыдущего прохода.
  Следовательно, здесь важен порядок,
  в котором мы подаем информацию и обучаем сеть:
  мы получим разные результаты, если сначала скормим ей "молоко",
  а затем "печеньки", или если сначала "печеньки", а потом уже "молоко".
  У RNN есть одна большая проблема
  - это проблема исчезающего (или взрывного) градиента:
  в зависимости от используемой функции активации
  информация со временем теряется,
  так же как и в очень глубоких сетях прямого распространения.
  Казалось бы, это не такая уж серьезная проблема,
  так как это касается только весов,
  а не состояний нейронов,
  но именно в весах хранится информация о прошлом;
  если вес достигнет значения 0 или 1 000 000,
  то информация о прошлом состоянии станет не слишком информативной.
  RNN могут использоваться в самых разнообразных областях,
  так как даже данные, не связанные с течением времени (не звук или видео)
  могут быть представлены в виде последовательности.
  Картинка или строка текста могут подаваться на вход
  по одному пикселю или символу,
  так что вес будет использоваться для предыдущего элемента последовательности,
  а не для того, что случилось X секунд назад.
  В общем случае, рекуррентные сети хороши
  для продолжения или дополнения информации, например, автодополнения.
  
  Elman, Jeffrey L. "Finding structure in time."
  Cognitive science 14.2 (1990): 179-211.
  
  Original Paper PDF
  https://crl.ucsd.edu/~elman/Papers/fsit.pdf
  
  Долгая краткосрочная память (Long short term memory, LSTM)
  - попытка побороть проблему взрывного градиента,
  используя фильтры (gates) и блоки памяти (memory cells).
  Эта идея пришла, скорее, из области схемотехники, а не биологии.
  У каждого нейрона есть три фильтра:
  входной фильтр (input gate), выходной фильтр (output gate)
  и фильтр забывания (forget gate).
  Задача этих фильтров - сохранять информацию,
  останавливая и возобновляя ее поток.
  Входной фильтр определяет количество информации с предыдущего шага,
  которое будет храниться в блоке памяти.
  Выходной фильтр занят тем, что определяет,
  сколько информации о текущем состоянии узла получит следующий слой.
  Наличие фильтра забывания на первый взгляд кажется странным,
  но иногда забывать оказывается полезно:
  если нейросеть запоминает книгу,
  в начале новой главы может быть необходимо забыть
  некоторых героев из предыдущей.
  Показано, что LSTM могут обучаться действительно сложным последовательностям,
  например, подражать Шекспиру или сочинять простую музыку.
  Стоит отметить, что так как каждый фильтр хранит свой вес
  относительно предыдущего нейрона,
  такие сети достаточно ресурсоемки.
  
  Hochreiter, Sepp, and Jurgen Schmidhuber.
  "Long short-term memory." Neural computation 9.8 (1997): 1735-1780.
  
  Original Paper PDF
  http://deeplearning.cs.cmu.edu/pdfs/Hochreiter97_lstm.pdf
  
  Управляемые рекуррентные нейроны (Gated recurrent units, GRU)
  - разновидность LSTM.
  У них на один фильтр меньше, и они немного иначе соединены:
  вместо входного, выходного фильтров и фильтра забывания
  здесь используется фильтр обновления (update gate).
  Этот фильтр определяет и сколько информации сохранить от последнего состояния,
  и сколько информации получить от предыдущего слоя.
  Фильтр сброса состояния (reset gate) работает почти так же,
  как фильтр забывания,
  но расположен немного иначе.
  На следующие слои отправляется полная информация о состоянии
  - выходного фильтра здесь нет.
  В большинстве случаем GRU работают так же, как LSTM,
  самое значимое отличие в том,
  что GRU немного быстрее и проще в эксплуатации
  (однако обладает немного меньшими выразительными возможностями).
  
  Chung, Junyoung, et al. "Empirical evaluation of gated recurrent neural networks
  on sequence modeling." arXiv preprint arXiv:1412.3555 (2014).
  
  Original Paper PDF
  https://arxiv.org/pdf/1412.3555v1.pdf
  
  Нейронные машины Тьюринга (Neural Turing machines, NMT)
  можно определить как абстракцию над LSTM
  и попытку "достать" нейросети из "черного ящика",
  давая нам представление о том, что происходит внутри.
  Блок памяти здесь не встроен в нейрон, а отделен от него.
  Это позволяет объединить производительность
  и неизменность обычного цифрового хранилища данных
  с производительностью и выразительными возможностями нейронной сети.
  Идея заключается в использовании адресуемой по содержимому памяти и нейросети,
  которая может читать из этой памяти и писать в нее.
  Они называются нейронными машинами Тьюринга,
  так как являются полными по Тьюрингу:
  возможность читать, писать и изменять состояние на основании прочитанного
  позволяет выполнять все, что умеет выполнять универсальная машина Тьюринга.
  
  Graves, Alex, Greg Wayne, and Ivo Danihelka. "Neural turing machines."
  arXiv preprint arXiv:1410.5401 (2014).
  
  Original Paper PDF
  https://arxiv.org/pdf/1410.5401v2.pdf
  
  Двунаправленные RNN, LSTM и GRU (BiRNN, BiLSTM и BiGRU)
   не изображены на схеме, так как выглядят в точности так же,
  как их однонаправленные коллеги.
  Разница лишь в том, что эти нейросети связаны не только с прошлым,
  но и с будущим.
  Например, однонаправленная LSTM может научиться прогнозировать слово "рыба",
  получая на вход буквы по одной.
  Двунаправленная LSTM будет получать также и следующую букву
  во время обратного прохода,
  открывая таким образом доступ к будущей информации.
  А значит, нейросеть можно обучить не только дополнять информацию,
  но и заполнять пробелы,
  так, вместо расширения рисунка по краям,
  она может дорисовывать недостающие фрагменты в середине.
  
  Schuster, Mike, and Kuldip K. Paliwal.
  "Bidirectional recurrent neural networks."
  IEEE Transactions on Signal Processing 45.11 (1997): 2673-2681.
  
  Original Paper PDF
  http://www.di.ufpe.br/~fnj/RNA/bibliografia/BRNN.pdf
  
  Глубокие остаточные сети (Deep residual networks, DRN)
  - это очень глубокие FFNN с дополнительными связями между слоями,
  которых обычно от двух до пяти,
  соединяющими не только соседние слои, но и более отдаленные.
  Вместо того, чтобы искать способ находить
  соответствующие исходным данным входные данные через, скажем, пять слоев,
  сеть обучена ставить в соответствие входному блоку
  пару "выходной блок + входной блок".
  Таким образом входные данные проходят через все слои нейросети
  и подаются на блюдечке последним слоям.
  Было показано, что такие сети могут обучаться образцам глубиной до 150 слоев,
  что намного больше, чем можно ожидать от обычной 2-5-слойной нейросети.
  Тем не менее, было доказано,
  что сети этого типа на самом деле просто RNN без явного использования времени,
  а также их часто сравнивают с LSTM без фильтров.
  //// А вот это интересное доказательство.
  //// Получается, что "интерференция" может рассматриваться как реккурентность,
  //// но не назад, а вперед, но с тем же результатом.
  //// Если конечно я правильно понял.
  //// В общем, это точно можно использовать, для алгоритмов "наставника",
  //// но в обратном направлении.
  //// И вообще, появилась мысль, что рассматривать "обратное распространение",
  //// как "виртуальную" нейронку, т.е. динамически возникающую сеть.
  //// и соответственно все что сказано про DRN для нее подходит.
  //// В общем, эта сеть и есть "наставник" и соответственно,
  //// можно рассматривать процесс прямого распространения,
  //// как, помимо целевой задачи, как обучение наставника,
  //// а обратное распространение как обучение студиоса.
  //// И не забыть еще и тот элемент из Sparse autoencoder,
  //// который дает "штраф за количество активированных нейронов".
  
  He, Kaiming, et al. "Deep residual learning for image recognition."
  arXiv preprint arXiv:1512.03385 (2015).
  
  Original Paper PDF
  https://arxiv.org/pdf/1512.03385v1.pdf
  
  Нейронные эхо-сети (Echo state networks, ESN)
  - еще один вид рекуррентных нейросетей.
  Они выделяются тем, что связи между нейронами в них случайны,
  не организованы в аккуратные слои,
  и обучаются они по-другому.
  Вместо подачи на вход данных и обратного распространения ошибки,
  мы передаем данные, обновляем состояния нейронов
  и в течение некоторого времени следим за выходными данными.
  Входной и выходной слои играют нестандартную роль,
  так как входной слой служит для инициализации системы,
  а выходной слой - в качестве наблюдателя
  за порядком активации нейронов,
  который проявляется со временем.
  Во время обучения изменяются связи только между наблюдателем и скрытыми слоями.
  //// Тоже можно/нужно использовать, но с меньшей зависимостью от случайности.
  //// Или, наоборот, с управляемой случайностью.
  
  Jaeger, Herbert, and Harald Haas. "Harnessing nonlinearity: Predicting
  chaotic systems and saving energy in wireless communication."
  science 304.5667 (2004): 78-80.
  
  Original Paper PDF
  https://pdfs.semanticscholar.org/8922/17bb82c11e6e2263178ed20ac23db6279c7a.pdf
  
  Extreme learning machines (ELM) - это те же FFNN,
  но со случайными связями между нейронами.
  Они очень похожи на LSM и ESN,
  но используются скорее подобно сетям прямого распространения,
  и не это связано не с тем, что они не являются рекуррентными или импульсными,
  а с тем, что их обучают методом обратного распространения ошибки.
  
  Cambria, Erik, et al. "Extreme learning machines [trends & controversies]."
  IEEE Intelligent Systems 28.6 (2013): 30-59.
  
  Original Paper PDF
  http://www.ntu.edu.sg/home/egbhuang/pdf/ieee-is-elm.pdf
  
  Машины неустойчивых состояний (Liquid state machines, LSM) подобны ESN.
  Главное их отличие в том, что LSM
  - это разновидность импульсных нейронных сетей:
  на замену сигмоидальной кривой приходят пороговые функции,
  и каждый нейрон также является накопительным блоком памяти.
  Когда состояние нейрона обновляется,
  значение рассчитывается не как сумма его соседей,
  а складывается с самим собой.
  Как только порог превышен, энергия освобождается
  и нейрон посылает импульс другим нейронам.
  //// Этакий импульсный накопитель.
  //// Тоже реализуемо. Но применительно к обучению.
  
  Maass, Wolfgang, Thomas Natschlager, and Henry Markram.
  "Real-time computing without stable states:
  A new framework for neural computation based on perturbations."
  Neural computation 14.11 (2002): 2531-2560.
  
  Original Paper PDF
  https://web.archive.org/web/20120222154641/http://ramsesii.upf.es/seminar/Maass_et_al_2002.pdf
  
  Метод опорных векторов (Support vector machine, SVM)
  служит для нахождения оптимальных решений в задачах классификации.
  В классическом смысле метод способен категоризировать
  линейно разделяемые данные:
  например, определить, на каком рисунке изображен Гарфилд, а на каком - Снупи.
  В процессе обучения сеть как бы размещает всех Гарфилдов и Снупи на 2D-графике
  и пытается разделить данные прямой линией
  так, чтобы с каждой стороны были данные только одного класса
  и чтобы расстояние от данных до линии было максимальным.
  Используя трюк с ядром, можно классифицировать данные размерности n.
  Построив 3D граф, мы сможем отличить Гарфилда от Снупи и от кота Саймона,
  и чем выше размерность, тем больше мультяшных персонажей
  можно классифицировать.
  Этот метод не всегда рассматривается как нейронная сеть.
  
  Cortes, Corinna, and Vladimir Vapnik. "Support-vector networks."
  Machine learning 20.3 (1995): 273-297.
  
  Original Paper PDF
  http://image.diku.dk/imagecanon/material/cortes_vapnik95.pdf
  
  И наконец, последний обитатель нашего зоопарка
  - самоорганизующаяся карта Кохонена
  (Kohonen networks, KN, или organising (feature) map, SOM, SOFM).
  KN использует соревновательное обучение
  для классификации данных без учителя.
  Сеть анализирует свои нейроны на предмет максимального совпадения
  с входными данными.
  Наиболее подходящие нейроны обновляются так,
  чтобы еще ближе походить на входные данные,
  кроме того, к входным данным приближаются и веса их соседей.
  То, насколько изменится состояние соседей,
  зависит от расстояния до наиболее подходящего узла.
  KN также не всегда относят к нейронным сетям.
  
  Kohonen, Teuvo. "Self-organized formation of topologically correct feature maps."
  Biological cybernetics 43.1 (1982): 59-69.
  
  Original Paper PDF
  http://cioslab.vcu.edu/alg/Visualize/kohonen-82.pdf
  
  .......
  
  //// Конец цитирования.
  
  Если после этого "посещения кунсткамеры" структур нейросетей,
  у Вас голова пошла кругом, то не расстраивайтесь - Вы не одиноки.
  Не заплутать в этих аббревиатурах, а самое главное,
  в настоящем "водовороте идей", у меня тоже пока не получается.
  Но мне было чуть легче при чтении этого текста -
  я пытался не запомнить все эти структуры/аббревиатуры,
  а вычленить какие подсказки для формирования набора гипотез
  для различных методов/подходов к обучению нейросетей.
  И что-то действительно удалось "углядеть" и приспособить к делу, см.:
  "Концепция "стапеля" для обучения нейронок".
  
  Собственно именно для этой цели я и счел нужным процитировать
  весь текст без существенных купюр.
  Рано или поздно появится, другая задача, или другое видение той же задачи,
  и будет полезно "пробежаться по кунсткамере"
  в поисках давно забытых "новых подходов".
  
  
  =========
  
  10.02.2024 19:53
  
  Структуры нейросетей для задач компьютерного зрения.
  В оглавление.
  
  Применение нейросетей в системах компьютерного зрения исторически было,
  наверно, одним из самых первых успешных реализаций
  подхода "машинного обучения" к решению практических задач.
  На этих задачах отрабатывались и методика обучения, и новые подходы
  и различные варианты структур нейросетей.
  И процесс этот продолжается и по сей день:
  
  "Компьютерное зрение сквозь года".
  Автор: NikitaShlapak (Никита Шлапак)
  https://habr.com/ru/articles/791532/.
  5 фев 2024 в 16:51
  
  //// Начало цитирования.
  
  Введение
  
  Как-то я столкнулся с довольно тривиальной, но новой для себя задачей
  - оптического распознавания символов (OCR).
  Так сложилось, что готовые инструменты (типа tesseract-ocr) мне не подошли,
  поэтому пришлось изобретать велосипед.
  Но к этому процессу я решил подойти со всей ответственностью:
  проверить несколько подходов, определить их преимущества, недостатки
  и выбрать наиболее подходящий для конкретной задачи.
  По итогу это мини-исследование вылилось в данную обзорную статью.
  Здесь я хочу привести примеры нейросетевых моделей,
  характерных для различных этапов становления области компьютерного зрения
  (далее - CV)
  в том виде, в котором мы его знаем сейчас. Итак, начнём...
  
  Постановка задачи
  
  Подготовка данных
  
  Довольно актуальной является задача получения текста с фотографии
  или скана документа.
  Самым простым способом является разбиение текста на отдельные буквы
  с дальнейшим распознавание каждой буквы по отдельности.
  
  Таким образом, сравнивать модели будем в контексте задачи
  классификации изображения.
  
  Датасет для обучения генерировался на основании написания русских букв 11-ю шрифтами:
  
  .....
  
  К каждой букве применялись аугментации из следующего списка:
  
   Зеркальное отображение (по вертикали и/или горизонтали)
  
   Размытие
  
   Поворот на случайный угол (до 15 градусов) по или против часовой стрелки
  
  Каждая аугментация применялась к изображению со своим шансом.
  При этом сохранялись все изображения:
  исходные и после каждой аугментации.
  После этого к некоторым из них применялось зашумление.
  
  Рис. Пример того, как буквы выглядят после нескольких аугментаций
  
  Условия сравнения
  
  Сравнивать модели будем по следующим параметрам:
  
   Точность (CategoricalAccuracy) - процент "угаданных" букв;
  
   Значение функции потерь (CategoricalCrossentropy)
   - не всегда информативный параметр,
   но при равных точностях может дать дополнительную информацию;
  
   Число параметров и скорость работы
   - для обработки текста по букве крайне важно,
   чтобы модель была небольшой и работала быстро;
  
   Время обучения и вес модели - чисто прикладные характеристики.
   Наиболее полезны будут, если кто-то захочит повторить этот эксперимент.
  
  Эксперимент
  
  Выбор конкурсантов
  
  Для эксперимента я отобрал 5 моделей:
  
   Простая свёрточная нейросеть;
  
   VGG-16;
  
   DenseNet;
  
   Vision Transformer (ViT)
  
   SWin
  
  По моему мнению, такой выбор довольно репрезентативен.
  Если у читателя на этот счёт другое мнение - прошу им поделиться.
  
  Непосредственно классифицирующая часть у всех моделей
  имеет одинаковое строение.
  Также для ускорения процесса обучения было использовано 2 колбека:
  
   ReduceLROnPlateau - уменьшение learning rate
   если длительное время нет улучшения целевой метрики.
  
   EarlyStopping - если длительное время целевая метрика не растёт,
   то обучение прекращается.
  
  В качестве целевой метрики в обоих случаях
  было значение функции потерь на валидационных данных (val_loss)
  
  Всё было написано с помощью библиотеки keras,
  которая с недавнего времени совместима как с tensorflow, так и с pytorch.
  Для детального ознакомления код и данные доступны в репозитории.
  
  Модели будем обозревать в логико-хронологическом порядке.
  Что это такое - поймёте сразу.
  
  Convolution Neural Network (CNN)
  
  Для начала разберёмся с базовым подходом.
  Свёрточные нейросети изначально разрабатывались для классификации изображений,
  поэтому использование свёрточной архитектуры напрашивается в первую очередь.
  
  Эксперименты показали, что самым оптимальным решением
  с точки зрения соотношения скорости обучения и финальной точности
  является использование трёх свёрточных слоёв.
  Структура модели приведена на рисунке.
  
  Рис. Свёрточная модель
  
  Значения метрик для этой и прочих моделей будут приведены в конце,
  а здесь отмечу, что по сравнению с конкурентами эта модель
  обучалась довольно быстро.
  Также к преимуществам можно отнести семантическую простоту
  (для понимания принципа работы эта архитектура самая простая).
  Однако существенным недостатком является её размер.
  Обученная модель весит более 100 Мб, что в разы больше, чем у конкурентов.
  
  Принцип работы свёрточной сети заключается в том,
  что свёрточные слои выделяют из изображения определённые признаки,
  формируя новое изображение - "карту признаков" -
  из которого в дальнейшем также можно извлечь признаки.
  В конце для классификации все эти признаки,
  выделенные из признаков,
  выделенные из... и. д.
  подаются на вход обычного многослойного перцепртона (MLP),
  который в данном случае является классификатором.
  
  Таким образом, качество классификации изображения свёрточной
  (да и, в принципе, любой другой) нейросетью
  определяется двумя вещами:
  качеством выделения признаков
  и качеством классификатора.
  Если с классификатором всё понятно:
  всё, что нужно, это перебрать различные числа слоёв и нейронов
  и выбрать те, которые дадут самую высокую точность,
  то с выделением признаков не всё так просто.
  Логическим продолжением идей простой свёрточной нейросети
  стало появление более сложных моделей,
  способных выделять более мелкие, сложные или неочевидные признаки.
  
  VGG-16
  
  Схематически структуру этой модели традиционно изображают так:
  
  Рис. VGG-16
  
  В ней свёрточные слои (чёрные) извлекают признаки,
  а операция "max pooling" отбирает из них наиболее значимые.
  И так 5 раз.
  Затем идёт уже знакомый нам MLP-классификатор.
  
  Как можно заметить, авторы решили пойти по пути увеличения числа слоёв.
  Действительно, это одна из первых мыслей,
  которая приходит в голову,
  когда ты остаёшься недоволен своей свёрточной нейросетью.
  Однако, в представленной модели имеют место целых 16
  (что и отражено в названии) слоёв,
  12 из которых - свёрточные.
  Используйся эти слои без каких-либо ухищрений
  (что, конечно же не так),
  это привело бы к просто непомерной "тяжести" модели.
  
  К счастью, ухищрения, всё-таки, присутствуют.
  Здесь используется конструкция из нескольких свёрточных слоёв подряд.
  Это позволяет охватывать большую область для определения признаков,
  не слишком сильно увеличивая число обучаемых и хранимых весов.
  
  Возвращаясь к нашей задаче, эта (и следующая) модель
  были использованы в предобученном виде.
  Т.е. оставалось только обучить классификатор.
  В конечном счёте эта модель показала достойную точность
  при меньшем, чем у простой свёрточной, объёме занимаемой памяти.
  Однако, в скорости она уступила.
  
  Увеличивать число слоёв свёрточных моделей до бесконечности нельзя.
  Точнее, конечно, можно,
  но рано или поздно пришлось бы для обучения таких моделей
  использовать квантовые суперкомпьютеры.
  Поэтому, в развитии свёрточных архитектур
  следующим шагом стала передача признаков с одного слоя на другой
  минуя промежуточные.
  
  DenseNet
  
  Характерным примером модели-классификатора,
  использующей этот приём (т.н. "skip connection") является DenseNet:
  
  Рис. DenseNet
  
  Как видно из иллюстрации, модель состоит из нескольких блоков
  и информация передаётся от предыдущего к последующему двумя путями:
  через все промежуточные блоки и напрямую - минуя их.
  
  Модель довольно громоздкая и рассчитана на задачи куда сложнее,
  чем определение буквы на чёрно-белой картинке,
  поэтому в эксперименте выдающихся результатов не показала.
  Но всё же модель гораздо больше всех своих конкурентов
  и гораздо медленнее VGG-16.
  
  Свёрточные архитектуры продолжают развиваться до сих пор
  и всё ещё являются отличными классификаторами
  (занимая первое место на соревнованиях по типу ImageNet) ,
  но среди многих из них прослеживается общая тенденция:
  не слишком впечатляющая скорость работы и огромные размеры.
  Это и стало причиной появления принципиально нового подхода.
  
  Vision Transformer (ViT)
  
  Как это часто случается в науке,
  прорыв произошёл благодаря тому,
  что кто-то обратил внимание на разработки коллег в другой области.
  В данном случае - области обработки естественного языка.
  А именно, вдохновением послужила модель Transformer.
  Эта модель представляет собой автоэнкодер с добавлением механизма внимания.
  
  Визуальный трансформер - это адаптация традиционно языковой архитектуры
  для задач компьютерного зрения.
  В оригинальной статье предлагается разделять картинку на фрагменты,
  затем генерировать для них позиционное кодирование
  и обрабатывать это всё как последовательность.
  Т.к. в нашем случае картинки довольно маленькие,
  то было решено упростить архитектуру до предела:
  отбросить позиционное кодирование
  и подавать на вход никак не изменённую картинку:
  
  Рис. Структура используемого трансформера
  
  Внутри для более качественного извлечения признаков
  стоит сразу 4 слоя TransformerEncoder.
  Такая архитектура не уступает свёрточной по скорости обучения,
  но сильно выигрывает в размере.
  Правда, скорость обработки у неё пониже.
  
  Модели на базе визуальных трансофрмеров сразу же стали активно развиваться.
  Одним из наследников стала модель с забавным
  для русскоговорящего человека названием SWin.
  
  Vision Transformer using Shifted Windows (SWin):
  
  Swin - это одна из самых совершенных архитектур на базе трансформеров.
  У неё есть 2 главных улучшения по сравнению с оригинальным ViT:
  
   Иерархическая структура.
   Он разбивает изображение не на фрагменты одного размера,
   как это делает базовый ViT,
   а сначала крупные,
   затем эти крупные фрагменты разбивает на фрагменты помельче и т.д.
  
   Матрицы внимания вычисляются 2 раза:
   для разбитой картинки и для такой же картинки,
   разбитой на фрагменты такого же размера, но со смещением
  
  На самом деле усовершенствований там довольно много.
  Есть статья, в которой это всё разобрано.
  https://habr.com/ru/articles/599057/
  
  В нашем случае, опять же, сильно усложнять нужды нет.
  Поэтому упрощаем.
  В данном случае код практически без изменений был скопирован
  с официальной документации.
  https://keras.io/examples/vision/swin_transformers/
  
  Рис. Структура модели на базе SWin
  
  Swin на голову опережает CNN и ViT по всем параметрам,
  кроме одного: скорости обучения.
  И точность у него примерно такая же, как и у всех остальных.
  Обучается он в 5-10 раз дольше и на первых эпохах обучения
  значения метрик у него крайне низкие
  (после 5 эпохи точность у него была около 50% при том,
  что ViT к этому моменту уже преодолел порог точности на обучающей выборке в 95%).
  
  Эта архитектура показала отличную точность классификации,
  обойдя все "трансформерные" модели и практически все свёрточные на ImageNet в момент выхода,
  чем по праву заслужила внимание, уделённое ей.
  Она получила улучшение в виде модели SWin-2 в апреле 2022 года
  https://arxiv.org/pdf/2111.09883.pdf
  и духовного преемника в виде NAT - в мае 2023.
  https://arxiv.org/pdf/2204.07143.pdf
  
  Итоги соревнования
  
  Численные сравнения приведены ниже.
  Жирным шрифтом выделены лучшие результаты по каждому критерию
  
  ......
  
  *модели были взяты с весами ImageNet согласно официальной документации keras
  
  **обучение проводилось на видеокарте NVidia 4060 для ноутбуков.
  
  Если обобщать, то в задаче оптического распознавания символов
  есть смысл использовать архитектуру на базе SWin,
  однако, стоит учитывать, что более сложные модели
  требуют гораздо больше времени и данных для обучения.
  В случае, если датасет небольшой и расширению поддаётся плохо,
  неплохо себя показывает базовая модель ViT,
  а если добавить позиционное кодирование,
  то точность можно повысить ещё больше.
  
  Полезные ссылки
  
  Документация Keras (примеры кода, инструкции по применению и объяснения)
  
  ......
  
  Статьи на хабре
  
   Свёрточные нейросети
  https://habr.com/ru/articles/348000/
  
   Максимально подробно про трансформер
  https://habr.com/ru/articles/341240/
  
   Тоже хорошая статья про ViT
  https://habr.com/ru/articles/599677/
  
   ...и про Swin
  https://habr.com/ru/articles/599057/
  
  
  Официальные публикации крутых дядек
  
   Attention is All You Need- про транформер
  
   An Image is Worth 16x16 Words- про визуальный трансформер (ViT)
  
   Swin Transformer: Hierarchical Vision Transformer using Shifted Windows -
  вершина эволюции визуальных трансформеров
  
   Swin Transformer V2 - как SWin,только лучше
  
   Neighborhood Attention Transformer - и ещё лучше
  
   Densely Connected Convolutional Networks - DenseNet
  
  И ссылка на репозиторий:
  
  https://github.com/NikitaShlapak/OCR
  
  .......
  
  //// Конец цитирования.
  
  По-моему, очень неплохой материал для начального введения
  в структуры нейросетей, используемые в компьтерном зрении.
  Отталкиваясь от него можно попробовать разбираться более детально
  с каждой из упомянутых структур.
  
  
  ========
  
  30.01.2024 9:10
  
  Структуры нейросетей для задач визуального детектирования.
  В оглавление.
  
  Нейросети для визуального детектирования объектов,
  это практически те же системы компьютерного зрения,
  но с некоторой существенной "спецификой".
  Это уже не просто классификатор объектов на картинке,
  но еще и инструмент для визуализации того в каком "месте" изображения
  идентифицирован тот или иной объект.
  
  Первоначально такие системы базировались на сверточных нейросетях (CNN)
  Но дальнейшее развитие этой области, новые задачи и новые требования
  привели к появлению все новых и новых, порой весьма экзотических структур.
  Вот и будем понемногу с ними разбираться, чтобы выделить основные тенденции:
  
  "Детекция объектов. R-CNN, Fast R-CNN, Faster R-CNN. Часть 1".
  Автор: nepexom (Максим Переходкин)
  https://habr.com/ru/articles/789942/.
  29 янв 2024 в 22:56
  
  //// Начало цитирования.
  
  ......
  
  Первая часть будет посвящена постановке задачи детекции
  и обзору первых алгоритмов.
  Последующие части будут уже про актуальные модели, в частности, про YOLO.
  
  Введение. Кто такой детектор?
  
  Ранее с CNN мы решали задачу классификации,
  где на вход модели подавалось изображение,
  а на выходе мы получали вектор вероятностей,
  где каждая компонента соответствует вероятности какого-то класса.
  
  В задаче детекции мы не только хотим знать КТО на изображении,
  но ещё и ГДЕ он находится.
  Положение объекта определяет прямоугольник,
  охватывающий объект и называется он Bounding box
  или в народе ббокс
  (красный прямоугольник на картинке сверху).
  
  Ббокс описывается пятью числами: x, y, w, h, c:
  
   x, y - иксовая и игрековая компоненты центра
  
   w, h - ширина и высота соответственно
  
   c - уверенность в том, что внутри этого ббокса
   вообще находится хоть какой-то объект
  
  + для каждого ббокса нам надо предсказать класс содержащегося внутри объекта.
  Вот список популярных датасетов с разметкой для детекции:
  
   Pascal voc 2012
  
   COCO
  
  Итак, еще разок. Модель должна предсказывать прямоугольники,
  в которых содержатся объекты + определять,
  к каким классам они принадлежат.
  Давайте немного погрузимся в историю и посмотрим,
  как люди начинали решать эту задачу.
  
  Первый подход к решению задачи детекции. Sliding-window (скользящее окно)
  
  Представим, что нам поставили задачу выделить прямоугольником лицо.
  Как бы мы её решали, если у нас уже есть
  обученная модель классификатора изображений?
  
  Ну поскольку классификатор уже есть,
  и нужно просто понять, где находится объект
  - давайте сделаем окно, которое будет попиксельно двигаться по изображению
  и кропать (обрезать) его,
  а затем кропнутые изображения кидать в модель классификатора.
  Если классификатор выдаст высокую вероятность лица,
  значит оно нашлось и нашелся соответствующий прямоугольник.
  
  Мы также хотим варьировать размер окна,
  чтобы улавливать объекты разной формы и масштаба,
  поэтому будет вложенный цикл по параметрам окна и по изображению.
  В целом такая схемка работает,
  но она очень неэффективная...
  Вот гифка того, как оно происходит для окна фиксированного размера:
  
  Двухстадийные детекторы
  
  Окей, скользящее окно не очень эффективно,
  поэтому надо думать дальше.
  А что если не перебирать втупую все возможные варианты положения объекта,
  а попробовать как-то сузить круг поиска?
  Именно эта идея легла в основе архитектур двухстадийных детекторов.
  Двухстадийными они называются,
  так как сначала мы находим Default Boxes
  (наши гипотезы о местонахождении объекта),
  а затем уже, опираясь на них, даем ответ.
  
  Архитектура R-CNN
  
  R-CNN сужает поиск возможных положений объекта
  при помощи алгоритма Region Proposal (Selective Search).
  Данный алгоритм получает на вход изображение,
  а на выходе выдает массив прямоугольников,
  в которых возможно находится объект.
  При этом в основе алгоритма лежит классический Computer Vision
  (вдаваться в подробности этого алгоритма думаю нет смысла,
  так как на практике он уже давно не используется).
  //// Но познакомиться, наверно, имеет смысл.
  
  Итак, сначала мы запускаем на изображении Selective Search,
  а далее в цикле подаем кропы с этих регионов в классификатор.
  Ниже приведена архитектура из оригинальной статьи:
  https://arxiv.org/abs/1311.2524
  
  ......
  
  Помимо метки класса мы так же предсказываем поправки (offset) к прямоугольникам.
  т. е. дополнительно предсказываем соответствующие поправки к x, y, w, h
  и строим функцию потерь для обучения,
  состоящую из потери для классификации и регрессии.
  
  Теперь алгоритм стал эффективнее,
  чем просто полный перебор всех возможных местоположений,
  НО все равно не достаточно эффективно.
  Ведь для каждого региона нужно запускать классификатор.
  Например, что если Selective Search выдал 100 регионов,
  а наш классификатор это жирный VGG,
  который будет работать около секунды?
  Получается больше минуты на поиск объекта на одном изображении.
  Тут ни о каком риалтайме и речи идти не может,
  поэтому нужно думать дальше.
  
  Архитектура Fast R-CNN
  
  Что нам не понравилось в прошлой архитектуре?
  Конечно же запуск сверточной сетки для каждой гипотезы,
  полученной из Selective Search.
  Именно эту проблему решает новая архитектура Fast R-CNN.
  Делает она это следующим образом:
  
   Сначала мы прогоняем изображение через сверточную сеть
   и получаем Feature Map
  
   Запускаем на изображении Selective Search
   и проецируем прямоугольники прямо на Feature Map.
  https://www.educative.io/answers/what-is-a-feature-map
   Например, если тензор исходного изображения был размерности [3, 244, 244],
   а размерность выходного тензора после сверток [1, 32, 32],
   то для того, чтоб спроецировать координаты ббоксов,
   нам нужно просто посчитать aspect ratio
   и умножить на него соответствующие координаты ббоксов.
   Дальше уже просто делать кропы с feature map.
  
   Приводим ббоксы на feature map к одному размеру
   и в цикле пробрасываем их в полносвязный слой.
   За этот пункт отвечает процедура RoI Pooling (RoI - region of interest)
  
  Что же поменялось?
  И тогда и сейчас мы запускали цикл по каждому предположению.
  НОО сейчас в цикле не запускается сверточная сеть,
  так как прямоугольники мы отмечали прям на feature map.
  Поэтому архитектура стала в разы эффективнее.
  Вот, кстати, схема из статьи с моим небольшим рисунком:
  https://arxiv.org/abs/1504.08083
  
  .......
  
  Ранее я говорил, что мы решаем две задачи в детекции:
  классификацию и регрессию (для корректировки прямоугольников),
  поэтому после FCs мы видим разветвление.
  Выход из полносвязных слоев идет в softmax (для классификации)
  и в bbox regressor (для поправок к ббоксам).
  Далее строится мульти-таск лосс,
  который выглядит примерно так
  (b - это поправки к прямоугольникам, c - вектор вероятностей классов):
  
  L(c_{pred}, b_{pred}, c_{true}, b_{tue}) = L_1(c_{pred}, c_{true}) + L_2(b_{pred}, b_{true})
  
  Faster R-CNN
  
  Это улучшение заменяет Selective Search на нейронную сеть.
  Теперь поиск ббоксов - это тоже обучаемый алгоритм под названием RPN.
  Цитата из оригинальной статьи:
  "The RPN is thus a kind of fully convolutional network (FCN)
  and can be trained end-to-end specifically
  for the task for generating detection proposals".
  
  Идейно это единственное отличие.
  т. е. раньше у нас был Selective Search,
  который брал на вход картинку, генерил нам боксы,
  ресайзил их с нужным коэффициентом и накладывал на Feature Map,
  а теперь, в Faster R-CNN,
  это делает отдельный модуль Region Proposal Network,
  который так же нам генерирует боксы на основе нашего датасета.
  //// И вот это надо будет внимательно посмотреть.
  
  Думаю далее вдаваться в подробности RPN не имеет смысла,
  так как архитектура не актуальна на сегодняшний день.
  Тут скорее хотелось дать качественное описание того, что менялось:)
  
  Заключение
  
  Итак, мы разобрались с тем, что такое детекция,
  и какие были первые подходы к решению этой задачи.
  Некоторые идеи из двухстадийных детекторов продолжили своё существование
  в новых одностадийных детекторах,
  которым будет посвящена моя следующая статья.
  Если быть конкретнее, то речь пойдет про архитектуру YOLO
  и то, чем она так всем угодила.
  
  .......
  
  //// Из Комментариев.
  
  ti_uporot
  9 часов назад
  
  Yolo по факту будет по круче, как минимум по причине того,
  что как минимум в 3-ей версии уже были анкоры,
  за счёт чего у тебя уже уменьшение по ресурсам идёт,
  а не перебирать буквально каждый пиксель)
  
  .......
  
  AndreyDmitriev
  30 янв в 11:14
  
  По поводу YOLO тут пара недель назад в линкед ин
  
  проскочила информация о YOLO 8.1,
  которая умеет в Oriented Bounding Boxes (OBB),
  ну то есть возвращаемые регионы не просто прямоугольники,
  а повёрнутые - к примеру тут модель на наборе данных DOTA v1:
  
  Я было попробовал со своим набором,
  но детальной информации практически нет,
  хотя бы как правильно разметку делать при обучении и как описать эти регионы.
  
  .....
  
  Если предположить. что всё, что у меня есть
  - куча своих изображений всяких разных деталек,
  то за пошаговое руководство "от А до Я" как установить, разметить
  и натренировать YOLO, чтобы получить результат типа такого:
  
  ......
  
  вероятно благодарность сообщества не имела бы границ в пределах разумного.
  
  ......
  
  //// Конец цитирования.
  
  Самое интересное, на мой взгляд, анализируя этот материал
  - это возможность обучения нейронок на выделение "ббоксов",
  причем делать это как-то инвариантно по отношению к масштабу этих "ббоксов".
  Вот как бы понять как это происходит.
  Есть интуитивное ощущение, что это, возможно, ключевой вопрос для понимания
  не только систем данного типа, но вообще систем в которых есть это самое
  "внутреннее свернутое представление", то бишь, "эмбеддинги".
  
  
  =========
  
  17.02.2024 17:16
  
  Структура сети YOLO для задач визуального детектирования.
  В оглавление.
  
  Продолжим изучение нейросетей предназначенных для визуального детектирования,
  как достаточно простых по архитектуре, если сравнивать их теми же LLM,
  но очень интересных по заложенных в них идеях:
  
  "Детекция объектов. YOLO. Часть 2".
  Автор: nepexom (Максим Переходкин)
  https://habr.com/ru/articles/792926/.
  11 фев 2024 в 15:25
  
  //// Начало цитирования.
  
  Введение.
  
  Когда пытаешься разобраться в работе YOLO по статьям в интернете,
  постоянно натыкаешься на примерно такое объяснение:
  <Алгоритм делит изображение сеткой SxS,
  где каждому элементу этой сетки соответствует N ббоксов с координатами,
  предсказаниями классов и тд...>.
  Но лично мне становилось только непонятнее от такого высокоуровнего описания..
  Ведь в исследованиях часто всё происходит примерно так:
  перебирают гипотезы, пока не получат приемлемый результат,
  а потом уже придумывают красивое описание.
  Поэтому для ясности хочется рассказать,
  как вообще приходили к идеям,
  которые ложились в основу YOLOv1 и последующих версий.
  
  Немного про особенности Feature Map
  
  Сначала поговорим про Feature Map,
  чтобы потом стало понятно откуда взялась эта непонятная сетка SxS.
  Итак, давайте представим, что у нас есть
  маленькое трехканальное (RGB) изображение 10*10 пикселей.
  Мы прогоняем его через две свёртки:
  с ядром 5*5 и ядром 3*3.
  
  .....
  
  Рис. Визуализация кода
  
  На изображении видно, что левая верхняя ячейка Feature map 2
  является результатом свертки выделенной области из Feature map 1.
  В то же время, каждая ячейка из выделенной области на Feature map 1
  является результатом сверки соответствующей области исходного изображения.
  Получается, что выделенный элемент на Feature map 2
  отображает признаки выделенной области на исходном изображении Input image.
  Поскольку Feature map 2 имеет размер 4*4
  - можно сказать, что он как бы делит исходное изображение сеткой 4*4,
  так как каждый его элемент смотрит на 1 из 16 частей изображения.
  
  Вдобавок становится понятно,
  что чем глубже находится Feature Map,
  тем более высокоуровневые признаки на изображении он описывает.
  Вот довольно популярная картинка, которая показывает это свойство:
  
  Рис. Low, Mid, High Level Features
  
  Low-Level Feature описывает всякие непонятные линии и закарючки,
  так как ядро сворачивает очень маленькую часть изображения.
  Mid-Level Feature описывает уже что-то более осмысленное,
  так как отображает часть побольше.
  И наконец High-Level Feature уже содержит информацию,
  которую можно как-то интерпретировать
  (наличие колеса, фар, решетки радиатора и тп)
  
  YOLOv1
  
  В 2015 году Joseph Redmon опубликовал статью You
  Only Look Once: Unified, Real-Time Object Detection.
  https://arxiv.org/abs/1506.02640
  Гипотеза, которую ему удалось проверить
  и получить хороший результат заключалась в следующем:
  <А что если взять какую-то предобученную модель
  для классификации картинок
  и просто заменить последний слои так,
  чтобы она предсказывала не вероятность классов,
  а какой-то тензор,
  в котором будет содержаться информация о ббоксах и классах.
  
  Архитектура
  
  В статье сначала строится архитектура для классификации изображений,
  вдохновленная GoogLeNet:
  
  Рис. я тут немного порисовал,
  так как в оригинальной статье уже сразу финальная архитектура
  с последними слоями для детекции.
  
  Эта архитектура училась классифицировать изображения на ImageNet (1000 classes)
  и на валидации вошла в top-5 Accuracy с 88%.
  После того, как мы обучили классификатор,
  замораживаем первые 20 слоёв.
  Т.е. их веса больше не будут меняться в ходе дальнейшего обучения
  (ничего волшебного - это обычный Fine-Tuning)
  
  Теперь у нас есть предобученные 20 слоёв,
  которые извлекают информацию из изображения.
  Добавим к ним 4 необученных сверточных слоя + полносвязный слой.
  В самом конце возвращается тензор,
  в котором будет информация о ббоксах и соответствующих классах.
  
  Вот финальная архитектура (Изменились только последние слои ):
  
  Рис. Архитектура YOLOv1
  
  Пока что не обращаем внимание на размерность выходного тензора 7\times7\times30
  
  Давайте подумаем, а как вообще записать информацию о ббоксах в выходной тензор?
  
  Размер выходного тензора
  
  В прошлой статье я говорил, что для описания бокса нам нужно 5 чисел:
  x, y, w, h, conf
  
  Для того, чтоб предсказать класс объекта, находящегося в боксе,
  нам нужен вектор длины C ,
  где C - это количество классов
  (каждая компонента соответствует вероятности какого-то класса).
  В датасете Pascal Voc 20 классов, так что C=20 .
  Следовательно для информации об одном ббоксе
  нам нужен вектор длины 25 (5 +20=25)
  
  Ббоксы должны соответствовать какой-то области изображения,
  следовательно, выходной тензор будет иметь размер S \times S,
  где каждый элемент отражает область на исходном изображении.
  Автор взял S=7, то есть выходной тензор как бы разбивает исходное изображение
  на 7 * 7 частей.
  
  Далее, пусть каждой области соответствует B ббоксов (автор выбрал B=2)
  
  Т.е. каждому элементу выходного тензора S \times S должен быть сопоставлен
  вектор размера B \cdot(5 + C).
  В статье класс решили предсказывать только для ббокса с самым большим conf ,
  поэтому формула немного упростится и станет B \cdot 5 + C
  
  Общая формула размера выходного тензора выглядит так:
  S\times S \times (B \cdot5 + C)
  
  Отсюда мы и получаем 7 \times 7 \times 30
  
  Лосс и обучение
  
  Вот и вся архитектура YOLOv1.
  Теперь остается только придумать функцию потерь,
  состоящую из ошибки предсказания ббоксов и классов.
  Далее в процессе обучения ошибка будет минимизироваться
  и в выходном тензоре будут получаться всё более и более осмысленные числа.
  
  Рис. Функция потерь YOLOv1
  //// Очень многочленная формула.
  //// И напрашивается вопрос, а может быть лучше не одна общая функция потерь
  //// а несколько разных с несколько соответствующих проходов
  //// обратного распространения ошибок?
  
  YOLO предсказывает несколько ббоксов для каждой области изображения.
  Во время обучения, мы хотим, чтобы только один ббокс
  был ответственным за каждый объект.
  Ответственным выбирается тот, у кого самый большой IoU c Ground Truth
  (истинным ббоксом из разметки)
  
  Далее в статье показываются метрики,
  по которым видно, насколько YOLO быстрее, чем Fast R-CNN
  и какая у неё хорошая метрика mAP на валидационном датасете VOC 2007.
  Интересно заметить, что в таблицах показаны метрики
  для комбинированной модели YOLO + Fast R-CNN,
  которые дают хороший результат по качеству.
  
  YOLOv2 (YOLO9000)
  
  На волне хайпа уже в следующем году Joseph Redmon публикует улучшение YOLOv1
  в этой статье.
  https://arxiv.org/abs/1612.08242
  Название 9000 говорит о том, что модель способна отличить аж 9к классов!
  При этом оставаясь достаточно качественной и быстрой.
  
  Главным недостатком предыдущей модели были
  ошибки локализации + маленький recall,
  по сравнению с двухстадийными детекторами.
  Относительно маленький recall значит,
  что модель часто вообще не видит объект там,
  где его видит, например, Fast R-CNN.
  Поэтому основная задача - это улучшить
  геометрическую точность предсказания ббоксов и recall.
  
  Anchor Boxes
  
  Помимо всяких улучшений за счет батч норма, увеличения разрешения и тп,
  вводится очень важное архитектурное изменение,
  заключающееся в добавлении Anchor Boxes
  (я не знаю как это перевести на русский).
  Ранее YOLO предсказывала координаты с нуля,
  прямо из полносвязного слоя.
  Как мы помним, двухстадийные детекторы предварительно имели
  целый набор гипотез для ббоксов.
  Как показывает практика,
  модели гораздо проще предсказывать поправки к наперед заданным ббоксам,
  чем с нуля их строить.
  Поэтому в YOLOv2 решили взять хорошую идею из двухстадийных детекторов
  и использовать Anchor Boxes!
  (Возможно такая идея пришла как раз после работы
  с комбинированной моделью YOLOv1 + Fast R?CNN).
  Такое нововведение также позволило предсказывать гораздо больше ббоксов.
  //// Очень интересная идея сама по себе.
  //// Использовать нейросеть как "корректор" какого-то
  //// предварительного "предсказания" полученного другим способом
  //// или другой системой.
  
  После добавления Anchor Boxes в YOLO появилась проблема,
  заключающаяся в том, что размеры боксов подбираются вручную.
  Решением проблемы стало использование k-means clustering
  для автоматической генерации гипотез.
  По сути дефолтные боксы (Anchor Boxes) в YOLO
  генерируются на основе конкретного датасета,
  на котором вы хотите обучать модель.
  
  Другая проблема заключалась в том,
  что на ранних итерациях обучения,
  нейронке довольно сложно предсказывать (x, y),
  поскольку изначально её веса рандомные,
  и смещение дефолт бокса может быть произвольным,
  т. е. он может вообще уплыть в любую часть изображения.
  Чтобы этого избежать,
  YOLOv2 вместо предсказания поправок,
  предсказывает относительные координаты внутри grid cell
  (элемент сетки, которая "делит" изображение),
  и коэффициенты для поправок к ширине и высоте.
  //// Вот это совсем не понял. Причем здесь трудности обучения,
  //// и как эта трудность была преодолена.
  
  Сеть выдаёт по прежнему 5 чисел для каждого ббокса: t_x, t_y, t_w, t_h, t_0
  
  Пусть (с_x, c_y) - это смещение координат левого верхнего угла grid cell
  (это надо для расчета абсолютных координат,
  тк ранее мы говорили, что предсказывать будем относительные координаты)
  
  Пусть (p_w, p_h) - это ширина и высота дефолт бокса
  
  Тогда финальные координаты предсказанного бокса считаются следующим образом:
  
   \begin{cases} b_x=\sigma(t_x)+c_x \\ b_y=\sigma(t_y) + c_y\\ b_w=p_w e^{t_w} \\ b_h=p_he^{t_h} \end{cases}
  
  Выглядит сложно на первый взгляд,
  но по сути модель просто КАК-ТО предсказала свои 5 чисел,
  потом для координат мы используем функцию активации \sigma(x),
  у которой область значений [0, 1],
  а далее прибавили координаты левого угла grid cell,
  чтобы перейти к абсолютным координатам.
  Ширину и высоту дефолт бокса мы просто домножили на коэффициенты,
  зависящие от параметров модели.
  Важно помнить, что это мы сами так ввели и определили вычисление координат ббоксов,
  а дальше оно само уже под капотом обучится.
  
  Детекция объектов на маленьких участках изображения
  
  Чтобы находить объекты разного масштаба,
  нам надо иметь несколько Feature Map.
  Как я уже говорил в начале этой статьи:
  есть Low-Level Features и High-Level Features.
  Так вот, чтобы находить мелкие объекты
  - нам нужен Low-Level Feature Map.
  В YOLOv2 используется passthrough layer,
  который конкатенирует разные Feature Map,
  предварительно приводя их к одному размеру.
  
  Немного конкретнее:
  в YOLOv2 после первых сверток есть Feature Map размера 26\times26\times512 ,
  который содержит в себе низкоуровневую информацию.
  После последних сверток у нас есть Feature Map размера 13\times13 .
  Чтобы их объединить,
  нам надо сделать reshape для низкоуровневых фичей:
  26\times26\times512=13*2\times13*2\times512=13\times13\times2048
  и теперь можно объединять с High-Level Features
  //// Интересное это "конкатенирование", очень созвучно с реализацией
  //// какого-то там "внутреннего внимания".
  //// Скорее всего и механизм действия этой "магии" однотипен.
  
  Новый Feature extractor
  
  В YOLOv2 поменяли backbone, теперь в основе лежит сеть Darknet-19.
  Она чем-то похожа на VGG, тк в основном там фильтры 3x3,
  но она не такая толстая и ресурсозатратная.
  Думаю про Darknet-19 читатель может отдельно почитать,
  если возник такой интерес.
  
  В целом, это все основные изменения в архитектуре YOLOv2
  
  YOLOv3
  
  Свою третью последнюю статью про YOLO Joseph Redmon
  начинает многообещающе со следующих слов:
  https://arxiv.org/abs/1804.02767
  I didn't do a whole lot of research this year.
  Spent a lot of time on Twitter.
  Played around with GANs a little.
  I had a little momentum left over from last year.
  I managed to make some improvements to YOLO.
  But, honestly, nothing like super interesting,
  just a bunch of small changes that make it better
  
  Во-первых, YOLOv3 теперь может работать уже на ТРЕХ разных скейлах.
  //// "Скейл", наверно, надо понимать как "масштаб".
  //// Но зато как круто звучит, особенно для "непосвященных".
  Это значит, что информация извлекается из 3-х разных Feature Map.
  Вдобавок в статье уже ссылаются на Feature Pyramid Networks.
  По сути эти "пирамиды" описывают способ,
  которым можно объединить Feature Map с разных уровней сверток.
  Вот пример того, как он работает:
  
  .......
  
  Отлично! Теперь надо сложить high_feature_map и mid_feature_map.
  Для этого сделаем high_feature_map такого же размера при помощи nn.Upsample
  
  .....
  
  Теперь аналогично делаем Upsampling для high_mid_feature_map,
  складываем его с low_feature_map и получаем тензор,
  который содержит информацию c 3-х разных scale.
  Таким образом YOLOv3 может видеть ещё более мелкие объекты на изображении.
  
  Darknet-19 ---> Darknet-53
  
  В YOLOv3 поменялся Feature extractor,
  теперь там 53 сверточных слоя, отсюда и название))
  Сеть стала значительно глубже, что позволило улучшить точность.
  В Darknet-53 встречаются Residual блоки,
  аналогичные тем, что используются в сети ResNet.
  Эти блоки позволяют эффективно передавать информацию через слои,
  что способствует обучению более глубоких нейронных сетей.
  Модель обычно предварительно обучается на больших наборах данных
  (например, ImageNet),
  а затем дообучается на конкретной задаче обнаружения объектов.
  Она является ключевым компонентом YOLOv3,
  обрабатывая входные изображения и извлекая признаки,
  которые затем используются для обнаружения объектов на изображениях.
  
  Заключение
  
  Сам создатель YOLO Joseph Redmon опубликовал 3 статьи,
  которые тут и описываются.
  Дальнейшие улучшения уже делали его последователи
  в YOLOv4, YOLOv5, YOLOv6 и тд.
  Тем не менее основные идеи и дальнейший вектор развития
  был заложен именно в первых трех версиях.
  YOLO сейчас широко используется для задач обнаружения объектов
  в реальном времени.
  Например, обработка кадров с видеопотока мобильного устройства, умных камер и тд.
  Следующие статьи думаю будут больше про практику
  и применение / внедрение моделей :)
  
  .......
  
  //// Конец цитирования.
  
  На что стоит, на мой взгляд, обратить внимание в этом материале.
  Это во-первых, на идею использования нейросети не как "генератора с нуля",
  а как корректора какого-то предварительного предсказания.
  Во-вторых, на сам подход использовать на выходе нейросети
  уже не просто вектор, а тензор, т.е. возможность более тонко настраивать
  нейросеть за счет, фактически, параллельного обучения по нескольким каналам,
  соответствующих разным "компонентам тензора".
  И в третьих, все более широкое использование Residual блоков,
  т.е. связей в обход отдельных слоев нейросети.
  Фича, которая как-то работает, но как именно особого понимания пока нет.
  
  Кстати, одна из целей этого модуля как раз и заключается в попытке
  разобраться именно с этой "фичей", точнее с тем почему и как она работает
  на самом деле, а не в путанных и противоречивых объяснениях/догадках,
  разбросанных по самым разным материалам.
  Даже устоявшегося термина нет, и это при всей любви к звучным терминам/аббревиатурам.
  Поэтому и такое внимание, к каждому упоминанию этого "архитектурного элемента".
  В данном тексте его применение обосновывается облегчением обучения
  И передачей какой-то информации от входных слоев к выходным.
  Но какой именно не уточняется - считается, что и так все понятно.
  Представляется, что именно такие "связи" это те самые "кончик нитки",
  которые могут помочь распутать "клубок" загадки
  "свернутого/скрытого пространства эмбеддингов".
  
  
  ==========
  
  10.02.2024 17:47
  
  Пошаговый разбор работы трансформера.
  В оглавление.
  
  Возможно, для того чтобы лучше понимать как работают различные структуры нейронок,
  стоит детально, пошагово пройтись по разбору работы какой-то конкретной структуры.
  И в этом случае, наверно, лучше всего подойдет материал
  по наиболее "хайповой" на данный момент архитектуре - трансфомерному блоку
  и, соответственно, "лидеру всех рейтингов" GPT:
  
  "Как работают трансформеры: разбираем математику".
  Автор: PatientZero
  https://habr.com/ru/articles/785474/.
  18 янв 2024 в 10:16
  
  Автор оригинала: Omar Sanseviero
  https://osanseviero.github.io/hackerllama/blog/posts/random_transformer/
  
  Материал объемный и сложный, но весьма полезный для понимания
  как работают реальные, а не учебные модели нейросетей.
  Постарался по максимуму урезать, но без потери смысла.
  Так что не обессудьте на то, что получилось.
  Надеюсь, это позволит оценить необходимость обращаться к оригиналу.
  
  //// Начало цитирования.
  
  В этом посте я представлю подробный пример математики,
  используемой внутри модели трансформера,
  чтобы вы получили хорошее представление о работе модели.
  Чтобы пост был понятным, я многое упрощу.
  Мы будем выполнять довольно много вычислений вручную,
  поэтому снизим размерность модели.
  Например, вместо эмбеддингов из 512 значений
  мы используем эмбеддинги из 4 значений.
  Это позволит упростить понимание вычислений.
  Мы используем произвольные векторы и матрицы,
  но при желании вы можете выбрать собственные значения.
  
  Как вы увидите, математика модели не так уж сложна.
  Сложность возникает из-за количества этапов и количества параметров.
  Перед прочтением этой статьи я рекомендую прочитать пост
  Illustrated Transformer
  (или читать их параллельно) [перевод на Хабре].
  https://habr.com/ru/articles/486358/
  Это отличный пост,
  объясняющий модель трансформера интуитивным (и наглядным!) образом,
  поэтому я не буду объяснять то, что уже объяснено в нём.
  Моя цель заключается в том,
  чтобы объяснить, как работает модель трансформера,
  а не что это такое.
  Если вы хотите углубиться в подробности,
  то изучите известную статью Attention is all you need
  [перевод на Хабре: первая и вторая части].
  https://habr.com/ru/companies/ruvds/articles/723538/
  https://habr.com/ru/companies/ruvds/articles/725618/
  
  Обязательные требования
  
  Для понимания статьи необходимы базовые знания линейной алгебры;
  в основном мы будем выполнять простые матричные умножения,
  так что специалистом быть необязательно.
  Кроме того, будут полезны знания основ машинного обучения и глубокого обучения.
  
  Что рассматривается в статье?
  
  Полный пример математических вычислений,
  происходящих в модели трансформера в процессе инференса
  
  Объяснение механизмов внимания
  
  Объяснение остаточных связей и нормализации слоёв
  
  Код для масштабирования модели
  
  Наша цель будет заключаться в использовании модели трансформера
  в качестве инструмента для перевода,
  чтобы мы могли передать модели входные данные
  и ожидать от неё генерации перевода.
  Например, мы можем передать на английском
  и ожидать на выходе получить на испанском.
  
  Давайте взглянем на пугающую диаграмму трансформера
  (не бойтесь, скоро вы её поймёте!):
  
  Рис. Модель трансформера из статьи
  
  Исходная модель трансформера состоит из двух частей:
  кодировщика (encoder) и декодера (decoder).
  Кодировщик занимается <пониманием> или <осознанием смысла> входного текста,
  а декодер выполняет генерацию выходного текста.
  Давайте рассмотрим кодировщик.
  
  Кодировщик
  
  Цель работы кодировщика заключается в генерации
  обогащённого эмбеддингами
  описания входного текста.
  Этот эмбеддинг отражает семантическую информацию о входном тексте
  и передаётся декодеру для генерации выходного текста.
  Кодировщик состоит из стека из N слоёв.
  Прежде чем переходить к слоям,
  нужно разобраться, как передавать слова (или токены) в модель.
  
  Примечание
  
  Термин <эмбеддинг> используется слишком часто.
  Сначала мы создадим эмбеддинг,
  который будет входными данными для кодировщика.
  Кодировщик тоже создаёт на выходе эмбеддинг
  (иногда называемый hidden states).
  Декодер тоже получает эмбеддинг!
  Весь смысл в том, что эмбеддинг описывает токен в виде вектора.
  
  0. Токенизация
  
  Модели машинного обучения могут обрабатывать числа, а не текст,
  так что нам нужно превратить входной текст в числа.
  Именно это и выполняет токенизация!
  Это процесс разбиения входного текста на токены,
  с каждым из которых связан ID.
  Например, мы можем разделить текст
  на два токена: и .
  Также мы можем разбить его на символы:
  , , , , , < >,, , , , .
  Мы сами можем выбирать принцип токенизации,
  он зависит от данных, с которыми мы работаем.
  
  Для токенизации по словам
  (разбиения текста на слова)
  требуется очень большой словарь
  (всех возможных токенов).
  В нём слова наподобие и или и
  будут разными токенами.
  Словарь символов потребует меньшего объёма,
  но будет обладать меньшим смыслом
  (он может быть полезен в языках наподобие китайского,
  где каждый символ содержит больше информации).
  
  Прогресс двинулся в сторону токенизации по подсловам.
  Это нечто среднее между токенизацией по словам и по символам.
  Мы разделяем слова на подслова.
  Например, слово можно разбить на и .
  Как принимается решение о месте разбиения слов?
  Это часть обучения токенизатора
  при помощи статистического процесса,
  задача которого заключается в выявлении подслов,
  которые лучше всего выбрать для конкретного датасета.
  Это детерминированный процесс
  (в отличие от обучения модели машинного обучения).
  
  В этой статье я для простоты использую токенизацию по словам.
  Наша цель будет заключаться
  в переводе с английского на испанский.
  Пример мы разобьём на токены и .
  Каждому токену присваивается в словаре модели ID.
  Например, может быть токеном 1, а - токеном 2.
  
  1. Эмбеддинг текста
  
  Хотя мы можем передать модели ID токенов (то есть 1 и 2),
  эти числа не несут никакого смысла.
  Нужно превратить их в векторы (список чисел).
  Именно это и выполняет процесс эмбеддинга!
  Эмбеддинги токена сопоставляют ID токена
  с вектором фиксированной длины,
  имеющим семантическое значение токенов.
  Это создаёт интересные свойства:
  схожие токены будут иметь схожий эмбеддинг
  (иными словами, вычисление косинусного коэффициента
  между двумя эмбеддингами даст нам хорошее понимание степени схожести токенов).
  
  Стоит заметить,
  что отображение токена в эмбеддинг изучается моделью.
  Хотя мы можем использовать уже обученный эмбеддинг
  наподобие word2vec или GloVe,
  в процессе своего обучения
  модели трансформеров
  изучают эти эмбеддинги.
  Это большое преимущество,
  поскольку модель может изучить наилучшее описание токенов
  для поставленной перед ней задачи.
  Например, модель может научиться тому,
  что и должны иметь схожие эмбеддинги.
  
  Все эмбеддинги в одной модели имеют одинаковый размер.
  В трансформере из научной статьи использовался размер 512,
  но чтобы мы могли выполнять вычисления, снизим его размер до 4.
  Я назначу каждому токену случайные значения
  (как говорилось выше, это отображение обычно изучается моделью).
  
  Hello -> [1,2,3,4]
  
  World -> [2,3,4,5]
  
  Примечание
  
  После публикации статьи многие читатели задали вопросы
  о представленных выше эмбеддингах.
  Мне было лениво и я просто записал числа,
  с которыми будет удобно выполнять вычисления.
  На практике эти числа будут изучаться моделью.
  Чтобы это было понятнее, я дополнил пост.
  
  Мы можем вычислить схожесть этих векторов
  при помощи косинусного коэффициента,
  который для представленных выше векторов будет слишком высоким.
  На практике вектор, скорее всего, будет выглядеть примерно так:
  [-0.071, 0.344, -0.12, 0.026, ..., -0.008].
  //// Т.е. в реальном эмбеддинге значения каких-то элементов могут быть
  //// ОТРИЦАТЕЛЬНЫМИ. И это достаточно плохо согласуется с версией,
  //// что эмбеддинг это просто распределение вероятностей,
  //// и больше с версией что эмбеддинг это координата в многомерном пространстве.
  //// Но по моим представлениям, это просто крайние случаи представления,
  //// а в общем случае "пространство эмбеддингов" это нечто другое,
  //// чему, возможно, еще и подходящего термина не придумано.
  //// Или есть, но где-то в самых "темных закоулках" ТОПОЛОГИИ.
  
  Мы можем представить наши входные данные в виде единой матрицы
  
  Примечание
  
  Хотя мы и можем обрабатывать два эмбеддинга как два отдельных вектора,
  проще работать с ними как с единой матрицей,
  потому что в дальнейшем мы будем выполнять умножение матриц.
  
  2. Позиционное кодирование
  
  Отдельные эмбеддинги в матрице не содержат информации
  о позиции слов в предложении,
  так что нам нужна информация о позиции.
  Её можно создать, добавив к эмбеддингу позиционное кодирование.
  
  Получить его можно различными способами;
  мы можем использовать изученный эмбеддинг или фиксированный вектор.
  В исходной научной статье используется фиксированный вектор,
  потому что авторы не увидели почти никакой разницы
  между двумя методиками
  (см. раздел 3.5 статьи).
  Мы тоже воспользуемся фиксированным вектором.
  Функции синуса и косинуса имеют волнообразный паттерн и повторяются.
  Благодаря использованию этих функций каждая позиция в предложении
  получает уникальное,
  но согласованное позиционное кодирование.
  Их повторяемость
  поможет модели проще изучать паттерны
  наподобие близости и расстояния между элементами.
  В статье используются следующие функции:
  
  ......
  
  Смысл заключается в интерполяции между синусом и косинусом
  для каждого значения в эмбеддинге
  (для чётных индексов используется синус, для нечётных используется косинус).
  Давайте вычислим их для нашего примера!
  
  Для
  
  i = 0 (чётный): PE(0,0) = sin(0 / 10000^(0 / 4)) = sin(0) = 0
  
  i = 1 (нечётный): PE(0,1) = cos(0 / 10000^(2*1 / 4)) = cos(0) = 1
  
  i = 2 (чётный): PE(0,2) = sin(0 / 10000^(2*2 / 4)) = sin(0) = 0
  
  i = 3 (нечётный): PE(0,3) = cos(0 / 10000^(2*3 / 4)) = cos(0) = 1
  
  Для
  
  i = 0 (чётный): PE(1,0) = sin(1 / 10000^(0 / 4)) = sin(1 / 10000^0) = sin(1) ? 0.84
  
  i = 1 (нечётный): PE(1,1) = cos(1 / 10000^(2*1 / 4)) = cos(1 / 10000^0.5) ? cos(0.01) ? 0.99
  
  i = 2 (чётный): PE(1,2) = sin(1 / 10000^(2*2 / 4)) = sin(1 / 10000^1) ? 0
  
  i = 3 (нечётный): PE(1,3) = cos(1 / 10000^(2*3 / 4)) = cos(1 / 10000^1.5) ? 1
  
  В итоге получаем следующее:
  
   -> [0, 1, 0, 1]
  
   -> [0.84, 0.99, 0, 1]
  
  Обратите внимание, что эти кодировки имеют ту же размерность,
  что и исходный эмбеддинг.
  
  Примечание
  
  Мы используем синус и косинус, как и в исходной научной статье,
  но есть и другие способы реализации.
  В очень популярном трансформере BERT
  применяются обучаемые позиционные эмбеддинги.
  
  3. Добавляем позиционное кодирование и эмбеддинг
  
  Теперь мы добавим к эмбеддингу позиционное кодирование.
  Это выполняется сложением двух векторов.
  
   = [1,2,3,4] + [0, 1, 0, 1] = [1, 3, 3, 5]
  
   = [2,3,4,5] + [0.84, 0.99, 0, 1] = [2.84, 3.99, 4, 6]
  
  То есть наша новая матрица,
  которая будет входными данными для кодировщика, выглядит так:
  
   [ 1, 3, 3, 5]
   [2.84, 3.99, 4, 6]
  
  Если посмотреть на изображение из научной статьи,
  то можно увидеть, что мы только что выполнили
  левую нижнюю часть изображения
  (эмбеддинг + позиционное кодирование).
  //// Вот это новенькое для меня. Я почему-то думал,
  //// что позиционное смещение добавляется в виде новых элементов вектора.
  //// а оказывается все по-другому. Нужно думать, как это интерпретировать.
  
  Рис. Модель трансформера из статьи
  
  4. Самовнимание
  
  4.1 Определение матриц
  
  Теперь мы введём концепцию многоголового внимания (multi-head attention).
  Внимание - это механизм,
  позволяющий модели сосредоточиться на определённых частях входных данных.
  Многоголовое внимание позволяет модели совместно уделять внимание информации
  из различных подпространств описаний.
  Для этого используются множественные головы внимания.
  Каждая голова внимания имеет собственные матрицы K, V и Q.
  
  Давайте в нашем примере используем две головы внимания.
  Для этих матриц мы применим случайные значения.
  Каждая матрица будет иметь размер 4x3.
  Благодаря этому каждая матрица будет преобразовывать четырёхмерные эмбеддинги
  в трёхмерные ключи (K), значения (V) и запросы (Q).
  Это снижает размерность механизма внимания,
  что помогает управлять вычислительной сложностью.
  Стоит отметить, что использование слишком малого размера внимания
  уменьшит точность модели.
  Давайте используем следующие значения (выбраны произвольно):
  
  Для первой головы
  
  .......
  
  Для второй головы
  
  .......
  
  4.2 Вычисление ключей, запросов и значений
  
  Для получения ключей, запросов и значений нужно умножить
  входные эмбеддинги на матрицы весов.
  
  Вычисление ключей
  
  .......
  
  На самом деле, нам не нужно вычислять всё это вручную,
  это будет слишком монотонно.
  Давайте схитрим и воспользуемся NumPy.
  
  Сначала определим матрицы
  
  ......
  
  
  И убедимся, что в приведённых выше вычислениях нет никаких ошибок.
  
  ......
  
  Отлично! Теперь давайте получим значения и запросы
  
  Вычисление значений
  
  .......
  
  Вычисление запросов
  
  .......
  
  Давайте пока пропустим вторую голову
  и сосредоточимся на окончательном результате первой головы.
  Ко второй голове мы вернёмся позже.
  
  4.3 Вычисление внимания
  
  Для вычисления показателя внимания требуется пара шагов:
  
  Вычисление скалярного произведения запроса и каждого ключа
  
  Деление результата на квадратный корень размерности вектора ключа
  
  Применение функции softmax для получения весов внимания
  
  Умножение каждого вектора значения на веса внимания
  
  4.3.1 Скалярное произведение запроса и каждого ключа
  
  Для вычисления результата для
  необходимо вычислить скалярное произведение q1
  и каждого вектора ключа (k1 и k2)
  
  .......
  
  В мире матриц это будет равно Q1, умноженному на перестановку K1
  
  .......
  
  
  4.3.2 Деление на квадратный корень размерности вектора ключа
  
  Затем мы делим показатели на квадратный корень размерности (d) ключей
  (в данном случае это 3, но в научной статье она была равна 64).
  Почему? При больших значениях d скалярное произведение растёт слишком быстро
  (ведь мы складываем умножение кучи чисел, что приводит к большим значениям).
  А большие значения - это плохо!
  //// А почему?
  Подробнее мы поговорим об этом чуть позже.
  
  ......
  
  4.3.3 Применение функции softmax
  
  Далее используем softmax для нормализации,
  чтобы все они были положительны и в сумме равнялись 1.
  
  Что такое softmax?
  
  Softmax - это функция, получающая вектор значений
  и возвращающая вектор значений между 0 и 1,
  в котором сумма значений равна 1.
  Это удобный способ получения вероятностей.
  Функция определяется следующим образом:
  
  .....
  
  Не пугайтесь этой формулы, на самом деле она довольно проста.
  Допустим, у нас есть следующий вектор:
  
  ......
  
  Softmax этого вектора будет такой:
  
  ......
  
  Как видите, все значения положительны и в сумме дают 1.
  
  ......
  
  //// Интересно, что здесь используется экспонента,
  //// тут действительно "большие числа" вырубят все что можно.
  
  4.3.4 Умножение матрицы значений на веса внимания
  
  Далее мы умножаем на матрицу значений
  
  ......
  
  Давайте объединим 4.3.1, 4.3.2, 4.3.3 и 4.3.4
  в одну формулу с использованием матриц
  (это из раздела 3.2.1 научной статьи):
  
  ......
  
  Да, вот и всё!
  Все проделанные нами вычисления можно легко свести
  к показанной выше формуле внимания!
  Давайте перенесём это в код.
  
  .......
  
  Мы убедились, что значения те же, что и получены выше.
  Давайте воспользуемся этим кодом для получения показателей внимания
  второй головы внимания:
  
  .......
  
  Если вас интересует, как внимание стало одинаковым для двух эмбеддингов,
  то это вызвано тем, что softmax переводит показатели в 0 и 1. Смотрите:
  
  .......
  
  Это вызвано плохой инициализацией матриц
  и маленьким размерам векторов.
  Большие различиях в показателях до применения softmax
  будут лишь усилены,
  приводя к том,
  что одно значение будет близко к 1, а другие к 0.
  На практике наши исходные значения матрицы эмбеддингов
  были слишком велики,
  что привело к высоким значениям для ключей, значений и запросов,
  которые при умножении становились только выше.
  
  Помните, как мы выполняли деление на квадратный корень размерности ключей?
  Именно поэтому мы это и делали,
  в противном случае значения скалярного произведения
  были бы слишком большими,
  из-за чего получились бы большие значения после softmax.
  Однако в данном случае, похоже, этого не было достаточно,
  учитывая наши небольшие значения!
  В качестве быстрого хака мы можем уменьшить масштаб значений
  на меньшее значение, чем квадратный корень трёх.
  Давайте переопределим функцию внимания,
  уменьшив масштаб на 30.
  В долгой перспективе это плохое решение,
  но оно поможет нам получить разные значения для показателей внимания.
  Позже мы вернёмся к более качественному решению.
  
  .....
  
  
  4.3.5 Выходные значения внимания голов
  
  Следующий слой кодировщика ожидает на входе одну матрицу, а не две.
  Первым этапом будет конкатенация выходных значений двух голов
  (см. раздел 3.2.2 научной статьи)
  
  .......
  
  Затем мы умножаем эту конкатенированную матрицу на матрицу весов,
  чтобы получить окончательный результат слоя внимания.
  Этой матрице весов модель тоже обучается!
  Размерность матрицы гарантирует,
  что мы вернёмся к той же размерности,
  что была у эмбеддинга (в нашем случае 4).
  
  .......
  
  Всё это можно объединить в изображение из The Ilustrated Transformer
  
  .......
  
  5. Слой с прямой связью
  
  5.1 Простой слой с прямой связью
  
  После слоя самовнимания у кодировщика идёт нейронная сеть с прямой связью
  (feed-forward neural network, FFN).
  Это простая сеть с двумя линейными преобразованиями
  и активацией ReLU между ними.
  В посте The Illustrated Transformer подробностей об этом нет,
  так что я вкратце объясню этот слой.
  Цель FFN заключается в обработке и трансформировании описания,
  созданного механизмом внимания.
  Поток обычно выглядит так (см. раздел 3.3 научной статьи):
  
  Первый линейный слой:
  обычно он расширяет размерность входных данных.
  Например, если размерность входных данных равна 512,
  то размерность выходных данных может быть равна 2048.
  Это выполняется для того,
  чтобы позволить модели изучать более сложные функции.
  В нашем простом примере с размерностью 4 мы расширимся до 8.
  
  Активация ReLU:
  нелинейная функция активации. Это простая функция,
  возвращающая 0, если входные данные отрицательны,
  и входные данные, если они положительны.
  Это позволяет модели обучаться нелинейным функциям.
  Вычисления выглядят так:
  
  .......
  
  Второй линейный слой: он противоположен первому линейному слою.
  Этот слой снова возвращает размерность к исходной.
  В нашем примере он выполнит снижение с 8 до 4.
  
  Всё это можно описать следующим образом
  
  .......
  
  Напомню, что входными данными для этого слоя является Z,
  которое мы вычислили в самовнимании.
  Вот какие значения мы там получили
  
  ......
  
  Теперь давайте зададим произвольные значения для матриц весов
  и векторов смещений.
  Я сделаю это в коде, но если у вас хватит терпения,
  то можете задать их вручную!
  
  ......
  
  А теперь давайте запишем функцию прямого прохода
  
  ......
  
  5.2 Объединяем всё: произвольный кодировщик
  
  Теперь давайте напишем код,
  чтобы объединить в блоке кодировщика многоголовое внимание и прямую связь.
  
  Примечание
  
  Код оптимизирован для понимания и образовательных целей,
  а не для производительности,
  не судите слишком строго!
  
  .......
  
  Вспомним наши входные данные в матрице E,
  имеющие позиционное кодирование и эмбеддинг.
  
  .....
  
  Теперь передадим это нашей функции random_encoder_block
  
  .......
  
  Отлично! Это был всего один блок кодировщика.
  В научной статье применяются шесть кодировщиков.
  Выходные данные одного кодировщика передаются на следующий и так далее:
  
  ......
  
  5.3 Остаточные связи и нормализация слоёв
  
  Ой-ёй! У нас начали появляться NaN!
  Похоже, наши значения слишком велики
  и при передаче следующему кодировщику они оказываются слишком большими
  и <взрываются>!
  Эта проблема слишком больших значений
  часто возникает при обучении моделей.
  Например, когда мы выполняем обратное распространение ошибки
  (методику, при помощи которой модели обучаются),
  градиенты могут оказаться слишком большими
  и в результате <взрываются>;
  это называется взрывом градиентов (gradient explosion).
  Без нормализации небольшие изменения во входных данных на первых слоях
  в последующих слоях усиливаются.
  Это распространённая проблема в глубоких нейросетях.
  Существует два способа борьбы с этой проблемой:
  остаточные связи и нормализация слоёв
  (они вкратце упоминаются в разделе 3.1 научной статьи).
  
  Остаточные связи просто прибавляют входные данные слоя к его выходным данным.
  Например, мы складываем исходный эмбеддинг с выходными данными внимания.
  Остаточные связи устраняют проблему исчезающих градиентов.
  Логика в том, что если градиент слишком мал,
  то мы можем просто сложить входные данные к выходным,
  и градиент станет больше. Вычисления очень просты:
  //// Т.е. внедрение "интерференции" объясняется
  //// борьбой с взрывающимися, исчезающими градиентами.
  
  Вот и всё!
  Мы сделаем это для выходных данных внимания
  и выходных данных слоя с прямой связью.
  
  Нормализация слоя - это методика нормализации входных данных слоя.
  Она выполняет нормализацию по размерности эмбеддинга.
  Логика в том, что мы хотим нормализовать входные значения слоя,
  чтобы они имели среднее значение 0 и квадратическое отклонение 1.
  //// Насчет среднего значения понятно, а вот квадратичное отклонение,
  //// это уже от "лукавой математики".
  Это помогает с градиентным потоком.
  Вычисления на первый взгляд выглядят не так уж просто.
  
  ......
  
  Давайте объясним каждый параметр:
  
  ? - это среднее значение эмбеддинга
  
  ? - это квадратическое отклонение эмбеддинга
  
  ? - это малое число, чтобы избежать деления на ноль.
  В случае нулевого значения квадратичного отклонения
  этот маленький эпсилон спасает нас.
  
  ? и ? - это изучаемые параметры,
  управляющие этапами масштабирования и сдвига.
  
  В отличие от пакетной нормализации
  (batch normalization, не волнуйтесь, если не знаете, что это такое),
  нормализация слоёв нормализует по размерности эмбеддинга;
  это означает, что на каждый эмбеддинг
  не будут влиять другие сэмплы в пакете.
  Идея заключается в том, что мы хотим нормализовать входные данные слоя,
  чтобы они имели среднее значение 0 и квадратичное отклонение 1.
  
  Зачем мы добавляем изучаемые параметры ? и ??
  Причина в том, что мы не хотим терять силу представления слоя.
  Если просто нормализовать входные данные,
  то какая-то информация может потеряться.
  Добавляя изучаемые параметры,
  мы можем научиться масштабировать и сдвигать нормализованные значения.
  
  Соединив эти уравнения, мы получим уравнение для всего кодировщика:
  
  ......
  
  Давайте проверим его на нашем примере! Возьмём прежние значения E и Z:
  
  .....
  
  Теперь давайте вычислим нормализацию слоя;
  можно разделить этот процесс на три этапа:
  
  Вычисление среднего и дисперсии для каждого эмбеддинга.
  
  Нормализация вычитанием среднего в своей строке
  и делением на квадратный корень дисперсии строки
  (плюс малое число, чтобы избежать деления на ноль).
  
  Масштабирование и сдвиг умножением на гамму и прибавлением беты.
  
  5.3.1 Среднее и дисперсия
  Для первого эмбеддинга
  
  ......
  
  То же самое можно сделать для второго эмбеддинга.
  Пропустим сами вычисления и покажем только результат.
  
  ......
  
  Давайте проверим при помощи Python
  
  .......
  
  Отлично! Теперь нормализуем
  
  5.3.2 Нормализация
  
  При нормализации из каждого значения в эмбеддинге
  мы вычитаем среднее и делим его на квадратичное отклонение.
  Эпсилон - это очень маленькое значение, например, 0,00001.
  Чтобы упростить, будем считать, что ? = 1, а ? = 0.
  
  .......
  
  Для второго эмбеддинга мы не будем выполнять вычисления вручную.
  Проверим их при помощи кода.
  Переопределим функцию encoder_block, внеся следующее изменение:
  
  .........
  
  Сработало! Давайте ещё раз попробуем пропустить эмбеддинг
  через шесть кодировщиков.
  
  ........
  
  Отлично! Значения приемлемые и отсутствуют NaN!
  Идея стека кодировщиков заключается в том,
  что на выходе они выдают непрерывное описание z,
  передающее смысл входной последовательности.
  //// А вот как именно - большой вопрос.
  Затем это описание передаётся декодеру,
  который генерирует выходную последовательность символов
  по одному элементу за раз.
  
  Прежде чем приступать к декодеру,
  взглянем на изображение из потрясающего поста Джея:
  
  .......
  
  Каждый из элементов в левой части должен быть вам уже понятен!
  Впечатляет, правда?
  А теперь давайте перейдём к декодеру.
  
  Декодер
  
  Большинство знаний, полученных при изучении кодировщиков,
  будет использоваться и в декодере!
  Декодер имеет два слоя самовнимания,
  один для кодировщика, другой для декодера.
  Также декодер имеет слой с прямой связью.
  Давайте разберём каждую из частей по порядку.
  
  Блок декодера получает два элемента входных данных:
  выходные данные кодировщика и сгенерированную выходную последовательность.
  Выходные данные кодировщика
  - это описание входной последовательности.
  В процессе инференса сгенерированная выходная последовательность
  начинается с особого токена начала последовательности
  (start-of-sequence token, SOS).
  Во время обучения целевая выходная последовательность
  - это действительная выходная последовательность,
  сдвинутая на одну позицию.
  Скоро это станет вам понятнее!
  
  Имея сгенерированный кодировщиком эмбеддинг и токен SOS,
  декодер генерирует следующий токен последовательности,
  то есть .
  Декодер авторегрессивен,
  то есть он берёт ранее сгенерированные токены
  и снова генерирует второй токен.
  
  Итерация 1: входные данные - SOS, выходные -
  
  Итерация 2: входные данные - SOS + , выходные -
  
  Итерация 3: входные данные - SOS + + , выходные - EOS
  
  Здесь SOS - это токен начала последовательности,
  а EOS - токен конца последовательности.
  После генерации токена EOS декодер прекращает работу.
  Он генерирует по одному токену за раз.
  Обратите внимание, что во всех итерациях используется эмбеддинг,
  сгенерированный кодировщиком.
  
  Примечание
  
  Такая авторегрессивная структура замедляет работу декодера.
  Кодировщик способен генерировать свой эмбеддинг за один прямой проход,
  а декодеру необходимо выполнить множество прямых проходов.
  Это одна из причин, по которым архитектуры,
  использующие один кодировщик
  (например, BERT или модели схожести предложений) гораздо быстрее,
  чем архитектуры с одними только декодерами
  (например, GPT-2 или BART).
  
  Давайте разберём каждый из этапов!
  Как и кодировщик, декодер состоит из стека блоков декодеров.
  Блок декодера чуть сложнее, чем блок кодировщика.
  Его общая структура такова:
  
  Слой самовнимания (маскированный)
  
  Остаточная связь и нормализация слоя
  
  Слой внимания кодировщика-декодера
  
  Остаточная связь и нормализация слоя
  
  Слой с прямой связью
  
  Остаточная связь и нормализация слоя
  
  Мы уже знакомы со всей математикой пунктов 1, 2, 3, 5 и 6.
  Взглянув на правую часть изображения ниже,
  вы увидите, что все эти блоки вам уже известны :
  
  Модель трансформера из статьи
  
  1. Эмбеддинг текста
  
  Первый текст декодера нужен для эмбеддинга входных токенов.
  Входным токеном является SOS,
  так что мы выполняем его эмбеддинг.
  Используется та же размерность эмбеддинга,
  что и для кодировщика.
  Предположим, вектор эмбеддинга для SOS имеет такой вид:
  
  ......
  
  2. Позиционное кодирование
  
  Теперь мы добавим в эмбеддинг позиционное кодирование,
  как делали это в случае с кодировщиком. Учитывая, что это так же позиция,
  что и у , у нас будет то же позиционное кодирование, что и раньше:
  
  i = 0 (чётный): PE(0,0) = sin(0 / 10000^(0 / 4)) = sin(0) = 0
  
  i = 1 (нечётный): PE(0,1) = cos(0 / 10000^(2*1 / 4)) = cos(0) = 1
  
  i = 2 (чётный): PE(0,2) = sin(0 / 10000^(2*2 / 4)) = sin(0) = 0
  
  i = 3 (нечётный): PE(0,3) = cos(0 / 10000^(2*3 / 4)) = cos(0) = 1
  
  3. Сложение позиционного кодирования и эмбеддинга
  
  Сложение позиционного кодирования с эмбеддингом выполняется
  сложением двух векторов:
  
  .......
  
  4. Самовнимание
  
  Первый этап в блоке декодера - это механизм самовнимания.
  К счастью, у нас есть для этого код и мы можем просто его использовать!
  
  ......
  
  Примечание
  
  С точки зрения инференса всё довольно просто,
  однако с точки зрения обучения есть сложности.
  При обучении мы используем неразмеченные данные:
  просто кучу текстовых данных,
  которые собираем частым скрейпингом в вебе.
  Цель кодировщика - передача всей информации входных данных,
  а задача декодера -предсказание следующего наиболее вероятного токена.
  Это значит, что декодер может использовать
  только ранее сгенерированные токены
  (он не может схитрить и посмотреть следующие токены).
  
  Из-за этого мы используем маскированное самовнимание:
  маскируем ещё не сгенерированные токены.
  Это выполняется присвоением показателям внимания значений -inf.
  Так делается в научной статье (раздел 3.2.3.1).
  Пока мы это пропустим,
  но важно помнить,
  что при обучении декодер чуть сложнее.
  
  5. Остаточные связи и нормализация слоёв
  
  Здесь нет ничего таинственного,
  мы просто складываем входные данные с выходными данными самовнимания
  и применяем нормализацию слоя.
  Используется тот же код, что и выше.
  
  .......
  
  6. Внимание кодировщика-декодера
  
  Эта часть новая!
  Если вы задавались вопросом,
  куда направляются генерируемые кодировщиком эмбеддинги,
  то сейчас самое время для них!
  
  Предположим, что выходными данными кодировщика является такая матрица:
  
  .....
  
  В механизме самовнимания мы вычисляем запросы, ключи и значения
  для входного эмбеддинга.
  
  Во внимании кодировщика-декодера мы вычисляем запросы
  из предыдущего слоя декодера и ключи и значения
  из выходных данных кодировщика!
  Все вычисления остаются такими же, что и раньше;
  единственное отличие в том,
  какой эмбеддинг использовать для запросов.
  Давайте взглянем на код
  
  ......
  
  Сработало! Возможно, вы зададитесь вопросом: <зачем мы это делаем?>.
  Дело в том, что мы хотим, чтобы декодер сосредоточился
  на релевантных частях входного текста (то есть ).
  Внимание кодировщика-декодера позволяет
  каждой позиции в декодере посетить все позиции входной последовательности.
  Это очень полезно для таких задач, как перевод,
  когда декодеру нужно сосредоточиться на релевантных частях
  входной последовательности.
  Декодер будет учиться сосредотачиваться на релевантных частях
  входной последовательности,
  учась генерировать правильные выходные токены.
  Это очень мощный механизм!
  
  7. Остаточные связи и нормализация слоя
  
  Всё то же, что и раньше!
  
  .......
  
  8. Слой с прямой связью
  
  И тут то же самое! После этого я также выполню остаточную связь
  и нормализацию слоя.
  
  .......
  
  9. Объединяем всё: произвольный декодер
  
  Давайте напишем код для одного блока декодера.
  Самое главное изменение заключается в том,
  что теперь у нас есть дополнительный механизм внимания.
  
  .......
  
  Генерация выходной последовательности
  
  У нас уже есть все необходимые части!
  Давайте сгенерируем выходную последовательность.
  
  У нас есть кодировщик, получающий входную последовательность
  и генерирующий его обогащённое описание.
  Он состоит из стека блоков кодировщиков.
  
  У нас есть декодер, получающий выходные данные кодировщика
  и сгенерированные токены
  и генерирующий выходную последовательность.
  Он состоит из стека блоков декодеров.
  
  Как перейти от выходных данных декодера к слову?
  Нужно добавить поверх декодера последний линейный слой и слой softmax.
  Весь алгоритм в целом выглядит так:
  
  Обработка кодировщиком:
  кодировщик получает входную последовательность
  и генерирует контекстуализированное описание всего предложения
  при помощи стека блоков кодировщиков.
  
  Инициализация декодера:
  процесс декодирования начинается с эмбеддинга токена SOS (Start of Sequence),
  соединённого с выходными данными кодировщика.
  
  Работа декодера:
  декодер использует выходные данные кодировщика
  и эмбеддинги всех ранее сгенерированных токенов
  для создания нового списка эмбеддингов.
  
  Линейный слой для логитов:
  линейный слой применяется к последнему выходному эмбеддингу декодера
  для генерации логитов,
  представляющих сырые предсказания следующего токена.
  
  Softmax для вероятностей:
  затем эти логиты передаются через слой softmax,
  преобразующий их в распределение вероятностей
  по потенциальным следующим токенам.
  
  Итеративная генерация токенов:
  этот процесс повторяется,
  и на каждом этапе декодер генерирует следующий токен
  на основании кумулятивных эмбеддингов
  ранее сгенерированных токенов
  и исходных выходных данных кодировщика.
  
  Формирование предложения:
  эти этапы генерации продолжаются,
  пока не будет создан токен EOS (End of Sequence)
  или не достигнута заранее заданная максимальная длина предложения.
  
  Об этом говорится в разделе 3.4 научной статьи.
  
  1. Линейный слой
  
  Линейный слой - это простое линейное преобразование.
  Он получает выходные данные декодера
  и преобразует их в вектор размера vocab_size.
  Это размер словаря.
  Например, если у нас есть словарь из 10000 слов,
  то линейный слой преобразовал бы выходные данные декодера
  в вектор размера 10000.
  Этот вектор содержал бы вероятность того,
  что каждое слово будет следующим словом в последовательности.
  Для простоты можно начать со словаря из 10 слов
  и предположить, что первые выходные данные декодера
  - это очень простой вектор: [1, 0, 1, 0].
  Мы используем произвольные веса и матрицы перекосов размера
  vocab_size x decoder_output_size.
  
  ......
  
  Примечание
  
  Что используется в качестве входных данных для линейного слоя?
  Декодер будет выводить по одному эмбеддингу
  для каждого токена в последовательности.
  Входными данными для линейного слоя станет
  последний сгенерированный эмбеддинг.
  Последний эмбеддинг включает в себя информацию
  для всей последовательности до этого этапа,
  то есть содержит всю информацию,
  необходимую для генерации следующего токена.
  Это значит, что каждый выходной эмбеддинг декодера
  содержит информацию о всей последовательности до этого этапа.
  
  2. Softmax
  
  Они называются логитами,
  но интерпретировать их не так просто.
  Для получения вероятностей можно применить функцию softmax.
  
  softmax(x)
  array([[0.01602618, 0.06261303, 0.38162024, 0.03087794, 0.0102383 ,
   0.00446011, 0.01777314, 0.00068275, 0.46780959, 0.00789871]])
  
  И так мы получили вероятности!
  //// Точнее мы получили вектор эмбеддинга, который автор интерпретирует
  //// как распределение вероятностей. Но так ли это на самом деле?
  Предположим, словарь имеет такой вид:
  
  .....
  
  Мы видим, что вероятности таковы:
  
  hello: 0.01602618
  
  mundo: 0.06261303
  
  world: 0.38162024
  
  how: 0.03087794
  
  ?: 0.0102383
  
  EOS: 0.00446011
  
  SOS: 0.01777314
  
  a: 0.00068275
  
  hola: 0.46780959
  
  c: 0.00789871
  
  Из этого видно, что наиболее вероятный следующий токен - это .
  Если всегда выбирается наиболее вероятный токен,
  это называется жадным декодингом.
  Это не всегда наилучший подход,
  потому что он может привести к субоптимальным результатам,
  //// Т.е. версия "вероятностей" не совсем работоспособна,
  //// но от этой мысли отмахиваются разными ссылками, типа "субоптимальности".
  но пока мы не будем сейчас углубляться в методики генерации.
  Если хотите узнать о них подробнее,
  то прочитайте потрясающий пост.
  
  3. Случайный трансформер из кодировщика и декодера
  
  Давайте напишем код целиком.
  Зададим словарь, сопоставляющий слова с их изначальными эмбеддингами.
  Надо отменить, что это тоже изучается при обучении,
  но пока мы используем случайные значения.
  
  ........
  
  А теперь напишем произвольный метод generate ,
  авторегрессивно генерирующий токены.
  
  .......
  
  Давайте запустим код!
  
  ......
  
  Отлично, теперь у нас есть токены , и .
  Это неправильный перевод, но этого вполне можно было ожидать,
  ведь веса мы использовали случайные.
  
  Советую ещё раз подробно изучить всю архитектуру кодировщика-декодера
  из научной статьи:
  
  ......
  
  Заключение
  
  Надеюсь, пост показался вам интересным и информативным!
  Мы рассмотрели множество аспектов.
  Но разве это всё?
  На самом деле, практически да!
  В архитектуры новых трансформеров добавляют множество трюков,
  но фундамент трансформера именно таков,
  каким мы его описали.
  В зависимости от задачи также можно использовать
  только кодировщик или декодер.
  Например, в задачах, требующих понимания,
  например, в классификации,
  можно использовать стек кодировщиков с линейным слоем поверх него.
  Для задач, требующих генерации,
  например, в переводе,
  можно использовать стеки кодировщиков и декодеров.
  А для свободной генерации, например, как в ChatGPT или Mistral,
  можно применять только стек декодеров.
  
  Разумеется, мы многое упростили.
  Давайте вкратце проверим, какие были числа в научной статье о трансформере:
  
  Размерность эмбеддингов: 512 (в нашем примере 4)
  
  Количество кодировщиков: 6 (в нашем примере 6)
  
  Количество декодеров: 6 (в нашем примере 6)
  
  Размерность прямой связи: 2048 (в нашем примере 8)
  
  Количество голов внимания: 8 (в нашем примере 2)
  
  Размерность внимания: 64 (в нашем примере 3)
  
  Мы рассмотрели множество тем, но довольно интересно,
  то мы можем достичь впечатляющих результатов,
  увеличив масштабы этих вычислений и проведя умное обучение.
  Мы не рассмотрели в посте обучение,
  потому что наша цель заключалась в понимании вычислений
  при использовании готовой модели,
  но я надеюсь, что это станет надёжным фундаментом для перехода к обучению!
  
  Также можно найти более формальный документ с вычислениями в этом PDF.
  https://johnthickstun.com/docs/transformers.pdf
  
  Упражнения
  Вот несколько упражнений, чтобы попрактиковаться в понимании трансформера.
  
  В чём предназначение позиционного кодирования?
  
  Чем отличаются самовнимание и внимание кодировщика-декодера?
  
  Что произойдёт, если размерность внимания слишком мала? А если слишком велика?
  
  Вкратце опишите структуру слоя с прямой связью.
  
  Почему декодер медленнее кодировщика?
  
  Какова цель остаточных связей и нормализации слоёв?
  
  Как выполняется переход от выходных данных декодера к вероятностям?
  
  Почему выбор каждый раз самого вероятного следующего токена
  может вызвать проблемы?
  
  Ресурсы
  
  The Illustrated Transformer [перевод на Хабре]
  https://habr.com/ru/articles/486358/
  
  Attention is all you need [перевод на Хабре: первая и вторая части]
  https://habr.com/ru/companies/ruvds/articles/723538/
  https://habr.com/ru/companies/ruvds/articles/725618/
  
  The Annotated Transformer
  
  Hugging Face free NLP course
  
  ......
  
  //// Из комментариев.
  
  Kreastr
  1 час назад
  
  Эмбеддинг это словарь переводящий слова/токены в вектора.
  Сам словарь составляется на отдельном этапе обучения.
  ЕМНИП принцип составления
  - задать такие значения многомерных векторов,
  чтобы для любой пары слов векторное произведение
  максимально хорошо коррелировало
  с вероятностью встретить их рядом в одном предложении
  в исходном корпусе текстов.
  //// А что происходит при добавлении позиционного кодирования
  //// так, как это описано в данном материале?
  //// Ведь таким образом эта корреляция прямо разрушается.
  0
  
  johnfound
  21 минуту назад
  
  А зачем тогда нужны токены?
  Можно сразу по словарю преобразовать в эмбединги.
  Ведь, они однозначно идентифицируют токен.
  
  Kreastr
  19 янв в 14:39
  
  Токен не всегда равен слову.
  В ранних системах токенами были слова больше минимальной длины
  и с обрезанными формами (падежами, лицами и временами смотря какой язык).
  Сейчас вроде как токенайзеры делят на группы букв сами.
  То есть отдельно токен приблизительно равный корню, отдельно окончания.
  Но может и приставку отделить и суффикс.
  Там нет четкой цели, чтобы оно совпало с грамматической интерпретацией.
  
  johnfound
  19 янв в 16:33
  
  Я имел ввиду, что если из токена однозначно получается эмбединг
  и наоборот из эмбединга однозначно получается токен,
  то сам токен не нужен.
  Можно из текста сразу получать эмбединги.
  
  Kreastr
  19 янв в 17:13
  
  Вообще не однозначно.
  Разные схемы токенизации дают разные разбиения на токены с разными свойствами.
  Разные способы расчета и размерности матриц эмбеддингов
  дают еще один слой для оптимизаций.
  То, что в примере из it is student получается три вектора
  причем каждое слово дает ровно один вектор
  - просто упрощение процесса.
  Так делали раньше.
  Но сейчас есть более эффективные подходы к токенизации и эмбеддингам,
  поэтому слова уже почти никогда не то же, что и токен,
  но объяснить проще, когда слово принимается за токен.
  
  ........
  
  //// Конец цитирования.
  
  17.02.2024 23:38
  
  Ну как лучше Вы стали понимать как работает в частности трансформер,
  и в целом ГПТэшка? Думаю, что не очень. Слишком много непонятных слов,
  и не смотря на "победный пафос" материала, есть ощущение,
  что что-то главное в объяснении каких-то ключевых, но неозвученных вопросов
  осталось где-то "за кадром".
  Если, конечно, такие объяснения на сегодняшний день вообще существуют.
  Какие-то детали, да, понятны, а вот какого-то общего понимания
  что происходит на тех же элементах суммирования, матричного умножения,
  и магической функции softmax, вот у меня почему-то не складывается.
  И самый главный вопрос почему это все-таки как-то работает
  остается без ответа.
  
  Именно поэтому и приходится раскапывать принципы работы нейросетей,
  опираясь на что-то другое, чем даже такое подробное описание.
  Такие описания могут ответить только на вопрос "как",
  но для вопросов "почему" и, тем более, "зачем",
  большей частью малопродуктивны.
  
  для того чтобы получить что-то похожее на уже работающую схему,
  с минимальной правкой кода такие материалы, безусловно, полезны.
  Ведь это действительно хороший, добротный, проработанный материал,
  и за это и автору и переводчику большое спасибо.
  Проблема недостаточного понимания процессов происходящих в нейросети,
  это "болячка" не одного этого текста, а, скорее всего,
  всей современной "нейронауки".
  
  И чтобы придумать что-то новое нужно искать и в таких материалах и где-то еще.
  И, самое главное, включать "режим" самостоятельного поиска понимания,
  тех вопросов, о которых "стыдливо умалчивают" либо "отделываются общими фразами".
  У меня, во всяком случае, этот текст особенно в той части,
  где описывается способ позиционного кодирования, используемый в трансфомере,
  привел к очень интересной дискуссии на эту тему с Bing,
  и в итоге родился достаточно интересный, для мнея, фрагмент, см.:
  "Заковыристая" структура вектора эмбеддинга."
  с последующим переосмыслением подходов к пониманию "пространства эмбеддингов".
  
  Желаю и Вам найти свое собственное представление/понимание
  и вектора эмбеддинга и пространства эмбеддингов.
  "И да пребудет с Вами Сила!"
  
  
  ========
  
  24.02.2024 10:50
  
  Структура сети ViT.
  В оглавление.
  
  Обычно объяснения того, как работают трансформеры,
  предлагаются на основе рассмотрения их классической архитектуры.
  И таких примеров/материалов даже в рамках этого проекта достаточно много,
  например, см.:
  "Трансформеры простыми словами."
  Очень большая и хорошая статья Стефена Вольфрама.
  Интересные и понятные ссылки о том, что у ГПТэшек "под капотом".
  
  Но могу судить по себе, что это не закрывает всех возникающих вопросов.
  Полного интуитивного понимания как же все-таки это работает "под капотом",
  даже после проработки всех этих материалов, как-то не сформировалось.
  
  Поэтому попробуем подступиться к этой достаточно сложной для понимания темы,
  как работают трансформеры немного с другой стороны.
  А именно, как используют структуру трансформеров для других задач,
  не только обработки текстов, но изображений.
  Что при этом изменяется, что становится не актуальным, ну и т.д.
  Может быть, это что-то прояснит в понимании основных идей трансформеров
  или даст какую-то новую "пищу для размышлений":
  
  "ViT - на кухне фаворит".
  Автор: 19blackadder97 (Денис Кузнеделев)
  https://habr.com/ru/articles/599677/.
  8 янв 2022 в 18:13
  
  //// Начало цитирования
  
  Прошедший 2021-й год ознаменовался настоящей революцией
  в области компьютерного зрения.
  
  Трансформеры, подобно новым штамма Ковида,
  вытеснившие конкурентов в области обработки естественного языка (NLP)
  и задачах, связанных с обработкой звука,
  добрались и до компьютерного зрения.
  
  Сверточные сети, чье место на Олимпе в различных бенчмарках компьютерного зрения
  и первые места в топах на PapersWithCode казались незыблемы
  (в том смысле, что против лома нет приема, если нет другого лома)
  были сброшены с них рядом архитектур
  частично или полностью основанных на механизме внимания.
  
  В данном обзоре я хотел бы рассказать о нескольких самых ярких прорывах и идеях
  в совершенствовании архитектур и обучении ViT-ов (Visual Transformers).
  
  Введение
  
  До сравнительно недавнего (если смотреть не по меркам DL) времени
  сверточные сети (CNN) безраздельно доминировали
  в области компьютерного зрения (Computer Vision).
  Сверки обладают рядом замечательных свойств
  - локальностью , позволяющей учитывать отношения близости между соседними пикселями,
  применением одних и тех же весов к каждому пикселю карты активации (feature map),
  построением иерархических представлений
  - от простых примитивов вроде границ и контуров до более сложных и составных понятий
  вроде кошек и собак
  (во всяком случае, так утверждается многими).
  
  Казалось бы, что можно вообще было бы придумать более подходящее и оптимальное
  с точки зрения использования параметров и вычислений
  среди возможных архитектур нейронной сети?
  Тем более, что за последние несколько лет было придумано
  множество наворотов и ухищрений для повышения качества сверточной нейронной сети,
  либо скорости работы.
  
  В качестве самых значимых достижений можно вспомнить
  добавление разных видов skip-connections, depthwise сверток, inverted bottlenecks.
  Современные архитектуры вроде EfficientNet, NFNet
  прошли большой путь эволюции по сравнению с vanilla ResNetа-ми.
  
  Но все же, сверточные сети несовершенны.
  Локальность операции свертки, преподнесенная выше как достоинство,
  является и недостатком.
  Пиксель в выходной карте активаций может зависеть
  лишь от области входной карты в пределах ядра свертки.
  Поэтому для сбора глобальной информации требуется большое количество слоев
  (при пулингах и свертках стандартного размера типа 2,3,5).
  
  Но статья Attention is all you need получила свое название не просто так,
  и название оказалось даже более глубокомысленным
  чем, полагаю, даже исходно полагали сами авторы.
  
  Трансформеры произвели настоящий фурор
  в области задач (NLP) обработки естественного языка,
  камня на камне не оставив от популярных ранее
  многослойных реккурентных сетей на LSTM и GRU,
  и вообще в задачах связанных с последовательностями.
  
  Но как применить self-attention в задачах компьютерного зрения
  стало очевидно далеко не сразу.
  Первое, что могло бы прийти в голову
  - рассматривать каждый пиксель картинки, как слово,
  и считать attention между всеми пикселями внутри картинки.
  Проблема здесь в том, что вычислительная сложность и обьем используемой памяти
  в стандартном self-attention
  растет квадратично с длиной последовательности.
  Картинки на датасете больше игрушечных MNIST и CIFAR-10
  имеют разрешение порядка сотен пикселей вдоль каждой размерности
  (скажем 224x224)
  и считать в лоб self-attention выходит слишкои накладно.
  
  Были работы, которые считали его локально,
  но такой подход в каком-то смысле сродни сверткам.
  В DETR было предложено использовать feature map с нижнего слоя ResNet,
  где количество пикселей уже невелико, для self-attention
  //// Т.е. чисто трансформерная архитектура имеет ограничение
  //// на размерность "входного эмбеддинга"
  //// и имеет смысл его как-то предварительно "сжать".
  //// Вопрос в том, за счет чего должно происходить это "сжатие",
  //// и что остается в "сжатом эмбеддинге".
  и полученная конструкция сработала довольно неплохо в задаче детекции.
  Но в этих решениях основной рабочей лошадкой не был механизм внимания.
  
  An image is worth 16x16 words
  
  Настоящий триумф трансформеров в компьютерном зрении пришел с работой
  An image is worth 16x16 words.
  https://arxiv.org/abs/2010.11929
  
  Решение, позволившее добиться адекватной вычислительной стоимости и памяти
  для хранения, оказалось гениальным в своей простоте
  - использовать в качестве слов не отдельные пиксели,
  а кусочки картинки некоторого размера P \times P,
  тем самым уменьшив вычислительную сложность с \mathcal{O}((H W)^2)
  до \mathcal{O}((H W / P^2)^2).
  Для стандартного разрешения на ImageNet - 224
  и патча размера 16 выходит вполне себе подьемно (196 токенов).
  //// Т.е. кусочки картинки стали токенами, или элементами эмбеддинга?
  
  Рис. (Слева) Принцип работы ViT. (Справа) Блок трансформера в ViT.
  
  Использованная архитектура является по существу цепочкой энкодеров а-ля BERT.
  
  Для задачи классификации в дополнение к токенам,
  соответствующим отдельным патчам, добавляется дополнительный [CLS] токен
  для классификации.
  
  Рис. SOTA на ImageNet на момент публикации статьи
  
  На момент публикации самая большая версия полученной архитектуры
  - ViT-H/14 (H - Huge) установила новый
  SOTA (state-of-the-art)
  на ImageNet-1k.
  Здесь, правда, нужно отметить важный нюанс
  - для достижения такого высокого качества необходимо обучение
  на огромном количестве данных.
  В распоряжении исследователей Google был датасет JFT-300M.
  Без предобучения на большом количестве данных,
  даже с сильной регуляризацией (weight_decay = 0.1)
  модель подвержена переобучению и работает заметно хуже ResNet-ов.
  //// Интересное замечание в том смысле,
  //// что обучение трансформеров "кусочкам картинки" много труднее,
  //// чем обучение той же сверточной сети.
  //// Но, вообще, сама оценка скорости обучения как критерий соответствия
  //// выбранной структуры нейросети поставленной задаче,
  //// тоже, наверно, имеет смысл.
  //// А пока "завяжем узелок на память", что для трансформеров,
  //// при обучении "в лоб", "кусочки картинки" более трудны для "понимания",
  //// "чем фрагменты текстов.
  
  Рис. Качество на ImageNet-1k в зависимости от датасета,
  на котором проходило предобучение.
  BiT - модификация ResNet.
  
  DeiT (Data-Efficient Image Transformer)
  
  Тот же ViT, но лучше.
  
  Рис. Кривые Парето для разных моделей на ImageNet.
  По оси пропускная способность V100 по количеству картинок в секунду.
  
  Необходимость предобучения на громадном количестве картинок
  могла бы ограничить применимость трансформеров в компьютерном зрении,
  но вскоре после вышеупомянутой работы вышла статья
  Training data-efficient image transformers & distillation through attention.
  https://arxiv.org/abs/2012.12877
  
  Так как основной проблемой трансформеров в исходной постановке
  является подверженность переобучению,
  //// Т.е. чтобы обучить трансформер "картинкам" требуется длительное обучение,
  //// но длительное обучение приводит к "переобучению".
  //// Противоречие.
  //// Типичная ситуация "хрупкого баланса".
  то естественно было бы предложить более совершенную процедуру регуляризации,
  и аугментация является признанным и эффективным средством
  для эффективного увеличения размера данных и борьбы с переобучением.
  Вопрос в том - достаточно ли хороша она?
  //// Т.е. решать противоречие не стали, а попытались облегчить проблему
  //// "признанными и эффективными средствами" "допиливания напильником".
  //// А, проблема, наверно, все-таки в том,
  //// чтобы понять что нужно ПРИНЦИПИАЛЬНО изменить либо в подходе/пониманию
  //// обучения трансформеров, либо в природе возникновения
  //// и/или преодоления самого "переобучения".
  //// Но для принципиальных решений нужна хоть какая-то теория/гипотеза,
  //// а за неименением таковой,
  //// применяются "признанные полушаманские/полуэвристические приемы".
  
  В статье авторы использовали мощный набор аугментаций
  и регуляризационных процедур:
  
  Label smoothing.
  Правильной метке дается вероятность 1-\varepsilon,
  а остальная вероятность \varepsilon
  распределяется равномерно между остальными классами.
  
  Rand Augment.
  Выбирается некоторое множество преобразований,
  из которых случайным образом для каждого примера
  применяется какое-то количество из них с некоторой вероятностью и параметрами.
  
  Stochastic Depth.
  Так как в трансформерах есть skip-connections
  с некоторой вероятностью можно проигнорировать выход блока энкодера
  и подать просто выход прошлого слоя вперед.
  
  Mixup и CutMix.
  Mixup смешивает две картинки
  и соответствующие им целевые метки в классификации.
  CutMix вставляет уменьшенную версию одной картинки поверх другой
  и целевая метка классификации берется как смесь меток для каждого класса,
  причем доля класса пропорциональна занимаемой площади.
  
  Repeated Augmentation.
  Прогонять через аугментации можно не только лишь один,
  но и большее количество раз.
  
  Erasing.
  Из картинки вырезается некоторая область случайным образом.
  
  Авторы провели основательный анализ важности тех или иных аугментаций
  для достижения хорошего качества классификации.
  
  Рис. Ablation study для разных способов аугментации картинок из ImageNet.
  
  Другим решением, дополнительно повысившим качество модели была дистилляция
  (knowledge distillation).
  Вкратце напомню, что идея дистилляции в том,
  чтобы кроме ground_truth меток подавать еще предсказания модели (учителя),
  хорошо обученной на рассматриваемом наборе данных.
  //// Вообще, "прием дистилляции" требует отдельного рассмотрения,
  //// так как фактически модель в значительной мере учится уже
  //// не на чистых исходных данных,
  //// а на смеси с какими-то уже "переработанными" представлениями.
  //// Так, записываем в раздел "to do".
  
  Если в функцию потерь подаются вероятности (или логиты)
  то мы имеем дело с soft-distillation:
  
  \mathcal{L} = (1 - \lambda) \mathcal{L}_{CE} (y_{pred},y_{true} ) + \lambda \tau^{2} D_{KL} (y_{pred} / \tau, y_{teacher} / \tau)
  
  Здесь \lambda определяет вес лосса учителя (D_{KL} (:, :)
  - дивергенции Кульбака-Лейблера) по сравнению с кроссэнтропией
  между предсказанием и истинной меткой,
  а температура \tau - регулирует уверенность моделей в предсказании.
  
  Если же подается предсказанный учителем класс (он может быть и ошибочным),
  то это hard-distillation.
  
  \mathcal{L} = \frac{1}{2}\mathcal{L}_{CE} (y_{pred}, y_{true}) + \frac{1}{2} \mathcal{L}_{CE} (y_{pred}, y_{teacher})
  
  Что занятно (и мне непонятно), второй способ сработал лучше.
  //// Действительно, забавно.
  //// Если считать, что понимание, того как проходит обучение, верное.
  //// А вот если это не так, то это информация к размышлению.
  
  Рис. Сравнение различных моделей дистиляции для DeiT
  
  В качестве учителя лучше всего себя показали RegNet-ы (сверточные сети),
  лучше, чем более крупная модель трансформера.
  По всей видимости, так как сверточные сети и трансформеры
  имеют различный способ построения признаков,
  то знание, переданное от CNN более ново и полезно,
  чем просто от более мощной модели той же структуры.
  //// Интересная гипотеза. Стоит запомнить. И поискать под нее материал.
  //// Кстати, есть интуитивное ощущение, что эта гипотеза коррелирует
  //// с наблюдениями о том, что нейросети лучше работают,
  //// если они работают не "с нуля",
  //// а отталкиваясь от какого-то предварительно вычисленной оценки.
  //// Может быть, и в отношении обучения нейросетей работает нечто похожее.
  
  С точки зрения архитектуры - DeiT ничем не отличается от ViT.
  
  PVT (Pyramid Vision Transformer)
  
  Интересное решение, позволившее использовать более мелкие патчи
  было предложено в статье
  Pyramid Vision Transformer: A Versatile Backbone for Dense Prediction without Convolutions.
  https://arxiv.org/abs/2102.12122
  
  Рис. Слева) Извлечение пирамиды признаков в типичных CNN
  (Центр) ViT не обладает иерархией признаков
  (Справа) Извлечение пирамиды признаков в PS-ViT
  
  FPN (Feature Pyramid Network) и различные ее вариации
  довольно неплохо зарекомендовала себя в задачах сегментации и детекции.
  Признаки с верхних слоев фокусируются на извлечении мелких деталей и примитивов,
  в то время как более глубокие слои имеют представление о глобальной семантике.
  Использование признаков с разных слоев позволяет
  одновременно учитывать мелкие и крупные детали.
  В vanilla ViT все feature maps имеют один и тот же размер,
  поэтому нет разделения на мелкие и крупные признаки.
  Кроме того, крупные патчи не обеспечивают достаточного разрешения
  для разрешения мелких деталей.
  
  Рис. Архитектура PVT. На каждой стадии разрешение feature map уменьшается вдвое.
  Красный бледный прямоугольник (Spatial Reduction)
  - одна из основных наработок статьи
  
  В PVT было предложено использовать патчи размера 4x4 на первой стадии
  и затем последовательно уменьшать разрешение.
  На каждой стадии разрешение уменьшается вдвое с помощью strided свертки
  с увеличением размерности вектора embedding.
  
  Тем не менее, на первых слоях при размере патча 4x4
  все еще остается слишком много операций.
  Для того, чтобы уменьшить расход памяти на верхних слоях
  авторы предложили уменьшать длину последовательностей key и value.
  //// А как это повлияло на качество?
  //// К сожалению, в таких материалах слишком большой упор делается
  //// на усилия по обеспечению меньших затрат памяти и вычислительных ресурсов,
  //// по сравнению с усилиями на обеспечение понимания того,
  //// что, как и почему при этом происходит.
  //// И почему это никого, в том числе и меня самого, уже не удивляет?
  
  Сложность вычисления произведения Q K^T
  пропорциональна произведению длин последовательностей key - L_Kи query L_Q.
  Полученная матрица имеет размер L_Q \times L_K.
  Если последовательность value имеет ту же длину, что и ключи,
  то возможно умножить матрицу внимания \mathrm{softmax}(Q K^T/\sqrt{d}) на Vи
  выход будет иметь ту же длину, что и query.
  
  Уменьшение длины последовательностей key и query достигается следующим образом.
  Пусть H_iи W_i- количество патчей вдоль каждой из осей (высоты и ширины)
  а C_i размерность эмбеддинга на i- й стадии. Тогда:
  
  Входная последовательность длины H_i \cdot W_i
  и размерности эмбеддинга C_i решейпится (звучит ужасно, знаю)
  в последовательность длины H_i W_i / R_i^2
  c размерностью эмбеддинга R_i^2 C_i.
  
  Слой nn.Linear(R_i ** 2 * C_i, C_i) уменьшает размерность эмбеддинга
  до исходной (проектирует на подпространство).
  
  Рис. Схема работы Attention с Spatial Reduction
  
  После этого поступаем точно так же, как и в стандартном self-attention.
  В итоге получается экономия в R_i^2в вычислительной сложности и памяти.
  
  Данная модификация, несомненно, ограничивает выразительности сети,
  //// На сколько?
  но выбор архитектуры - почти всегда баланс между качеством и скоростью (размером).
  
  В первых слоях фактор R_i довольно большой - 8,
  и уменьшается вдвое на каждой следующей стадии.
  На самой последней стадии R_i = 1.
  Кроме того, патч размера 2x2 c feature map с прошлой стадии
  используется в качестве пикселя (элементарной ячейки карты активации)
  на следующей стадии.
  
  Рис. Разные версии моделей PVT.
  
  Наличие карт активации разного размера позволяет применить идею
  Feature Pyramid в PVT.
  
  Полученная модель неплохо себя показывает на ImageNet.
  
  Рис. PVT против других (порошков) моделей
  
  Но по-настоящему польза от PVT становится заметной на детекции и сегментации.
  
  Рис. Сравнение детекции + сегментации на MS COCO (val 2017)
  с использованием Mask R-CNN головы.
  
  Рис. Семантическая сегментация на ADE20K.
  Сравнение проводится по метрике mIoU (mean Intersection over Union)
  
  Swin (Hierarchical Vision Transformer using Shifted Windows)
  
  Рис. Дементий, тащи свиней!
  
  Основной проблемой при использовании ViT, особенно в Dense Prediction tasks
  - детекции и сегментации,
  является быстрый рост сложности с уменьшением размера патча.
  Патч размера 16x16 выходит слишком грубоватым для извлечения тонких деталей.
  
  В статье Swin Transformer: Hierarchical Vision Transformer using Shifted Windows
  https://arxiv.org/abs/2103.14030
  был предложен изящный способ уменьшить вычислительную сложность для feature map
  с большим количеством патчей.
  Как и PVT, подход в Swin мотивирован пирамидой признаков из CNN.
  Карта признаков на верхнем уровне составлена из мелких патчей
  (более конкретно, размера 4x4)
  и через некоторое количество слоев пространственная размерность
  уменьшается вдвое вдоль каждой оси
  (происходит слияние соседних патчей),
  а размерность эмбеддинга удваивается.
  
  Но способ "удешевления" attention в верхних слоях другой.
  В верхних слоях attention считается только в пределах окна некоторого размера,
  причем количество токенов в окне постоянно во всех слоях сети.
  То есть, если на нижней стадии размер патча P
  и attention захватывает для каждого токена все остальные токены,
  то на предыдущей стадии с размером патча P/2
  attention локализован лишь на четверти входной картинки,
  а слое еще ниже (где патчи имеют размер P/4 на 1/16 картинки.
  Благодаря этому становится возможным использование мелких патчей.
  
  Сравним вычислительную сложность windowed self-attention
  c глобальным self-attention.
  Пусть ширина и высота feature map на данном слое - H и W, соответственно.
  Тогда при использовании окон, захватывающих области высотой H/R и шириной W/R
  потребуется R^2 вычислять self-attention для каждого из окон.
  Но так как вычислительная сложность операции внимания
  растет квадратично с длиной последовательности,
  то в силу R \cdot O((H W / R^2)^2) = O((H W)^2) / R^2
  имеем в конечном итоге выигрыш в R^2 раз по сравнению с исходной операцией.
  
  Рис. Последовательное слияние патчей и увеличение размера окон для attention
  
  Но при таком подходе токены из соседних окон не взаимодействуют друг с другом,
  что ограничивает выразительную способность сети.
  Взаимодействие с соседями реализовано в Swin следующим образом:
  
  на четных слоях разбиваем на патчи одним способом
  (так чтобы верхний левый угол верхнего левого патча совпал
  с верхним левым углом всей картинки)
  
  на нечетных шагах сдвигаем разбиение на половину размера патча в данном слое
  
  Рис. Окна в Swin в двух последовательных блоках трансформера
  
  В остальном блоки трансформера в Swin повторяют ViT.
  Вычисление двух последовательных блоков в Swin имеет следующий вид:
  
  \begin{aligned} \hat{z}^{l} &= \mathrm{W-MSA}(\mathrm{LN} (z^{l})) + z^{l} \\ z^{l} &= \mathrm{MLP} (z^{l}) + \hat{z}^l \\ \hat{z}^{l+1} &= \mathrm{SW-MSA}(\mathrm{LN}(z^{l})) + z^{l} \\ z^{l+1} &= \mathrm{MLP}(\hat{z}^{l+1}) + \hat{z}^{l+1} \end{aligned}
  
  В итоге получился очень сильный бэкбоун для задачи классификации
  и Dense predictions tasks (детекции, сегментации).
  
  Рис. Сравнение моделей на ImageNet-1k
  (без использования дополнительных данных)
  
  При сопоставимом количестве операций с плавающей точкой
  модели Swin значительно превосходят ViT и DeiT
  (но все же уступают наиболее совершенным CNN вроде EfficientNet).
  
  Стандартные фреймворки детекции и сегментации состоят из backbone,
  который строит признаки и новое представление объекта,
  и головы (head) для детекции и сегментации.
  Для того, чтобы сравнить качество извлекамых с помощью Swin признаков
  авторы статьи обучили модели с Cascade Mask R-CNN
  (голова для одновременной детекции и сегментации) на MS COCO.
  
  Модели Swin заметно превзошли бейзлайны на основе ResNet-ов и DeiT
  с сопоставимыми характеристиками
  (числом параметров и операций)
  как в детекции, так и сегментации.
  
  Рис. Сравнение Swin-T и ResNet50 в качестве бэкбоуна
  для детекции с помощью Cascade MASK R-CNN.
  Сравнение метрик AP проводится на датасете MS COCO.
  
  Рис. Сравнение метрики mIoU (mean Intersection over Union)
  для сегментации на ADE20K.
  
  Использование shifted windows, как показывает ablation study,
  действительно важно для достижения хорошего результата,
  особенно для детекции и сегментации.
  
  Рис. Ablation study для испозования shifted windows.
  Сверху - без сдвига окон, снизу - со сдвигом окон.
  
  XCiT (Cross-Covariance Image Transformers)
  
  Еще один подход побороть квадратичную зависимость от количества патчей
  был предложен в статье XCiT: Cross-Covariance Image Transformers
  https://arxiv.org/abs/2106.09681
  от исследователей из Фейсбука (ныне Мета).
  
  Идея состоит в том, чтобы транспонировать операцию attention.
  //// Вот этого не понял.
  
  В исходной операции self-attention c hголовами:
  
  \mathrm{Attention} (Q, K, V) = \mathrm{softmax} (Q K^T / \sqrt{d}) V
  
  Сложность вычисления - O(d N^2), а расход по памяти O(h N^2 + N d).
  
  Для транспонированного внимания
  (называемого в статье cross-covariance)
  операция имеет следующий вид:
  
  \mathrm{XC-Attention}(Q, K, V) = V \mathrm{softmax} \ (K Q^T/ \tau)
  
  где \tau - некоторый параметр температуры.
  Квадратичная сложность переносится с длины последовательности
  на размерность эмбеддинга.
  Для cross-attention вычислительная сложность O(N d^2/h)
  и расход памяти - O(d^2/h + Nd).
  Поэтому вычислительная сложность для XCiT будет расти не так быстро,
  как для ViT, с уменьшением размера патчей или увеличением разрешения.
  
  Рис. XCA (Cross-covariance) блок в XCiT
  и различие между Self-Attention и Cross-Covariance Attention
  
  XC-attention, как и Self-attention,
  позволяет агрегировать глобальный контекст.
  Но агрегация происходит несколько в менее явной форме,
  через свертку по внутренней размерности в вычислении K Q^T.
  
  Для того, чтобы иметь явное взаимодействие между соседними патчами,
  авторы добавили так называемое локальное взаимодействие патчей
  (Local Patch Interaction).
  В качестве LPI используется последовательность двух depthwise сверток
  3 \times 3с батч-нормализацией и GeLU между ними.
  Последовательность токенов перед LPI разворачивается в 2d картинку,
  к этой картинке применяется описанная выше последовательность слоев,
  и картинка сворачивается обратно в последовательность токенов.
  
  Приятным бонусом от XC-attention является меньшая чувствительность
  к изменению разрешения подаваемой картинки.
  Так как свертка при вычислении XC-attention проводится вдоль внутренней оси,
  размер матрицы внимания не меняется.
  Качество модели, обученной на разрешении 224 \times 224
  проседает не так сильно при уменьшении разрешения,
  по сравнению с ResNet и DeiT,
  и даже заметно возрастает при увеличении разрешения до 288 \times 288.
  
  Рис. XCiT более устойчив к изменению разрешения входной картинки.
  
  Бэкбоун получился очень даже замечательным.
  При сопоставимых размерах различные варианты XCiT оказываются эффективнее
  не только EfficientNet-ов и ранних ViT,
  но и сильных конкурентов вроде Swin-ов.
  
  Рис. Сравнение различных моделей классификации на ImageNet
  cо сравнимыми характеристиками.
  
  В задаче детекции и сегментации XCiT показал себя с хорошей стороны,
  превзойдя бэкбоуны на основе PVT и ViL (не затронутого в данном обзоре).
  XCiT-S12/8 превзошел даже Swin-T с похожими характеристиками,
  но более крупный свин таки подложил свинью в сравнении с XCiT-S24/8.
  
  Рис. Сравнение разных моделей с MASK-RCNN головой на MS COCO
  в задаче детекции (сравнение проводится по AP^b)
  и instance сегментации (сравнение по AP^m).
  
  PS-ViT (Pooling and Attention Sharing)
  
  Рис. Нет, это совершенно здесь не при чем
  
  В сверточных сетях обыкновенно карты признаков на верхних слоях
  обладают большим разрешением,
  и постепенно посредством pooling или strided-сверток
  разрешение уменьшается с увеличением числа каналов.
  Таким образом, производится переход от локальных признаков
  к глобальным представлениям.
  
  Разумно предположить, что аналогичный подход может хорошо сработать
  и для visual трансформеров.
  
  И в работе Better Vision Transformer via Token Pooling and Attention Sharing
  https://arxiv.org/abs/2108.03428
  была предложена архитектура такая архитектура,
  давшая существенный прирост качества на ImageNet по сравнению с DeiT
  при том же числе операций (6.6% для PSViT-2D-Tiny по сравнению с DeiT-Tiny).
  
  В качестве основных результатов данной статьи следует отметить:
  
  Механизм уменьшения количества токенов с увеличением глубины сети
  
  Переиспользование одного и того же attention
  в нескольких последовательных блоках трансформера
  
  Рис. Структура PS-ViT. После каждого блока количество токенов уменьшается вдвое.
  
  Pooling в PS-ViT
  
  В статье авторы рассматривают разные стратегии модификации архитектуры
  (взяв за основу DeiT-Tiny)
  и сохраняя примерно то же количество FLOPs.
  
  Увеличение глубины сети (количества блоков)
  при сохранении размерности эмбеддинга неизменной
  
  Увеличение размерности эмбеддинга при том же количестве блоков
  
  И то, и то сработало достаточно неплохо,
  но увеличение ширины несколько лучше.
  Кроме того, авторы рассматривают два варианта пулинга.
  
  В первом случае, где классификация осуществляется через [CLS] токен,
  свертка 1x1 меняет размерность эмбеддинга,
  а затем проводится MaxPooling.
  Эта стратегия называется PSViT-1D.
  
  В другом случае для классификации используется
  результат усреднения последней карты активации
  и для пулинга strided свертка с шагом 2.
  Этот подход, называемый PSViT-2D, работает даже немного лучше.
  
  Рис. Сравнение глубокой и широкой сети по сравнению с исходным DeiT
  
  Вторым важным наблюдением является то,
  что карты внимания (attention map) в соседних слоях
  сильно скоррелированы друг с другом.
  Так как вычисление attention является дорогостоящим по числу параметров и операций,
  переиспользование его в следующем слое дает серьезную экономию.
  //// Опять интересный момент. Но опять же непонятный,
  //// и все потому, что нет интуитивного понимания,
  //// что же все-таки есть это пресловутый "attention",
  //// который еще может и по разному вычисляться,
  //// например, с уменьшенной размерностью или через "транспонирование".
  //// Похоже, "переиспользование attention" в чем-то аналогично,
  //// использованию различных "карт признаков",
  //// т.е. дополнительной связи между различными представлениями.
  //// "Но это не точно".
  
  Рис. Корреляции attention maps в соседних слоях
  
  И последним по порядку, но по значению
  является оптимальный выбор расположения элементов
  и количества слоев в трансформере.
  
  Полный перебор возможных вариантов расположения слоев
  с пулингом и размерностей эмбеддингов
  - слишком сложная комбинаторная задача,
  поэтому пространство поиска пришлось существенно ограничить.
  Размерности эмбеддинга и максимальное число блоков
  зафиксировано на каждой стадии (при фиксированном количестве токенов).
  
  В каждом блоке есть 3 выбора:
  
  Использовать обычный блок трансформера
  
  Два последовательных блока с одним и тем же attention
  
  Тождественную операцию (Identity)
  
  На каждом проходе (forward pass) один из трех вариантов
  выбирается из равномерного распределения
  и при обратном проходе (backward pass)
  обновляются параметры для этого варианта
  (если это не Identity, конечно).
  Оптимальная архитектура определяется с помощью эволюционного алгоритма.
  
  Рис. Суперсеть из возможных конструктивных элементов в PS-ViT.
  
  Возможная глубина сети от 0 (только Identity)
  до 36 (везде два Sharing Layer) блоков трансформера.
  
  Работает это, по всей видимости, и правда неплохо:
  
  Рис. Сравнение моделек на ImageNet
  
  VOLO (Vision Outlooker for Visual Recognition)
  
  Довольно занятную вариацию внимания предложили в статье VOLO
  https://arxiv.org/abs/2106.13112
  (если честно, я даже не понимаю, почему она работает так здорово).
  
  Блок энкодера имеет стандартный вид:
  
  \begin{aligned} \hat{X} &= \mathrm{OutlookAttn} (\mathrm{LN}(X)) + X\\ Z &= \mathrm{MLP} (\mathrm{LN} (\hat{X})) + \hat{X}\end{aligned}
  
  Здесь \mathrm{LN}(...)- это LayerNorm,
  а вот что действительно интересно,
  так это операция\mathrm{OutLookAttn}(...).
  Делается она следующим образом (C - число каналов, K - размер ядра свертки):
  
  Линейный слой nn.Linear(C, K ** 4) для каждого пикселя из feature map
  создает вектор размерности K ** 4.
  
  Полученный вектор решейпится (прошу прощения за англицизм)
  в матрицу K ** 2 x K ** 2.
  Данная матрица играет роль матрицы внимания в пределах окна размера K x K.
  То есть матрица внимания предсказывается в один шаг,
  без создания ключей (keys) и запросов (queries)
  c последующим вычислением попарных скалярных произведений.
  //// То есть keys и queries оказываются не обязательными?
  //// И это тоже будет "трансформер"?
  
  Линейный слой nn.Linear(C, С) выдает значения (values) для каждого токена
  (как в обычном трансформере).
  
  Полученная на шаге 2 матрица attention перемножается на values
  и получается выходное представление.
  
  Рис. Как работает Outlook Attention
  
  Таким образом, получается некий trade-off между локальностью операции
  и вычислительной сложностью.
  В стандартном self-attention вычислительная сложность растет
  как O((H W / P^2)^2)
  поэтому использовать патчи размером меньше 16,
  особенно при большом разрешении довольно проблематично.
  В предложенном подходе же асимптотика линейна по количеству токенов O((HW/P^2) K^4).
  Размер ядра свертки K должен быть небольшим (в работе K= 3).
  Благодаря этому можно брать меньший патч (скажем 8)
  при большом разрешении (384x384, 512x512).
  
  Рис. Разные версии VOLO
  
  OutlookAttn - гибрид свертки и стандартного self-attention
  - локальный, но с большим receptive field.
  При таком подходе большой receptive field
  может быть достигнут при меньшем числе блоков, чем в типичной CNN
  и в то же время зашито понятие локальности и близости в саму архитектуру.
  
  Рис. Кривые Парето для VOLO и еще нескольких современных моделей на ImageNet
  
  Получился классный бэкбоун, позволивший добиться впечатляющих результатов
  не только на ImageNet (87.1% без дополнительных данных),
  но и в задачах семантической сегментации на Cityscapes и ADE20K.
  
  Рис. (Слева) Качество сегментации (по mIoU) на CityScapes.
  (Справа) Качество сегментации (по mIoU) на ADE20K.
  
  Заключение
  
  Универсальность и гибкость архитектуры трансформера,
  способность улавливать глобальный контекст,
  оказалась полезной и в области компьютерного зрения.
  
  За год с небольшим, прошедших с публикации An image is worth 16x16 words,
  трансформеры сильно изменили наши представления о том,
  как надо решать задачи компьютерного зрения, толкнули науку далеко вперед.
  //// Это не "наука", а "практика", т.к. отсутствует "теоретическая база".
  
  В данном обзоре я рассмотрел лишь отдельные работы
  из моря публикаций по этой теме за 2021 год.
  Многие другие интересные идеи,
  вроде Transformer in Transformer и CoAtNet
  https://arxiv.org/abs/2103.00112
  не были затронуты в силу ограниченности объема обзора.
  Кроме того, были рассмотрены только задачи классификации,
  детекции и сегментации картинок.
  ViT-ы показали впечатляющие задачи так же в мультимодальных задачах,
  при работе с видео и self-supervised, semi-supervised learning,
  генеративных моделях.
  
  В настоящий момент сложно сказать,
  как будет развиваться эта область в будущем.
  Мне кажется, что в следующие несколько лет мы увидим
  последовательное развитие и улучшение архитектур Visual трансформеров,
  которое имело место для сверточных сетей.
  Будет ли архитектура на основе механизма внимания
  или ее гибрид со свертками конечным этапом развития нейронных сетей
  в компьютерном зрении
  или придет другая, еще более мощная и универсальная архитектура,
  не берусь судить.
  
  Но я уверен, что за развитием этой области будет очень интересно следить в 2022.
  
  Список источников
  
  Статьи
  
  An image is worth 16x16 words
  
  Training data-efficient image transformers & distillation through attention
  
  Pyramid Vision Transformer: A Versatile Backbone for Dense Prediction without
  Convolutions
  
  Swin-Transformer
  
  PSViT: Better Vision Transformer via Token Pooling and Attention Sharing
  
  XCiT: Cross-Covariance Image Transformers
  
  VOLO
  
  Stand-Alone Self-Attention in Vision Models
  
  DETR
  
  Большой Перечень архитектур ViT
  https://github.com/dk-liang/Awesome-Visual-Transformer
  
  Ну и куда без Янника Килхера
  https://www.youtube.com/c/YannicKilcher
  
  .......
  
  //// Из комментариев.
  
  masai
  8 янв 2022 в 18:27
  
  \\\ Но статья Attention is all you need
  \\\ получила свое название не просто так, и название оказалось даже более
  \\\ глубокомысленным чем, полагаю, даже исходно полагали сами авторы.
  
  Говорят, что и внимание не очень-то нужно. :)
  https://github.com/sail-sg/poolformer
  
  Да и ResNet хоронить пока что рано - ResNet strikes back.
  https://arxiv.org/abs/2110.00476
  
  19blackadder97
  8 янв 2022 в 18:40
  
  спасибо, про Poolformer не видел статью.
  Правда, навскидку сравнивая перформанс Poolformer и Swin на ImageNet,
  кажется, что Swin эффективнее выходит (именно Swin а не Swin-Mixer).
  Про ResNet читал статью - действительно процедура обучения решает многое,
  и к моменту массового использования ViT у исследователей
  был большой опыт в подборе сильных процедур обучения.
  Но все же кажется, что если ViT-ы смогли составить сходу конкуренцию
  давно развиваемым сверточным сетям,
  то у них еще большой потенциал для дальнейшего развития.
  
  masai
  8 янв 2022 в 21:13
  
  Ну, там идея в том, что attention не так уж и важен сам по себе.
  PoolFormer - это просто пример.
  
  Я вовсе не против трансформеров.
  Наоборот, мне кажется, всё это очень интересно
  и нам только предстоит понять, что делает те или иные модели эффективными.
  
  Скажем, недавно была статья, в которой сделали NeRF без нейронок.
  То есть, значительная часть эффективности приходится
  на дифференцируемый рендерер,
  вносящий inductive bias с информацией о внешнем мире.
  https://habr.com/ru/post/591779/
  Статья Deep Image Prior показала, что сам факт использования свёрток
  - это уже важная штука,
  с помощью которых многое можно сделать.
  (И, кстати, идеи оттуда были использованы в известной статье
  про ретайминг видео.)
  
  В общем, всё это очень и очень любопытно. :)
  
  19blackadder97
  8 янв 2022 в 23:25
  
  Очень познавательно! Действительно, интересные работы.
  Кажется, что практика сильно убежала вперед теории.
  Интересно, смогут ли когда нибудь теоретики приблизиться
  к сколько либо точному предсказанию поведения нейронной сети
  на реальном датасете при условиях, близких к реальным нейронным сетям
  (то есть не в пределе NTK или среднего поля, скажем)?
  
  masai
  9 янв 2022 в 03:19
  
  Да, deep learning - это сейчас экспериментальная наука.
  Но может, в ближайшее время появится хорошая теория, кто знает.
  
  kraidiky
  10 окт 2023 в 15:00
  
  Я бы даже сказал, что пора распрощаться с мыслью,
  что нейросети - точная наука,
  и начать относиться к ней, как к естественной.
  Как биологи, разглядывающие под микроскопом своих подопечных дрозофил
  и изучающие даже всякие химические и генетические взаимосвязи,
  но признающие при этом, что их понимание бесконечно не полно.
  //// Очень печально было прочитать этот комментарий от автора,
  //// который десять лет назад как раз и пытался
  //// что-то новое и оригинальное сказать
  //// именно в области понимания нейросетей.
  //// Но, похоже, не получив ни понимания, ни одобрения своим устремлениям,
  //// пришел к такому печальному прогнозу относительно этой "точной науки".
  
  .......
  
  19blackadder97
  9 янв 2022 в 12:54
  
  Идея сделать предобучение, как BERT, выглядит естественно,
  но вот главный вопрос был в том к поставить задачу,
  чтобы представить картинку как слово.
  Авторы BeiT придумали хорошее решение
  с подачей патчей в дискретный автоэнкодер,
  и, как я понял, их решение достаточно быстро файнтьюнится на ImageNet и сегментации.
  Работает даже немного лучше, чем DINO, судя по табличкам в их статье.
  
  Еще есть свежий результат в этом направлении
  - Masked Autoencoders Are Scalable Vision Learners.
  Тут авторы маскируют большой процент (75% токенов)
  прогоняют через энкодер незамаскированные патчи
  и декодером восстанавливают картинку на предобучении.
  На файнтьюнинге используется только энкодер со всей
  (незамаскированной картинкой).
  
  .......
  
  ount_enable
  9 янв 2022 в 00:48
  \\\ При сопоставимом количестве операций с плавающей точкой модели Swin
  \\\ значительно превосходят ViT и DeiT и сравнимы с EfficientNet
  \\\ (эффективнее по числу операций, чуть уступают в плане эффективности по
  \\\ параметрам).
  
  В табличке выше самый мелкий трансформер на 4.5 Гфлопс имеет точность 81.3,
  а EfficientNet на 1.8 Гфлопс выдает 81.6%.
  Где они эффективнее?
  
  Ещё с трансформерами большая проблема в квантизации.
  Если свёрточные сети спокойно квантизируются в 8 бит
  или даже меньше с минимальной потерей точности,
  то трансформеры сильно ухудшаются,
  и совершенно неэффективны для практических применений,
  особенно вне дата-центра.
  
  ......
  
  19blackadder97
  9 янв 2022 в 08:09
  Ух, куда же я смотрел в этот момент) Действительно, EfficientNet выходит круче.
  Интересно, что в плане throughput таблица наиболее выигрышная для них,
  хотя, казалось бы, что он должен напрямую зависеть от FLOPs.
  
  С квантизацией не доводилось особо работать.
  Могу предположить, что причина падения качества
  - более резкие оптимумы по сравнению с сверточными сетями
  (большая кривизна босс-поверхности).
  //// Думаю, что не в этом дело,
  //// а в "топологической сложности пространства эмбеддингов".
  Вероятно, если брать модели, обученные с помощью SAM,
  они будут лучше квантоваться.
  Возможно ли дообучение квантованных моделей в низкой точности?
  
  По личному опыту еще могу сказать, что visual transformer плохо прунится.
  //// То бишь, плохо "сжимается"
  //// за счет исключения "вроде как" несущественных связей.
  //// А это может быть свидетельством, что "внутреннее пространство"
  //// трансформеров более сложное или более связное, чем у сверточных сетей.
  Если ResNet можно запрунить без потери качества достаточно сильно,
  EfficientNet и NFNet не так хорошо,
  в силу их оптимизированности,
  до 70-80% обычно качество не проседает,
  а при небольшом прореживании качество слегка растет даже на валидации,
  то для ViT (DeiT, Swin) я наблюдал монотонное ухудшение качества
  и модель c 50% весов уже теряет пару процентов на ImageNet.
  
  count_enable
  9 янв 2022 в 21:44
  
  Я навскидку посмотрел - уже есть пара публикаций о квантизации трансформеров,
  авось через пару лет и дойдут до практических примеров.
  
  Прунинг звучит круто ("мы выбросили 90% параметров!!!111"),
  на практике очень редко даёт ускорение
  ибо всё железо заточено под плотные,
  а не разряженные матрицы,
  и кроме слабеньких процессоров мало где можно получить ощутимый выигрыш.
  
  .......
  
  9blackadder97
  10 янв 2022 в 23:40
  
  Справедливо, спасибо за замечание.
  Похоже, что реальная польза будет в массовых применениях,
  если каким-то образом железо на мобильных устройствах
  сможет поддерживать и эффективно обрабатывать разреженные тензоры.
  
  kraidiky
  10 окт 2023 в 15:09
  
  На обычной моей карточке разреженные тензоры обрабатываются,
  грубо говоря x3 по сравнению с dense с таким же количеством весов.
  Так что как только вы напрунили больше чем две трети вы уже вы выигрыше.
  
  А кроме того никто, почему-то, не говорит,
  что удалять можно не только веса, но и целиком нейроны или свёртки.
  Это делается вообще без накладных расходов.
  Прунинг явно сильно недооценён.
  
  ........
  
  
  kraidiky
  12 окт 2023 в 11:28
  
  Я с полносвязаными слоями работаю,
  использую https://pypi.org/project/torch-sparse/
  У него манипулирование индексами показалось менее проблематичным.
  Там кроме весов хранится ещё тензор с индексами x2 размером
  потому что две координаты,
  так что экономия по памяти начинается только после того,
  как проредили хотя бы на 2/3 и по скорости исполнения та же ситуация,
  примерно раза в три медленнее при том же количестве весов.
  Для моих достаточно экспериментальных целей подходит.
  Если зарубаться за скорость инференса думаю можно
  и что-то более эффективное подыскать.
  Я почти уверен, что если подумать головой можно хранить один индекс,
  а не два и не требовать обязательно long int,
  учитывая реальные размеры матриц,
  а хранить оба индекса в одном лонге.
  
  >> 30-40% ускорения при сохранении качества не реальной задаче
  - это хороший результат, и требует обычно серьезного дообучения.
  
  30-40% процентов на инференсе это не просто бабло, а баблище,
  и я не знаю почему народ
  это не стало золотым стандартом постобработки сети перед инференсом.
  
  ........
  
  count_enable
  12 янв 2022 в 16:52
  
  И вот опять свёрточные сети лучше всех: https://arxiv.org/abs/2201.03545 .
  
  19blackadder97
  13 янв 2022 в 12:14
  
  Да, похоже , пространство параметров в архитектурах еще мало исследовано.
  Здесь, правда замечу, что разница все же не так велика
  в производительности Swin и их ConvNext,
  более того, если сравнивать с XCiT,
  то они выйдут круче обоих моделей.
  
  .......
  
  Справедливости ради надо заметить, они с обучались дистилляцией с учителем,
  и разницу может делать именно этот факт.
  
  А вообще, кажется что оптимальная архитектура бы брала лушчее из двух миров
  - свертки с сильным inductive bias
  и attention со свойством улавливания глобального контекста.
  
  .......
  
  //// Конец цитирования.
  
  Опять, вроде, не сильно много добавилось к пониманию трансформеров,
  но совершенно бесполезным этот материал тоже никак нельзя считать.
  Например, мне очень заинтересовала информация
  об особенностях обучения трансформеров "элементам картинок",
  досточно "вольным обращением" с матрицами key и value,
  возможностью "переиспользования attention map",
  как механизма связи различных сегментов сети.
  ну, и куча полезных ссылок, вкупе с личными авторскими оценками.
  
  И, кроме того, подсказал еще одно из возможных направлений поиска
  - "метод дистилляции".
  Похоже, тут, тоже можно что-то интересное накопать, см.:
  "Дистилляция диффузионки" для "чайников".
  
  Короче, моя признательность и автору этого материала и комментариев к нему, есть о чем задуматься.
  
  
  ==========
  
  20.02.2024 21:16
  
  Структура сети Swin.
  В оглавление.
  
  Продолжим изучение архитектуры трансформеров на примере их применения
  в обработке изображений:
  
  "Обзор архитектуры Swin Transformer".
  Автор: vovaf709 (Филипенко Владимир)
  https://habr.com/ru/articles/599057/.
  1 янв 2022 в 23:18
  
  //// Начало цитирования.
  
  Трансформеры шагают по планете!
  В статье вспомним/узнаем как работает visual attention,
  поймём, что с ним не так,
  а главное как его поправить, чтобы получить на выходе best paper ICCV21.
  
  CV-трансформеры in a nutshell
  
  Attention Is All You Need
  
  Начнём издалека, а именно с 2017 года, когда A Vaswani et al.
  опубликовали знаменитую статью ,
  в которой была предложена архитектура нейронной сети Transformer
  для решения задачи seq2seq и в частности машинного перевода.
  Не буду говорить о том, насколько значимым было это событие для всего NLP.
  Скажу лишь, что на данный момент почти каждое ML решение,
  работающее с текстом,
  пожинает плоды того успеха,
  используя Transformer-based архитектуру напрямую,
  работая с эмбеддингами из BERT-а
  или еще каким-нибудь образом.
  Ключевым и идейно чуть ли не единственным компонентом трансформера
  является слой Multi-Head Attention.
  В применении к задаче машинного перевода он дал возможность
  учитывать взаимодействие между словами,
  находящимися на произвольно большом расстоянии в тексте,
  что выгодно выделило трансформер на фоне других моделей перевода
  и позволило ему занять место под солнцем.
  Формально этот слой записывается в терминах следующих преобразований:
  
  \text{Attention}(Q, K, V) = \text{Softmax}\left(\frac{QK^{\mathsf{T}}}{\sqrt{d_k}}\right)V,
  
  \text{MultiHeadAttention}(Q, K, V) = \text{Concat}(\text{head}_1, \dots, \text{head}_h)W^O,
  
  где
  
  \text{head}_i = \text{Attention}(QW_i^Q, KW_i^K, VW_i^V).
  
  С 2017 года было предложено бесчисленное множество модификаций трансформера
  (Linformer, Reformer, Perfomer, etc.),
  делающих его более вычислительно эффективным,
  стабилизирующих обучение и так далее.
  Такой бум трансформеров не мог не затронуть
  другие сферы применения глубинного обучения помимо NLP,
  и с ~2020 года они начали проникать в CV.
  
  Трансформеризация Computer Vision-а
  
  Вообще идея применения трансформера к изображениям изначально
  может смутить читателя.
  Всё-таки текст и картинки - это довольно отличающиеся модальности,
  как минимум тем, что текст является последовательностью слов.
  Изображение - это тоже в некотором смысле последовательность (пикселей),
  направление которой можно определить искусственно,
  например построчно, правда у такого определения
  не будет семантического смысла в отличие от текста.
  Однако не стоит забывать, что Multi-Head Attention
  на самом деле является операцией не над последовательностями,
  а над неупорядоченными множествами векторов,
  а последовательной структурой текст наделяется искусственно
  с помощью positional encoding-а,
  так что аргумент выше становится невалидным.
  Валидным аргументом против Visual Transformer-ов может быть
  отсутствие в них приятных inductive bias-ов,
  имеющихся у свёрточных сетей:
  эквивариантности относительно сдвигов
  и предположении о пространственной локальности принзнаков.
  Однако это так же спорный момент,
  подробнее про который можно почитать здесь.
  https://habr.com/ru/post/591779/
  А пока сомневающиеся сомневались,
  исследовательские группы делали,
  и явили миру несколько Visual Transoformer-ов (неплохой survey),
  https://arxiv.org/abs/2111.06091
  в том числе ViT, на примере которого мы выясним
  как же переформулировать Multi-Head Attention для изображений.
  
  An Image Is Worth 16x16 Words
  
  Авторы ViT-иа предложили довольно прямолинейную архитектуру:
  
  Исходная картинка нарезается на патчи 16x16,
  они вытягиваются в вектора и все пропускаются через линейный слой.
  Далее к ним прибавляются обучаемые вектора,
  играющие роль positional embedding-ов,
  а также к набору добавляется отдельный обучаемый эмбеддинг,
  являющийся прямым аналогом CLS-токена BERT-а.
  А на этом то и всё!
  Далее идёт самый обычный Transformer Encoder
  (N x Multi-Head Attention если угодно),
  и класс изображения предсказывается маленьким перцептроном,
  берущим на вход то, что получилось на месте CLS-токена.
  Как и ~любой трансформер, модель получилась очень прожорливой
  в том смысле, что для получения околосотовых результатов
  ей нужно предобучаться на громадных датасетах,
  таких как закрытый гугловский JFT-300M.
  Тем не менее в определённом сетапе сетка смогла обойти
  сотовых BiT-L и Noisy Student-а,
  что можно считать успехом.
  За подробностям отсылаю читателя к оригинальной статье,
  https://arxiv.org/abs/2010.11929
  много интересного можно найти в ablation-е,
  особенно советую изучить графики Mean Attention Distance-а,
  являющимся аналогом receptive field-а.
  
  Всё вроде и неплохо, но не классификацией единой занимаются в CV.
  Есть задачи по типу Object Detection-а,
  в которых зачастую важны мелкие детали,
  или же задачи сегментации,
  для которой вообще необходимо делать pixel-level предсказание.
  Все это требует как минимум возможности работы
  с изображениями высокого разрешения,
  то есть значительного увеличения размера входа.
  А как нетрудно видеть, Attention работает
  за квадратичное по входу время,
  что в случае картинок 1920х1920 является острейшей проблемой,
  так как время forward pass-а взмывает до небес.
  К тому же мелкие детали могу потеряться уже на первом слое,
  который суть свёртка 16х16 со страйдом 16.
  Кто виноват и что делать?
  На первый вопрос ответ +- понятен -
  дело в слишком твердолобой адаптации трансформерной архитектуры под CV.
  А ответу на второй вопрос посвящается оставшаяся часть этой статьи.
  
  Swin Transformer
  
  Проблемы ViT-а обозначились ещё в предыдущем параграфе,
  поэтому не будем ходить вокруг да около и сразу перейдем
  к рассмотрению архитектуры, предложенной в статье
  :
  https://arxiv.org/abs/2103.14030
  
  .........
  
  Первый слой качественно такой же, как и в ViT-е
  - исходная картинка нарезается на патчи и проецируется линейным слоем.
  Единственное отличие в том, что в Swin-е на первом слое патчи имеют размер 4х4,
  что позволяет обрабатывать более мелкий контекст.
  Далее идут несколько Patch Merging и Swin Transformer Block слоёв.
  Patch Merging занимается тем, что конкатенирует фичи
  соседних (в окне 2х2) токенов и понижает размерность,
  получая более высокоуровневое представление.
  Таким образом, после каждого Stage-а образуются <карты> признаков,
  содержащие информацию на разных пространственных масштабах,
  что как раз и позволяет получить иерархическое представление изображения,
  полезное для дальнейшей сегментации/Object Detection-а/etc:
  
  .......
  
  Благодаря этому Swin Transfomer может служить универсальным backbone-ом
  для различных задач CV.
  
  Swin Transformer Block - ключевая изюминка всей архитектуры:
  
  ......
  
  Как видно из схемы, два последовательных блока представляют собой
  два классических трансформерных блока с MLP, LayerNorm-ами
  и Pre-Activation Residual-ами,
  однако Attention заменён на нечто более хитрое,
  к разбору чего мы непременно переходим.
  
  (Shifted) Window Multi-Head Attention
  
  Как было упомянуто, проблемой Multi-Head Attention-а
  является его квадратичная сложность,
  больно стреляющая в ногу при применении на картинках высокого разрешения.
  На ум приходит довольно простое решение,
  представленное еще в статье про Longformer
  - давайте для каждого токена считать Attention
  не со всеми другими токенами,
  а только с находящимися в некотором окне фиксированного размера
  (Window Mutli-Head Attention).
  Если размерность токенов - C, а размер окна - MxM,
  то сложности для (Window) Multi-Head Self Attention-ов получаются следующие:
  
  \Omega(MSA) = 4hwC^2 + 2(hw)^2C,\Omega(W\text{-}MSA) = 4hwC^2 + 2M^2hwC
  
  То есть Attention теперь работает за линейное по hw время!
  Однако такой подход уменьшает общую репрезентативную способность сети,
  так как токены из различных окон никак не будут взаимодействовать.
  Чтобы исправить ситуацию, авторы поступили любопытным образом.
  После каждого блока с Window Multi-Head Attention-ом
  они поставили аналогичный слой,
  со смещёнными по диагонали окнами Attention-а:
  
  ......
  
  Это вернуло взаимодействие между токенами,
  оставив при этом линейную вычислительную сложность.
  //// Интересное решение. Как бы его сформулировать так, чтобы понять и не забыть.
  //// Может быть так, делим на меньшие независимые части,
  //// а затем эти независимые части связываем за счет частичного наложения.
  //// Вроде, понятная формулировка схожая с тем,
  //// что используется в сверточных сетях, но реализуемая несколько иначе.
  
  Как проиллюстрировано выше,
  сдвиг окон Attention-а увеличивает их количество.
  Это значит, что реализация этого слоя
  с наивным паддингом исходной <карты> признаков нулями
  обяжет считать больше Attention-ов (9 вместо 4 в примере),
  чем мы посчитали бы без сдвига.
  Чтобы не производить лишних вычислений,
  авторы предложили перед подсчётом циклически сдвигать само изображение
  и вычислять уже маскированный Attention,
  чтобы исключить взаимодействие не соседних токенов.
  Такой подход вычислительно эффективнее наивного,
  так как количество считаемых Attention-ов не увеличивается:
  //// Вот этого приема не понял.
  
  .......
  
  Также в Swin-е авторы использовали несколько другие positional embedding-и.
  Их заменили на обучаемую матрицу В,
  называемую relative position bias,
  которая прибавляется к произведению query и key под софтмаксом:
  
  \text{Attention}(Q, K, V) = \text{Softmax}\left(\frac{QK^{\mathsf{T}}}{\sqrt{d_k}}+ B\right)V.
  
  Как оказалось, такой поход приводит к лучшему качеству.
  //// А вот это стоит запомнить.
  //// И, наверно, что-то подобное, скоро появится и в языковых моделях.
  //// Ведь "позиционное кодирование" в тексте не обязательно должно быть
  //// "математически точным",
  //// а, наверняка, лучше если бы это было "смысловое позиционирование".
  
  Эксперименты и результаты
  
  Всего авторы предложили 4 модели разных размеров:
  
  Для честного сравнения параметры были подобраны так,
  чтобы по размерам и количеству вычислений Swin-B
  примерно соответствовал ViT-B/DeiT-B,
  а Swin-T и Swin-S ResNet-50 и ResNet-101 соответственно.
  
  ImageNet-1k классификация
  
  В данном бенчмарке были проверены два сетапа:
  обучение на ImageNet-1k и предобучение на ImageNet-22K
  с дообучением на ImageNet-1K.
  Модели сравнивались по top-1 accuracy.
  
  В первой постановке Swin-ы более чем на 1.5%
  обошли другие Visual Transformer-ы, в том числе ViT-ы,
  отстающие от первых на целых 4%.
  Сотовые же EfficienetNet-ы и RegNet-ы оказались соперником посерьёзнее
  - статистически значимо тут можно говорить
  разве что об улучшении баланса между точностью и быстродействием.
  Во второй постановке предобучение на ImageNet-22K дало ~2%-ый прирост точности,
  а Swin-L достиг 87.3% top-1 accuracy.
  Это ещё раз подтверждает важность предобучения
  в особенности для трансформерных архитектур.
  
  COCO детектирование объектов
  
  Для оценки Swin-а в качестве backbone-а для детекции
  авторы использовали его вместе с такими фреймворками детекции
  как Cascade Mask R-CNN, ATSS, RepPointsV2 и Sparse R-CNN.
  В качестве backbone-ов для сравнения были взяты ResNe(X)t, DeiT
  и несколько сотовых свёрточных аритектур.
  
  Для всех фреймворков Swin backbone дал уверенные +3.5-4.2% AP
  относительно классического ResNet50.
  Относительно ResNe(X)t-а Swin также показал рост в ~3% AP
  сразу для нескольких его версий Swin-T, Swin-S и Swin-B.
  DeiT проиграл Swin-у чуть меньше - около 2% AP,
  но был сильно медленнее из-за честного Multi-Head Attention-а по всей картинке.
  Ну и относительно большого набора сотовых детекторов Swin-L с HTC
  показал улучшение в ~2.6 AP.
  
  ADE20K семантическая сегментация
  
  Для сегментации с помощью Swin-а был выбран фреймворк UperNet,
  он сравнивался с несколькими популярными сегментаторами,
  а так же с моделью на основе DeiT.
  Swin-S обошел Deit-S на целых 5.3 mIoU, а ResNet-101
  и ResNeSt на 4.4 и 2.4 mIou соответственно.
  При этом Swin-L, предобученный на ImageNet-22k,
  выбил 53.5 mIoU, обойдя SETR на 3.2 mIoU.
  
  Итоги
  
  В результате имеем следующее:
  авторам удалось несколько переформулировать трансформерную архитектуру
  под задачи CV,
  сделав её вычислительно более оптимальной
  за счёт использования локального Attention-а.
  При этом Shifted Window Multi-Head Attention
  оставил репрезентативную способность сети на уровне,
  достаточном, чтобы соревноваться с текущими сотовыми моделями.
  Благодаря этому стало возможным построить архитеткуру,
  позволяющую извлекать из изображений фичи
  на разных пространственных масштабах,
  что позволило успешно использовать Swin как backbone
  в задачах сегментации и детекции,
  где до этого трансформеры были на более низких позициях.
  This is success!
  
  Полезные ссылки
  
  
   https://arxiv.org/abs/2103.14030
  
  
   https://arxiv.org/abs/2010.11929
  
   Реализация Swin Transformer на PyTorch
   https://github.com/microsoft/Swin-Transformer
  
   NLP Course | For You - качественный ресурс по NLP,
   где в том числе подробно разбирается механизм Attention
   https://lena-voita.github.io/nlp_course.html#main_page_content
  
  .......
  
  //// Конец цитирования.
  
  24.02.2024 14:56
  
  Основная идея, насколько я понял, позволившая этой архитектуре
  успешно конкурировать с другими решениями,
  это своеобразное решение в виде комбинации "иерархичного" и "сетевого" подходов,
  т.е. как бы разбиения на более простые/частные в вычислительном отношении задачи,
  а затем "принудительное скрещивание" частных решений.
  Как в части классической "мультиголовости",
  так и в части применения соединительных слоев "со смещением".
  
  Это не совсем иерархический подход, и не совсем сетевой,
  даже подходящего термина подобрать не получается.
  И представляется, что в таком ракурсе стоит еще раз проработать тему
  иерархического подхода применительно к нейросетевым архитектурам,
  задавшись целью понять, а где имеет смысл использовать такой "гибридный подход".
  Попытаться нащупать принципы декомпозиции задач,
  и, наоборот, какого осмысленной увязки частных решений.
  
  Отдельного внимания заслуживает интересная идея
  относительно "обучаемого" позиционного кодирования,
  которая, наверняка получит свое развитие.
  Впрочем, как и, скорее всего, большинство "точных математических операций",
  особенно вычислительно затратных, в обозримом будущем будут,
  так или иначе, заменяться на "обучаемые нейросетевые блоки".
  Но это, наверно, будет следующим этапом в развитии нейросетвых архитектурах.
  
  И в этом отношении интересен вопрос, что именно представляют
  собой различные блоки в архитектуре нейросетей с позиций inductive bias.
  
  
  ========
  
  26.02.2024 21:57
  
  Сверточная сеть "для чайников".
  В оглавление.
  
  Сверточная нейронная сеть (СНС/CNN) архитектура достаточно старая
  и "всем хорошо известная". И к тому же,
  если хотя бы немного с ней разобраться,
  она, наверно, наиболее "интуитивно" понятна
  из всех действительно работоспособных нейронок.
  Поэтому, как Вы могли уже заметить, упоминание этой архитектуры,
  отсылки к ее компонентам встречаются в материалах по нейронным сетям,
  практически через раз.
  
  И имеет смысл, если эта архитектура полностью отсутствует в "вашем багаже",
  хотя бы вскользь с ней познакомиться.
  Можно это сделать с материала по-проще, см.:
  "Сверточные сети простыми словами."
  А можно с более углубленного материала,
  правда, в нем частично нестандартная терминология:
  
  "Сверточная нейронная сеть, часть 1:
  структура, топология, функции активации и обучающее множество"
  Автор: HybridTech (Иван Голиков)
  https://habr.com/ru/articles/348000/
  31 янв 2018 в 16:47
  
  //// Начало цитирования.
  
  .......
  
  Введение
  
  Наилучшие результаты в области распознавания лиц показала
  Convolutional Neural Network или сверточная нейронная сеть (далее - СНС),
  которая является логическим развитием идей таких архитектур НС
  как когнитрона и неокогнитрона.
  Успех обусловлен возможностью учета двумерной топологии изображения,
  в отличие от многослойного персептрона.
  
  Сверточные нейронные сети обеспечивают частичную устойчивость
  к изменениям масштаба, смещениям, поворотам, смене ракурса и прочим искажениям.
  Сверточные нейронные сети объединяют три архитектурных идеи,
  для обеспечения инвариантности к изменению масштаба,
  повороту сдвигу и пространственным искажениям:
  
   локальные рецепторные поля
   (обеспечивают локальную двумерную связность нейронов);
  
   общие синаптические коэффициенты
   (обеспечивают детектирование некоторых черт в любом месте изображения
   и уменьшают общее число весовых коэффициентов);
  
   иерархическая организация с пространственными подвыборками.
  
  На данный момент сверточная нейронная сеть и ее модификации
  считаются лучшими по точности и скорости алгоритмами нахождения объектов на сцене.
  //// Речь идет о 2018 годе. Т.е. уже "очень очень давно".
  Начиная с 2012 года, нейросети занимают первые места
  на известном международном конкурсе по распознаванию образов ImageNet.
  
  ......
  
  Структура сверточной нейронной сети
  
  СНС состоит из разных видов слоев:
  сверточные (convolutional) слои,
  субдискретизирующие (subsampling, подвыборка) слои
  и слои <обычной> нейронной сети - персептрона,
  в соответствии с рисунком 1.
  
  Рисунок 1 - топология сверточной нейронной сети
  
  Первые два типа слоев (convolutional, subsampling), чередуясь между собой,
  формируют входной вектор признаков для многослойного персептрона.
  
  Свое название сверточная сеть получила по названию операции - свертка,
  суть которой будет описана дальше.
  
  Сверточные сети являются удачной серединой
  между биологически правдоподобными сетями и обычным многослойным персептроном.
  На сегодняшний день лучшие результаты в распознавании изображений
  получают с их помощью.
  В среднем точность распознавания таких сетей превосходит обычные ИНС на 10-15%.
  СНС - это ключевая технология Deep Learning.
  
  Основной причиной успеха СНС стало концепция общих весов.
  //// Стоит обдумать этот момент. Может быть, это "ключик"
  //// к чему-то не совсем тривиальному.
  //// Может быть, стоит рассмотреть концепцию "группового обучения параметров"
  Несмотря на большой размер,
  эти сети имеют небольшое количество настраиваемых параметров
  по сравнению с их предком - неокогнитроном.
  Имеются варианты СНС (Tiled Convolutional Neural Network),
  похожие на неокогнитрон, в таких сетях происходит,
  частичный отказ от связанных весов,
  но алгоритм обучения остается тем же
  и основывается на обратном распространении ошибки.
  СНС могут быстро работать на последовательной машине
  и быстро обучаться за счет чистого распараллеливания процесса свертки
  по каждой карте,
  а также обратной свертки при распространении ошибки по сети.
  
  На рисунке ниже продемонстрирована визуализация свертки и подвыборки:
  
  ......
  
  Топология сверточной нейросети
  
  Определение топологии сети ориентируется на решаемую задачу,
  данные из научных статей и собственный экспериментальный опыт.
  
  Можно выделить следующие этапы влияющие на выбор топологии:
  
   определить решаемую задачу нейросетью
   (классификация, прогнозирование, модификация);
  
   определить ограничения в решаемой задаче
   (скорость, точность ответа);
  
   определить входные
   (тип: изображение, звук, размер: 100x100, 30x30,
   формат: RGB, в градациях серого)
   и выходных данные (количество классов).
  
  ......
  
  Рисунок 2 - Топология сверточной нейросети
  
  Входной слой
  
  Входные данные представляют из себя цветные изображения типа JPEG,
  размера 48х48 пикселей.
  Если размер будет слишком велик, то вычислительная сложность повысится,
  соответственно ограничения на скорость ответа будут нарушены,
  определение размера в данной задаче решается методом подбора.
  Если выбрать размер слишком маленький,
  то сеть не сможет выявить ключевые признаки лиц.
  Каждое изображение разбивается на 3 канала: красный, синий, зеленый.
  Таким образом получается 3 изображения размера 48х48 пикселей.
  
  Входной слой учитывает двумерную топологию изображений
  и состоит из нескольких карт (матриц),
  карта может быть одна, в том случае,
  если изображение представлено в оттенках серого, иначе их 3,
  где каждая карта соответствует изображению с конкретным каналом
  (красным, синим и зеленым).
  
  Входные данные каждого конкретного значения пикселя нормализуются
  в диапазон от 0 до 1, по формуле:
  
  ......
  
  Сверточный слой
  
  Сверточный слой представляет из себя набор карт
  (другое название - карты признаков, в обиходе это обычные матрицы),
  у каждой карты есть синаптическое ядро
  (в разных источниках его называют по-разному: сканирующее ядро или фильтр).
  
  Количество карт определяется требованиями к задаче,
  если взять большое количество карт,
  то повысится качество распознавания, но увеличится вычислительная сложность.
  Исходя из анализа научных статей, в большинстве случаев предлагается брать
  соотношение один к двум,
  то есть каждая карта предыдущего слоя
  (например, у первого сверточного слоя, предыдущим является входной)
  связана с двумя картами сверточного слоя,
  в соответствии с рисунком 3.
  Количество карт - 6.
  
  Рисунок 3 - Организация связей между картами сверточного слоя и предыдущего
  
  Размер у всех карт сверточного слоя - одинаковы и вычисляются по формуле 2:
  
  .....
  
  Ядро представляет из себя фильтр или окно,
  которое скользит по всей области предыдущей карты
  и находит определенные признаки объектов.
  Например, если сеть обучали на множестве лиц,
  то одно из ядер могло бы в процессе обучения выдавать наибольший сигнал
  в области глаза, рта, брови или носа,
  другое ядро могло бы выявлять другие признаки.
  Размер ядра обычно берут в пределах от 3х3 до 7х7.
  Если размер ядра маленький, то оно не сможет выделить какие-либо признаки,
  если слишком большое, то увеличивается количество связей между нейронами.
  Также размер ядра выбирается таким,
  чтобы размер карт сверточного слоя был четным,
  это позволяет не терять информацию при уменьшении размерности
  в подвыборочном слое, описанном ниже.
  
  Ядро представляет собой систему разделяемых весов или синапсов,
  это одна из главных особенностей сверточной нейросети.
  В обычной многослойной сети очень много связей между нейронами,
  то есть синапсов, что весьма замедляет процесс детектирования.
  В сверточной сети - наоборот, общие веса позволяет сократить число связей
  и позволить находить один и тот же признак по всей области изображения.
  
  ......
  
  Изначально значения каждой карты сверточного слоя равны 0.
  Значения весов ядер задаются случайным образом в области от -0.5 до 0.5.
  Ядро скользит по предыдущей карте и производит операцию свертка,
  которая часто используется для обработки изображений, формула:
  
  .......
  
  Неформально эту операцию можно описать следующим образом
  - окном размера ядра g проходим с заданным шагом (обычно 1) все изображение f,
  на каждом шаге поэлементно умножаем содержимое окна на ядро g,
  результат суммируется и записывается в матрицу результата, как на рисунке 4.
  
  .......
  
  Рисунок 4 - Операция свертки и получение значений сверточной карты (valid)
  
  Рис. Операция свертки и получение значений сверточной карты.
  Ядро смещено, новая карта получается того же размера, что и предыдущая (same)
  
  При этом в зависимости от метода обработки краев исходной матрицы
  результат может быть меньше исходного изображения (valid),
  такого же размера (same) или большего размера (full),
  в соответствии с рисунком 5.
  
  Рисунок 5 - Три вида свертки исходной матрицы
  
  В упрощенном виде этот слой можно описать формулой:
  
  .......
  
  При этом за счет краевых эффектов размер исходных матриц уменьшается, формула:
  
  .......
  
  Подвыборочный слой
  
  Подвыборочный слой также, как и сверточный имеет карты,
  но их количество совпадает с предыдущим (сверточным) слоем, их 6.
  Цель слоя - уменьшение размерности карт предыдущего слоя.
  Если на предыдущей операции свертки уже были выявлены некоторые признаки,
  то для дальнейшей обработки настолько подробное изображение уже не нужно,
  и оно уплотняется до менее подробного.
  К тому же фильтрация уже ненужных деталей помогает не переобучаться.
  
  В процессе сканирования ядром подвыборочного слоя (фильтром)
  карты предыдущего слоя, сканирующее ядро не пересекается
  в отличие от сверточного слоя.
  Обычно, каждая карта имеет ядро размером 2x2,
  что позволяет уменьшить предыдущие карты сверточного слоя в 2 раза.
  Вся карта признаков разделяется на ячейки 2х2 элемента,
  из которых выбираются максимальные по значению.
  
  Обычно в подвыборочном слое применяется функция активации RelU.
  Операция подвыборки (или MaxPooling - выбор максимального)
  в соответствии с рисунком 6.
  
  Рисунок 6 - Формирование новой карты подвыборочного слоя
  на основе предыдущей карты сверточного слоя.
  Операция подвыборки (Max Pooling)
  
  Формально слой может быть описан формулой:
  
  ......
  
  Полносвязный слой
  
  Последний из типов слоев это слой обычного многослойного персептрона.
  Цель слоя - классификация,
  моделирует сложную нелинейную функцию,
  оптимизируя которую, улучшается качество распознавания.
  
  ........
  
  Нейроны каждой карты предыдущего подвыборочного слоя связаны
  с одним нейроном скрытого слоя.
  Таким образом число нейронов скрытого слоя равно числу карт подвыборочного слоя,
  но связи могут быть не обязательно такими,
  например, только часть нейронов какой-либо из карт подвыборочного слоя
  быть связана с первым нейроном скрытого слоя,
  а оставшаяся часть со вторым,
  либо все нейроны первой карты связаны с нейронами 1 и 2 скрытого слоя.
  Вычисление значений нейрона можно описать формулой:
  
  .......
  
  Выходной слой
  
  Выходной слой связан со всеми нейронами предыдущего слоя.
  Количество нейронов соответствует количеству распознаваемых классов,
  то есть 2 - лицо и не лицо.
  Но для уменьшения количества связей и вычислений для бинарного случая
  можно использовать один нейрон
  и при использовании в качестве функции активации гиперболический тангенс,
  выход нейрона со значением -1 означает принадлежность к классу "не лица",
  напротив выход нейрона со значением 1 - означает принадлежность к классу лиц.
  
  Выбор функции активации
  
  Одним из этапов разработки нейронной сети является
  выбор функции активации нейронов.
  Вид функции активации во многом определяет
  функциональные возможности нейронной сети
  и метод обучения этой сети.
  Классический алгоритм обратного распространения ошибки
  хорошо работает на двухслойных и трехслойных нейронных сетях,
  но при дальнейшем увеличении глубины начинает испытывать проблемы.
  Одна из причин - так называемое затухание градиентов.
  По мере распространения ошибки от выходного слоя к входному
  на каждом слое происходит домножение текущего результата
  на производную функции активации.
  Производная у традиционной сигмоидной функции активации
  меньше единицы на всей области определения,
  поэтому после нескольких слоев ошибка станет близкой к нулю.
  Если же, наоборот, функция активации имеет неограниченную производную
  (как, например, гиперболический тангенс),
  то может произойти взрывное увеличение ошибки
  по мере распространения,
  что приведет к неустойчивости процедуры обучения.
  
  В данной работе в качестве функции активации в скрытых и выходном слоях
  применяется гиперболический тангенс,
  в сверточных слоях применяется ReLU.
  Рассмотрим наиболее распространенные функций активации,
  применяемые в нейронных сетях.
  
  ......
  
  Функция активации сигмоиды
  
  Эта функция относится к классу непрерывных функций
  и принимает на входе произвольное вещественное число,
  а на выходе дает вещественное число в интервале от 0 до 1.
  В частности, большие (по модулю) отрицательные числа превращаются в ноль,
  а большие положительные - в единицу.
  Исторически сигмоида находила широкое применение,
  поскольку ее выход хорошо интерпретируется, как уровень активации нейрона:
  от отсутствия активации (0) до полностью насыщенной активации (1).
  Сигмоида (sigmoid) выражается формулой:
  
  ......
  
  График сигмоидальной функции в соответствии с рисунком ниже:
  
  ......
  
  Крайне нежелательное свойство сигмоиды заключается в том,
  что при насыщении функции с той или иной стороны (0 или 1),
  градиент на этих участках становится близок к нулю.
  
  Напомним, что в процессе обратного распространения ошибки
  данный (локальный) градиент умножается на общий градиент.
  Следовательно, если локальный градиент очень мал,
  он фактически обнуляет общий градиент.
  В результате, сигнал почти не будет проходить через нейрон
  к его весам и рекурсивно к его данным.
  Кроме того, следует быть очень осторожным
  при инициализации весов сигмоидных нейронов,
  чтобы предотвратить насыщение.
  Например, если исходные веса имеют слишком большие значения,
  большинство нейронов перейдет в состояние насыщения,
  в результате чего сеть будет плохо обучаться.
  
  Сигмоидальная функция является:
  
   непрерывной;
   монотонно возрастающей;
   дифференцируемой.
  
  Функция активации гиперболический тангенс
  
  В данной работе в качестве активационной функции для скрытых и выходного слоев
  используется гиперболический тангенс.
  Это обусловлено следующими причинами:
  
   симметричные активационные функции,
   типа гиперболического тангенса обеспечивают более быструю сходимость,
   чем стандартная логистическая функция;
  
   функция имеет непрерывную первую производную;
  
   функция имеет простую производную,
   которая может быть вычислена через ее значение,
   что дает экономию вычислений.
  
  График функции гиперболического тангенса показан на рисунке:
  
  .....
  
  Функция активации ReLU
  
  Известно, что нейронные сети способны приблизить сколь угодно сложную функцию,
  если в них достаточно слоев и функция активации является нелинейной.
  Функции активации вроде сигмоидной или тангенциальной являются нелинейными,
  но приводят к проблемам с затуханием или увеличением градиентов.
  Однако можно использовать и гораздо более простой вариант
  - выпрямленную линейную функцию активации (rectified linear unit, ReLU),
  которая выражается формулой:
  
  .....
  
  График функции ReLU в соответствии с рисунком ниже:
  
  ......
  
  Преимущества использования ReLU:
  
   ее производная равна либо единице, либо нулю,
   и поэтому не может произойти разрастания или затухания градиентов,
   т.к. умножив единицу на дельту ошибки мы получим дельту ошибки,
   если же мы бы использовали другую функцию,
   например, гиперболический тангенс, то дельта ошибки
   могла, либо уменьшиться, либо возрасти, либо остаться такой же,
   то есть, производная гиперболического тангенса возвращает число
   с разным знаком и величиной, что можно сильно повлиять
   на затухание или разрастание градиента.
   Более того, использование данной функции приводит к прореживанию весов;
  
   вычисление сигмоиды и гиперболического тангенса требует выполнения
   ресурсоемких операций, таких как возведение в степень,
   в то время как ReLU может быть реализован с помощью
   простого порогового преобразования матрицы активаций в нуле;
  
   отсекает ненужные детали в канале при отрицательном выходе.
  
  Из недостатков можно отметить, что ReLU не всегда достаточно надежна
  и в процессе обучения может выходить из строя (<умирать>).
  Например, большой градиент, проходящий через ReLU,
  может привести к такому обновлению весов,
  что данный нейрон никогда больше не активируется.
  Если это произойдет, то, начиная с данного момента,
  градиент, проходящий через этот нейрон, всегда будет равен нулю.
  Соответственно, данный нейрон будет необратимо выведен из строя.
  Например, при слишком большой скорости обучения (learning rate),
  может оказаться, что до 40% ReLU <мертвы>
  (то есть, никогда не активируются).
  Эта проблема решается посредством выбора надлежащей скорости обучения.
  
  Обучающие выборки использующиеся в экспериментах
  
  Обучающая выборка состоит из положительных и отрицательных примеров.
  В данном случае из лиц и "не лиц".
  Соотношение положительных к отрицательным примерам 4 к 1,
  8000 положительных и 2000 отрицательных.
  
  В качестве положительной обучающей выборки использовалась база данных LFW3D [7].
  Она содержит цветные изображения фронтальных лиц типа JPEG,
  размером 90x90 пикселей, в количестве 13000.
  
  ......
  
  Пример лиц из базы данных показан в соответствии с рисунком ниже:
  
  ......
  
  В качестве отрицательных обучающих примеров использовалась база данных SUN397 [8],
  она содержит огромное количество всевозможных сцен,
  которые разбиты по категориям.
  Всего 130000 изображений, 908 сцен, 313000 объектов сцены.
  
  ......
  
  Результаты
  
  Прямое распространение сигнала от входного изображения размером 90х90 пикселей
  занимает 20 мс (на ПК), 3000 мс в мобильном приложении.
  При детектировании лица в видеопотоке в разрешении 640х480 пикселей,
  возможно детектировать 50 не перекрытых областей размером 90х90 пикселей.
  Полученные результаты с выбранной топологией сети хуже
  по сравнению с алгоритмом Виолы-Джонса.
  
  Выводы
  
  Сверточные нейронные сети обеспечивают частичную устойчивость
  к изменениям масштаба, смещениям, поворотам, смене ракурса и прочим искажениям.
  
  Ядро - представляет из себя фильтр, который скользит по всему изображению
  и находит признаки лица в любом его месте (инвариантность к смещениям).
  
  Подвыборочный слой дает:
  
   увеличение скорости вычислений (минимум в 2 раза),
   за счет уменьшение размерности карт предыдущего слоя;
  
   фильтрация уже ненужных деталей;
  
   поиск признаков более высокого уровня (для следующего сверточного слоя).
  
  Последние слои - слои обычного многослойного персептрона.
  Два полносвязных и один выходной.
  Этот слой отвечает за классификацию,
  с математической точки зрения моделирует сложную нелинейную функцию,
  оптимизируя которую, улучшается качество распознавания.
  Число нейронов в слое 6 по числу карт признаков подвыборочного слоя.
  
  Возможные улучшения
  
   рассмотреть нейросети Fast-RCNN, YOLO;
   распараллеливание процесса обучения на графические процессоры;
   использование Android NDK (C++) для улучшения производительности
  
  Обучение сверточной нейронной сети описано во второй части.
  https://habrahabr.ru/post/348028/
  
  .......
  
  Ссылки
  
  - Что такое свёрточная нейронная сеть
  https://habr.com/post/309508/
  
  - Обучающие множества:
  Effective Face Frontalization in Unconstrained Images // Effective Face. SUN Database // MIT Computer Science and Artificial Intelligence Laboratory
  
  - Информация по сверточным нейронным сетям
  http://mechanoid.kiev.ua/
  
  - О функциях обучения нейросети
  https://www.monographies.ru/ru/book/section?id=2465
  
  - Виды нейронных сетей (подобная схема классификации нейронных сетей)
  https://ai-science.ru/vidy-nejronnyx-setej/
  
  - Нейронные сети для начинающих: раз и два.
  https://habrahabr.ru/post/312450/
  https://habrahabr.ru/post/313216/
  
  ......
  
  //// Конец цитирования.
  
  Вроде все с этой архитектурой более-менее понятно,
  но это только в теории, а на практике почему-то вылезают
  какие-то "неясные детали".
  Вот что пишут в комментариях к такого рода описаниям архитектур:
  
  \\\ https://habr.com/ru/articles/309508/comments/
  
  \\\ DistortNeo
  \\\ 9 сен 2016 в 01:52
  
  \\\ \\\ почему ядро свертки 3*3, 5*5 или 11*11
  
  \\\ А это просто объяснить через аналогию с фонариком.
  \\\ Вырезаете из картинки кусочек определённого размера
  \\\ и пытаетесь понять,
  \\\ можно ли только по этому кусочку сделать обработку или классификацию.
  \\\ Если нет (кусочек слишком мал) - берите размер фильтра побольше.
  \\\ Если же вам кажется, что размер кусочка можно уменьшить,
  \\\ не потеряв в точности классификации - смело уменьшайте.
  \\\ Чем меньше лишних данных принимает алгоритм машинного обучения,
  \\\ тем легче он обучается и более точные результаты выдаёт.
  
  \\\ \\\ нужно или нет ресайзить исходные картинки,
  \\\ \\\ и если надо в какое разрешение и aspect-ratio
  
  \\\ Зависит от конкретной задачи.
  \\\ В общем случае да, нужно подавать на вход нормализованные данные.
  \\\ Вместо обучения нейросети на нахождение объектов разных размеров
  \\\ (отличие в разы)
  \\\ эффективнее обучать на нахождение объектов фиксированного размера
  \\\ и масштабировать саму картинку.
  //// Т.е. масштабировать нейронка все-таки умеет плохо?
  //// Или тут особенность обучения.
  
  \\\ \\\ как выбрать топологию сети, сколько слоёв
  
  \\\ Если честно, то:
  \\\ 1. Методом научного тыка:
  \\\ попробовать разные варианты и выбрать наиболее удачный.
  
  \\\ 2. Поизучать научную литературу по данной тематике
  \\\ и выбрать готовую успешную топологию из статьи,
  \\\ авторы которой потратили кучу времени
  \\\ и добились успешных результатов, применяя один из этих двух методов.
  
  И как показывает анализ комментариев к материалам по архитектуре СНС
  есть два варианта:
  Либо пытаться реализовать эту структуру с нуля самостоятельно,
  т.е. на основе чисто теоретических знаний.
  Либо "честно содрать" какой-то работающий вариант,
  с использованием стандартных библиотек,
  и попытаться чуть-чуть доработать для своей задачи.
  
  По срокам, то второй вариант, при удачном стечении обстоятельств,
  может занять где-то неделю.
  А первый, при неудачном раскладе, и за год не осилить.
  
  Так что даже хорошее понимание одной конкретной архитектуры
  не дает гарантию того, что для новой задачи/архитектуре
  все сложится более-менее удачно.
  "Наука имеет много гитик".
  
  И в итоге опять остаются два варианта,
  либо махнуть руко на все это "безобразие",
  и перейти к "честному подражательству".
  либо копать дальше тему структур нейросетей,
  в надежде, что когда-то придет "просветление".
  
  \\\ JetHabr
  \\\ https://habr.com/ru/companies/jetinfosystems/articles/791974/
  \\\ 7 фев 2024 в 11:55
  
  \\\ Пришёл ученик к мастеру. И спросил:
  \\\ - Что вы делали до просветления? Как жили?
  \\\ Мастер ответил:
  \\\ - Колол дрова, носил воду, готовил еду.
  \\\ - А что вы делаете после просветления? - спросил ученик.
  \\\ - Колю дрова, ношу воду, готовлю еду, - ответил мастер.
  \\\ - А что изменилось?
  \\\ - Да всё!
  
  
  ========
  
  16.03.2024 17:51
  
  И еще немного сверточных сетей.
  В оглавление.
  
  Чтобы лучше понимать и структуру сверточных нейронных сетей (СНС/CNN)
  и то влияние которые они оказали на архитектуры других нейронок,
  полезно взглянуть, хотя бы вкрадце, на их историю развития.
  Неплохой обзор на эту тему появился и исчез на Хабре,
  но что-то в архивах осталось:
  
  "Заметки на полях из истории развития свёрточных нейросетей".
  Автор: anikengur (Аня Кангур)
  https://habr.com/ru/articles/800077/
  13 мар 2024 в 19:35
  
  Так как сейчас материал не доступен по прямой ссылке,
  то приведу его максимально подробно.
  Есть в нем и хорошие формулировки, и интересные наблюдения.
  
  //// Начало цитирования.
  
  Эти заметки отражают лишь небольшую часть истории развития
  сверточных нейронных сетей,
  и каждый из этих моментов играл важную роль
  в улучшении производительности и эффективности нейронных сетей
  в области компьютерного зрения.
  
  Ключевые элементы:
  
  Convolution Layer (сверточный слой)
  https://habr.com/ru/articles/795223/
  - наложение фильтров (ядер) на разные кусочки изображения (окна).
  На выходе получается карта активаций,
  которая говорит о том, насколько фильтр оказался похож
  на кусочек изображения, к которому был приложен.
  Находится скалярным произведением.
  
  Pooling (слой подвыборки)
  объединяет информацию из соседних нейронов.
  MaxPool - выбор максимального значения окна,
  AvgPool - вычисление среднего из окна.
  Обычно применяется после сверточного слоя.
  
  Activation function (функция активации)
  привносит нелинейность в нейронную сеть.
  Известные функции: Sigmoid, Tanh, ReLU, ELU и другие.
  Применяется поэлементно.
  
  Flatten преобразует многомерный массив в вектор построчно.
  
  Fully Connected Layer (полносвязный слой)
  - самый обычный нейронный слой:
  на вход подаются все значения из предыдущего слоя
  и скалярно перемножаются на веса.
  
  SoftMax преобразует вектор чисел в вектор вероятностей.
  В выходном векторе сумма всех элементов равна 1.
  
  Архитектуры:
  
  LeNet
  
  AlexNet
  
  VGG - Visual Geometry Group
  
  GoogLeNet
  
  ResNet
  
  1. LeNet (1998)
  
  Архитектура LeNet была предложена Яном Лекуном
  для решения задачи распознавания рукописных цифр от 0 до 9 из датасета MNIST.
  Датасет состоит из 60k обучающих и 1k тестовых примеров размером 28 x 28 (одноканальные).
  
  LeNet пропускает изображения через два набора свёрток,
  затем распрямляет вектор,
  и применяет полносвязные слои.
  На выходе получается вектор из 10 цифр - вероятностей классов.
  //// Возможно с этого решения и пошла вся последующая "традиция"
  //// трактовать результаты выходного слоя как "распределения вероятностеей".
  //// Причем, именно для этой конкретной архитектуры это выглядело
  //// вполне логично и обоснованно.
  В качестве функции активации используется сигмоида или гиперболический тангенс,
  но в современных реализациях предпочтение отдаётся ReLU и его вариациям.
  
  Архитектура LeNet имела огромное значение для развития области
  компьютерного зрения и глубокого обучения,
  показав, что сверточные нейронные сети могут эффективно применяться
  для задач распознавания изображений.
  
  2. AlexNet (2012)
  
  Задача MNIST - несколько игрушечная.
  Современные нейронные сети соревнуются в решении ImageNet 1000:
  задачи о разбиении 15 миллионов изображений на тысячу классов
  (автомобили, породы собак, какие-то канцелярские принадлежности и т.д.).
  Причем, хороших изображений (которые действительно относятся
  к этой тысяче классов) около 1.5 миллиона.
  Первая нейронная сеть, которая научилась решать эту задачу - AlexNet.
  
  На вход принимается трехканальные изображение размером 224 x 224.
  AlexNet содержит восемь слоев:
  первые пять - сверточные
  (за некоторыми из них следуют MaxPooling слои),
  а последние три - полносвязные.
  
  Из "трюков":
  MaxPooling используется после каскада сверток (нескольких сверток подряд),
  а проблема затухающего градиента решается с помощью функции активации ReLU.
  
  3. VGG - Visual Geometry Group (2014)
  
  Большое количество функций активаций все равно приведет к затуханию градиента.
  При этом, VGG, в своем финальном варианте содержит аж 19 слоев
  и показало хорошие результаты благодаря своему особому способу обучения:
  
  Сначала обучаются лишь 11 слоёв (8 сверток и 3 полносвязных слоя).
  
  Затем, к сети добавляются еще два сверточных слоя на глубоких слоях
  (после первой и второй свертки).
  В результате, добавленные слои дообучаются чуть быстрее,
  чем если бы сразу делалась такая сеть.
  //// Интересно было бы найти исследование по такому последовательному обучению
  //// с анализом того, что именно при этом происходит в обучаемых слоях,
  //// как новых, так и предобученных.
  
  После, добавляются ещё три слоя (свертки 1 x 1 после 6, 8 и 10 слоев)
  и дообучается сеть. Так она адаптируется под дополнительные элементы.
  
  Затем выбрасываются свёртки 1 x 1
  и добавляются на их место свёртки размером 3 x 3, и дообучаются.
  //// Тоже интересный момент с этой заменой сверток разной размерности.
  //// Как это проявляется в процессе обучения?
  
  После, добавляются еще три свёрточных слоя после 7, 10 и 13 слоев
  и дообучаются.
  
  Построенный таким образом процесс обучения приводит
  к достаточно сложной, но хорошо обученной нейронной сети,
  в которой и первые слои и последние слои обучены достаточно хорошо.
  //// А что, промежуточные слои обучены "недостаточно хорошо"?
  //// Что подразумевается под этой фразой?
  
  VGG - достаточно мощная сеть с большим количеством параметров.
  Она может использоваться в качестве backbone для более сложных архитектур.
  
  Backbone значит что можно убрать последние полносвязные слои из VGG,
  <заморозив> все предыдущие сверточные
  (не обучать, оставить параметры как есть),
  добавить свои новые сверточные и полносвязные слои
  и обучить новую сеть под свою задачу.
  
  4. GoogLeNet
  
  Более сложная архитектура,
  решившая задачу ImageNet 1000 с использованием трюка
  под названием Inception Block:
  одновременное применение нескольких разных сверток или pooling-ов,
  с последующей поканальной конкатенацией результатов
  (выходные изображения должны быть одинакового размера).
  
  Рис. Inception Block
  
  BottleNeck (бутылочное горлышко)
  - свертки 1 x 1 для уменьшения или увеличения количества каналов.
  
  GoogLeNet - огромная сеть с 22 слоями,
  состоящая преимущественно из inception блоков.
  
  Проблему затухающего градиента они решили
  с помощью вспомогательных функций потерь.
  Идея такая:
  если при обратном распространении ошибки на слой приходит маленький градиент,
  то основная функция потерь заменяется на вспомогательную
  и вглубь начинает распространяться новый градиент, достаточно большой.
  Такие вспомогательные функции можно было поставить в каждом Inception блоке,
  но в GoogLeNet их всего две.
  //// Тоже интересная идея, в том смысле,
  //// что оказывается можно сильно подкорректировать
  //// "классическое обратное распространение ошибки",
  //// просто принудительно используя "вспомогательные функции".
  //// Интересно, было ли дальнейшее развитие этой методики?
  
  Рис. GoogLeNet
  
  5. ResNet, Residual neural network (Microsoft, 2015)
  
  Свое название архитектура получила благодаря трюку
  под названием Residual Block.
  Основная идея в том, что входные данные передаются через блоки (слои)
  без изменений и соединяются с выходным данным блока.
  Таким образом была решена проблема затухания градиента
  при обучении очень глубоких нейронных сетей.
  //// Мне почему-то кажется, что решение "проблемы затухающего градиента"
  //// в этом приеме далеко не главное,
  //// Использование таких прямых или, наоборот, обходных связей
  //// несет в себе возможность более глубокого анализа входных данных,
  //// более точной настройки на какие-то "детали".
  //// И по факту, Residual Block, правда часто называемых как-то по-другому,
  //// сейчас используются очень широко в различных архитектурах,
  //// включая и трансформерные блоки.
  //// И то, что такое решение, попутно уменьшает проблему "затухающих градиентов",
  //// на самом деле, просто "приятный бонус" к чему-то более существенному.
  
  Рис. Residual Block
  
  Сеть ResNet состоит из Residual Block-ов следующих друг за другом.
  При этом, вариантов ResNet несколько:
  ResNet18 (состоящий из 18 слоев), ResNet32 и даже ResNet1024.
  
  Рис. ResNet
  
  Так же, в ResNet отсутствуют полносвязные слои.
  Вместо этого, с помощью AvgPooling,
  тензор масштабируется до размера полносвязного слоя.
  После пропускается через один полносвязный слой
  (чтобы на выходе был вектор 1 x 1000) и применятся SoftMax.
  За счет этого ResNet неважно,
  сколько пикселей во входном изображении,
  но, желательно, чтобы размер был кратен 32,
  т.к. в сети происходит 5 раз уменьшение изображения в 2 раза.
  
  ResNet довольно часто используется как backbone.
  Например, вот недавнее упоминание в статье
   о прогнозировании последствий извержения вулканов на Камчатке.
  https://habr.com/ru/companies/yandex/articles/794883/
  
  ........
  
  //// Конец цитирования.
  
  На мой взгляд, очень неплохой материал для расширения кругозора.
  Почему к нему закрыли доступ, мне совершенно непонятно,
  Может быть, автор в чем-то там ошиблась, не знаю - квалификации не хватает,
  а возможно решила в чем-то его доработать.
  В любом случае, спасибо и за этот вариант.
  
  
  ========
  
  16.03.2024 17:51
  
  И снова трансформеры.
  В оглавление.
  
  Еще один очень неплохой материал по трансформерам.
  Во всяком случае, именно по материалу я разобрался в парочке вопросов,
  которые ну никак не удавалось осмыслить по другим материалам.
  Очень рекомендую познакомиться с ним в оригинале,
  там очень наглядные иллюстрации, которые обязательно нужно увидеть,
  чтобы понимание работы трансформеров поднялось на новый уровень:
  
  "Наглядно о том, почему трансформеры работают настолько хорошо".
  Автор: factorial42
  https://habr.com/ru/companies/skillfactory/articles/562928/
  20 июн 2021 в 17:17
  
  Автор оригинала: Ketan Doshi
  https://towardsdatascience.com/transformers-explained-visually-not-just-how-but-why-they-work-so-well-d840bd61a9d3
  
  //// Начало цитирования.
  
  Трансформеры за последние несколько лет штурмом захватили мир NLP,
  а сегодня они с успехом применяются в выходящих за рамки NLP приложениях.
  Они обладают такими возможностями благодаря модулю внимания,
  который схватывает отношения между всеми словами последовательностей.
  Но самый важный вопрос - как именно трансформеры делают это?
  Попытаемся ответить и понять,
  почему трансформеры способны выполнять такие вычисления.
  Итак, цель статьи, чуть сокращённым переводом которой мы делимся
  к старту курса о машинном и глубоком обучении,
  - разобраться не только с тем, как что-то работает,
  но и почему работает так.
  Чтобы понять, что движет трансформерами,
  мы должны сосредоточиться на модуле внимания.
  Начнём с входных данных и посмотрим, как они обрабатываются.
  
  Как входная последовательность попадает в модуль внимания
  
  Модуль внимания присутствует в каждом энкодере внутри стека каждого энкодера,
  а также внутри стека каждого декодера.
  Сначала внимательно посмотрим на энкодер.
  
  Рис. Модуль внимания в энкодере
  
  Для примера предположим,
  что мы работаем над задачей перевода с английского на испанский,
  где исходная последовательность слов - ,
  а целевая последовательность - .
  
  Исходная последовательность сначала проходит
  через слой векторного представления и позиционного кодирования,
  генерирующего векторы векторного представления
  для каждого слова последовательности.
  Векторное представление передаётся в энкодер,
  где вначале попадает в модуль внимания.
  
  Внутри модуля внимания последовательность векторного представления
  проходит через три линейных слоя,
  создающих три отдельные матрицы
  - запроса (Query), ключа (Key) и значения (Value).
  Именно эти три матрицы используются для вычисления оценки внимания
  [прим. перев. - оценка определяет, сколько внимания нужно уделить
  другим частям входного предложения,
  когда мы кодируем слово в определённой позиции].
  Важно помнить, что каждая "строка" этих матриц соответствует
  одному слову исходной последовательности.
  
  Рис. Поток исходной последовательности
  
  Каждая входная строка - это слово из последовательности
  
  Чтобы понять, что происходит с модулем внимания,
  мы начнём с отдельных слов исходной последовательности,
  проследив их путь через трансформер.
  Если конкретнее, мы хотим сосредоточиться
  на происходящем внутри модуля внимания.
  Это поможет нам чётко увидеть,
  как каждое слово в исходной и целевой последовательностях
  взаимодействует с другими словами этих последовательностей.
  
  Пока вы разбираетесь с этим объяснением,
  сосредоточьтесь на том, какие операции выполняются с каждым словом
  и как каждый вектор отображается на исходное входное слово.
  Не нужно думать о множестве других деталей,
  таких как формы матриц, особенности арифметических вычислений,
  множественное внимание и так далее,
  если эти детали не относятся напрямую к тому,
  куда направляется каждое слово.
  Итак, чтобы упростить объяснение и визуализацию,
  давайте проигнорируем размерность векторного представления
  и будем отслеживать только строки для каждого слова.
  
  Рис. Расположение каждого слова в исходной последовательности
  
  Каждое слово проходит серию обучаемых преобразований (трансформаций)
  
  Каждая такая строка была сгенерирована из соответствующего исходного слова
  посредством серии трансформаций
  - векторного представления, позиционного кодирования и линейного слоя.
  Все эти трансформации возможно обучить;
  это означает, что используемые в этих операциях веса не определены заранее,
  а изучаются моделью таким образом,
  чтобы они давали желаемые выходные прогнозы.
  
  Рис. Линейные веса и веса векторного представления обучены
  
  Ключевой вопрос заключается в том, как трансформер определяет,
  какой набор весов даст ему наилучшие результаты?
  Держите этот момент в памяти - мы вернёмся к нему немного позже.
  
  Оценка внимания
  - это скалярное произведение матрицы ключа и матрицы запроса слов
  
  Модуль внимания выполняет несколько шагов,
  но здесь мы сосредоточимся только на линейном слое и на оценке внимания.
  
  Рис. Многоголовое внимание
  
  Рис. Расчёт оценки внимания
  
  Как видно из формулы, первый шаг в рамках модуля внимания
  - умножение матрицы, то есть скалярное произведение
  между матрицей Query (Q) и транспонированием матрицы ключа Key (K).
  /// "транспонированной".
  Посмотрите, что происходит с каждым словом.
  Итог - промежуточная матрица
  (назовём её <факторной> матрицей [матрицей множителей]),
  где каждая ячейка - это результат матричного умножения двух слов.
  
  Рис. Скалярное произведение матрицы запроса и матрицы ключа
  
  Например, каждый столбец в четвёртой строке
  соответствует скалярному произведению между четвёртым словом запроса
  и каждым ключевым словом.
  
  Рис. Скалярное произведение между матрицами запроса и ключа
  
  Оценка внимания - скалярное произведение между запросом-ключом
  и значением слов
  
  Следующим шагом является матричное умножение
  между этой промежуточной матрицей <множителей>
  и матрицей значений (V),
  чтобы получить оценку внимания,
  который выводится модулем внимания.
  Здесь мы можем видеть,
  что четвёртая строка соответствует четвёртой матрице слов запроса,
  умноженной на все остальные ключевые слова и значения.
  
  Рис. Скалярное произведение между матрицами ключа запроса и значения
  
  //// На мой взгляд, это ключевая иллюстрация в данном материале.
  //// Во всяком случае, именно этой иллюстрации мне лично не хватало,
  //// чтобы понять идеологию "внутреннего внимания",
  //// как суммы произведения матриц "запроса" и "ключа" на вектор "значения".
  
  Получается вектор оценки внимания (Z),
  который выводится модулем внимания.
  Выходной результат можно представить следующим образом:
  для каждого слова это закодированное значение каждого слова
  из матрицы <Значение>,
  взвешенное матрицей множителей.
  Матрица множителей представляет собой
  точечное произведение значения запроса для данного конкретного слова
  и значения ключа для всех слов.
  
  Рис. Оценка внимания - это взвешенная сумма значения слов
  
  //// Ну наконец-то окончательно понял эту математику.
  //// Лишь бы к завтрашнему дню не забыть.
  //// И, интересно, что сразу же появились мысли, как это хотелось бы
  //// представить/преобразовать в "побитной логике".
  
  Какова роль слов запроса, ключа и значения?
  
  Слово запроса - это слово,
  для которого мы рассчитываем внимание.
  В свою очередь слово ключа и значения
  - это слово, на которое мы обращаем внимание,
  то есть определяем, насколько это слово соответствует слову запроса.
  
  Рис. Оценка внимания для слова обращает внимание на каждое слово
  
  //// Т.е., по факту, речь идет об определенной "связанности"
  //// элементов входной последовательности,
  //// реализуемой посредством "умножения обучаемых матриц",
  //// и последующего "взвешивания".
  
  Например, для предложения
  строка для слова будет содержать оценку внимания
  для слова с каждым вторым словом.
  Здесь - это слово запроса,
  а другие слова - <ключ/значение>.
  Выполняются и другие операции,
  такие как деление и softmax,
  но мы можем проигнорировать их в этой статье.
  Они просто изменяют числовые значения в матрицах,
  но не влияют на положение каждой строки слов в ней.
  Они также не предполагают никаких взаимодействий между словами.
  
  Скалярное произведение сообщает нам о сходстве слов
  
  Итак, мы увидели, что оценка внимания отражает некоторое взаимодействие
  между определённым словом и каждым другим словом
  в предложении путём скалярного произведения
  с последующим их сложением.
  Но как матрица умножения помогает трансформеру
  определять релевантность между двумя словами?
  
  Чтобы понять это, вспомните,
  что строки запроса, ключа и значения
  на самом деле являются векторами с размерностью векторного представления.
  Давайте посмотрим, как умножаются матрицы между этими векторами.
  
  Рис. Каждая ячейка представляет собой скалярное произведение двух векторов слов
  
  Для получения скалярного произведения двух векторов мы умножаем пары чисел,
  а затем суммируем их.
  
   Если два парных числа (например, и выше) оба положительны
   или оба отрицательны, произведение положительно.
   Произведение увеличит итоговую сумму.
  
   Если одно число положительное, а другое отрицательное,
   произведение будет отрицательным.
   Произведение уменьшит итоговую сумму.
  
   Если произведение положительное,
   то, чем больше два числа, тем больше их вклад в окончательную сумму.
  
  Это означает, что, если знаки соответствующих чисел в двух векторах выровнены,
  итоговая сумма будет больше.
  //// Все больше и больше в голову приходят мысли о "побитовой логике".
  
  Как трансформер изучает релевантность между словами?
  
  Скалярное произведение также применимо к оценке внимания.
  Если векторы для двух слов более выровнены, оценка внимания будет выше.
  Итак, какого поведения мы хотим от трансформера?
  Мы хотим, чтобы оценка внимания была высокой
  для двух релевантных друг другу слов в предложении.
  И мы хотим, чтобы оценка двух слов, не связанных друг с другом, была низкой.
  
  Например, в предложении
  слово очень релевантно к ,
  возможно, немного менее релевантно для ,
  и нерелевантно к .
  Мы хотим, чтобы и давали высокую оценку внимания,
  чтобы и давали немного более низкую оценку,
  а для и - незначительную.
  Мы хотим, чтобы модель научилась воспроизводить этот результат.
  Чтобы достичь воспроизводимости,
  векторы слов и должны быть выровнены.
  Векторы и несколько разойдутся.
  А для и они будут совершенно разными.
  
  Давайте вернёмся к вопросу, который мы откладывали:
  как трансформер определяет,
  какой набор весов даст ему наилучшие результаты?
  Векторы слов генерируются на основе векторного представления слов
  и весов линейных слоёв.
  Следовательно, трансформер может изучить эти векторные представления,
  линейные веса и так далее, чтобы создать векторы слов, как требуется выше.
  
  Другими словами, он будет изучать эти векторные представления и веса
  таким образом, что если два слова в предложении релевантны друг другу,
  то их векторы слов будут выровнены,
  следовательно, получат более высокую оценку внимания.
  Для слов, которые не имеют отношения друг к другу,
  их векторы не будут выровнены и оценка внимания будет ниже.
  
  Следовательно, векторные представления слов и
  будут очень согласованными и обеспечат высокую оценку внимания.
  Они будут несколько отличаться для и ,
  производить немного более низкую оценку
  и будут совершенно разными в случае и :
  оценка внимания будет низкой
  - вот лежащий в основе модуля внимания принцип.
  //// Принцип, вроде, понятен.
  //// Но остается вопрос: "как происходит обучение матриц "запроса" и "ключа"
  //// "не в принципе, а в кожухе"?
  //// И этот вопрос теперь следующий в очереди на понимание
  //// работы трансформерных блоков.
  //// И что-то пока я не видел ни одного материала на эту тему.
  
  Итак, как же работает трансформер?
  
  Скалярное произведение между запросом и ключом
  вычисляет релевантность между каждой парой слов.
  Эта релевантность затем используется
  как <множитель> для вычисления взвешенной суммы всех <значений> слов.
  Эта взвешенная сумма выводится как оценка внимания.
  Трансформер изучает векторные представления и т. д.
  таким образом, что релевантные друг другу слова были более согласованы.
  
  В этом кроется одна из причин введения трёх линейных слоёв
  и создания трёх версий входной последовательности:
  для запроса, ключа и значения.
  Такой подход даёт модулю внимания ещё несколько параметров,
  которые он может изучить, чтобы подстроить процесс создания векторов слов.
  
  Самовнимание энкодера в трансформере
  
  Внимание используется в трансформере в трёх местах:
  
   Самовнимание в энкодере
   - исходная последовательность обращает внимание на себя.
  
   Самовнимание в декодере
   - целевая последовательность обращает внимание на себя.
  
   Энкодер-декодер-внимание в декодере
   - целевая последовательность обращает внимание на исходную последовательность.
  
  Рис. Внимание в трансформере
  
  В самовнимании энкодера мы вычисляем релевантность каждого слова
  в исходном предложении каждому другому слову в исходном предложении.
  Это происходит во всех энкодерах стека.
  
  Декодер самовнимания в трансформере
  
  Большая часть того, что мы только что видели в энкодере самовнимания,
  применима и к вниманию в декодере,
  но с некоторыми существенными отличиями.
  
  Рис. Внимание в декодере
  
  В декодере самовнимания мы вычисляем релевантность каждого слова
  в целевом предложении каждому другому слову в целевом предложении.
  
  Рис. Самовнимание декодера
  
  Энкодер-декодер модуля внимания в трансформере
  
  В энкодере-декодере запрос получается из целевого предложения,
  а ключ/значение - из исходного предложения.
  Таким образом, он вычисляет релевантность каждого слова
  в целевом предложении каждому слову в исходном предложении.
  
  Рис. Энкодер-декодер Внимания
  
  Заключение
  
  Надеюсь, статья дала вам хорошее представление
  об элегантности архитектуры трансформера.
  Прочтите также другие статьи о трансформере из моей серии,
  чтобы лучше представлять, почему сегодня трансформер
  - это предпочтительная архитектура многих приложений глубокого обучения.
  
  Здесь мы видим, что за сложными идеями скрываются простые решения.
  Более того, есть ощутимая вероятность того,
  что вскоре понимание внутренних механизмов глубокого обучения
  станет <второй грамотностью>,
  как сегодня второй грамотностью стало знание ПК в целом...
  
  .....
  
  //// Конец цитирования.
  
  Очень полезная для меня оказалась эта статья.
  И как раз вовремя.
  Совместно с работой/размышлениями над структурой значений
  одноэлементного эмбеддинга, подробнее см.:
  "Металоция неведомого. Модуль Э. Эмбеддинги."
  этот материал послужил толчком к разработке структуры битовых нейросетей (БНС),
  за что и автору и переводчику этого материала
  глубокая и искренняя благодарность.
  
  P.S.
  Если интересно, что это за БНС, то какую-то первоначальную формулировку см.:
  "Первая попытка сформулировать концепцию битовой нейронной сети (БНС)".
  
  
  ========
  
  23.03.2024 11:13
  
  Что общего между структурным мышлением и структурой нейросетей?
  В оглавление.
  
  Знакомство с "зоопарком" и "кунсткамерой" нейросетей
  - дело, конечно, полезное.
  Но все-таки главная цель этого не только понимать существующие конструкции,
  но и научиться видеть определенные перспективы их дальнейшего развития.
  И чтобы как-то начать подступаться к этому вопросу,
  на мой взгляд, стоит попытаться разобраться,
  а что собственно не хватает существующим архитектурам:
  
  "Структурное мышление или важное отличие человека от ИИ".
  Автор: Atmyre (Татьяна Гайнцева)
  https://habr.com/ru/articles/687646/
  14 сен 2022 в 16:00
  
  //// Начало цитирования.
  
  В этой статье я расскажу об одном из самых важных отличий
  человеческого мышления от того,
  как работают нейросети:
  о структурном восприятии мира.
  Мы поймем, как это отличие мешает ИИ эффективно решать многие задачи,
  а также поговорим об идеях,
  с помощью которых можно внедрить в нейросети понимание структуры.
  В том числе обсудим недавние работы таких известных в области AI людей,
  как Джеффри Хинтон и Ян ЛеКун.
  
  .......
  
  Структурное мышление
  
  Существуют убедительные данные, что мы - люди - воспринимаем мир
  с помощью структуры.
  
  (ссылки на научные работы касательно структурного восприятия мира человеком,
  подкрепляющие утверждения этого раздела,
  можно найти в разделе "Литература" в конце статьи)
  
  Это значит, что мы делим все сложные абстрактные понятия на части,
  и воспринимаем все объекты и понятия
  как сложные составные сущности,
  состоящие из простых элементов (building blocks),
  которые взаимодействуют между собой (имеют relations).
  
  ........
  
  Эти понятия (улица, город, страна в нашем примере) и связи между ними
  создают иерархическую структуру с взаимодействиями
  между элементами у нас в голове.
  
  ........
  
  Вообще, иерархия - самый эффективный способ организации систем
  с точки зрения взаимодействия элементов системы,
  их специализации и передачи информации между частями системы.
  Почему это так, можно прочитать в книге "Азбука системного мышления"
  (Глава 3: "Почему системы так хорошо работают")
  https://www.mann-ivanov-ferber.ru/books/azbuka-sistemnogo-myishleniya/
  Скорее всего, иерархическое мышление у людей также развилось
  по причине его эффективности.
  Мысля таким образом, мы затрачиваем меньше энергии,
  чем если бы мышление было устроено другим образом.
  
  Далее, кроме иерархии мы также оперируем ассоциациями:
  проводим аналогии, ищем связи между различными сущностями.
  Ассоциации могут основываться на совершенно разном:
  форме объектов, запахе, цвете, звуковых сигналах.
  По сути, ассоциации - это вид взаимодействий между объектами,
  который основан на их схожести по какому-то принципу.
  
  ......
  
  Структурное ассоциативное мышление помогает нам
  эффективно воспринимать мир и приспосабливаться к новому.
  Вот как:
  
  Сталкиваясь с чем-то новым,
  мы пытаемся разделить это новое
  на известные нам из прошлого опыта составляющие
  (те самые building blocks)
  и таким образом создать структурное представление новой сущности.
  Как только структурное представление новой сущности создано,
  мы можем делать выводы о новой сущности.
  Эти выводы основаны на том,
  из каких известных элементов состоит структура нового объекта
  и наших знаний об этих известных элементах и их взаимодействиях.
  //// Но ведь это по факту ассоциативно-структурное мышление,
  //// где ассоциации идут впереди структуры.
  
  Некоторые элементы, на которые мы разделили новую сущность,
  могут быть новыми:
  точно таких же вы никогда не видели.
  Но ассоциативное мышление может создать связь между этим новым элементом
  и тем, что вы видели раньше.
  Перенеся свойства ранее виденного элемента на новый,
  вы многое поймете о новом элементе.
  //// Похоже, "телега" (структура), поставлена впереди "лошади" (ассоциаций).
  //// Странно, что данный исследователь этого не замечает.
  
  ......
  
  Идем далее:
  структурное мышление позволяет нам создавать новое
  на основе отдельных известных частей:
  спроектировать новый город будущего,
  по-разному соединяя отдельные известные части (building block'и: дома и улицы)
  с помощью разных известных взаимосвязей (relations).
  Например, кто-то же создал несуществующее животное с картинки выше.
  Оно состоит из вполне стандартных, известных нам элементов.
  
  .......
  
  Таким образом, структурное мышление помогает нам взаимодействовать с миром,
  жить и развиваться.
  Так или иначе, мы каждый день сталкиваемся с чем-то новым
  и успешно с ним взаимодействуем благодаря механизму восприятия,
  описанному выше.
  Столкнувшись с чем-то новым,
  мы либо встраиваем новую сущность
  в существующую в нашей голове структуру мира,
  либо изменяем вид структуры в голове так,
  чтобы новая сущность и старый опыт органично вписывались в эту структуру.
  //// Либо откладываем это действие до получения дополнительной информации.
  
  Это умение разбивать высокоуровневые понятия на структурные элементы,
  осознавать и создавать новое,
  собирая его из хорошо известных старых понятий,
  называется комбинаторным обобщением (conbinatorial generalization).
  И это - то, что суперлегко дается мозгу человека
  и суперсложно - искусственному интеллекту.
  В частности, подходам, основанным на нейросетях.
  //// Все это имело смысл заявлять два года назад,
  //// а сейчас уже очевидно, что "что-то не так".
  
  ......
  
  Нейросети и структура
  
  Если посмотреть на принципы работы современных нейросетей,
  в них, на самом деле, можно найти структурные элементы.
  
  Возьмем, к примеру, сверточные нейросети (CNN).
  Сверточные слои состоят из фильтров,
  которые выделяют из изображения информацию о паттернах,
  которые присутствуют на изображении.
  Причем каждый последующий сверточный слой реагирует
  на все более сложные, высокоуровневые паттерны, чем предыдущие слои.
  //// А не наоборот, на все более "унифицированное", то бишь "упрощенное"?
  //// Тут вопрос, что есть "высокоуровневое" представление?
  
  Рис. https://www.quora.com/How-does-a-convolutional-neural-network-recognize-an-occluded-face
  Примеры паттернов, на которые реагируют последовательные слои сверточной нейросети.
  Первые слои реагируют на низкоуровневые паттерны
  вроде вертикальных/диагональных линий,
  следующие слои реагируют на более сложные паттерны (глаз/нос),
  последние - на паттерны наличия лица.
  
  Получается, сверточные слои как бы обрабатывают картинку,
  распознавая на ней сначала низкоуровневые паттерны,
  а затем постепенно собирая эти паттерны вместе в более сложные конструкции.
  //// Типично "ассоциативно-структурное представление".
  //// Кстати, сверточная сеть очень удобный пример для такого анализа,
  //// и именно поэтому в этом модуле ей, наряду с трансформерами,
  //// уделяется особое внимание.
  //// В какой-то мере идея этого модуля родилась под влиянием этого текста.
  Это напоминает структуру:
  нейросеть учится находить на изображении отдельные элементы (паттерны),
  а затем собирает целое из составных элементов.
  
  Однако такой идеи устройства нейросети недостаточно,
  чтобы нейросеть развила понимание структуры,
  приближенное к тому, как структуру понимает человек.
  Свидетельством этому служат проблемы,
  которые возникают и у сверточных,
  и у практически всех других нейросетей повсеместно.
  Далее мы рассмотрим некоторые из них.
  
  Можете подумать о том, почему той структуры,
  что есть в сверточных нейросетях,
  не хватает для имитации восприятия человека.
  Чего недостает сверточным сетям?
  
  Общие проблемы нейросетей
  
  У нейросетей есть несколько известных общих проблем.
  Общих - потому что эти проблемы характерны для всех видов нейросетей.
  Рассмотрим три из них:
  те, которые, на мой взгляд, связаны
  с отсутствием у нейросетей понимания структуры.
  
   Знания нейросетей плохо переносятся из домена в домен,
   даже если домены сильно похожи.
   Например, нейросеть, которая отлично распознает лица европейцев,
   будет плохо работать на лицах людей из Африки.
   Эта проблема называется domain shift / out-of-domain.
   Или, еще по-другому - отсутствие у нейросетей обобщающей способности.
   Есть отдельные направления исследований,
   которые ищут подходы для улучшения адаптации нейросетей к новым доменам:
   эти области называются domain adaptation или transfer learning.
   Но все эти техники далеки от совершенства,
   проблема domain shift еще не решена.
  //// И опять эта информация устаревшая, особенно по отношению к LLM.
  
   Для человека проблемы domain shift практически не стоит.
   Мы легко проводим аналогии между объектами из двух доменов,
   выделяя в каждом структурные элементы и сопоставляя их между собой.
  //// Неверно, отличать лица европейцев европейцам на порядок легче чем лица азиатов.
   Выделив в объекте из неизвестного домена знакомую структуру,
   мы понимаем, что примерно представляет из себя объект
   и как с этим объектом взаимодействовать.
   Другими словами, мы сравниваем разные объекты из разных доменов
   между собой на основе структуры,
  //// Структуры или ассоциаций?
  //// Вопрос не риторический, ведь если для "ассоциаций" в той же сверточной сети
  //// есть хоть какая-то "аппаратная поддержка",
  //// то для "структур" как-то ничего не наблюдается.
  //// А что есть у человека вообще неизвестно.
   не обращая внимания на мелкие неважные различия.
   Мы поймем, что перед нами человек,
   даже если этот человек будет неизвестной нам ранее расы:
   мы поймем это, проведя аналогию между людьми известных нами рас
   и людьми новой расы на основе того,
   что оба типа людей состоят из одинаковых структурных элементов:
   головы, глаз, носа, рук и т.д.
   Таким образом, умение к комбинаторному обобщению
  //// Комбинаторное обобщение - интересный термин.
  //// А как его можно реализовать?
  //// И нет ли здесь какой-то связи/аналогии с трансформерными блоками?
   позволяет людям взаимодействовать
   со структурно похожими элементами из разных доменов.
  
   Нейросети чувствительны к шуму и малым изменениям в данных
   (это проблема отсутствия устойчивости/робастности нейросетей).
  //// Это не совсем так, а иногда совсем не так.
  //// Ту скорее проблема "нелинейности"/"разрывности" структуры значений эмбеддингов.
   Даже самое малое изменение картинки, малое добавление шума
   может сильно изменить ответ нейросети.
   Посмотрим, например, на две картинки ниже.
   Человеку явно понятно, что на картинках один и тот же объект,
   и малый шум не мешает это осознать,
   точно так же как и новая шляпа из примера выше не мешала понять,
   что перед нами тот же друг Петя.
   Просто для нас картина и шум - это две сущности,
   которые взаимодействуют между собой.
   И взаимодействуют они так,
   что шум не меняет значения объектов на картине.
  //// Это выделение шума/фона/ритма чем-то похожа и чем-то обратна
  //// задаче "учета контекста". Так что может быть и решение будет
  //// очень похожим в виде "нойз-трансформера".
  
   У нейросетей же так не получается:
   совсем малый шум может сильно изменить восприятие объекта нейросетью.
   Это выдает отсутствие в нейросетях структуры,
   а также позволяет создавать adversarial атаки на сети.
   Adversarial атака - это когда входящий объект изменяется
   очень малым образом,
   так, что человеку практически не заметно,
   но ответ нейросети на этот объект при этом сильно искажается.
   Более подробно об adversarial атаках можно почитать тут.
  https://engineering.purdue.edu/ChanGroup/ECE595/files/chapter3.pdf
  
  Рис. https://medium.comr/the-unusual-effectiveness-of-adversarial-attacks-e1314d0fa4d3
  Пример adversarial attack.
  При подаче в нейросеть картинки слева модель классифицирует ее правильно: "поросенок".
  Но при добавлении небольшого шума, не видного глазу,
  нейросеть начинает классифицировать правую картинку как "авиалайнер".
  
   Для обучения нейросетей требуется огромное количество данных.
   При малом количестве обучающих данных нейросети переобучаются.
  //// Опять эта мантра про "переобучение".
  //// И когда много данных тоже может быть "переобучение" и когда мало,
  //// а кто-то пытался сформулировать условия,
  //// когда его гарантированно быть не может?
   Человек же может обучиться под новую задачу на основе ограниченного опыта.
   Это умение людей, опять же, связано со структурным мышлением:
   как было показано в примере с диким зверем,
   мы можем собирать общее представление о новом объекте,
   разложив объект на известные составные части
   и проанализировав их взаимодействия.
   Пары объектов нового вида будет достаточно,
   чтобы на основе их структуры сделать о них выводы
   и научиться правильно с ними взаимодействовать.
  
   По сути, эта проблема - следствие первой проблемы
   (отсутствия обобщающей способности).
  //// А как тогда быть с повальным "увлечением" нейросетями именно
  //// из-за их какой-то "магической обобщающей способности"?
  //// Или это какой-то другой вид "обобщающей способности"?
   Если бы нейросети обладали хорошей обобщающей способностью,
   то хорошее предобучение нейросети позволило бы дообучать
   ее на новые задачи,
  //// А именно это сейчас как раз и есть основной тренд в обучении.
   используя малое количество данных.
   Здесь предобучение сети можно сравнить с человеческим опытом:
   человек быстро научается решать новые задачи
   благодаря структурному мышлению и опыту.
  
  В общем-то, все описанные проблемы имеют одну основу:
  нейросети плохо справляются с любыми данными,
  которые как-то отличаются от тех, на которых нейросеть была обучена.
  //// Все это имело смысл до "явления ChatGPT народу и миру".
  
  Один из возможных способ решить эту проблему
  - наделить нейросети способностью к комбинаторному обобщению,
  "заставив" нейросеть воспринимать объекты структурно.
  //// А вот с этим полностью соглашусь.
  //// Неплохо бы это сделать, вот только как?
  
  Есть несколько идей, как это можно сделать.
  Далее мы рассмотрим некоторые из них.
  
  Внедрить в нейросеть понимание структуры
  
  ......
  
  Идея #1: Больше данных в модель!
  
  Многие считают, что чтобы нейросеть стала лучше "понимать мир",
  нужно просто сделать очень большую модель (с огромным количеством параметров)
  и обучить ее на намного большем и разнообразном количестве данных,
  чем это делается сейчас.
  Типа, очень большая модель в процессе обучения на разнообразных данных
  сама поймет, как лучше всего представлять объекты,
  и в итоге у нее само собой возникнет понятие структуры.
  В этом есть резон: практика показывает,
  что чем больше в обучающей выборке разнообразных примеров,
  тем лучше генерализация нейросети,
  и тем менее проявляются эффекты out of domain, adversarial attack
  и чувствительности к шуму.
  
  Но достаточно ли этого,
  чтобы достичь комбинаторного обобщения?
  Похоже, что все-таки нет.
  Посмотрим на DALL-E 2: нейросеть для text-to-image,
  которая обучалась на просто огромном количестве данных.
  При этом понимания структуры у этой нейросети,
  увы, не возникло.
  Казалось бы, это странно: DALL-E 2 отлично генерирует картинки
  по текстовым запросам, комбинируя различные сущности:
  даже те, которые обычно несовместимы (вспомним знаменитый авокадо-стул).
  Но нет. Ученые из Гарварда провели исследование,
  по итогам которого сделали вывод,
  что у DALL-E 2 нет даже базового понимания отношений между объектами
  и, соответственно, структуры
  (цитата: "... current image generation models do not yet have
  a grasp of even basic relations involving simple objects and agents")
  //// А вот мне встретился материал с противоположным выводом, см.:
  //// "Тарабарские языки", используемые ИИ-системами".
  //// И кто в данном случае прав?
  //// А спросишь того же Bing об отношениях категорий в какой-нибудь
  //// математической формулировке, то просто балдеешь от того,
  //// как он "раскладывает все по полочкам".
  //// Так что этот аргумент, как минимум, устарел.
  //// И как раз LLM это наглядно продемонстрировали.
  //// Так что, скорее всего, это связано с конкретным процессом обучения И,
  //// может быть, со специфическими конструктивными решениями,
  //// а не "врожденной неспособностью" нейросетей
  //// "разобраться в конкретных отношениях/связях".
  
  Рис. https://arxiv.org/pdf/2208.00005.pdf
  Пример генерации DALL-E 2 по запросу "чашка под цилиндром".
  Видно, что модель не понимает отношения "под":
  на большинстве картинок чашка не расположена под цилиндром.
  //// Еще бы запросили "под наркозом",
  //// и этим бы аргументировали свой окончательный вывод.
  
  ......
  
  Обратимся поэтому к другим идеям того,
  как внедрить понимание структуры в нейросети.
  Другая идея состоит в том, чтобы как-то изменить
  идею устройства модели.
  Другими словами, внедрить в модель некий inductive bias,
  спроектировать архитектуру модели так,
  чтобы при обучении она была вынуждена выучивать
  некое подобие структуры и отношений между объектами.
  //// Ну, структуры точно со временем поменяются,
  //// но в какую сторону пока неясно.
  //// Но "inductive bias" - запомним.
  
  В случае с text-to-image моделями, к слову,
  такой подход работает: добавление в архитектуру сети некоторых трюков
  помогает улучшить восприятие моделью отношений между объектами.
  К примеру, text-to-image модель Parti (Google, 2022)
  достаточно хорошо передает взаимодействия объектов:
  
  Рис. https://gweb-research-parti.web.app/parti_paper.pdf
  Пример генерации картинок моделью Parti.
  Видно, как точно на картинке переданы отношения между объектами
  (wombat, chair, martinim keyboard), описанные в тексте.
  
  .....
  
  Идея #2: Графовые нейросети
  
  Графовая нейросеть -это архитектура,
  которая прямо в своем устройстве содержит понятие структуры
  и связей между объектами,
  и успешно применяется для работы с определенными видами данных.
  Как понятно из названия, основа графовой нейросети - граф.
  
  Граф - это, наверное, самый наглядный способ представления структур.
  Вершины графа соответствуют сущностям (понятиям, объектам),
  а ребра между вершинами - отношениям между этими сущностями.
  
  Некоторые виды данных прямо таки представляют собой графы.
  Примеры - графы социальных сетей или молекул веществ.
  
  С такими видами данных очень удобно работать с помощью графовых нейросетей
  //// А как быть с теми данными, которые НЕ ИМЕЮТ простого графого представления,
  //// например текст, изображение и др?
  
  ........
  
  Графовая нейросеть строит граф объекта.
  Во время обучения GNN выучивает эмбеддинги (векторы-описания) каждой вершины
  и каждого ребра.
  То есть, GNN выучивает информацию о каждом элементе (вершине) графа
  и о природе связей (ребер) между этими элементами.
  Получается, GNN в процессе обучения "понимает" структуру объекта.
  //// Т.е. опять все упирается в структуру/пространство "эмбеддинга".
  
  Подробно о том, как обучаются графовые нейросети,
  есть прекрасные статьи на distill.pub, towardsdatascience и arxiv.
  https://distill.pub/2021/gnn-intro/
  https://towardsdatascience.com/a-gentle-introduction-to-graph-neural-network-basics-deepwalk-and-graphsage-db5d540d50b3
  https://arxiv.org/abs/1710.10903
  
  Успех графовых нейросетей в работе с графовыми типами данных очевиден:
  в последнее время большинство успешных моделей
  для разработки лекарств или других химических соединений
  были основаны на графовых нейросетях.
  Пример: MoLeR (модель от Microsoft для разработки новых лекарств).
  Эта модель - VAE, энкодер и декодер которой - графовые нейросети.
  
  К сожалению, применить графовые сети для работы с другими типами данных
  (вроде картинок или текста) намного сложнее.
  Их, при желании, тоже можно представить в виде графов,
  но это представление не будет идеальным.
  //// Т.е. "граф", а, возможно, и само структурное представление
  //// не являются универсальным инструментом для многих задач.
  //// Или, что скорее, могут являться, но не в том прямолинейном виде,
  //// как это предлагается сейчас.
  
  ......
  
  Получается, графовые нейросети - не универсальная идея,
  которая позволит внедрить структуру в модель для работы
  с любыми видами данных.
  По крайней мере, в том виде, в котором графовые нейросети существуют сейчас.
  
  В заключение про графовые сети порекомендую эту статью от DeepMind.
  https://arxiv.org/pdf/1806.01261.pdf
  В ней вводится понятие графовой нейросети:
  как она устроена, для каких задач применима и как ее обучать.
  Также в ней подробно разбирается то,
  как различные архитектуры нейросетей (сверточные, полносвязные, рекуррентные)
  оперируют связями между объектами
  (т.е. какой в них relational inductive bias),
  и в чем преимущество графовых нейросетей в этом плане.
  
  .......
  
  Идея #3: Мысли Джеффа Хинтона
  
  Джефф Хинтон в феврале 2021 года выпустил большую авторскую статью
  https://www.cs.toronto.edu/~hinton/absps/glomfinal.pdf
  под названием "How to represent part-whole hierarchies in a neural network".
  В своей работе он концентрируется именно на создании нейросетей
  для компьютерного зрения (обработки картинок и видео),
  но, тем не менее, содержит интересные идеи.
  
  Главный лейтмотив работы Хинтона - иерархическая структура.
  
  ......
  
  Хинтон в статье предлагает идею модели, которую он назвал GLOM.
  GLOM - это не четко прописанная архитектура,
  которую завтра можно написать на PyTorch и обучить;
  это, скорее, абстрактная идея устройства модели.
  
  ........
  
  Как мы могли бы представить изображение
  в виде иерархической структуры в компьютере?
  Очевидный ответ - в виде дерева
  (заметим, что тут мы снова приходим к идее графа. Дерево - это тоже граф).
  Вот как он будет выглядеть:
  
  Рис. Дерево иерархии портрета Мона Лизы
  
  Подобные деревья иерархии можно построить для любой сцены.
  Было бы очень круто научить нейросети создавать для изображений такие деревья:
  это гарантировало бы, что нейросеть "воспринимает" визуальные сцены структурно.
  
  Но с этой идеей есть серьезная проблема:
  деревья иерархии для разных изображений будут совершенно разные.
  Они будут разной глубины
  (отдельный вопрос: как понять, когда остановиться делить элементы
  на все более мелкие составляющие?),
  на каждом уровне будет разное количество вершин,
  и все вершины будут соответствовать разным элементам:
  лицу, носу, машине, цветку и т.д.
  Короче говоря, граф должен строиться динамически.
  И тогда в нейронной сети нейроны должны будут в зависимости от изображения
  "представлять" разные сущности и по-разному взаимодействовать между собой.
  Проще говоря, нейросети для обработки разных картинок
  должны будут иметь разную структуру.
  Это не согласуется с тем,
  что мы хотим строить универсальные нейросети,
  которые могут обрабатывать сразу огромное количество различных картинок.
  //// Это не согласуется с представлением, что "структура картинки"
  //// должна как-то "коррелировать" со "структурой сети".
  //// Это первый "камень преткновения", точнее первый барьер "инерции мышления",
  //// когда задача решалась в основном удачным подбором структуры нейросети.
  
  Стоит сказать, что добиться разных видов взаимодействий между нейронами сети
  в зависимости от входящей картинки, на самом деле, не так сложно.
  //// О, "тепленькая пошла".
  Можно применить механизм гейтов или тот же Attention.
  Но с остальным - как строить иерархические деревья
  с разным количеством вершин,
  которые будут соответствовать разным элементам - неясно.
  //// А здесь снова вернулись к упомянутому "барьеру".
  //// Нужно по другому научиться оперировать эибеддингами,
  //// и тогда, возможно, задача станет более понятной.
  //// Начать хотя бы с вопроса как вообще представлять иерахическую структуру,
  //// и попробовать ее решить методом детектирования объектов,
  //// как, например, упоминалось в материалах выше.
  
  Хинтон в своей статье предлагает устройство нейросети,
  которое обрабатывает изображения похожим образом.
  
  Делим изображение на регионы одинакового размера.
  Например, 8х8.
  Каждому региону ставим в соответствие пять автоэнкодеров
  (далее я буду часто вместо слова "автоэнкодер" писать AE, чтобы было короче).
  Латентный вектор каждого из этих автоэнкодеров
  будет содержать информацию об этом регионе изображения.
  Но векторы разных AE будут выражать разную по структуре,
  уровню абстракции информацию.
  Поясню, что имеется в виду.
  Посмотрим на картинку и выделенный красным регион:
  
  .....
  
  Этому региону будут соответствовать пять автоэнкодеров.
  Латентный вектор первого AE будет содержать информацию,
  что в этом регионе изображена сережка.
  Латентный вектор второго AE будет содержать информацию,
  что в регионе изображено ухо.
  Третьего AE - что в регионе изображено лицо человека.
  Четвертого - что тут изображен человек,
  пятого - что тут изображен человек на розовом фоне.
  
  То есть, каждый следующий автоэнкодер воспринимает регион изображения
  как часть все большей сущности.
  Первый AE концентрируется на "локальной" сути региона
  (на нем изображена сережка),
  следующий AE воспринимает регион как часть большей сущности (уха),
  третий - еще большей (лицо) и т.д.
  
  Тут может возникнуть вопрос:
  как второй и последующий атоэнкодеры понимают,
  что регион - это часть уха/лица/человека,
  если они не имеют доступ к другим регионам?
  Ответ такой: в процессе обработки картинки
  каждый автоэнкодер обменивается информацией с другими AE.
  А именно, каждый автоэнкодер получает информацию от:
  
   AE того же региона уровня ниже;
  
   AE того же региона уровня выше;
  
   AE соседних регионов того же уровня.
  
  Таким образом, после нескольких итераций обмена информацией между автоэнкодерами
  латентные векторы всех AE стабилизируются
  и будут содержать нужную информацию.
  //// Вот это ключевое. Вся "иерархическая информация" как-то закодирована
  //// в "латентном векторе", то бишь, "эмбеддинге".
  //// Вопрос в том: как именно?
  Разумеется, чтобы этого добиться,
  нужно грамотно построить процесс обучения модели GLOM.
  //// Этого мало. Надо научиться понимать "кодировку эмбединга".
  Как это сделать, читайте в оригинальной статье Хинтона.
  //// То бишь, скорее всего, конкретных прорывных решений пока нет.
  
  А мы заметим вот что:
  при таком подходе латентные векторы многих соседних AE уровней 2 и выше
  будут содержать одинаковую информацию.
  //// Но по-разному закодированную. И это принципиально важно понимать.
  Действительно, посмотрим на четыре соседних региона, выделенных красным:
  
  ......
  
  Все эти регионы - части лица человека.
  Поэтому векторы AE третьего уровня (и всех уровней выше)
  должны будут содержать одинаковую информацию
  - что в этих регионах изображено лицо.
  И чем выше уровень, тем больше соседних AE будут иметь
  похожие латентные векторы.
  //// А вот это не факт. Это только предположение. И, скорее всего, неправильное.
  //// Точнее не так. Что-то общее, конечно, будет, но что именно
  //// - никто заранее сказать не может, а это равносильно тому,
  //// что "искать иголку в стоге сена".
  
  Таким образом, AE каждого уровня буду распадаться на "островки",
  //// О, вот это уже более "конструктивно".
  //// Но, скорее всего, и это "не совсем так",
  //// какая-то структура/связи между этими "островками", наверняка, будет.
  //// Вспоминаем о "магическом свойстве генерализации" нейросетей,
  //// а "мозаичное"/"островное" представление вряд ли можно считать "обобщением".
  внутри каждого из которых латентные векторы будут похожи.
  Проиллюстрировать это можно так (рисунок взят из оригинальной статьи):
  
  Рис. https://www.cs.toronto.edu/~hinton/absps/glomfinal.pdf
  
  Здесь каждый столбик - пять AE, соответствующих одному региону картинки.
  Нижний квадрат в столбце - AE первого уровня,
  второй снизу квадрат - AE второго уровня и т.д.
  Видно, что чем выше уровень,
  тем больше соседних AE имеют одинаково направленные векторы.
  У AE верхнего уровня стоят знаки вопроса,
  потому что векторы этих AE еще не стабилизировались
  в процессе обработки изображения.
  
  Мы видим, что при таким подходе автоэнкодеры образуют
  явную иерархическую структуру,
  которая очень напоминает деревья иерархии,
  которые мы обсуждали выше.
  Действительно, каждый "островок" AE - это одна вершина дерева.
  Вершины могут выражать разную по семантике информацию
  в зависимости от того, что именно изображено на картинке.
  //// Учитывая разнообразие "картинок" количество возможных
  //// "разбиений на острова" совершенно не определено.
  //// Но сама мысль, на мой взгляд, идет в нужном направлении
  //// вектор эмбеддинга можно и нужно рассматривать не как "множество",
  //// а как "множество подмножеств", причем всех возможных комбинаций,
  //// т.е. по формуле "це из эн по эм".
  //// Тогда этот подход, вполне возможно, заиграет новыми красками.
  И из разных картинок могут получиться разные по устройству деревья иерархии:
  AE каждого уровня будут по-разному собираться в "островки".
  
  Вот такая изящная идея пришла в голову Хинтону.
  Конечно, к ней есть много вопросов.
  Самые очевидные, на мой взгляд, эти:
  
   Как выбрать количество AE для каждого региона
   (т.е. как понять, сколько будет уровней абстракции). Почему именно 5?
  
   Как выбрать деление картинки на регионы? Какого размера они должны быть?
  
  Сам Хинтон рассуждает об этих и других вопросах.
  А еще он утверждает, что такое устройство модели имеет связь с биологией.
  Подробнее обо всем этом - в его статье.
  https://www.cs.toronto.edu/~hinton/absps/glomfinal.pdf
  
  ......
  
  Идея #4: Мысли Яна ЛеКуна
  
  Если Джефф Хинтон концентрировался именно на AI для обработки картинок,
  то Ян ЛеКун мыслит шире:
  его работа посвящена устройству AGI (Artificial General Intelligence).
  Опять же, эта работа - не полное техническое описание модели,
  а набор идей и рассуждений.
  
  В начале статьи ЛеКун приводит три главных, на его взгляд,
  вызова для современного AI:
  
   Как машины могут научиться представлять мир,
   делать предсказания и действовать, основываясь на наблюдениях?
   (Тут имеется в виду, что человек учится, в основном взаимодействуя с миром.
   Дать AI возможность учиться на основе реальных взаимодействий
   - слишком сложно и дорого.
   Хочется обучить AI, скармливая ему только наблюдения)
  
   Как научить машину рассуждать и планировать способами,
   основанными на вычислениях градиентов?
   (Тут имеется в виду, что современный AI в большинстве своем
   основан на нейросетях, которые обучаются с помощью градиентного спуска.
   Это накладывает на нейросети существенное ограничение:
   все функции должны быть дифференцируемы)
  //// Вроде какая-то есть техника преодоления этого барьера.
  //// Но это не точно. Нужно поискать уточнение.
  
   Как машины могут научиться воспринимать мир
   и строить планы действий иерархически,
   на нескольких уровнях абстракции и в разных временных масштабах?
  
  Получается, один из трех наибольших вызовов AI, по мнению ЛеКуна
  - это то, как заставить AI думать иерархически, структурно.
  
  В статье ЛеКун предлагает идеи для решения всех этих вопросов.
  Мы здесь рассмотрим только ту идею, которая связана с иерархией.
  Это модуль JEPA (Joint Embedding Predictive Architecture).
  Ян называет этот модуль "центральной частью" (centerpiece) свой работы.
  
  Устройство JEPA показано на картинке ниже:
  
  ......
  
  На вход модуль принимает два объекта - х и y.
  Они могут быть разных модальностей:
  например, картинка и звук.
  Далее х и y прогоняются каждый через свой энкодер.
  На выходе получаются два векторных представления х и y - s_x и s_y.
  Потом s_x подается на вход модулю Pred,
  задача которого - на выходе получить s_y с волной,
  который будет близок к s_y ("близок" по некоторой метрике).
  Грубо говоря, задача модуля Pred - научиться по s_x предсказывать s_y.
  Или, по-другому, ассоциировать s_x с s_y.
  
  .......
  
  Конечно, чтобы JEPA работал именно так, как описано выше,
  нужно грамотно выстроить процесс обучения и подобрать лосс-функции.
  О том, как устроено обучение JEPA, читайте в разделе 4.5 статьи ЛеКуна.
  https://openreview.net/pdf?id=BZ5a1r-kVsf
  
  .......
  
  Чтобы наделить модель возможностью создавать ассоциации
  и предсказания разной семантики и уровня,
  ЛеКун предлагает объединить несколько модулей JEPA в иерархию.
  Он назвал это Hierarchical JEPA (H-JEPA).
  Схематично это можно представить так:
  
  ......
  
  Общая идея здесь в том, что несколько слоев энкодеров (Enc1, Enc2, ...)
  выделяют из входных объектов информацию разного уровня.
  Enc1 выделяет low-level информацию,
  содержащую больше низкоуровневых деталей.
  Enc2 использует выход Enc1 и фильтрует его далее:
  выделяет из входа более абстрактную, общую информацию,
  содержащую меньше деталей.
  Далее можно навесить еще энкодеры: Enc3 и т.д.
  
  На основе выходов Enc1, Enc2, ... модули Pred1, Pred2, ...
  строят ассоциации/предсказания разного уровня.
  К примеру, Pred2 на основе выхода Enc2 строит
  более далекое во времени предсказание, чем предсказание Pred1,
  так как для более близких во времени предсказаний требуется больше деталей.
  Точно так же ассоциация, построенная с помощью Pred2,
  будет более абстрактной, чем с помощью Pred1.
  
  Подробнее о H-JEPA читайте в статье (раздел 4.6).
  Также в разделе 4.7 приводятся идеи,
  как адаптировать H-JEPA и всю идею планирования на реальный мир,
  где присутствует очень много uncertanty
  и никакие предсказания не могут быть стопроцентно верными.
  
  Вот такие мысли крутятся в голове (а теперь и в статье) Яна ЛеКуна.
  На мой взгляд, довольно лаконичная идея,
  сочетающая в себе и ассоциативное мышление, и иерархию, и планирование.
  //// Не скажу, что суть идеи я уловил.
  //// Кроме разве, что построения ассоциаций и каскадирования энкодеров.
  
  ......
  
  Сложность внедрения структуры в модели
  
  В заключение темы структуры в AI добавлю такую мысль:
  на мой взгляд, основная сложность внедрения структурного восприятия
  в модели машинного обучения - это то, как сделать структуру гибкой.
  
  Люди с рождения начинают выстраивать структурное восприятие мира,
  но структура любой сущности в нашей голове постоянно меняется.
  Когда-то люди считали, что атом - это неделимая сущность,
  то есть, это единичный структурный элемент.
  Теперь же мы знаем, что атомы тоже состоят из частей:
  протонов, электронов, и т.д.
  То есть, наше структурное представление о веществе изменилось:
  в нем появился еще один уровень вложенности.
  И таких новых уровней может появляться бесконечное число:
  элементы могут делиться на новые структурные части.
  
  Или, еще интереснее:
  мы можем делить один и тот же элемент на структурные части по-разному.
  //// Вот именно. Причем самое характерное, что такие "деления"
  //// происходят тогда, когда нужно,
  //// а не изначально, при первом знакомстве с объектом.
  //// Изначально устанавливаются какие-то отдельные ассоциативные связи,
  //// а вовсе не "жесткий" и "законченный" граф.
  
  .......
  
  И вот то, как дать возможность нейросетям оперировать структурой
  так же гибко - это, на мой взгляд, основная сложность.
  Выше мы рассматривали несколько идей,
  как наделить модели структурным восприятием,
  но, кажется, ни одна ни из них не обладает достаточной гибкостью.
  В графовой нейросети количество вершин четко задано,
  больше появиться не может.
  В идее Хинтона четко заданы количество уровней автоэнкодеров
  и деление картинки на области.
  В модели ЛеКуна может быть ограниченное количество модулей JEPA,
  а один модуль отвечает за ассоциации определенного уровня.
  Как развить эти идеи, чтобы структура стала гибче,
  на мой взгляд, открытый вопрос.
  //// Типовой прием ТРИЗ - переход в другое пространство,
  //// а именно научиться работать не со структурой нейросети,
  //// а со структурой "пространства эмбеддингов".
  
  Заключение
  
  В этой статье мы рассмотрели одно из главных отличий современного AI
  от человека - структурное мышление.
  Мы поняли, как именно структура помогает человеку воспринимать
  и взаимодействовать с миром и рассмотрели основные проблемы AI,
  которые возникают от отсутствия понимания им структуры.
  Ну и разобрали несколько идей,
  как эту структуру в нейросеть внедрить.
  
  Разумеется, существует еще много идей того,
  как заставить AI воспринимать объекты более структурно.
  В статье я описала те, что привлекли мое внимание,
  и, на мой взгляд, являются наиболее гибкими и "общими",
  т.е. могут быть применены к широкому классу задач,
  и поэтому обладают хорошим потенциалом.
  В разделе "Литература" ниже вы найдете еще несколько ссылок на работы,
  в которых предлагаются механизмы для внедрения структурного знания
  в модели машинного обучения.
  
  Также стоит сказать такие две вещи:
  
   структурное восприятие мира - далеко не единственная преграда,
   отделяющая нас от создания AGI.
   Не менее интересная тема, к примеру - проблема causality vs correlation,
   т.е. Как научить AI оперировать причинно-следственными связями.
   Здесь проблемы начинаются прямо с порога:
   мы не можем даже дать нормального определения тому,
   что такое causality.
   Но это тема уже совершенно иной статьи =)
  
   описанные выше идеи - не единственные на тему того, как создать AGI.
   Есть, к примеру, не менее интересный подход embodied intelligence.
  https://link.springer.com/chapter/10.1007/978-3-662-43505-2_37
   Но тема этой статьи - не AGI, а структурное мышление,
   поэтому другие идеи AGI мы не рассматривали.
  
  На этом все, я уже и так слишком много слов написала. Спасибо за прочтение!
  Надеюсь, было интересно.
  
  Благодарности
  
  Выражаю огромную благодарность Александру Петюшко за вычитку статьи,
  ценные замечания и правки.
  
  Литература
  
  Ссылки на научные работы по структурному мышлению у людей,
  которые подкрепляют идеи из первой части статьи:
  
  ......
  
  //// Из комментариев.
  
  maslyaev
  16 сен 2022 в 10:26
  
  Ну здрасте, приехали.
  Ещё совсем недавно, каких-то 20 лет назад,
  отличием человеческого ума от ИИ было как раз то,
  что мы воспринимаем вещи как единое целое,
  а для ИИ (был тогда представлен экспертными системами, базами знаний,
  системами логического вывода) всё нужно разложить на структуры.
  
  По ходу дела, просто память у ребят короткая.
  -2
  
  ......
  
  CyaN
  21 сен 2022 в 15:51
  
  Иерархия это частный и очень узкий случай графа.
  0
  
  ......
  
  //// Конец цитирования.
  
  Безусловно, данный достаточно объемный материал,
  стоит рассматривать не как "сборник готовых рецептов",
  а направления поиска таких "рецептов".
  
  Во всяком случае для меня этот текст стал той "соломинкой",
  которая сподвигла и на работу по данному модулю,
  и подтолкнула мысль при проработке вопросов,
  связанных со структурой значений элементов эмбеддинга,
  "Металоция неведомого. Модуль Э. Эмбеддинги."
  а потом и проработки концепции битовых нейронных сетей (БНС).
  
  Так что я выражаю свою благодарность автору за материал,
  оказавшийся для меня весьма полезным, хоть и "немного" дискуссионным.
  Но это и к лучшему.
  Говорят, "в спорах рождается истина".
  До "истины", конечно, еще очень далеко,
  но хотя бы направление поиска можно как-то "оконтурить".
  
  
  ========
  
  23.03.2024 11:13
  
  Inductive bias в нейронных сетях.
  В оглавление.
  
  Заинтересовал меня термин "inductive bias" применительно к структурам нейросетей,
  и вот какой материал удалось раскопать в архивах Хабра:
  
  "Inductive bias и нейронные сети".
  Автор: Atmyre (Татьяна Гайнцева)
  https://habr.com/ru/articles/591779/
  26 ноя 2021 в 12:21
  
  //// Начало цитирования.
  
  В этой статье я расскажу, что такое inductive bias,
  зачем он нужен и где встречается в машинном обучении.
  Спойлер: везде.
  Любая нейросеть имеет inductive bias
  (даже та, что в человеческом мозге, хе-хе)
  
  Также вы узнаете:
  
   почему inductive bias - это очень хорошо
  
   способы внедрить inductive bias в модели машинного обучения
  
   какой inductive bias в сверточных нейросетях
   и как успех архитектуры Image Transformer связан с inductive bias
  
  Ну что, поехали:
  
  Что такое inductive bias
  
  Я намеренно не буду переводить термин "inductive bias" на русский язык:
  общепринятого перевода нет, а все разумные варианты перевода,
  на мой взгляд, не передают суть термина.
  К тому же, в профессиональной среде все используют англицизм.
  
  У термина inductive bias в литературе есть много определений.
  Все они - неформальные.
  Формального определения вообще не существует,
  а наиболее строгое из возможных опирается на формальную математическую логику.
  Мы здесь ограничимся следующим определением:
  
  Inductive bias - это априорные знания о природе данных,
  которые человек некоторым образом вкладывает в модель машинного обучения.
  //// Наверно, не только о "природе данных",
  //// но и ожидаемых способах их представлений/обработки.
  //// Причем, тут могут быть как желаемые/явные/"полезные" "подсказки",
  //// так и неявные и, соответственно, "нежелательные"/"паразитные" "артефакты".
  
  Чтобы лучше понять суть inductive bias, рассмотрим примеры:
  
   Модель линейной регрессии.
   Линейная регрессия строится в предположении,
   что между целевой переменной и зависимыми переменными (признаками)
   существует линейная зависимость.
   В модель как бы "вложены" знания о том, что данные имеют линейную природу.
   Из-за этого ограничения линейности модели
   линейная регрессия плохо обучается под любые данные,
   в которых целевая переменная от признаков зависит не линейно (см. рис ниже).
   Это предположение о линейной связи между признаками о ответом
   - и есть ее inductive bias
   (точнее, один из ее inductive bias'ов, как мы увидим далее)
  
  Рис. Ось Х - значение признака, ось Y - значение целевой переменной.
  Видно, что зависимость Y от Х нелинейна.
  Из-за этого модель линейной регрессии,
  которая пытается построить линейную зависимость между X и Y,
  будет очень плохо описывать эти данные.
  
   Модель K ближайших соседей (k-nearest neighbours).
   Эта модель работает в предположении "компактности",
   то есть "значение целевой переменной для неизвестного объекта
   однозначно определяется значениями целевой переменной
   для k ближайших (в некотором смысле) к нему объектов".
   Это допущение - inductive bias алгоритма k ближайших соседей.
   В модель KNN вложены знания о том,
   что ответ для любого объекта должен быть вычислен
   только на основе того, какие значения ответов были
   у ближайших к этому объекту элементов обучающей выборки.
  
  Рис. Иллюстрация классификации объекта (зеленая точка) алгоритмом KNN.
  Синие точки - объекты одного класса, оранжевые - объекты другого класса.
  При k=3 зеленая точка будет отнесена к "голубому" классу.
  
   Нелинейная регрессия:
   пусть у меня есть данные, полученные из некоторого физического эксперимента.
   Пусть в данных две переменные - x и y.
   Я хочу построить модель машинного обучения,
   которая могла бы по переменной x предсказывать значение y.
   Пусть я знаю из теоретической физики,
   что уравнение зависимости y от x должно выглядеть определенным образом:
   в виде функции y= w_1 \exp(w_2 x) + w_3.
   Тогда мне остается обучить модель машинного обучения
   находить подходящие значения коэффициентов w_1w_2 и w_3
   на основании моих данных с датчика.
   Я могу сделать это, например, с помощью градиентного спуска (см. рис).
   Это знание о том, что модель машинного обучения, описывающая наши данные,
   должна иметь вид определенной функции y= w_1 \exp(w_2 x) + w_3
   и есть inductive bias.
  
  Рис. Иллюстрация нахождения оптимальных коэффициентов функции y = w1*exp(w2*x) + w3
  для описания данных (голубые точки).
  
  Итак, подведем итог:
  inductive bias - это некоторые априорные допущения о природе данных,
  которые человек "передает" модели машинного обучения,
  накладывая ограничения на то,
  в каком виде модель будет искать зависимость значения целевой переменной
  от входящих данных.
  
  Здесь мы рассмотрели довольно тривиальные примеры inductive bias
  - те, которые достигаются наложением ограничений на сам вид модели.
  Вообще "передать" модели априорные знания
  (наделить модель inductive bias)
  можно разными способами:
  не только с помощью определенного устройства архитектуры модели.
  Об этом мы поговорим ниже.
  А пока что давайте заметим, что...
  
  Без inductive bias не обойтись
  
  Из примеров о линейной регрессии и KNN может показаться,
  что inductive bias - плохая штука.
  Ведь это ограничивает модели!
  Inductive bias линейной регрессии не позволяет ей хорошо обучаться под данные,
  которые не имеют линейной зависимости между целевой переменной и признаками.
  Inductive bias алгоритма KNN не позволяет ему хорошо работать на данных,
  в которых целевая переменная объекта
  не однозначно определяется значениями целевых переменных "близких" элементов.
  Одни недостатки!
  Можно ли сделать модель совсем без ограничений?
  
  Но без inductive bias модель машинного обучения существовать не может.
  Вот почему:
  
  Цель модели машинного обучения - используя обучающую выборку данных,
  вывести общее правило,
  по которому можно будет выдавать ответ на любой элемент из доменной области
  (а не только на элементы из обучающей выборки).
  //// Это только "надежда и вера" в "магическую генерализацию" нейросетей,
  //// а по факту имеется некая "корреляция" с таким поведением.
  //// Причем, "корреляция" именно из-за явных и неявных inductive bias модели.
  Пример задачи - имея 100.000 изображений лиц людей,
  научиться решать задачу распознавания лиц
  и уметь распознавать лица любого человека в мире.
  Этот процесс - выведение общего правила для всех элементов домена
  на основе ограниченного числа наблюдений -
  называется генерализацией (обобщением) модели машинного обучения.
  
  Рис. https://bit.ly/31bvCvP
  
  Такая генерализация невозможна без наличия inductive bias у модели.
  Почему?
  Потому что обучающая выборка всегда конечна.
  Она точно не покрывает все возможные в реальном мире наблюдения.
  А из конечного набора наблюдений,
  не делая совсем никаких дополнительных предположений о данных,
  вывести общее правило можно бесконечным числом способов.
  Ведь, в целом, значение целевой переменной
  для элементов вне обучающей выборки может быть каким угодно.
  
  Inductive bias - это дополнительная информация о природе данных для модели;
  способ показать модели, "в какую сторону думать",
  в каком виде искать решение,
  по какому принципу строить алгоритм генерализации.
  //// Не совсем так.
  //// Модель не "строит алгоритмы", а подбирает более-менее подходящие эвристики,
  //// причем в зависимости от последовательности обучающих примеров,
  //// "эвристики" могут быть сильно разные из "бесконечного числа" возможных.
  Он позволяет модели приоритизировать один способ генерализации над другим.
  Он загоняет модель в рамки при выборе метода генерализации,
  внутри которых практически все варианты генерализации
  будут достаточно адекватные.
  Модель становится как бы "сдвинута" (biased)
  в сторону решения определенного вида.
  
  Рис. Иллюстрация того, как inductive bias показывает модели,
  "в какую сторону думать"
  
  Например, inductive bias линейной регрессии заставляет модель
  из всех вариантов функций, описывающих данные,
  выбирать ту, которая имеет линейную природу.
  А inductive bias модели из третьего примера говорит модели,
  что искать зависимость ответа от входных данных
  нужно в виде определенной функции,
  и модели остается подобрать для этой функции подходящие параметры.
  
  И при выборе модели для обучения для решения определенной задачи
  нужно выбрать такую модель,
  чей inductive bias лучше проходит под природу данных
  и лучше позволит решить эту задачу.
  Вообще говоря, изобретение новых архитектур моделей машинного обучения
  (например, нейросетей)
  и состоит в том, чтобы изобрести такую архитектуру,
  которая будет иметь нужный inductive bias для решения конкретной задачи.
  //// Тоже не совсем так.
  //// Нормальное изобретательство опирается хоть на какую-то теоретическую базу,
  //// а вот в области "архитектуростроения" нейросетей "правит бал",
  //// откровенный "метод научного тыка",
  //// правда, с опорой на какие-то удачные и опробованные решения.
  
  Итак, мы поняли, что inductive bias - хорошая и полезная штука.
  Давайте поговорим о том, какими способами
  можно внедрить inductive bias в модель.
  Мы увидим, что манипулирование устройством архитектуры модели
  - лишь один из многих способов внедрения inductive bias.
  
  Способы внедрить inductive bias в модель.
  
  Выше мы рассматривали примеры inductive bias моделей линейной регрессии и KNN.
  У обеих этих моделей inductive bias "встроен" в саму архитектуру модели
  - в сам механизм того, как эти модели получают значение целевой переменной
  на основе входных данных.
  Давайте убедимся, что внедрить в модель априорные знания
  о данных можно и другими способами.
  Для этого рассмотрим нейронные сети и inductive bias в них.
  
  Прежде всего, каждая нейронная сеть обладает архитектурой (строением).
  Архитектура нейросети - это то, какие слои в ней присутствуют
  (полносвязные, сверточные, рекуррентные, ...),
  сколько нейронов в каждом слое, какая функция активации на каждом из слоев,
  используется ли dropout и attention и т.д.
  
  Архитектура нейросети описывает вид функций,
  которые может выражать нейросеть.
  Да, нейронная сеть по своей сути - это просто функция,
  описывающая зависимость выхода от входа,
  как и линейная регрессия или функция y = w1*exp(w2*x) + w3 из третьего примера.
  Только нейросеть - сильно более сложная функция,
  с большим числом обучаемых параметров и нелинейностей.
  Отсюда понятно, что архитектура нейросети - это уже ее inductive bias.
  
  Более того, каждый вид слоев сетей - сверточный, полносвязный, рекуррентный -
  имеют свой inductive bias, обусловленный строением этих слоев.
  Причем их inductive bias помогают им обрабатывать данные того вида,
  для которых они предназначены:
  сверточному слою - изображения,
  рекуррентному - данные, представленные в виде последовательностей.
  Об inductive bias сверточного слоя мы поговорим ниже.
  
  Далее, алгоритм обучения нейросети тоже накладывает на модель ограничения.
  Мы обучаем нейросеть с помощью алгоритма обратного распространения ошибки
  (backpropagation),
  а не с помощью какого-либо другого метода.
  И это тоже внедряет в модель некоторые знания о том,
  как должен быть устроен предпочтительный способ генерализации.
  А именно: алгоритм backpropagation минимизирует
  среднюю ошибку модели на обучающей выборке
  с точки зрения некоторой метрики качества.
  То есть заставляет модель из всех возможных способов генерализации
  выбирать такой, который будет показывать
  лучшее значение некоторой метрики в среднем на обучающей выборке.
  //// Вот тут хочется чуть не криком кричать,
  //// да не "выбирает модель" что-то, а ее "гнут через колено",
  //// чтобы хоть как-то улучшить "метрику качества",
  //// даже если при этом получаются какие-то "неприятные артефакты".
  
  Тут становится понятно, что выбор learning rate, алгоритма оптимизации
  (Adam, RMSProp, ...) - все это тоже вносит вклад в inductive bias:
  заставляет модель искать способ генерализации определенным способом.
  
  Далее: данные. Через обучающие данные тоже можно внести вклад в inductive bias.
  (то есть, через данные передать модели знания о данных, хе-хе)
  
  Пример: пусть мы обучаем нейросеть на задачу
  классификации изображений яблок и груш.
  И пусть на всех картинках из обучающей выборки яблоки и груши
  расположены ровно вертикально:
  
  ......
  
  Обучив нейросеть на такой выборке, мы, скорее всего, получим модель,
  которая будет плохо классифицировать фрукты, лежащие на боку.
  Это легко объяснимо:
  при обучении модель не видела ни одного фрукта,
  расположенного не вертикально,
  и просто не научилась их классифицировать.
  Мы хотим избежать такого и заставить модель выбрать тот способ генерализации,
  при котором она смогла бы хорошо классифицировать фрукты,
  повернутые на любое число градусов.
  Для этого мы можем изменить обучающую выборку:
  аугментировать ее так, чтобы она содержала изображения повернутых фруктов:
  
  ......
  
  При обучении на таком аугментированном датасете
  модель будет вынуждена выбрать тот способ генерализации,
  при котором хорошо сможет классифицировать не только вертикальные,
  но и повернутые картинки фруктов.
  //// Модель не "выберет", а "настроится" на обучающую выборку
  //// и ... "метрику качества". Это ведь тоже inductive bias.
  //// И иногда самый существенный.
  
  Таким образом мы внедрили inductive bias в нейросеть
  с помощью аугментации датасета.
  Теперь обучающие данные и алгоритм обучения нейросети (backpropagation)
  устроены так, что модель в процессе обучения "понимает",
  что данные (картинки фруктов) бывают
  не только расположенными строго вертикально,
  но и повернутыми на произвольное число градусов.
  И учится одинаково хорошо классифицировать фрукты, повернутые по-разному.
  
  Обратите внимание, что нужный inductive bias
  - понимание, что картинки фруктов бывают не только вертикальные -
  появляется у модели не только благодаря наличию повернутых
  на разное число градусов картинок фруктов в обучающем датасете,
  но и благодаря определенному устройству процесса обучения нейросети.
  Backpropagation заставляет нейросеть учиться
  одинаково хорошо классифицировать все картинки из обучающего датасета,
  и поэтому нейросеть учится классифицировать и повернутые фрукты в том числе.
  //// Но такое обучение не обеспечивает "понимание",
  //// что есть "груша" сама по себе как "объект",
  //// и есть ориентация "объекта" самого по себе.
  //// И это опять же результат используемого inductive bias
  //// в виде и структуры нейросети и метода ее обучения.
  
  Это важное замечание для понимания сути inductive bias,
  потому как чаще всего когда говорят о внедрении inductive bias в нейросети,
  упоминают только манипуляции с архитектурой нейросети
  и/или обучающими данными.
  Так происходит, потому что все нейросети по умолчанию
  обучаются с помощью backpropagation
  и о роли этого алгоритма во внедрении inductive bias в нейросеть
  можно умолчать.
  Однако без определенного устройства алгоритма обучения
  манипуляции с обучающими данными могли бы не иметь желаемого эффекта.
  //// Здесь полностью согласен.
  //// Только хочу добавить, что понимание этого момента
  //// требует разработки каких-то еще алгоритмов обучения,
  //// или хотя бы понимания того как можно более умно использовать backpropagation.
  
  Проиллюстрируем это на примере:
  представьте, что мы поменяли алгоритм обучения нейросети.
  Пусть мы вместо backpropagation используем следующий алгоритм обучения сети:
  
   100 раз выбери случайные значения параметров нейросети;
  
   для каждого значения параметров посчитай значение
   метрики качества на тестовом датасете;
  
   "обученная" нейросеть - это нейросеть с параметрами,
   для которых получено лучшее значение метрики на тестовом датасете
  
  Будет ли при таком способе обучения достигаться хорошее качество нейросети
  в задаче классификации?
  А сможем ли мы утверждать, что при таком способе обучения
  и добавлении в обучающие данные повернутых картинок фруктов
  сеть будет хорошо работать на повернутых изображениях фруктов?
  Кажется, что нет.
  При таком способе обучения никакие махинации с обучающими данными
  особо не повышают вероятность улучшения работы алгоритма.
  
  Более того:
  устройство архитектуры тоже играет роль в том,
  будут ли махинации с датасетом иметь нужный эффект.
  Например, какой бы inductive bias вы ни вложили в данные и обучающий алгоритм,
  вы никогда не научите линейную регрессию хорошо решать
  задачу распознавания лиц.
  
  Таким образом, внедрение любого inductive bias в модель машинного обучения
  опирается на определенные характеристики архитектуры модели,
  обучающего алгоритма и обучающих данных.
  Все это совместно влияет на то,
  как алгоритм выбирает способ генерализации и какой inductive bias получает.
  
  Иногда случается и так, что те ограничения,
  которые человек наложил на модель в целях получить некий inductive bias,
  имеют не тот эффект, который ожидался.
  Это случается потому, что человек не учел всех особенностей строения модели,
  данных и способа ее обучения:
  чаще всего это сделать просто невозможно.
  //// Особенно это относится к такому inductive bias как backpropagation.
  Об этом мы поговорим в разделе,
  где обсудим inductive bias сверточной нейросети.
  
  Далее в этой статье мы также будем предполагать,
  что при обучении нейросетей используется алгоритм backpropagation
  и будем умалчивать о его роли в формировании inductive bias.
  //// Очень жаль. Проблемы и следствия, порождаемые бездумным использованием
  //// backpropagation заслуживают отдельной и наверно очень объемной статьи.
  //// Жаль, что пока не могу найти такой развернутый материал,
  //// по-видимому, стоит завести специальный модуль по этому вопросу.
  Мы будем говорить об inductive bias,
  которые модель получает из определенного устройства архитектуры
  и обучающих данных.
  
  Итак, мы поняли, что внедрить inductive bias в модель
  можно произвольным способом
  - манипуляциями с архитектурой модели, данными, способом ее обучения.
  Главное - придумать, каким из возможных способов
  передать модели нужную вам информацию о данных,
  чтобы она получила желаемый inductive bias.
  
  Inductive bias и размер обучающей выборки
  
  Выше мы обсудили, что обучающие данные также являются
  способом внедрения в модель inductive bias .
  Заметим теперь, что чем больше и разнообразнее обучающая выборка,
  тем больше знаний о природе данных модель получает во время обучения.
  А значит, тем меньше вероятность модели выбрать "плохой" способ генерализации,
  который будет плохо работать на данных вне обучающей выборки.
  
  Короче говоря, чем больше данных, тем лучше обучится модель.
  И наоборот: чем меньше данных,
  тем больше вероятность модели выбрать плохой способ генерализации.
  
  Вы, наверное, знаете,
  что если обучающая выборка мала, нейронные сети часто переобучаются.
  Например, при решении задачи классификации изображений кошек и собак
  иногда обращают внимание на фон, а не на самих животных.
  Переобучение модели - не что иное,
  как выбор неудачного способа генерализации
  из-за отсутствия достаточно информации в обучающих данных.
  Чтобы помочь модели не переобучиться,
  отсутствующие в датасете "знания" о природе данных
  нужно передать ей другим способом
  - например, через внедрение более сильного inductive bias
  в архитектуру модели путем создания больших ограничений
  на устройство модели.
  
  Отсюда вывод: чем меньше обучающая выборка и сложнее задача,
  тем более сильный inductive bias требуется вложить в устройство модели
  для успешного обучения модели.
  Иными словами, тем большие ограничения нужно наложить на модель,
  чтобы она не "ушла сильно в сторону".
  
  Кстати, если вы спросите, почему люди, в отличие от нейросетей,
  могут быстро обучиться на задачу классификации кошек и собак,
  имея всего десяток картинок в обучающей выборке
  - это потому, что у людей есть inductive bias:
  мы знаем, что на картинке есть фон, а есть объект,
  и при классификации картинок нужно обращать внимание только на сам объект.
  А нейросеть до обучения ни о каких "фонах" и "объектах" не знает
  - ей просто дают разные картинки и просят научиться их отличать.
  
  Давайте увидим работу принципа
  "чем меньше данных - тем больший нужен inductive bias в архитектуре" на примере.
  Для этого рассмотрим две архитектуры нейросетей для работы с изображениями:
  сверточные нейросети и Visual Transformer.
  Поймем, как их успех связан с inductive bias
  и в чем заключается различие их принципа обработки картинок.
  
  Inductive bias сверточного слоя
  
  Рассмотрим сверточный слой (convolution).
  
  Рис. Принцип работы свертки
  https://brandinho.github.io/mario-ppo/
  
  Inductive bias сверточного слоя
  - предположение компактности и нечувствительности к переносу
  (translation invariance).
  Фильтр свертки устроен так, что за один раз захватывает
  компактную часть всего изображения
  (например, квадрат 3х3 пикселя, как показано на гифке),
  не обращая внимания на дальние пиксели изображения.
  Также в сверточном слое один и тот же фильтр используется
  для обработки всего изображения
  (как на гифке - один и тот же фильтр обрабатывает все квадраты 3х3 изображения).
  
  Эти inductive bias помогают сверточным нейросетям (CNN)
  обрабатывать изображения так, как их "обрабатывает" человек:
  предположение компактности отвечает человеческому представлению о том,
  что каждый объект на изображении расположен компактно,
  т.е. в определенной области изображения,
  а не разреженно по всей площади картинки;
  а нечувствительность к переносу заставляет нейросеть
  одинаково обрабатывать один и тот же объект на изображении
  вне зависимости от того, в какой части картинки он находится (см. рис. ниже):
  
  Рис. Объект на картинке (собака) расположена компактно.
  Плюс, обрабатывая обе картинки сверточной нейросеть,
  мы хотим получить один и тот же результат
  (например, ответ в задаче классификации, что на картинке - собака).
  
  Получается, сверточный слой устроен так,
  что его inductive bias отлично соотносится с природой изображений и объектов на них,
  поэтому сверточные нейросети так хороши в обработке картинок.
  
  Какие inductive bias у других слоев:
  рекуррентного, полносвязного и т.д.,
  предлагаю подумать самостоятельно =)
  А мы упомянем о таком явлении,
  как "скрытый inductive bias" (implicit inductive bias):
  
  Скрытые inductive bias
  
  Часто бывает так, что устройства нейросетей или обучающих данных
  порождают не только нужные inductive bias,
  но и "скрытые" - такие, которые человек не хотел сознательно вкладывать в модель
  и которые сложно выявить при первом взгляде на устройство модели.
  Исследователи проводят много экспериментов с нейросетями,
  пытаясь выявить наличие и суть таких скрытых эффектов.
  
  Пример со свертками:
  сверточные нейросети строились так, чтобы наделить их двумя inductive bias,
  которые описаны выше:
  предположением компактности и нечувствительности к переносу.
  Эти bias - те, которые хотел вложить в сверточные сети человек,
  и они явно порождены самой структурой операции свертки.
  Но оказалось, что кроме этих двух inductive bias архитектура сверток
  порождает и другие, которые не так просто выявить,
  просто взглянув на то, как работает свертка.
  
  Например, не так давно одно исследование показало,
  что у сверток есть inductive bias,
  касающийся текстуры изображений:
  оказывается, сверточные сети устроены так,
  что при обработке картинок обращают больше внимания на текстуры,
  а не на формы объектов.
  Это пример вредного inductive bias:
  мы бы хотели, чтобы было наоборот:
  чтобы нейросеть делала выводы не на основе текстур,
  а на основе форм предметов.
  Из-за этого "перекоса" в сторону текстур
  сверточные сети плохо распознают картинки,
  на которых текстуры объекта сильно отличаются от текстур тех картинок,
  что были в обучающей выборке.
  
  Чтобы избавиться от такого нежелательного поведения сверток,
  нужно внедрить в нейросеть еще один inductive bias,
  который заставит модель обращать больше внимания на формы объектов,
  а не на их текстуры.
  Такой inductive bias внедряется через изменение обучающих данных,
  а не архитектуры модели.
  Изображения из тренировочного датасета аугментируются так,
  чтобы датасет содержал больше изображений одинаковой формы
  (например, картинок слонов),
  но с разными видами текстур (см. рис. ниже)
  
  Рис. https://arxiv.org/pdf/1811.12231.pdf
  Пример аугментации изображений тренировочной выборки,
  чтобы уменьшить влияние текстуры изображений на работу CNN.
  Слева - исходное изображение;
  справа - аугментированные версии левого изображения с разными текстурами,
  но одной формой.
  
  //// А интересно, как такой нежелательный эффект - зависимость от текстуры -
  //// можно устранить "архитектурными приемами"?
  //// Представляется, что это было бы очень полезные "приемчики"
  //// в самых разных задачах.
  
  Это еще один пример того,
  как разные inductive bias могут внедряться в модель посредством разных техник
  - не только с помощью изменения архитектуры модели,
  но и манипуляцией тренировочными данными.
  А также пример того, что наличие любых inductive bias
  зависит не от отдельного компонента - архитектуры модели,
  устройства данных или алгоритма обучения - а от всех сразу.
  
  Понимание, какие скрытые inductive bias есть у модели,
  помогает лучше понять, как именно модель обрабатывает данные
  и сделать модель более эффективной,
  если выявленные скрытые inductive bias окажутся вредными.
  
  В английском языке "скрытые" inductive bias называются implicit.
  А те, которые человек осознанно вложил в модель - explicit.
  
  Итак, мы выяснили, как inductive bias сверточных слоев
  помогает CNN эффективно обрабатывать изображения.
  Рассмотрим другую архитектуру нейросетей для работы с картинками
  - Visual Transformer - и поймем,
  как ее недавний успех связан с inductive bias.
  
  Visual Transformer и inductive bias
  
  Возможно, вы слышали об архитектуре Visual Transformer.
  Это НЕсверточная архитектура нейросетей для обработки изображений,
  которая показывает лучшие результаты, чем сверточные сети,
  на некоторых задачах:
  например, на задаче классификации картинок из датасета JFT-300M.
  В этом наборе данных 300 миллионов изображений.
  
  Модель Visual Transformer основана на той же идее,
  что и архитектура Transformer из области обработки естественного языка (NLP):
  на механизме Attention.
  По сути, Visual Transformer - это адаптация модели Transformer для языка
  на область картинок.
  Модель была предложена сравнительно недавно - в 2020 году -
  но уже завоевала популярность,
  получила широкое применение в задачах и считается "убийцей сверток".
  Подробно об архитектуре читайте в оригинальной статье.
  
  Мы же поговорим о том, почему Visual Transformer работает лучше, чем свертки,
  правда ли, что свертки больше не нужны и при чем тут inductive bias:
  
  Так как у Visual Transformer нет сверток,
  у этой архитектуры нет и inductive bias,
  которые есть у сверточных нейросетей.
  При этом, конечно, некоторые inductive bias у Transformer все же есть
  - как мы убедились выше, совсем без них нейросеть сделать нельзя.
  
  Visual Transformer почти полностью основан на механизме attention (внимания),
  поэтому модель имеет те inductive bias, которые есть у attention.
  Один из них - сдвиг в сторону простых функций.
  Как и у сверток и всех нейросетей в целом,
  у трансформеров есть скрытые inductive bias,
  и все они пока неизвестны:
  ведутся исследования для их выявления.
  Вот, например, ссылка на одно такое.
  https://arxiv.org/pdf/2106.13122.pdf
  В общем, предстоит еще много исследований трансформеров,
  но что можно сказать точно
  - inductive bias трансформера намного проще,
  чем у сверточных нейросетей,
  они накладывают меньше ограничений на модель.
  //// Т.е. пока, на момент написания статьи,
  //// список inductive bias для трансформеров реально неизвестен.
  
  Меньшие ограничения на модель дают Visual Transformer
  больше возможностей для выбора лучшего способа генерализации при обучении.
  И на очень больших датасетах типа JFT-300M трансформеры
  действительно показывают лучшие результаты при обучении, чем свертки.
  В JFT-300M достаточно изображений,
  чтобы нейросеть с очень легким inductive bias хорошо обучилась решать задачу,
  и не выбрала "неправильный" способ генерализации.
  
  Но вот на датасетах размером поменьше (как ImageNet)
  Visual Transformer проигрывает классическим сверткам.
  На графике ниже представлены результаты нескольких моделей,
  обученных на разных датасетах:
  ImageNet (~1.2 млн изображений), ImageNet-21k (~15 млн изображений)
  и JFT-300M (~300 млн изображений).
  
  BiT - сверточная архитектура на основе ResNet,
  ViT - архитектура Visual Transformer.
  На графике видно, что трансформеры начинают показывать результаты лучше сверток
  только на больших датасетах:
  
  https://arxiv.org/pdf/2010.11929.pdf
  
  Результаты моделей BiT (ResNet-based) и ViT (Visual Transformer)
  на датасетах разных размеров.
  Внутри серой области заключены результаты различных моделей BiT.
  Видно, что ViT начинает выигрывать у BiT
  только при достаточно большом размере датасета
  
  Другими словами, если у вас есть огромный датасет для обучения сети,
  Transformer - ваш выбор,
  однако для обучения на небольших датасетах лучше выбрать свертки.
  
  Преимущество Visual Transformer над свертками на больших датасетах
  имеется ровно потому,
  что у архитектуры Visual Transformer нет inductive bias,
  какие есть у сверточного слоя.
  Здесь мы наблюдаем подтверждение того,
  что чем меньше обучающий датасет,
  тем более сильный inductive bias нужен для успешного обучения модели.
  Но верно и обратное:
  чем больший датасет есть у нас в распоряжении,
  тем меньший inductive bias требуется
  и тем лучше модель может обучиться под задачу
  (потому что у нее меньше ограничивающих bias'ов,
  а величина датасета позволяет получить всю нужную информацию
  для хорошей генерализации из него)
  
  А также убеждаемся, что inductive bias сверточных нейросетей
  действительно сильно помогает для решения задач,
  связанных с изображениями.
  
  Свертки + Transformer
  
  Выше мы разобрали два подхода к обработке картинок нейросетями:
  с помощью сверточных слоев и архитектуру Transformer.
  Оба подхода имеют преимущества и недостатки:
  у сверток сильный inductive bias,
  но они хорошо показывают себя на небольших датасетах,
  а трансформеры могут показывать лучшие результаты в обработке изображений,
  но им для этого требуется очень много данных.
  
  Ребята из Facebook (ой, Меты, извините) решили использовать
  преимущества обоих подходов:
  совместить архитектуры Transformer и CNN.
  Гибридная модель ConViT сможет обрабатывать картинки почти так же хорошо,
  как и Transformer,
  при этом требуя меньше данных для обучения.
  Вот статья с описанием предлагаемой модели и рассуждениями,
  почему это должно сработать (там есть слова inductive bias!)
  
  Надеюсь, такое погружение в устройство сверток и трансформеров
  помогло глубже осознать понятие inductive bias =)
  
  Заключение
  
  Итак, сделать модель без inductive bias в принципе невозможно,
  так как уже само устройство модели вносит ограничения в ее возможности
  и порождает inductive bias.
  Да и делать такую модель не нужно:
  как мы увидели из статьи, inductive bias часто помогает в решении задач.
  Вопрос лишь в том, насколько сильный нужен inductive bias
  для решения конкретной задачи,
  насколько он поможет решить нужную задачу
  и как создать архитектуру модели, которая породит нужный inductive bias
  (ну и вместе с этим не породит много вредных скрытых bias).
  
  Главная задача при создании архитектуры модели машинного обучения
  - наделить модель таким inductive bias,
  чтобы он помогал модели обучиться решать поставленную задачу
  (как в случае сверток),
  а не мешал. Собственно, в изобретении таких inductive bias
  и заключается задача поиска новых эффективных архитектур нейросетей.
  
  Надеюсь, эта статья помогла вам в понимании того,
  что такое Inductive bias и почему он полезен,
  а не вреден =)
  Вот еще несколько полезных ссылок по теме:
  
  Литература:
  
  ......
  
  //// И самое интересное из комментариев.
  
  aarmaageedoon
  27 ноя 2021 в 11:42
  
  Отличная статья, спасибо.
  
  Очень ценно замечание,
  что несмотря на способность нейросетей аппроксимировать
  сколь угодно сложные функции,
  их архитектура может быть заточена под определенные условия,
  что в свою очередь также вызывает смещение моделей.
  Как это ускользало от меня.
  0
  
  ......
  
  Alexey2005
  27 ноя 2021 в 17:14
  
  Основная проблема backpropagation в том,
  что этот метод требует дифференцируемой loss-функции.
  В итоге даже очень простые правила запихнуть в loss-функцию
  оказывается крайне сложно.
  
  Допустим, мы хотим натренировать наш трансформер так,
  чтобы в выдаче отсутствовали какие-то словосочетания.
  Вот каждое слово по отдельности присутствовать могло,
  а в указанной комбинации - нет.
  
  И вот тут возникает проблема таких масштабов,
  что проще оказывается применить фильтрацию выдачи
  - генерировать в разы больше результатов, чем нужно,
   а потом прогонять их через фильтр.
  Потому что в loss-функцию вы даже такое простейшее правило не запихнёте.
  Т.е. тренировать сеть так,
  чтобы <штрафовать> её за нарушение некоего набора правил,
  оказывается крайне сложно.
  Backpropagation для этого не годится.
  0
  
  Atmyre
  27 ноя 2021 в 20:00
  
  Да, такая проблема у backprop есть, вы правы)
  я и не говорю, что backprop - панацея, нет,
  я лишь говорю, что он вносит вклад в inductive bias.
  0
  
  dimka11
  14 дек 2021 в 16:31
  
  Возможно с развитием RL, что-то получится сделать с этой проблемой
  0
  
  Atmyre
  16 дек 2021 в 19:28
  
  ну кстати да, я еще в 2017 году свой бакалаврский диплом делала по тому,
  как с помощью RL обучать сеть для NLP на недифференцируемую функцию потерь.
  //// Интересное замечание: RL vs BP. Надо подумать.
  //// Ради одного этого замечания стоило прорабатывать всю статью.
  Так что охотно верю)
  0
  
  ......
  
  Atmyre
  1 дек 2021 в 00:08
  
  Да, вы правы. Это вопрос того, что вы от модели хотите при обучении,
  то есть, на какую метрику обучаете)
  В зависимости от того, что вам нужно, чтобы модель делала,
  нужно внедрять соответствующий inductive bias
  и, в частности, конструировать соответствующую лосс-функцию.
  0
  
  victorsenkevich
  16 дек 2021 в 19:29
  
  Inductive bias ~ abductive relation Или, проще,
  можно понимать как область существования (модели etc)
  Или как общая функция, описывающая рассматриваемые данные
  (которая может быть неизвестной).
  Или как смысл - это самое короткое определение.
  Кстати, inductive этот bias, строго говоря,
  не является, поскольку индуктивным выводом его не получить.
  0
  
  ......
  
  victorsenkevich
  21 дек 2021 в 14:24
  
  Ваш комментарий это тоже пример Inductive bias.
  Смысл субъективен и существует лишь для тех, кто его воспринимает.
  Если чего-то не понимаешь, то это действительно не существует.
  А для того, кто понимает, существует.
  Так что мы оба правы.
  Inductive bias это фактически понимание.
  Ну или смысл, как я уже писал.
  У меня статья на эту тему.
  Там есть формальное определение когнитивных понятий,
  в том числе "смысл".
  И определение интеллекта из 2(двух) слов.
  Ссылку давать не буду.
  Пожалуй, лишь добавлю, что фраза "не понимаю поэтому неверно"
  является очевидно неверной.
  
  Да, и <Шерлок Холмс использовал абдукцию, а не дедукцию>
  \\\ "Sherlock Holmes practised abduction, not deduction"
  
  Поэтому индукция тут ни при чем. Впрочем, и это я уже писал.
  0
  
  ......
  
  nicmname
  16 дек 2021 в 19:29
  
  Англицизм "inductive bias" не воспринимается, вот вообще никак.
  Прям отторжение. Неужели нет термина соответствующего в математике,
  я полагаю это же всё равно основано на каком-то математическом аппарате?
  И ещё хотелось бы подробный разбор Альфафолда "для чайников", можно?
  Мне бы даже в частном формате, понимаю, что статью писать
  - это большой и долгий труд.
  0
  
  Atmyre
  16 дек 2021 в 19:31
  
  Что ж, а я не воспринимаю русские аналоги ?\_(?)_/?
  
  Я пишу статью и стараюсь, чтобы всем было максимально понятно,
  о чем идет речь.
  В моем понимании "максимально понятно" - это вот так.
  Потому что именно этот термин используется в проф. среде
  (по крайней мере, я так его слышу)
  и человек, прочитав статью, сразу поймет, о чем речь.
  +1
  
  ......
  
  //// Конец цитирования.
  
  На мой взгляд, очень хороший материал для понимания того,
  что любое решение при разработке архитектуры нейросетей
  и процесса ее обучения имеет "много гитек"
  не только в плане "полуэвристических правил",
  но и, так сказать, в "методологическом плане".
  И которые нужно заранее превратить в согласованную систему,
  а не пытаясь постфактум пытаться исправить
  откуда-то позаимствованную архитектуру с обучающим датасетом
  какими-то "полушаманскими методами", типа подбора гиперпараметров.
  
  Хотя в настоящее время ничего лучше этого никто предложить не может.
  Слишком много явных/известных и неявных/неизвестных inductive biases
  по факту приходится использовать в моделях "машинного обучения".
  
  
  ========
  
  20.04.2024 10:34
  
  Двоичные нейронные сети "для чайников".
  В оглавление.
  
  В процессе проработки материалов по различным структурам нейросетей
  меня заинтересовала сама концепция бинарных/битовых нейросетей (BNN)
  с самых разных точек зрения.
  Даже попытался самостоятельно сформулировать собственное видение того,
  что и как в эту концепцию стоит включить.
  Но, естественно, я не первооткрыватель такого подхода к конструкции нейросетей
  и, соответственно, стоит ознакомится с тем, что в этом направлении уже сделано,
  и с чем столкнулись при реализации.
  
  К сожалению, русскоязычных материалов по этой тематике оказалось
  очень не много, и большей частью достаточно "древние"
  по меркам сегодняшней эпохи "бури и натиска" в нейротехнологиях.
  Так что наиболее интересную часть информации удается найти
  даже не в самих публикациях, а в комментариях к ним,
  вот как в данном случае:
  
  "Как работают двоичные нейронные сети, и почему они будут популярными в 2020-м".
  Автор: SLY_G (Вячеслав Голованов)
  https://habr.com/ru/articles/483674/
  13 янв 2020 в 10:00
  
  Автор оригинала: Henk Muller
  https://thenextweb.com/podium/2019/12/20/how-binarized-networks-work-and-why-theyll-be-big-for-ai-in-2020/
  
  //// Начало цитирования.
  
  Нейросети - штука классная,
  однако их потенциал до сих пор ограничивают стоимость и энергия;
  с этим, возможно, помогут справиться двоичные нейросети
  
  Концепция нейросетей впервые появилась более 40 лет назад,
  когда учёные экспериментировали с математическим моделированием функций мозга.
  Они придумали, как сделать механическую реализацию нейросети,
  которую можно обучить распознаванию закономерностей и классификации данных
  - к примеру, распознавать, есть ли на видео кошка или собака.
  
  За последнее десятилетие сложность и способности нейросетей значительно выросли.
  Совместно с беспрецедентным ростом мощностей недорогих и доступных суперкомпьютеров
  и графических процессоров (GPU)
  они вышли на передний план в качестве метода по умолчанию для решения задач,
  распознавания закономерностей и обнаружения аномалий.
  Сегодня организации используют их для составления прогнозов,
  исследования предпочтений пользователей,
  подтверждения данных и управления риском.
  //// Но не для управления реальными производственными процессами.
  //// Пока, в лучшем случае, диагностика, но в основном - рекомендации.
  
  Но, несмотря на такое их активное использование,
  у них есть свои недостатки, ограничивающие их потенциал.
  Святой Грааль - это нейросеть, способная быстро анализировать информацию,
  будучи недорогой и не жадной до энергии.
  //// Не, даже не это, а точность на уровне минимум "шесть девяток".
  Создать удовлетворяющую этим критериям сеть - сложная задача,
  но её нужно решить,
  чтобы мы смогли воспользоваться преимуществами нейросетей ближе к краю IT
  и сетей связи, а также на оконечных устройствах.
  
  Одна из альтернатив, которые изучают многие организации
  - двоичные сети.
  Это достаточно новая технология,
  но она, вероятно, станет достаточно влиятельной в 2020-м.
  //// Здесь автор сильно ошибся - мир увлекся "трансформерами".
  Чтобы понять, почему, нам нужно уяснить, как работают оба типа сетей.
  
  Как работают нейросети
  
  Нейросети состоят из нескольких слоёв взвешенных сумм.
  Каждая взвешенная сумма даёт число,
  которое либо говорит о том, что в этих данных,
  вероятно, есть некий признак,
  или его там, вероятно, нет.
  Эти слои комбинируют, к примеру, необработанные изображения в наборы признаков,
  и рекомбинируют их,
  чтобы в итоге прийти к ответу.
  //// Это так. Ключевая операция в обычных сетях - суммирование.
  
  Проще говоря, допустим, вы хотите,
  чтобы нейросеть могла распознавать лица на фотографиях.
  Система делит изображение на небольшие сегменты,
  а потом слои сети сканируют каждый сегмент изображения,
  ища признак, который их научили определять.
  Первый слой, допустим, может искать базовые признаки:
  чёрные круги, белые круги, белые прямоугольники, цвет кожи.
  Эти признаки просто заметить.
  
  Второй слой может искать глаза (чёрный круг внутри белого),
  рты (набор белых прямоугольников, расположенных рядом, и окружённых кожей),
  следующей слой может искать два глаза надо ртом и с кожей вокруг.
  Каждый признак даёт каждому сегменту изображения
  оценку вероятности присутствия нужного признака
  в этой части фотографии.
  Затем эти вероятности комбинируются,
  и если достаточное количество слоёв считает,
  что разыскиваемый признак имеется на фото,
  то сеть делает заключение, что лицо там есть.
  
  Рис. 1
  
  На рис. 1 (а это фото Барака Обамы) видно,
  как эти слои анализа и вероятностей суммируются,
  позволяя сети, работающей с приближёнными значениями,
  выдавать относительно точный ответ.
  
  Отметим, что такие признаки, как чёрные круги, глаза или рот
  не программируются человеком, а обнаруживаются сетью во время обучения.
  Возможно, что для поиска лиц лучше подходит другая закономерность
  (допустим, нос, уши или линия волос),
  и прелесть нейросетей в том,
  что их можно использовать для поиска подобных закономерностей.
  //// Вопрос в том, что мы до конца не понимаем
  //// как реально ищутся/фиксируются "подобные закономерности".
  
  Недостатки традиционных нейросетей
  
  Проблема в том, что в поисках наивысшей возможной точности
  возникает необходимость иметь дело
  с очень подробно разграниченными уровнями вероятности,
  а для этих математических расчётов требуются серьёзные ресурсы.
  Из-за использования чисел с плавающей запятой для анализа сегментов,
  нейросетям требуется относительно много вычислительных мощностей,
  памяти и времени на работу.
  
  Хотя в облаках есть достаточно вычислительных мощностей и памяти,
  многие краевые приложения не могут полагаться на облако.
  К примеру, робомобилям требуется принимать решения мгновенно
  на основе их окружения,
  и в этом они не могут положиться на ограниченную по пропускной способности связь.
  
  Нейросети, работающие с числами с плавающей запятой,
  на конечных устройствах использовать не получается.
  Многие компании из-за этого используют целочисленную арифметику,
  что экономит большое количество памяти и вычислительных мощностей,
  однако есть способ лучше - именно здесь и проявляют себя двоичные нейросети.
  
  Как работают двоичные сети
  
  Если обычная нейросеть - это картина Пикассо,
  то двоичная нейросеть - это грубый карандашный набросок.
  
  Если нейросети присваивают каждому сегменту точно подсчитанную вероятность,
  то двоичные нейросети, как следует из их имени,
  сводят вероятные значения к чёрно-белому варианту,
  то есть, либо к -1 (если сеть считает, что признака в этом фрагменте нет),
  либо +1 (если он есть).
  
  Теперь взвешенная сумма оценивает каждый признак либо положительно
  (умножая на +1),
  либо отрицательно
  (умножая на -1),
  и вместо полных перемножений нам нужно рассматривать
  лишь умножения на +1 и -1.
  
  Рис. 2
  
  Такой подход жертвует определённой долей точности,
  но мы можем возместить потери, немного увеличив сеть.
  Двоичные сети по своей сути гораздо проще.
  
  По сравнению со своими двойниками с плавающей запятой,
  им требуется в 32 раза меньше места для хранения числа (1 бит вместо 32),
  и в сотни раз меньше энергии,
  из-за чего они куда как более применимы для <краевых приложений>
  типа робомобилей,
  когда сами устройства могут обработать информацию,
  не привлекая облачные вычисления.
  
  Обычно в двоичной сети всё же встречаются слои с небинарными значениями,
  особенно на входе, и иногда на выходе.
  На входе изображение будет, скорее всего, полноцветным,
  и его нужно будет численно интерпретировать перед тем,
  как начнутся двоичные слои.
  И на выходном слое тоже всегда будет небинарный выход.
  
  Будущее двоичных сетей
  
  Такая простота открывает обширное поле для коммерческого применения в условиях,
  когда эффективность решает всё.
  На встроенном чипе с большей вероятностью получится хранить
  коэффициенты двоичной сети,
  чем сети с коэффициентами с плавающей запятой.
  Производителям процессоров нужно будет взять на вооружение эту технологию
  и обеспечить поддержку двоичных сетей.
  
  2020-й с большой вероятностью станет годом двоичных сетей.
  Компании активно работают над реализацией этой технологии,
  а ПО, требуемое для обучения двоичных сетей, быстро развивается.
  Мы, скорее всего, очень скоро увидим первое реальное применение этой технологии,
  и на краевых устройствах появятся недорогие чипы с низким энергопотреблением,
  способные классифицировать изображения или другие данные.
  
  Таким образом, следующее поколение технологий будет основано на простоте.
  //// Но прошло пять лет и "простых технологий" так и не появилось,
  //// а требования к сетям только усложнились,
  //// а сети стали еще более "прожорливы".
  //// Что пошло не так?
  
  .......
  
  //// Из комментариев.
  
  WhiteBlackGoose
  13 янв 2020 в 10:44
  
  Эээм. А что там по обучению этого чуда?
  "Классические" сетки основаны как раз на аналоговости своих весов.
  Если это пропадает, то мы не можем шагнуть на маленький шаг.
  
  Далее, для такой же точности, дайте угадаю, понадобится сетка,
  у которой в 32 раза больше весов, чем у классической?
  
  Alert1234
  13 янв 2020 в 10:58
  
  Возможно придумают как преобразовать аналоговую в бинарную.
  Тогда обучать ее будут по-старому,
  а в девайсах использоваться она будет в readonly в более производительном виде.
  //// Т.е. это "квантование" нейросетей в явном виде,
  //// которое все больше и больше применяется
  //// именно с целью добиться "экстремального уменьшения размерности".
  //// Может быть, успехи в этом направлении как раз уменьшают
  //// необходимость "задрав штаны бежать за комсомолом",
  //// то бишь, получить чистую бинарную сеть.
  
  P.S. Вот у интела написано, что только на этапе обучения
  используются полные веса
  software.intel.com/en-us/articles/binary-neural-networks
  
  WhiteBlackGoose
  13 янв 2020 в 11:17
  
  Действительно, что-то не догадался. Тогда уже интереснее
  
  buriy
  13 янв 2020 в 15:24
  
  1) с обучением как раз всё как-то работает:
  как один из вариантов решения,
  в бинарных сетях используется стохастическое обучение.
  Если backprop даёт 0.65, то это значит,
  то с вероятностью 0.65 текущий вес поменяется.
  Плохонько, но работает.
  Кроме того, пока что не придумали,
  как к такому прикрутить тот же BatchNorm (хотя Dropout - запросто).
  
  2) нет, опыты показывают, что float32 хранит в среднем
  только 5 значащих разрядов.
  Поэтому примерно ему можно поставить в соответствие 5-10 бинарных нейрончиков
  (5 при идеальном разбиении, 10 при неидеальном).
  Итого экономия в 3-6 раз.
  Но вот прунинг показывает более хорошие результаты - в 10-50 раз:
  \\\ Прунинг нейронных сетей - это метод сжатия
  \\\ (уменьшения расхода памяти и вычислительной сложности) сети
  \\\ за счет устранения части параметров в предобученной модели.
  
  3) но вообще, нейроны на выходах и так бинарные:
  но вот что делать со входом?
  Как нормально заменить в традиционной компьютерной архитектуре
  аналоговое суммирование с 10-100 входов?
  тем более, бинаризовав:
  ну, есть векторные popcnt и and,
  но это нам чтобы считать каждый нейрон нужно конвертировать результаты в int8/int16,
  а потом перевести в бинарный вид.
  вот если железо будет ещё больше заточено на это,
  то выигрыш может быть ещё в разы или в десятки раз больше,
  наверное.
  
  но, заметим, что такой же трюк с аккумуляцией и умножением
  можно применить и для float16 входов:
  и получаем 100 TFlops на видюшке для подобных же вычислений,
  и не меньшую эффективность на нейрон, чем с бинарными данными,
  но без требований стохастической бинаризации,
  снижающей скорость и качество обучения.
  
  ситуация может в очередной раз поменяться
  только когда вместо 10-1000 ALU на устройстве
  мы захотим сделать миллионы ALU с собственной памятью,
  вот тогда бинаризация существенно упростит конструкцию
  и расход энергии на один ALU.
  //// Т.е. Существующие и вновь разрабатваемые "железячные ускорители",
  //// "заточенные" под существующие архитектуры нейросети,
  //// достаточно эффективно блокируют потребность в новых подходах.
  
  leshabirukov
  13 янв 2020 в 16:03
  
  1)... Вроде бы стохастическое это скорее так:
  у нас есть бинаризованный вес, и есть непрерывный,
  в расчетах прямого и обратного прохода используем бинаризованный,
  но вычисленный градиент прибавляем к непрерывному,
  а его используем как вероятность выбора нового веса для следующего прохода.
  
  Как нормально заменить в традиционной компьютерной архитектуре
  аналоговое суммирование с 10-100 входов?
  Да всё также, умножением на матрицу весов, только веса +-1.
  Вон, NVidia поддержала 4-битные данные,
  у нас вот в Нейроматриксе есть умножение на упакованный вектор двухбитных чисел.
  
  Brak0del
  13 янв 2020 в 21:13
  
  \\\ ситуация может в очередной раз поменяться только
  \\\ когда вместо 10-1000 ALU на устройстве мы захотим сделать
  \\\ миллионы ALU с собственной памятью,
  \\\ вот тогда бинаризация существенно упростит конструкцию и расход энергии
  \\\ на один ALU.
  
  Вроде как такие вещи хорошо делаются на FPGA, например.
  https://www.nallatech.com/wp-content/uploads/Nalllatech-Whitepaper-FPGA-Accelerated-BNN.pdf
  
  buriy
  15 янв 2020 в 23:34
  
  Ага, в теории. А на практике, по ссылке лишь 200к ALUs на 35 вт,
  и никакой бинаризации.
  А без бинаризации получилось решение в 5 раз слабее видеокарты,
  жрущее в 5 раз меньше энергии, и не дешевле.
  
  Brak0del
  16 янв 2020 в 23:07
  
  Вот ещё ссылка, правда здесь уже не коробочный акселератор,
  https://arxiv.org/abs/1702.06392
  а университетское исследование на стартките.
  В таблице в конце 7.6 TOPs на 8 Вт.
  В статье они также грубо оценивают вычислительный параллелизм GPU и FPGA,
  при этом на 1 LUT в среднем по их прикидке выходит 2.5 операции XNOR.
  Не знаю, корректно ли это считать за АЛУ,
  но если да, то вот вам порядка миллиона АЛУ на кристалле.
  
  Конечно есть вопросы к их реализации:
  как и в ссылке на Nallatech,
  они тоже кодили с использованием средств высокоуровневого синтеза (HLS),
  вероятно обычным RTL было бы эффективнее по ресурсам и частоте,
  кроме того, по идее могли бы попробовать вписаться
  в меньший и более дешёвый кристалл.
  У них там дорогой Virtex за 5K$,
  хотя наверно удалось бы влезть в Kintex за 1.5К$.
  
  За пределами FPGA что-то похожее на описанные вами
  миллионы АЛУ с собственной памятью делают GSI Technology:
  вот презентация их APU,
  здесь простейшие вычислители совмещены с ячейками памяти.
  
  buriy
  17 янв 2020 в 15:22
  
  Спасибо. Да, многие пытаются,
  но пока вычислительная эффективность на традиционных дизайнах FPGA
  не очень высока почему-то...
  Но энергоэффективность при предсказании при этом раз в 3-10 выше
  по сравнению с максимальным TDP неспециализированной видюшки,
  поэтому крупные компании их всё же используют.
  
  Мои догадки: остаётся критичной узкая шина обращения к памяти,
  и плохо исследованы эффективные под FPGA модификации
  алгоритмов обучения и предсказания с бинарными весами:
  предсказания на сетке с прунингом+int8 сейчас работают лучше
  (заметим, что всё это обычно и исследуется на картинках, где int8 на входе).
  
  Я надеюсь на то, что допилят мемристоры,
  энергоэффективность ALU повысится,
  проблема с памятью рядом с вычислениями решится:
  в результате, аналоговые/float вычисления станут
  ещё более конкурентоспособными,
  можно будет делать быстрое обучение прямо на чипе,
  и одновременно решится проблема быстрого суммирования при inference
  - в том числе, бинарного.
  
  mpakep
  13 янв 2020 в 11:59
  
  У таких сетей есть еще масса преимуществ.
  Не обязательно считать всю сеть а можно лишь ее часть.
  Я считал как то сколько это может быть и у меня вышли такие цифры
  Для расчета достаточно 3.2% (32 нейрона) при сети в тысячу нейронов,
  0.1% (1 тыс) при миллионе <нейронов> в сети
  и 0.003% (32 тыс) при сети размером в миллиард <нейронов>.
  Цифры могут немного разница от результата расчета,
  но порядки будут оставаться в близких пределах.
  Это даст просто огромное преимущество
  на действительно больших массивах данных.
  И еще одной свойство это отсутствие эффекта переобучения,
  то, чем страдает большая часть <аналоговых> алгоритмов.
  
  kuza2000
  13 янв 2020 в 13:02
  
  \\\ И еще одной свойство это отсутствие эффекта переобучения,
  \\\ то, чем страдает большая часть <аналоговых> алгоритмов
  
  А можно пруфы?
  Не вижу никаких причин для отсутствия переобучения в таких сетях:
  
  kogemrka
  13 янв 2020 в 13:41
  
  Предупреждаю, у этого товарища своё определение <Переобучения>,
  никак не связанное с настоящим переобучением.
  А ещё свой чудесный алгоритм без <переобучения> (в его формулировке).
  
  WhiteBlackGoose
  13 янв 2020 в 19:08
  
  Может он имеет ввиду проблемы со значениями весов
  (которые, правда, фиксятся L1 и L2)?
  
  arquolo
  13 янв 2020 в 21:36
  
  Нет, у него переобучение
  - это не когда <на трейне - отлично, на тесте - хреново>,
  а когда с увеличением количества эпох на тренировочной
  (и единственной, ибо весь тест слит туда) выборке данных
  не растёт точность.
  
  Его в ods.ai уже на протяжении 5700 сообщений народ переубедить пытается.
  
  ........
  
  KvanTTT
  13 янв 2020 в 23:43
  
  А что если вместо одного бита использовать чуть больше: 2 или 4?
  
  .......
  
  
  Vinchi
  15 янв 2020 в 20:52
  
  https://arxiv.org/abs/1602.02830
  Есть bnn
  Возможно речь о них.
  Вопрос один есть ли готовая библиотека для создания обучения и тестов?
  
  Leo_Gan
  17 фев 2020 в 07:16
  
  Статья отражает многие современные исследования.
  На ум приходит компания Numenta,
  Jeff Howkins with Hierarchical Temporal Memory.
  У них много есть чего на youtube в том числе очень интересные курсы по HTM.
  Так вот они тоже все строят на бинарной идее.
  
  Далеко ходить не надо. Наш мозг построен на бинарной основе
  и пока что никакие супер-сложные и быстрые процессоры его не переплюнули.
  Numenta как раз идет от работы мозга.
  Так что, я тоже думаю, что бинарные сети будут рулить.
  Похоже, что самая большая проблема на этом пути
  - в создании "правильного" двоичного железа.
  Не того, что моделирует плавающую арифметику на двоичной элементной базе,
  а железа, похожего на HTM.
  ... и вдогонку.
  Дискуссии о проблемах имплементирования бинарных сетей
  на существующих процессорах понятны,
  но, по большому счету, мало что значат.
  Как в свое время быстренько выдумали GPU для каких-то там игра,
  так и сейчас, быстренько сварганят двоичные процессоры для бинарных сетей.
  С современными компьютерами - это небольшая работа :)
  //// Т.е. проблемы не в "железе", а скорее в "идеологии".
  //// Нет хороших архитектурных решений, подтвержденных практикой,
  //// а тем более нет "хорошей теории", ведь не считать же таковой,
  //// ссылки на биологические нейросети.
  
  .....
  
  //// Конец цитирования.
  
  Суммируя вышесказанное, можно сказать,
  что основным стимулом исследований в этом направлении
  пока является стремление снизить требования к нейросетям
  по необходимой памяти и вычислительным мощностям.
  При этом ориентиром служат биологические нейронные сети,
  и устоявшиеся решения в традиционных ИИ-моделях,
  в частности, обучение методом обратного распространения ошибки.
  И при таких "вводных" бинарные нейронные сети
  составить реальную конкуренцию традиционным архитектурам нейросетям
  на сегодняшний день явно не смогли.
  Не смотря ни на какие "обоснованные прогнозы".
  Хотя, конечно, "еще не вечер".
  
  Но, с моей точки зрения, бинарные нейронные сети заслуживают большего внимания
  совершенно по иной причине, причем, не столько технической
  - память и вычислительные мощности, это чисто технические параметры,
  и они в соответствии с "законом Мура" будут удваиваться каждые полтора года,
  так что в исторической перспективе это не самая большая проблема.
  Главное, что могут дать бинарные нейронные сети
  - это принципиально новые технические решения
  как архитектурные, так и алгоритмические,
  которые в мэйнстриме традиционных нейросетей
  могут проявиться очень не скоро.
  В области "идей" "закон Мура" пока не работает.
  Скорее, даже, наоборот - зачем придумывать что-то новое,
  если старый подход еще работает.
  
  И в первую очередь это может касаться действительно "болевой точки" нейронауки
  - новых методов "машинного обучения" нейросетей.
  И об одном таком непривычном подходе в следующем материале.
  
  
  ========
  
  16.04.2024 21:34
  
  Насколько реально обучение BNN методом сплошного перебора?
  В оглавление.
  
  Продолжая тему бинарных/битовых нейронных сетей (BNN),
  хочу предложить Вам для ознакомления один достаточно "древний" материал,
  в котором предлагается метод обучения бинарной нейронной сети методом,
  на первый взгляд, чудовищно неэффективным - сплошным перебором параметров.
  Но "не все так однозначно", есть в этом предложении пара интересных моментов,
  помимо других не менее интересных предложений.
  А, впрочем, судите сами, но не забудьте посмотреть комментарии:
  
  "Бинарная матричная нейронная сеть".
  Автор: akazant (Александр Казанцев)
  https://habr.com/ru/articles/343304/
  27 ноя 2017 в 16:10
  
  //// Начало цитирования
  
  Бинарная матричная нейронная сеть
  
  Искусственная нейронная сеть в виде матрицы,
  входами и выходами которой являются наборы битов,
  а нейроны реализуют функции двоичной логики нескольких переменных.
  Такая сеть значительно отличается от сетей перцептронного типа
  //// Т.е. основанных на суммировании входов.
  //// Это принципиальное отличие.
  //// И, вообще, хорошая формулировка принципиального разделения
  //// BNN от других традиционных NN.
  и может дать такие преимущества как конечное число вариантов
  полного перебора функций сети,
  а следовательно и конечное время обучения,
  сравнительная простота аппаратной реализации.
  
  Рис.
  
  Предпосылки создания бинарной матричной нейронной сети
  
  Попытки создания искусственных нейронных сетей основываются
  на факте существования их естественных прототипов.
  Способ передачи и обработки информации в естественной нейронной сети
  определяется химико-биологическими свойствами живых клеток-нейронов.
  Однако, модель искусственной нейронной сети
  не обязана полностью копировать
  как функцию нейронов, так и структуру естественного мозга,
  так как реализует только функцию преобразования информационных входов в выходы.
  //// Вот это одно из ключевых положений в инженерии информационных систем,
  //// которое почему-то как-то не акцентируется в "традиционной нейронауке",
  //// при том, что, по факту, только это и применяется.
  Поэтому реализация функции искусственной нейронной сети
  может значительно отличаться от ее естественного аналога.
  Попытка прямого копирования структуры естественного мозга
  неизбежно сталкивается со следующими проблемами,
  которые, при отсутствии их решения,
  могут оказаться непреодолимыми.
  Как известно, в мозге млекопитающих выход нейрона
  может быть подключен к входам нескольких других нейронов.
  
  Как узнать входы каких нейронов
  должны быть связаны с выходами других нейронов?
  Сколько нейронов должно быть связано с каждым конкретным нейроном в сети
  для того чтобы сеть выполняла свою функцию?
  
  Ответов на эти вопросы пока нет,
  а подключение нейронов друг к другу методом перебора
  гарантирует практически бесконечное время обучения такой сети,
  учитывая, что количество нейронов реального мозга исчисляется миллиардами.
  
  В искусственных нейронных сетях перцептронного типа
  все нейроны соседних слоев связаны друг с другом.
  А "сила" связи определяется значением коэффициентов.
  Связь "все-со-всеми", это решение проблемы связей нейронов
  методом "грубой силы".
  В этом случае, нейронная сеть может содержать
  только сравнительно небольшое число нейронов на промежуточных слоях
  для приемлемого времени обучения,
  например, в течение нескольких недель [2].
  
  Прежде чем нейронная сеть станет выдавать результат,
  например, классифицировать изображения,
  она должна пройти этап обучения,
  то есть этап настройки.
  На этапе обучения как раз и определяются конфигурация взаимодействия
  и общая функция нейронов сети.
  По сути, обучить нейронную сеть означает
  подобрать функцию преобразования таким образом,
  чтобы на заданных входах она давала правильные выходы
  с заданным уровнем ошибки.
  Затем, после обучения,
  мы даем на вход сети произвольные данные,
  и надеемся, что функция нейронной сети подобрана достаточно точно
  //// Хорошая формулировка "надеемся".
  и сеть станет правильно,
  с нашей точки зрения,
  классифицировать любые другие входные данные.
  //// А если "надежды" не оправдались, начинаем рассуждать
  //// о "локальных минимумах" и "переобучении".
  В популярных сетях перцептронного типа структура сети
  задается изначально фиксированной,
  см. например [2],
  а функция находится подбором коэффициентов связей нейронов промежуточных слоев.
  Прежде чем переходить к описанию матрицы,
  заметим, что одновременную связь всех нейронов соседних слоев
  можно разложить в последовательные связи
  пар нейронов
  пользуясь тем, что функция нейрона
  это линейная комбинация выходов нейронов предыдущего слоя
  и коэффициентов связи.
  То есть, по крайней мере, для сетей перцептронного типа,
  каждый нейрон можно представить как принимающий данные
  только от двух других нейронов.
  //// Вот это момент, на мой взгляд очень важен.
  //// Представление какой-то одной связи/нейрона комбинацией нескольких,
  //// более простых в реализации позволяет, в конечном итоге,
  //// перейти от регулярных структур нейросетей к не регулярным,
  //// а затем и к самонастраивающимся.
  
  Принцип разложения нескольких параллельных связей
  в последовательность пар или троек связей
  только соседних нейронов
  и лежит в основе матрицы описываемой ниже.
  Принимается ограничение,
  что вовсе не обязательно обучать сеть подключая к нейрону
  все остальные,
  достаточно ограничиться только соседними нейронами,
  а затем последовательно уменьшать ошибку функции обучения сети.
  Данная версия нейронной сети основывается
  на предыдущей работе автора [1].
  
  Структура матрицы и нейрона
  
  Следующая матричная структура нейронной сети
  позволяет решить проблему подключения нейронов
  и ограничить число комбинаций при поиске функции нейронной сети.
  Эта сеть также в теории позволяет найти функцию нейронной сети
  с нулевой ошибкой на обучающих наборах входов/выходов
  за счет того, что функция сети является
  дискретной векторной функцией нескольких переменных.
  
  На рис.1 представлен пример бинарной матрицы.
  Входы и выходы этой матрицы - двоичные четырех-компонентные векторы.
  Входы подаются снизу, сверху получаем выходные значения.
  Каждая клетка матрицы это нейрон с двоичной функцией нескольких переменных f.
  Каждый нейрон имеет горизонтальную и вертикальную перегородки,
  отделяющие его от соседних нейронов и определяющие перетоки данных.
  Вертикальная перегородка нейрона, изображена слева от каждого нейрона,
  может иметь три положения:
  закрыто (темная полоса),
  открыта вправо (зеленая стрелка вправо),
  открыта влево (желтая стрелка влево).
  
  Горизонтальная перегородка, изображена снизу от нейрона,
  может иметь два положения:
  закрыто <стоп> (темная полоса)
  или открыто вверх (зеленая стрелка).
  Таким образом, переток данных в матрице может быть снизу вверх и влево/вправо.
  Для того чтобы избежать выделения граничных разрядов данных
  первый и последний нейроны в каждом ряду логически зациклены,
  то есть, например, стрелка влево первого нейрона в ряду
  является входом последнего нейрона в этом же ряду,
  как показано на рис.1 для нейронов второго ряда.
  
  Рис. 1. Пример бинарной матрицы из 3-х строк и 4-х двоичных входов/выходов.
  
  Структура матрицы подчиняется правилам поэтапного построчного построения.
  Если данный набор строк нейронов не решает задачу,
  то к ним добавляются следующие,
  и так пока целевая функция не будет достигнута.
  //// Тут стоит еще подумать, как сделать матрицу "переменной по ширине",
  //// чтобы, например, обеспечить реализацию "бутылочного горлышка",
  //// сжимающего размерность "эмбеддинга"/"латента".
  
  Перед обучением матрица состоит из одной первой строки.
  Обучение матрицы заключается в последовательном добавлении строк.
  Новые строки добавляются после нахождения одной
  или нескольких конфигураций перегородок на текущей строке,
  а также внутренних параметров нейронов,
  при которых значение ошибки на обучающих наборах матрицы минимально
  и меньше чем значение ошибки обучения на предыдущей строке.
  
  Нейроны выполняют функцию преобразования данных,
  передачу или остановку сигнала. Функция нейрона f,
  в зависимости от текущей конфигурации перегородок и внутренних констант,
  должна удовлетворять следующим обязательным требованиям:
  
  1. иметь возможность передачи данных без изменений;
  
  2. уметь передавать константу (0 или 1) без входных данных;
  
  3. не должна зависеть от последовательности применения входных данных
  от соседних нейронов,
  то есть нейрон выдает результирующее значение
  от всех своих входов поступивших как бы одновременно.
  
  Один из вариантов такой функции f это сложение по модулю 2
  или исключающее ИЛИ или XOR,
  как она часто обозначается в языках программирования.
  
  Передача без изменения означает фактическое отсутствие нейрона
  и нужна только с точки зрения пропускания уровня матрицы без изменения данных.
  //// Ну, тут стоит подумать над возможностью прямых связей
  //// между нейронами различных уровней напрямую, наподобие Residual Blocks,
  //// чтобы уменьшить количество просто транзитных нейронов.
  //// А это, в свою очередь, откроет возможность отказаться от структуры
  //// "плотной матрицы" и перейти к "разреженной"
  //// и, по факту, вообще к "свободной" архитектуре нейросети,
  //// в которой понятие "слоя" вообще становится чисто условным.
  //// Т.е. в предлагаемой архитектуре нужно сделать более гибкой,
  //// а, точнее, настраиваемой АДРЕСАЦИЮ связей каждого отдельного нейрона.
  
  Кроме обработки и передачи сигнала нейроны также имеют функцию памяти
  и ее использования или неиспользования в зависимости
  от функции реализуемой нейроном.
  
  В зависимости от положения (значений) перегородок нейрона
  и его соседних нейронов,
  каждый нейрон может иметь от нуля до трех входов
  (снизу, справа и слева)
  и всегда один выход (вверх),
  который, однако, может быть не подключен к нейрону следующей строки,
  из за положения горизонтальной перегородки верхнего нейрона "стоп".
  //// А тогда зачем он нужен? Как резерв? Ну, может быть и так.
  
  Рис. 2. Нейрон с бинарной функцией f, ячейкой памяти Memo и полем Res.
  
  Каждый нейрон выполняет одну и ту же двоичную функцию f,
  //// Не обязательно. Это может быть набор матричных операций,
  //// потенциально реализующих более богатый функционал, чем одна операция.
  //// И лучше если это будет определяться в результате обучения/настройки.
  которая отличается только количеством входных значений
  в зависимости от конфигурации перегородок нейрона,
  которые разрешают входные данные от нейрона предыдущей строки
  и двух боковых соседних нейронов,
  а также от бинарной внутренней константы Memo.
  //// Можно "немного" расширить количество одновременно рассматриваемых данных,
  //// как минимум, до разрядности логического устройства процессора,
  //// например, 8 или даже 64 бит.
  
  Нейрон получает данные на вход,
  выполняет двоичную функцию нейрона f на основе входов и поля Memo
  и помещает результат в поле Res.
  Варианты использования поля Memo могут быть различны.
  Если выход всей матрицы зависит только от входов сети,
  то поле Memo является частью конфигурации сети
  вместе со значениями перегородок нейронов.
  Если же сеть должна обучаться также и на основе предыдущих значений,
  то есть обладать памятью,
  например, для задач реализации искусственной жизни,
  то поле Memo может принимать вновь вычисленное значение Res
  как показано на рис. 2 пунктирной стрелкой.
  //// Наверно, можно рассмотреть вариант,
  //// когда ячейки Memo и Res, собственно, одно и то же,
  //// и таким образом обеспечить реализацию нейроном БИХ
  //// - бесконечную импульсную характеристику.
  
  Допустим что функция нейрона f это бинарная операция XOR
  применяемая последовательно ко всем входным параметрам.
  Проверим, что она отвечает трем необходимым требованиям.
  
  1. Передача данных без изменений обеспечивается вариантом,
  изображенным на Рис. 3.
  Здесь Memo = 0,
  Горизонтальная нижняя перегородка в значении "вверх",
  Левая и правая перегородки в значении "стоп".
  
  Рис. 3. Вариант параметров нейрона,
  реализующий передачу входа с предыдущей строки без изменения в случае f = XOR.
  
  2. Передача константы обеспечивается значениями горизонтальной
  и вертикальных перегородок "стоп",
  а значение Memo - это значение передаваемой константы.
  
  Рис. 4. Нейрон с функцией, передающей независимую бинарную константу Memo.
  Входные значения снизу, слева и справа не используются.
  
  3. Требование независимости значения функции нейрона
  от последовательности обработки входных значений нейрона
  обеспечивается ассоциативностью XOR.
  
  Число комбинаций полного перебора функций строки
  
  Последовательное, построчное построение функции матрицы
  позволяет эффективно оптимизировать процесс обучения
  за счет замены полного перебора комбинаций бинарных функций
  всех нейронов матрицы полным перебором комбинаций функций нейронов строк.
  Одним из ключевых моментов в обучении сети
  является количество комбинаций полного перебора функций нейронов одной строки.
  
  Для варианта нейрона описанного выше в переборе функций нейрона участвуют:
  
  1. горизонтальная перегородка с двумя положениями: стоп и вверх;
  
  2. вертикальная перегородка нейрона с тремя положениями: стоп, влево и вправо;
  
  3. двоичное поле Memo со значениями 0 и 1.
  
  Чтобы подсчитать число вариантов функций нейрона
  на основе комбинаций этих параметров
  перемножаем количество вариантов значений для каждого из этих параметров:
  
  $Q_n = 2\times2\times3=12$.
  
  Таким образом, каждый нейрон,
  в зависимости от количества пришедших на вход параметров,
  может иметь один из 12 вариантов двоичной функции.
  Подсчитаем число вариантов полного перебора функций одной строки матрицы из 8 нейронов,
  которая, таким образом, может обрабатывать данные размером 1 байт:
  Q_s=12^8=429 981 696.
  
  Для современного персонального компьютера
  это не очень большое число вычислений.
  При выборе функции нейрона c меньшим числом вариантов,
  например, без поля Memo,
  число комбинаций значительно уменьшается до 6^8=1 679 616.
  Даже такая значительно упрощенная версия функции нейрона
  демонстрирует уменьшение ошибки обучения в процессе оптимизации.
  В программных тестах с разными вариантами нейронных функций на языке C#
  автору удавалось получить скорость перебора
  в диапазоне 200-600 тысяч вариантов в секунду,
  что дает полный перебор вариантов функций строки матрицы примерно за 3 секунды.
  Однако, это не означает, что например, матрица размером 8x8
  будет обучена в течении 24 секунд.
  Дело в том, что возможно несколько вариантов функции строки
  дающих одно и то же текущее минимальное значение ошибки обучения (метрики).
  Какая из этих, десятков, сотен или тысяч комбинаций приведет в итоге
  к нулевой ошибке обучения всей матрицы мы не знаем,
  и тогда в наихудшем случае нужно будет проверить каждую из них,
  что приводит к построению дерева оптимизационного поиска.
  //// Тут нужно думать. Интуитивно понятно, что какая-то оптимизация.
  //// наверняка, возможна, но в этих вопросах я "не копенгаген".
  
  Естественным образом возникает вопрос,
  а какая двоичная функция нейрона f является наилучшей для обучения матрицы.
  Очевидно, что идеальной будет функция обладающая
  свойством функциональной полноты [3]
  для строки матрицы в заданном наборе параметров перегородок и поля Memo.
  В этом случае мы будем иметь большую,
  если не полную, гарантию нахождения матрицы с нулевой ошибкой обучения.
  Однако, вопрос нахождения такой функции нейрона еще требует изучения.
  
  Построение дерева оптимизации или поиска нуля ошибки обучения матрицы
  
  Функцию ошибки обучения матрицы будем называть метрикой.
  Значение метрики показывает степень отклонения выхода матрицы
  от ожидаемого на обучающих данных.
  
  Пример метрики.
  Предположим что входы и выходы матрицы это 4-х битные числа.
  И мы хотим обучить матрицу умножать входные числа на $2$.
  Допустим, что для обучения используется три входных значения $\{1, 2, 3\}$,
  идеальный выход для которых будут числа $R_1,R_2,R_3:\{2, 4, 6\}$.
  
  Тогда входы обучения для матрицы будут четырех-битовые значения:
  $\{0001, 0010, 0011\}$,
  а выходы, соответственно
  $\{0010, 0100, 0110\}$,
  по одному биту на нейрон входной и выходной строк, соответственно.
  
  Процесс обучения матрицы состоит в последовательном переборе
  положений перегородок нейронов и значений полей Memo в нейронах строки,
  которые вместе выполняют роль параметров поиска.
  После каждого изменения одного из этих параметров,
  то есть, например, смены положения горизонтальной перегородки
  одного из нейронов из положения <стоп> на положение <вверх>
  или смены значения поля Memo c 1 на 0,
  получаем текущую комбинацию перегородок и полей
  и вычисляем значение метрики.
  
  Чтобы получить значение метрики на некоторой комбинации перегородок
  и полей Memo
  //// А вот как учесть это Memo в метриках совершенно непонятно.
  подставляем значения обучающих входов в матрицу и получаем выходы.
  
  Например,
  на некоторой комбинации перегородок и полей
  мы получили выходные значения матрицы $\{0010, 0001, 1000\}$.
  Переводим их в десятичный вид $r_1, r_2, r_3: \{2, 1, 8\}$.
  
  Получаем значение метрики для текущих выходов матрицы:
  
  $M=\sum\limits_{i=1}^3{|R_i-r_i|}=|2-2|+|4-1|+|6-8|=5$
  
  В данном случае ошибка обучения равна 5
  и задача найти такую конфигурацию нейронов на текущей верхней строке матрицы,
  для которой значение метрики меньше $5$.
  
  Рассмотрим один из вариантов поиска нуля метрики,
  при котором каждая новая строка матрицы добавляется
  к предыдущим строкам с конфигурацией перегородок и полей Memo,
  дающей минимальное значение метрики на обучающих данных.
  //// Напрашивается стратегия добавления не целой строки матрицы нейронов,
  //// а такого количества нейронов, которого достаточно для запоминания
  //// конкретного примера.
  
  Общий алгоритм построения дерева оптимизации матрицы.
  
  1. Задаем начальное положительное значение метрики, например max(Int32).
  Создаем матрицу, изначально состоящую из одной строки
  с начальными значениями перегородок "стоп" и нулевыми константами Memo.
  
  2. Цикл: для каждой конфигурации перегородок и констант нейронов первой строки
  вычисляем значение метрики по всему обучающему набору данных.
  
   a. Если значение метрики меньше ее текущего минимального значения,
   то запоминаем новое минимальное значение,
   а матрицу заносим в список поиска как точку ветвления,
   предварительно очистив этот список.
  
   b. Если значение метрики равно текущему,
   то заносим текущую конфигурацию матрицы в список поиска
   как точку ветвления.
  
   c. Если значение метрики больше текущего минимального,
   то матрица отбрасывается, берем следующую комбинацию
   и идем на начало цикла.
  
   d. Если значение метрики равно нулю,
   то поиск закончен и найден один
   (из нескольких возможных)
   вариант обученной матрицы.
  
  3. После перебора всех комбинаций функций на первой строке
  берем последовательно матрицы из списка поиска на первой строке,
  добавляем к ним строку и для каждой из этих матриц применяем алгоритм поиска.
  
  Детали этого алгоритма могут быть различны,
  как в плане экономии памяти, так и ускорения скорости работы,
  например, сортировкой списков
  за счет особенностей конфигураций перегородок нейронов матриц
  или отбрасывания предыдущих списков ветвлений
  в соответствии с уменьшением текущего значения метрики.
  
  Заключение
  
  Практические эксперименты показывают что алгоритм обучения матрицы
  в большинстве случаев сходится.
  //// Значит есть ситуации, когда даже такой алгоритм "не сходится",
  //// и становится чрезвычайно интересно, что это за случаи.
  Например, в одном из тестов с функцией нейрона XOR,
  матрица шириной 8 битов научилась умножать на 2 числа от 1 до 6
  с нулевой ошибкой обучения.
  Подставив на вход 7, на выходе получил 14,
  значит матрица научилась экстраполировать на один ход вперед,
  но уже на числе 8 матрица дала неправильный результат.
  Все обучение заняло несколько минут на домашнем персональном компьютере.
  Однако эксперименты с более сложными обучающими выборками
  требуют иных вычислительных мощностей.
  
  Кроме передачи данных снизу вверх,
  можно также рассмотреть и обратные потоки,
  когда некоторые нейроны в текущей конфигурации матрицы
  передают результаты на предыдущие строки.
  С одной стороны, такие конфигурации могут давать необычные функции матрицы,
  включая циркулирующие данные,
  но, с другой стороны, увеличивают время обучения матрицы,
  так как добавляют еще один параметр конфигурации
  при переборе вариантов решения.
  
  От плоских нейронов можно перейти к трехмерным,
  т.е. рассматривать их не как квадратные элементы,
  а как кубики, каждая грань которых получает или передает данные,
  и тогда (пока теоретически) можно получить вполне осязаемый
  трехмерный искусственный мозг.
  
  Ссылки
  
  1. A.V. Kazantsev, VISUAL DATA PROCESSING AND ACTION CONTROL USING BINARY NEURAL NETWORK
  - IEEE Eighth International Workshop (WIAMIS '07)
  Image Analysis for Multimedia Interactive Services, 2007.
  http://ieeexplore.ieee.org/document/4279131/
  
  2. Наталья Ефремова, Нейронные сети: практическое применение (habrahabr.ru)
  https://habrahabr.ru/post/322392/
  
  3. Функциональная полнота булевых функций (Wikipedia)
  https://ru.wikipedia.org/wiki/Функциональная_полнота
  
  ..........
  
  //// Из комментариев.
  
  Randl
  27 ноя 2017 в 23:28
  
  Show me the code!
  //// Как-то приходилось читать про одного физика,
  //// который на всех семинарах прерывал докладчиков пытающихся,
  //// что-то объяснить простыми словами,
  //// требованием "пишите формулы".
  //// Наверное, по этому физика стала такой "понятной".
  
  Или хотя бы результаты решения стандартной задачи посложнее XOR
  
  akazant
  28 ноя 2017 в 15:26
  
  Немного <причешу> код и выложу проект на C# в общий доступ.
  
  akazant
  29 ноя 2017 в 21:09
  
  Демо-исходники github.com/vuguzum/BinaryNeuralNetwork
  
  fareloz
  28 ноя 2017 в 13:20
  
  Очень интересная концепция и статья выделяется
  на фоне других однотипных статей в стиле <нейросети для чайников>
  которых сейчас слишком много на ресурсе.
  Но это все теория и ее сложно понять без каких-либо практических
  (а еще лучше - графических) примеров.
  
  BelerafonL
  28 ноя 2017 в 14:44
  
  Правильно ли я понял, что автор предлагает обучать свою сеть брутфорсом?
  
  akazant
  28 ноя 2017 в 15:23
  
  Наоборот, брутфорса стараемся всячески избегать.
  Последовательное, построчное построение функции матрицы
  позволяет эффективно оптимизировать процесс обучения
  за счет замены полного перебора комбинаций бинарных функций
  всех нейронов матрицы полным перебором комбинаций функций нейронов строк.
  
  Согласитесь, что, например, восемь полных переборов восьми нейронов каждой
  из строк по отдельности быстрее, чем полный перебор всей матрицы 8x8.
  
  mazkorulez
  28 ноя 2017 в 14:44
  
  Нейронные сети обычно позволяют параллельно выполнять умножение,
  суммирование, вычисление функции для каждого из нейрона
  на уровне одного слоя.
  Как в Вашем случае с учетом перегородок и распространение данных
  осуществляются параллельные вычисления?
  
  akazant
  28 ноя 2017 в 15:40
  
  Если кратко, то в текущей программной реализации
  пришлось идти на уловки которые позволяют достичь эффекта параллельности
  при фактически последовательном алгоритме.
  Но в принципе, в требованиях к функции нейрона указано,
  что последовательность применения входных значений не меняет выход нейрона,
  что позволяет распараллелить процесс.
  
  mazkorulez
  28 ноя 2017 в 16:23
  
  Тогда такой вопрос, как эффективно распараллелить такую сеть
  с учетом того, что сеть необходимо тактировать
  (ведь при получении элементом сети сигнала справа и снизу
  её выход можно будет рассчитать только после того,
  как сигнал справа и снизу будет получен)?
  Иными словами, в слое появляются зависимости между нейронами,
  которые накладывают ограничения на параллельное выполнение кода.
  //// Хороший вопрос.
  //// В том смысле, что подталкивает мысль
  //// к какой-то иной схеме работы нейросети,
  //// не просто к прямому последовательному распространению
  //// входных данных от слоя к слою, но и как-то иначе как в RNN.
  
  akazant
  28 ноя 2017 в 17:00
  
  Затронули интересный вопрос.
  В процессе его решения лично я пришел к довольно неожиданному,
  двоякому результату.
  Во-первых, действительно, возбуждение нейрона означает,
  что все входы у него актуальны на данный момент.
  И тогда передача данных по сети должна представляться
  как передача некой волны сигнала,
  на фронте которой возбуждаются нейроны.
  На практике для этого нужно запрограммировать специальный механизм,
  который находит все нейроны на фронте
  (можно назвать это уровнем) этой волны,
  независимо подставляет в них данные,
  выполняет нейронные функции и находит нейроны реципиенты,
  которые будут возбуждены на следующем шаге волны, и т.д.
  
  Однако, после создания такого механизма на практике,
  получилось, что для вычисления функции метрики в процессе обучения
  нужно было прогонять обучающие входы через всю матрицу
  от первой строки до текущей последней и получать выходы.
  Теоретически так и надо делать,
  но для отладки это долго.
  Ведь изменяются только параметры нейронов последней (одной) строки,
  а прогонять тестовые значения приходится через всю матрицу.
  Если структура матрицы такова,
  что выходы на предыдущей строке на заданных входах остаются известными,
  то эти выходы и будут входами следующей обучаемой строки.
  Эта модификация, на мой взгляд, не сильно меняет концепцию
  одновременной обработки данных нейронами.
  Просто в этом случае мы ограничиваем <фронт волны>
  одной единственной строкой.
  То есть принимаем что одновременно могут возбуждаться
  только нейроны одной строки,
  затем данные передаются на следующую строку и т.д.
  
  LaRN
  29 ноя 2017 в 18:07
  
  В вашем варианте нейронной сети количество нейронов
  должно быть сильно больше чем в традиционной,
  для решения аналогичной задачи.
  Не сведет ли увеличение количества нейронов в вашей сети
  (по сравнению с традиционной сетью) на нет
  преимущество простоты расчета?
  Ну т.е. процесс обучения у вас вроде бы вычислительно проще,
  но и сеть сильно больше получается из-за того
  что нейрон не <аналоговый>, а <цифровой>.
  
  akazant
  29 ноя 2017 в 21:22
  
  Вопрос закономерный.
  Тесты на сложных данных в программной реализации
  даже в несколько потоков сейчас вряд ли возможны за приемлемое время.
  Впрочем, так же как и задачи быстрой визуализации в 3D графике, например.
  Поэтому для них делают аппаратные ускорители ).
  
  //// Конец цитирования.
  
  Лично для меня, этот материал оказался очень полезным в плане того,
  что показал что на методе обратного распространения ошибки
  "свет клином не сошелся".
  Возможны и другие варианты и думать в этих направлениях,
  вполне возможно, далеко не бесполезно.
  И даже "грубый" сплошной перебор можно где-то с успехом применить.
  
  А с другой стороны, показал, что проблем/вопросов у бинарных/битовых нейросетей
  пока что больше чем достаточно.
  И простая "ставка" на уменьшение требований к памяти и вычислительным ресурсам
  в легкую перебивается "ставкой" трудностью обучения, распараллеливания,
  и просто непонимания, что же принципиально нового они могут предложить.
  
  В общем, надо продолжать поиск.
  Хотя, похоже, активные публикации по теме BNN практически "сошли на нет".
  Поэтому имеет смысл попытаться "переложить" сегодняшние разработки
  в области перцептронных нейросетей в контексте бинарных нейросетей.
  
  
  ========
  
  Тральщик Наставник. Модель Kandinsky 2.1 нарисовала:  95cfcf461d744c41ae79fb4651964f34_00000
  
  Тральщик Наставник. Модель Kandinsky 3.0 нарисовала:  efcd02a8553343b79e988c6c4da97c76_res_00000_image
  
  Тральщик Наставник. Модель Kandinsky 3.0 нарисовала:  db7a37e902e74fd5a44477e3f61beb84_res_00000_image
  
  Тральщик Наставник. Модель Kandinsky 3.1 нарисовала:  17772662d2504dcbadc96681a7ae794c_res_00000_image
  Flag Counter
  Free counters!
  
 Ваша оценка:

Связаться с программистом сайта.

Новые книги авторов СИ, вышедшие из печати:
О.Болдырева "Крадуш. Чужие души" М.Николаев "Вторжение на Землю"

Как попасть в этoт список
Сайт - "Художники" .. || .. Доска об'явлений "Книги"