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

Когда вы впервые видите эту строчку в книге, она выглядит так:

В книге функции, вычисляющие градиент, называются gradient (). Здесь я заключил код в функцию с именем gradient_one_input (). Название подчеркивает тот факт, что этот код работает, когда у нас есть одна входная переменная. Например, мы используем его для прогнозирования продаж пиццы по резервациям.

Однако код меняется, когда мы переходим от одной ко многим входным переменным. В главе 4 (Гиперпространство!) это становится:

Более ранняя версия кода в gradient_one_input () является прямым портом формулы: производная потерь по весу. Если вы перечитаете Немного математики в главе 3, вы увидите, как этот код объединяется. Напротив, код в gradient_multiple_inputs () менее прост. Со всеми этими матричными операциями трудно понять, как это работает. Откуда взялось матричное умножение? А как насчет операции транспонирования на X?

Чтобы сэкономить место, я не отвечаю на эти вопросы в книге. Я бросаю вам код градиента и иду дальше. Действительно, последняя версия кода градиента может быть единственной строкой в ​​книге, которую я не объясняю подробно.

Этот пост восполняет недостающее объяснение. Я собираюсь показать вам, что gradient_multiple_inputs () реализует те же шаги, что и gradient_one_input (), только более общий характер. Хотя gradient_one_input () работает с одной входной переменной, gradient_multiple_inputs () снимает это ограничение.

Начнем с обзора gradient_one_input ().

Разбор кода с одним вводом

Чтобы понять gradient_multiple_input (), давайте начнем с gradient_one_input (). И снова вот оно:

В этой ранней версии кода X и Y - одномерные массивы примеров, а w - скалярный вес. Давайте объясним, что делает эта функция:

  1. Он вычисляет различия между прогнозами системы и метками: (прогноз (X, w) - Y). Результат представляет собой массив ошибки предсказания.
  2. Он умножает каждый ввод в X на соответствующую ошибку предсказания.
  3. Он усредняет результаты.
  4. Наконец, он умножает все на 2.

Это шаги, которые выполняет gradient_one_input (). Теперь давайте посмотрим, как gradient_multiple_inputs () выполняет те же шаги - только с несколькими входами.

Переход к нескольким входам

Мы собираемся изучить код в gradient_multiple_inputs ():

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

Добро пожаловать обратно! Начнем с рассмотрения параметров gradient_multiple_inputs () и их форм:

Теперь посмотрим, что делает gradient_multiple_inputs (). Во-первых, он вычисляет ошибки предсказания:

Этот расчет выглядит так же, как и в gradient_one_input (). Однако его операнды имеют другую форму, как и его результат. В результате получится матрица тех же размеров, что и Y:

Затем gradient_multiple_inputs () умножает X на E - за исключением того, что если вы проверите размеры этих матриц, вы увидите, что они не соответствовать:

Видеть? Внутренние размеры X и E различны, поэтому вы не можете их умножить. С другой стороны, если вы транспонируете X, размеры будут соответствовать:

Именно это и делает gradient_multiple_inputs (). Он заменяет X и умножает его на ошибки:

Давайте внимательно посмотрим на результат. По правилам умножения матриц в нем столько строк, сколько X.T (количество входных переменных), и столько же столбцов, сколько E (1). Каждый элемент в этой матрице представляет собой сумму входных переменных в строке X.T, умноженную на их соответствующие веса:

Наконец, функция берет синюю матрицу выше, делит ее элементы на X.shape [0] и умножает их на 2. Обратите внимание, что X.shape [0] - это количество строк в X - то есть количество примеров:

Давайте вспомним шаги, которые выполняет gradient_multiple_inputs ():

  1. Он вычисляет ошибки предсказания. Ошибок столько, сколько примеров.
  2. Для каждого примера в X он умножает входные переменные примера на ошибку сопоставления.
  3. Он складывает результаты и делит их на количество примеров - это все равно что сказать, что берется их среднее значение.
  4. Он умножает все на 2.

Вернитесь и сравните четыре шага выше с четырьмя шагами gradient_one_input (). Ага! Они точно такие же.

Итог: gradient_one_input () и gradient_multiple_inputs () делают то же самое. Только gradient_multiple_inputs () делает это с матрицами. Благодаря этим матрицам последняя функция может работать со многими входными переменными.

Подведение итогов

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

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

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

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