Я пытаюсь следовать книге о глубоком обучении, но я нашел некоторую часть об аффинном слое сети сбивающей с толку. Скажем, у меня есть сеть, которая принимает несколько изображений (0 ~ 9
), написанных от руки (mnist), которые сведены в одномерный массив, например, np.array([123, 255, 0, ...])
, и он будет выводить оценки для каждого возможного выхода, например, np.array([0., 0., 0.3, 0., 0., 0.6, 0., 0., 0., 0.1])
(Таким образом, изображение может быть числом 5
).
Вот моя реализация аффинного слоя:
class AffineLayer(object):
...
def backward(self, dy):
dx = np.dot(dy, self._W.T)
self._dW = np.dot(self._x.T, dy) # Question related part
self._db = np.sum(dy, axis=0)
dx = dx.reshape(self._original_x_shape)
return dx
...
Вот некоторые объяснения:
self._W
- весовая матрица.
- Часть беспокойства здесь
self._dW = np.dot(self._x.T, y) # Question related part
.
Эта строка получена из равенства:
X * W + B = Y
(N,2) matrix product (2,3) (1,3) (N,3).
Обозначение (2,)
взято из X.shape
из numpy.array
и т. Д. Чтобы упростить мою задачу, я выбираю эти номера измерений.
Конец терминологии, теперь возникает вопрос:
С помощью некоторой математики (опущено) мы можем получить равенство, используемое при обратном распространении, (поэтому в коде используется self._dW = np.dot(self._x.T, y)
):
d L T d L
--- == X * ---
d W d Y
(2,3) (2,N) * (N,3).
Обратите внимание, что независимо от того, как я настраиваю N
, то есть размер партии, размерность dL/dW
, весовую матрицу частичной производной от L, не изменится, и она всегда (2,3)
.
Означает ли это, что суммарный эффект этих N
партий объединяется / уплотняется в dL/dW
? Это связано с тем, как я реализую выходной слой, например, Softmax-кросс-энтропийный слой в качестве конечного слоя. Мой текущий вывод для этого состоит в том, что N
партия означает выполнение обратного распространения N
раз, и для градации / амортизации общего эффекта этой партии требуется деление градиента dL/dW
на N
. Но теперь кажется, что мне нужно сделать это только один раз, и деление должно быть «на первом этапе».
Edit:
Я также нахожу версию, которая, кажется, разделяет ее на последнем шаге mnielsen / neural-network-and-deep-learning - GitHub , для справки.
Так как класс слоя softmax-cross-entropy является последним слоем сети, при обратном распространении он станет "первым шагом", как я упоминал выше:
class SoftmaxCrossEntropy(object):
...
def backward(self, dout=1):
batch_size = self._t.shape[0]
# one-hot
if self._t.size == self._y.size:
dx = (self._y - self._t) / batch_size # <-- why divided by N here?
else: # not one-hot
dx = self._y * 1
dx[np.arange(batch_size), self._t] -= 1
dx = dx / batch_size # <-- why divided by N here?
return dx
...