Юзабилити: эффективность, результативность и удовлетворение.

TL;DR и за то, что вы можете не увидеть в этом посте.

  • Знать (что такое) себя и других (часть-1);
  • Управление состояниями PRNG, а не только их начальными номерами (часть-2);
  • Раскройте побочные эффекты, например:
  • Смешанная точность, обратите внимание на разрыв шкалы динамических потерь[1][2];
  • — cuDNN, избегайте использования его встроенного исключения;
  • — Недетерминированность/нестабильность использования многоядерных/процессных/поточных приложений.

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

Удовлетворение

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

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

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

Эффективность

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

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

def __init__(...):
...
    self.loss_scale = ifnone(loss_scale, 2**16 if dynamic else 512)
...
def on_backward_begin(...):
...
    ret_loss = last_loss * self.loss_scale
...
def on_backward_end(...):
...
    if self.dynamic and grad_overflow(self.model_params) and self.loss_scale > 1:
        self.loss_scale /= 2
...
    else:
...
        if self.noskip >= self.max_noskip and self.loss_scale < self.max_scale:
            self.loss_scale *= 2
...

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

Говоря об усилиях по кодированию, использование API cuDNN кажется несложным. К сожалению, их слепое использование может привести к серьезной неудаче, если вы хотите провести разумное испытание. Можно легко найти много свидетельств встроенного отсева cuDNN (особенно при использовании его с двунаправленными моделями) на StackOverflow и github. «Не используйте его», — говорит жюри.

Эффективность

Но почему? Потому что реализация с несколькими что-то вроде ядра снова требует написания кода. Хотя API-интерфейсы cuDNN предоставляют детерминированные аналоги типичных операций, существует слишком много переключателей, чтобы переключаться последовательно. Насколько мне известно, TensorFlow не заботится о них. Хотя PyTorch поддерживает приветственный флаг cudnn.deterministic, он также не влияет на встроенный отсев cuDNN.

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

Полезный и полезный

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