Этой линия: delta3[range(num_examples), y] -= 1
является частью вычисляя градиент функции потери softmax. Я ссылаюсь на эту приятную ссылку, которая дает вам больше информации о том, как сформулирована эта функция потерь и интуиция за ней: http://peterroelants.github.io/posts/neural_network_implementation_intermezzo02/.
Кроме того, я ссылаюсь на это сообщение в разделе «Обмен математической статистикой», которое показывает вам, как получается градиент потери softmax: https://math.stackexchange.com/questions/945871/derivative-of-softmax-loss-function. Рассмотрим первое звено как глубокое погружение, тогда как второе звено - это tl;dr
первой ссылки.
Градиент функции потери softmax - это градиент выходного уровня, который вам нужно будет распространять назад в слой перед слоем вывода, чтобы продолжить с алгоритмом backpropagation.
Подводя итог сообщению, которое я связал выше, если вы вычисляете градиент потери softmax для примера обучения, для каждого класса градиент потери является просто значением softmax, оцененным для этого класса. Вам также необходимо вычесть значение потерь на 1 для класса, к которому принадлежит фактический пример обучения. Помните, что градиент примера для класса i
равен p_i - y_i
, где p_i
- это оценка softmax класса i
для примера, а y_i
- это классификация с использованием схемы горячего кодирования. В частности, y_i = 0
, если i
не является истинным классом примера и y_i = 1
, если это так. delta3
содержит градиент функции потери softmax на пример в мини-партии. В частности, это 2D-матрица, где общее число строк равно количеству примеров обучения, или num_examples
, а число столбцов - общее количество классов.
Сначала мы вычисляем оценки softmax для каждого примера обучения и для каждого класса. Далее для каждой строки градиента мы определяем местоположение столбца, соответствующее истинному классу, к которому принадлежит пример, и мы вычитаем оценки на 1. range(num_examples)
будет генерировать список от 0
до num_examples - 1
и y
содержит истинные метки классов на пример , Следовательно, для каждой пары range(num_examples)
и y
это обращение к правильной строке и расположению столбца для вычитания 1 для завершения градиента функции потерь.
Теперь в столбце «Математика» Exchange, а также ваше понимание, градиент delta3 = probs - y
.Это предполагает, что y
является один горячий закодированные матрицы, что означает, что y
имеет такой же размер, как probs
и для каждой строки y
это все равны нулю исключением для индекса столбца, который содержит правильный класс, который установлен в 1 Поэтому, если вы думаете об этом правильно, если вы создали матрицу y
, где для каждой строки столбцы равны нулю, за исключением номера класса, к которому принадлежит этот пример, это эквивалентно простому доступу к правому столбцу для каждой строки и вычитанию оценки на 1.
В MATLAB вам действительно нужно создать линейные индексы, чтобы облегчить это вычитание. В частности, вам нужно использовать sub2ind
для преобразования этих строк и столбцов места для линейных индексов, то мы можем получить доступ матрицы градиента и вычитать значения на 1.
Поэтому:
ind = sub2ind(size(delta3), 1 : num_examples, y + 1);
delta3(ind) = delta3(ind) - 1;
В учебнике Python вы связанные метки, предполагается, что метки классов от 0
до N-1
, где N
- общее количество классов. Вы должны быть осторожны в MATLAB, где начинаете индексирование массивов, начиная с 1
, поэтому я добавил 1
в y
в приведенном выше коде, чтобы ваши метки начинались с 1
вместо 0
. ind
содержит линейные индексы местоположений строк и столбцов, которые нам нужны для доступа, и поэтому мы завершаем вычитание с использованием этих индексов.
Если бы вы сформулировать это, используя те знания, которые вы приобрели в вашей редактирования, вы могли бы сделать это вместо:
ymatrix = full(sparse(1 : num_examples, y + 1, 1, size(delta3, 1), size(delta3, 2));
delta3 = probs - ymatrix;
ymatrix
содержит матрицу, что я говорил о том, где каждая строка соответствует примеру со всеми ноль, за исключением столбца, относящегося к классу, к которому принадлежит пример, который равен 1. То, что вы, возможно, раньше не видели, это функции sparse
и full
. sparse
позволяет создать нулевую матрицу, и вы можете указать местоположения строк и столбцов, которые не равны нулю, а также значения, которые принимают каждое из этих местоположений. В этом случае я получаю доступ к одному элементу за строку и используя идентификатор класса для примера для доступа к столбцам и установки каждого из этих местоположений на 1. Также помните, что я добавляю по 1, поскольку я предполагаю, что ваш класс Идентификаторы начинаются с 0. Поскольку это матрица sparse
, я затем конвертирую ее в full
, чтобы дать вам числовую матрицу, а не представлять ее в форме sparse
. Поэтому этот код эквивалентен в работе предыдущему фрагменту кода, который я показал. Тем не менее, это более эффективно сделать это первым способом, поскольку вы не создаете дополнительную матрицу для облегчения вычисления градиента. Вместо этого вы изменяете градиент.
Как Замечание, sklearn
является пакетом обучения scikit-learn Python машины и NameError
в ссылке к вам, не имея фактический установленный пакет. Чтобы установить его, используйте pip
или easy_install
установить пакет Python на свой компьютер .... поэтому в командной строке, это так просто, как:
pip install sklearn
или:
easy_install sklearn
Однако scikit Для выполнения вышеуказанного кода вычитания не требуется.Вам нужно NumPy, хотя убедитесь, что у вас установлен этот пакет.
Для pip
:
pip install numpy
... и easy_install
:
easy_install numpy
Что такое 'delta3'? «NameError» означает, что он не может найти «sklearn», поэтому вы, вероятно, не «импортировали» его правильно. –