프로젝트_랜드마크 - 12일차
Trouble Shooting
generator가 구조와 다른 element를 출력함.
에러메시지
- generator yielded an element that did not match the expected structure ~~ expected (tf.float32,tf.float32), element = […대충 엄청난 양의 array 데이터]
원인
-
나의 경우에는 ImageDataGenerator의 flow_from_directory()를 사용해서 데이터셋을 생성함.
-
여기서 class_mode는 None으로 설정해 두었는데, 이미지 데이터 배치만 생성해주고 하위 디렉토리의 이름을 통해 자동으로 레이블을 달아준다는것으로 해석했었다.
-
classes 옵션(클래스 하위 레이블의 목록을 설정)에는 os.listdir()을 통해 레이블 이름을 리스트로 넣어둔 상태였다.
### 해결
- class_mode를 ‘categorical’로 설정해주자 해당 오류는 나타나지 않았다.
- 아무래도 classes를 지정해준 상태에서는 class_mode를 categorical등으로 설정해주어야 이상없이 작동하는것 같다.
-
에러 메시지와 연관지어 결론을 내보자면
-
원래 나와야 할 데이터 :
이미지 데이터(tf.float32), 레이블 데이터(tf.float32) -
class_mode가 꼬여 레이블 데이터가 사라짐
-
실제 나온 데이터 : 이미지 데이터(tf.float32)
-
예상한 데이터와 실제 나온 데이터가 다르므로, 에러 메시지 출력
- 정도로 추측된다.
-
- 해결법을 찾아도 구글에 명확하게 나온것이 없어 고치는데 상당한 시간이 들었다.
레이블과 logit은 첫 dimension이 같아야 함.
에러메시지
- logits and labels must have the same first dimension
원인
-
model.compile에서 손실함수를 ‘SparseCategoricalCrossentropy’(이하 scce) 로 사용중이었다.
-
scce는 레이블이 정수로 제공되어야 한다.
-
하지만 내 데이터셋은 class_mode를 categorical로 사용하고 있으므로, 레이블이 one-hot encoding된 2D numpy 배열로 제공되고 있었다.
해결
- 1번 방법. 손실함수를 ‘CategoricalCrossentropy’(cce)로 변경하여 사용한다.
- cce의 경우, 각 샘플이 여러 클래스에 속할수 있거나, label이 확률일때 사용하는것이 좋다고 한다.
- 반면, scce의 경우 각 샘플이 오직 하나의 클래스에 해당할때 사용하는것이 좋다고 한다.
- loss 결과는 거의 차이가 없다고 한다.
- 관련 글
- 2번 방법. 데이터셋 class_mode를 ‘sparse’로 변경하고, label_shape를 (None,)로 변경하여 정수형 shape로 변경해준다.