프로젝트_랜드마크 - 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로 변경해준다.
