단일 ReLU가 ReLU를 배울 수없는 이유는 무엇입니까?


15

내 신경망에 대한 후속 조치로 유클리드 거리를 알 수조차 없으므로 나는 더 단순화하고 단일 ReLU (임의의 무게로)를 단일 ReLU로 훈련하려고했습니다. 이것은 가장 간단한 네트워크이지만 수렴하지 못하는 시간의 절반입니다.

초기 추측이 목표와 같은 방향에 있다면, 빠르게 학습하고 올바른 가중치 1로 수렴합니다.

ReLU 학습 애니메이션 ReLU

수렴 점을 보여주는 손실 곡선

초기 추측이 "뒤로"이면, 가중치 0에 갇히고 더 낮은 손실 영역으로 넘어 가지 않습니다.

ReLU를 배우지 못한 ReLU의 애니메이션

ReLU를 배우지 못하는 ReLU의 손실 곡선

0에서 손실 곡선의 근접 촬영

왜 그런지 모르겠습니다. 그라디언트 하강이 손실 곡선을 쉽게 따라 가면 안될까요?

예제 코드 :

from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, ReLU
from tensorflow import keras
import numpy as np
import matplotlib.pyplot as plt

batch = 1000


def tests():
    while True:
        test = np.random.randn(batch)

        # Generate ReLU test case
        X = test
        Y = test.copy()
        Y[Y < 0] = 0

        yield X, Y


model = Sequential([Dense(1, input_dim=1, activation=None, use_bias=False)])
model.add(ReLU())
model.set_weights([[[-10]]])

model.compile(loss='mean_squared_error', optimizer='sgd')


class LossHistory(keras.callbacks.Callback):
    def on_train_begin(self, logs={}):
        self.losses = []
        self.weights = []
        self.n = 0
        self.n += 1

    def on_epoch_end(self, batch, logs={}):
        self.losses.append(logs.get('loss'))
        w = model.get_weights()
        self.weights.append([x.flatten()[0] for x in w])
        self.n += 1


history = LossHistory()

model.fit_generator(tests(), steps_per_epoch=100, epochs=20,
                    callbacks=[history])

fig, (ax1, ax2) = plt.subplots(2, 1, True, num='Learning')

ax1.set_title('ReLU learning ReLU')
ax1.semilogy(history.losses)
ax1.set_ylabel('Loss')
ax1.grid(True, which="both")
ax1.margins(0, 0.05)

ax2.plot(history.weights)
ax2.set_ylabel('Weight')
ax2.set_xlabel('Epoch')
ax2.grid(True, which="both")
ax2.margins(0, 0.05)

plt.tight_layout()
plt.show()

여기에 이미지 설명을 입력하십시오

바이어스를 추가하면 비슷한 일이 발생합니다 .2D 손실 기능은 부드럽고 간단하지만 relu가 거꾸로 시작하면 주위를 맴돌고 붙어 (빨간색 시작점) 기울기를 따라 가지 않습니다. 파란색 시작점에 해당) :

여기에 이미지 설명을 입력하십시오

출력 무게와 바이어스를 추가하면 비슷한 일이 발생합니다. (왼쪽에서 오른쪽으로 또는 아래에서 위로 뒤집지 만 둘다는 아닙니다.)


3
@Sycorax 아니요 이것은 중복이 아니며 일반적인 조언이 아닌 특정 문제에 대해 묻습니다. 나는 이것을 최소, 완전 및 검증 가능한 예제로 줄이는 데 많은 시간을 보냈습니다. 다른 광범위한 질문과 모호하기 때문에 삭제하지 마십시오. 이 질문에 대한 답을 얻는 단계 중 하나는 "먼저 단일 숨겨진 계층으로 소규모 네트워크를 구축하고 올바르게 작동하는지 확인한 다음 모델 복잡성을 점차적으로 추가하고 이들 각각이 잘 작동하는지 확인하는 것"입니다. 정확히 내가하고있는 일이며 작동하지 않습니다.
endolith

2
NN 간단한 기능에 적용에 난 정말이 "시리즈"를 즐기고있다 : eats_popcorn_gif :
Cam.Davidson.Pilon

ReLU 는 다이오드와 같은 이상적인 정류기처럼 작동합니다. 단방향입니다. 방향을 수정하려면 softplus를 사용하고 훈련이 긍정적일 때 ReLU로 전환하거나 ELU와 같은 다른 변형을 사용하십시오.
Carl

이 또 다른 방식으로 말을하기 위해, ReLU은 쓸모가 될 것으로 예상된다 에 대한 학습 봐 ; 평평하고 배우지 않습니다. x < 0x<0x<0
Carl

1
그라디언트는 가 0보다 작은 경우 0이됩니다. 실속합니다. x
Carl

답변:


14

의 함수로서 손실에 대한 힌트가 있습니다 . 이 플롯은 가지고 "꼬임"근처 : 때문에 왼쪽 공의에 대한 그의는 그라데이션 손실의는, 그러나 (0 사라지는이다 손실이가보다 더 높은 존재하기 때문에 최적의 솔루션입니다 ) 또한,이 그림은 손실 함수가 볼록하지 않음 (3 개 이상의 위치에서 손실 곡선을 가로 지르는 선을 그릴 수 있음)을 나타내므로 SGD와 같은 로컬 최적화 프로그램을 사용할 때주의해야 할 신호입니다. 실제로, 다음 분석은 가 음으로 초기화 될 때 차선의 솔루션으로 수렴 할 수 있음을 보여줍니다 .ww=0w = 0 w = 1 ww=0w=1w

최적화 문제는

minw,bf(x)y22f(x)=max(0,wx+b)

1 차 최적화를 사용하고 있습니다. 이 접근법의 문제점은 에 그라디언트 가 있다는 것입니다f

f(x)={w,if x>00,if x<0

시작할 때 정답에 더 가깝게하려면 의 반대쪽으로 이동해야합니다 ( . 이 수행하기 어려운 있기 때문에 당신이아주, 아주 작은, 그래디언트도 사라질 것입니다. 또한 왼쪽에서 0에 가까울수록 진행 속도가 느려집니다!w<00w=1|w|

이것이 음수 인 초기화에 대한 플롯에서 궤적이 모두 근처에서 멈 춥니 다 . 이것은 또한 두 번째 애니메이션이 보여주는 것입니다.w(0)<0w(i)=0

이것은 죽어가는 relu 현상과 관련이 있습니다. 자세한 내용은 내 ReLU 네트워크가 시작되지 않음을 참조하십시오.

보다 성공적인 접근 방식은 소위 "배니싱 그라디언트"문제가없는 누출 된 relu와 같은 다른 비선형 성을 사용하는 것입니다. 새는 relu 기능은

g(x)={x,if x>0cx,otherwise
여기서 는 상수이므로작고 긍정적입니다. 이것이 작동하는 이유는 도함수가 "왼쪽에"0이 아니기 때문입니다.c|c|

g(x)={1,if x>0c,if x<0

설정 하면 일반적인 해상도입니다. 대부분의 사람들은 를 또는 과 같은 것으로 선택합니다 . 사용 된 것을 보지 못했지만 그러한 네트워크에 어떤 영향을 미치는지에 대한 연구에 관심이 있습니다. (주 동안 그 이 식별 기능을 감소시킨다 대해 기울기 연속 레이어 커지기 때문에, 이러한 많은 층 조성물 그라데이션 폭발의 원인이된다.)c=0c0.10.3c<0c=1,|c|>1

OP 코드를 약간 수정하면 활성화 기능 선택에 문제가 있음을 보여줍니다. 이 코드는 를 음수로 초기화 하고 일반 대신에를 사용합니다 . 손실은 빠르게 작은 값으로 감소하고 가중치는 올바르게 이동하여 최적입니다.wLeakyReLUReLUw=1

LeakyReLU가 문제를 해결

from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, ReLU
from tensorflow import keras
import numpy as np
import matplotlib.pyplot as plt

batch = 1000


def tests():
    while True:
        test = np.random.randn(batch)

        # Generate ReLU test case
        X = test
        Y = test.copy()
        Y[Y < 0] = 0

        yield X, Y


model = Sequential(
    [Dense(1, 
           input_dim=1, 
           activation=None, 
           use_bias=False)
    ])
model.add(keras.layers.LeakyReLU(alpha=0.3))
model.set_weights([[[-10]]])

model.compile(loss='mean_squared_error', optimizer='sgd')


class LossHistory(keras.callbacks.Callback):
    def on_train_begin(self, logs={}):
        self.losses = []
        self.weights = []
        self.n = 0
        self.n += 1

    def on_epoch_end(self, batch, logs={}):
        self.losses.append(logs.get('loss'))
        w = model.get_weights()
        self.weights.append([x.flatten()[0] for x in w])
        self.n += 1


history = LossHistory()

model.fit_generator(tests(), steps_per_epoch=100, epochs=20,
                    callbacks=[history])

fig, (ax1, ax2) = plt.subplots(2, 1, True, num='Learning')

ax1.set_title('LeakyReLU learning ReLU')
ax1.semilogy(history.losses)
ax1.set_ylabel('Loss')
ax1.grid(True, which="both")
ax1.margins(0, 0.05)

ax2.plot(history.weights)
ax2.set_ylabel('Weight')
ax2.set_xlabel('Epoch')
ax2.grid(True, which="both")
ax2.margins(0, 0.05)

plt.tight_layout()
plt.show()

또 다른 복잡성 계층은 우리가 무한으로 움직이지 않고 무한히 많은 "점프 (jump)"로 이동한다는 사실에서 비롯됩니다. 이러한 점프는 한 번의 반복에서 다음 번으로 이동합니다. 이는 음의 초기 값 멈출 수없는 상황이 있음을 의미합니다 . 이러한 경우는 과 그라디언트 하강 단계 크기가 소실 그라디언트를 뛰어 넘을 정도로 충분히 큰 경우 발생 합니다.w w(0)

나는이 코드를 가지고 놀았고 에서 초기화를 떠나고 옵티 마이저를 SGD에서 Adam, Adam + AMSGrad 또는 SGD + 운동량으로 변경해도 아무런 도움이되지 않는다는 것을 알았습니다. 또한, SGD에서 Adam으로 변경하면 실제로이 문제에 대한 소멸 구배를 극복하는 데 도움이되지 않고 진행 속도가 느려집니다 .w(0)=10

반면 초기화를 변경하고 옵티 마이저를 Adam으로 변경하면 (단계 크기 0.01) 실제로 사라지는 기울기를 극복 할 수 있습니다. 또한 및 SGD를 운동량 (단계 크기 0.01)과 함께 사용하는 경우에도 작동합니다 . 바닐라 SGD (단계 크기 0.01) 및 을 사용하는 경우에도 작동합니다 .w(0)=1 w(0)=1w(0)=1

관련 코드는 다음과 같습니다. opt_sgd또는을 사용하십시오 opt_adam.

opt_sgd = keras.optimizers.SGD(lr=1e-2, momentum=0.9)
opt_adam = keras.optimizers.Adam(lr=1e-2, amsgrad=True)
model.compile(loss='mean_squared_error', optimizer=opt_sgd)

출력 무게와 바이어스가있을 때 LeakyReLU, ELU, SELU와 동일한 문제가 발생했지만 출력이없는 것을 시도했는지 확실하지 않습니다. 나는 점검 할 것이다
endolith

1
(예, 맞아요이 예에 대한 LeakyReLU 및 ELU는 잘 작동)
endolith

2
아, 알겠습니다. 그것은 되는 손실 함수의 기울기 하강을하고, 그것은 부정적인 측면에서 접근 할 때 그라데이션 하강이 붙어있다 얻을 수 있도록 손실 함수는, 0 플랫 (0 구배)가된다 단지입니다. 이제 분명해 보인다. : D
endolith

2
바로 그거죠. 손실 대 의 플롯이 0 근처에 "kink"를 갖는 방법에 주목하십시오 . 즉, 0의 왼쪽 에서 손실 의 기울기 가 0으로 사라지기 때문입니다 (단, 손실이 이전보다 높기 때문에 차선 책임) 대 ). 또한,이 그림은 손실 함수가 볼록하지 않음 (3 개 이상의 위치에서 손실 곡선을 가로 지르는 선을 그릴 수 있음)을 나타내므로 SGD와 같은 로컬 최적화 프로그램을 사용할 때주의해야 할 신호입니다. ww=0
Sycorax는 Reinstate Monica가

2
relu 활성화를 사용할 때 단계 크기가 의 특정 값에 대해 충분히 클 경우 운동량이 없는 SGD 입술을 넘어갈 수 있습니다 . w(i)
Sycorax는 Reinstate Monica가
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.