1 minute read

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등으로 설정해주어야 이상없이 작동하는것 같다.
  • 에러 메시지와 연관지어 결론을 내보자면

    1. 원래 나와야 할 데이터 :
      이미지 데이터(tf.float32), 레이블 데이터(tf.float32)

    2. class_mode가 꼬여 레이블 데이터가 사라짐

    3. 실제 나온 데이터 : 이미지 데이터(tf.float32)

    4. 예상한 데이터와 실제 나온 데이터가 다르므로, 에러 메시지 출력

    • 정도로 추측된다.
  • 해결법을 찾아도 구글에 명확하게 나온것이 없어 고치는데 상당한 시간이 들었다.

레이블과 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로 변경해준다.