파이썬 tensorflow - ValueError: Shapes (...) and (...) are incompatible
모델 학습을 실행했는데,
...[생략]...
model.add(Dense(units=256, input_dim=784, activation='relu'))
model.add(Dense(units=128, activation='relu'))
model.add(Dense(units=64, activation='relu'))
model.add(Dense(units=10, activation='softmax'))
hist = model.fit(X_train, Y_train, epochs=1, batch_size=50, validation_data=(X_val, Y_val))
ValueError가 발생한다면?
raise ValueError("Shapes %s and %s are incompatible" % (self, other))
상황에 따라 다를 수 있지만, 제가 겪은 상황에서의 self와 other의 의미는 각각 다음과 같습니다.
self == (batch_size, 요소의 dim)
other == (batch_size, 출력 층의 units)
사실 대개의 경우 이 오류는 model.fit에 전달한 X_train, Y_train과 validation_data에 전달한 값들의 차원이 신경망의 units와 맞지 않기 때문에 발생합니다.
예를 들어, validation_data에 전달할 Y_val에 대해 요구되는 차원이 "Y_val: (데이터 수, 10)"인데, 실수로 Y_val: "(데이터 수, 28, 28, 10)"라는 식의 값을 전달하게 되면, model.fit에서 X_train, Y_train에 대한 1차 학습은 끝났다는 식의 메시지와 함께,
993/1000 [============================>.] - ETA: 0s - loss: 0.2695 - accuracy: 0.9186
이어서 validation_data를 검증하려고 수행되는 시점에 다음과 같은 식의 Traceback 오류가 발생합니다.
...[생략]...
raise ValueError("Shapes %s and %s are incompatible" % (self, other))
ValueError: Shapes (50, 28, 28, 10) and (50, 10) are incompatible
언급했듯이, 이것은 다음과 같이 해석될 수 있고,
Shapes (batch_size, 요소의 dim) and (batch_size, 출력 층의 units) are incompatible
따라서 정황으로 보아 model.fit의 validation_data에 전달한 데이터 중에 (데이터 수, 28, 28, 10)에 해당하는 값이 있으며 이것은 출력 Dense(batch_size, 10개의 출력)에 맞지 않으므로 오류가 발생했음을 짐작게 합니다. 실제로 validate_data에 전달한 값의 차원을 살펴보면,
print("X_val:", X_val.shape) # X_val: (10000, 784)
print("Y_val:", Y_val.shape) # Y_val: (10000, 28, 28, 10)
오류 메시지에서 나왔던 "(크기,
28, 28, 10)"과 동일하게 겹쳐 있는 Y_val의 데이터가 정확하지 않음을 알 수 있습니다. 사실, "(50, 10)"이라는 출력에서 "10"이 마지막 Dense(출력 층)의 units에 해당하기 때문에 이런 경우 X_val을 살펴볼 필요 없이 Y_val 값만 조사하면 됩니다.
한 가지 더 볼까요? ^^
model.add(Dense(units=5, activation='softmax'))
hist = model.fit(X_train, Y_train, epochs=1, batch_size=50, validation_data=(X_val, Y_val))
위와 같이 실행했는데 다음과 같은 오류가 발생한다면?
...[생략]...
raise ValueError("Shapes %s and %s are incompatible" % (self, other))
ValueError: Shapes (50, 10) and (50, 5) are incompatible
게다가 이번엔 "993/1000 [============================>.] - ETA: 0s - loss: 0.2695 - accuracy: 0.9186"라는 식의 메시지도 전혀 없었습니다. 그렇다면, 이번엔 model.fit에 전달된 데이터 중 아직 validation_data를 검증하는 단계까지 가기도 전에 X_train, Y_train부터 맞지 않은 데이터가 전달된 것입니다.
따라서, 이렇게 해석해 볼 수 있고,
Shapes (batch_size, 요소의 dim) and (batch_size, 출력 층의 units) are incompatible
따라서 위의 예제에서는 마지막 Dense의 units가 5인데, 입력으로 전달된 데이터의 차원이 출력과 맞지 않은 것이므로 X_train이 아닌 Y_train의 데이터가 잘못된 경우라고 판정할 수 있습니다. 실제로 이에 대해 shape을 검사해 보면,
print("Y_train:", Y_train.shape) # (데이터 크기, 10)
전달된 Y_train의 차원이 10으로 나오는데 Dense에는 5라고 지정했기 때문에 불일치가 발생한 것입니다. 만약 Dense에 지정한 units가 맞는 값이라면, 저 코드의 출력값(Y_train.shape)은 5가 나와야 했습니다. 혹은 반대로 데이터가 맞는 경우라면, 마지막 Dense의 출력을 잘못 지정한 것이므로 Dense의 units 값을 "model.add(Dense(
units=10, activation='softmax'))"로 바꿔야 합니다.
이 정도면, 향후 ValueError가 발생했을 때 어떤 데이터가 잘못된 것인지 판단할 수 있을 것입니다.
[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]