손실 함수를 바꿔도 그래디언트가 바뀌지 않는다. README의 Loss[MSE] 열은 실험이 아니다
#Sequential.backward는 self.loss를 전혀 참조하지 않고 BCE의 미분식 -(Y/A - (1-Y)/(1-A))를 직접 써 넣는다. Loss 클래스 계층에는 backward가 아예 정의되어 있지도 않다. 즉 --loss mean_squared_error로 컴파일해도 순전파 후 찍히는 손실값만 MSE로 바뀔 뿐, 파라미터 갱신에 쓰이는 그래디언트는 BCE 그대로다.
직접 확인했다. 같은 시드로 두 모델을 만들어 각각 binary_crossentropy와 mean_squared_error로 컴파일한 뒤 1스텝 역전파를 돌리면 layer0.dW가 [[0.001737, 0.005505], [-0.000279, -0.00089]]로 완전히 동일하다. README 비교표의 NNN 행에서 Base와 Loss[MSE]가 나란히 97.27로 적혀 있는 것은 우연이 아니라 같은 학습을 두 번 기록한 결과다. 전체 7개 설정을 재현해 봤을 때도 두 값은 소수점까지 똑같이 97.27%로 나왔다.
def backward(self, Y: np.ndarray) \
-> np.ndarray:
super(Sequential, self).backward(Y)
grad = -(np.divide(Y, self._last_output) - np.divide(1 - Y, 1 - self._last_output)) # ← self.loss 는 어디에도 쓰이지 않음
result = reduce(lambda g, layer: layer.backward(g), [grad, *reversed(self.layers)])
return result=== [4] MSE loss: does backward use MSE gradient? === gradients identical for BCE vs MSE compile: True layer0.dW under 'binary_crossentropy' = [[ 0.001737 0.005505] [-0.000279 -0.00089 ]] layer0.dW under 'mean_squared_error' = [[ 0.001737 0.005505] [-0.000279 -0.00089 ]]