1. 오늘의 에러메세지
InvalidArgumentError: {{function_node __wrapped__IteratorGetNext_output_types_2_device_/job:localhost/replica:0/task:0/device:CPU:0}} Input to reshape is a tensor with 1204224 values, but the requested shape has 150528 [[{{node Reshape}}]] [Op:IteratorGetNext] name:
2. 문제 발생 지점
def decode_tfrecord(self, tfrecord):
"""
Decode a tfrecord item.
You need to specify how many bytes to read from this byte sequence per feature to retrieve a data point.
Question (b)
- Use tf.io.FixedLenFeature([], 'type of feature')
- Use tf.io.parse_single_example, tf.io.decode_raw
- Use InputPipelineBuilder.INPUT_SHAPE to reshape after decoding frames.
- Use tf.cast to cast label to tf.int32 after decoding label.
- Refer to TensorFlow TFRecord Tutorial for further information!
Inputs
- tfrecord
Returns
- frames
- labels
"""
feature = {
'frames': tf.io.FixedLenFeature([], tf.string),
'label': tf.io.FixedLenFeature([], tf.int64),
}
example = tf.io.parse_single_example(tfrecord, feature)
frames_flat = tf.io.decode_raw(example['frames'], tf.float64) # 오류의 원인
# 디버깅 목적 (Input Size 오류)
# print("Decoded raw size:", tf.size(frames_flat))
# print("frames_flat_shape:", tf.shape(frames_flat))
# print("Expected size:", np.prod(self.INPUT_SHAPE))
frames = tf.reshape(frames_flat, self.INPUT_SHAPE)
#print("After reshaping size:", tf.size(frames))
#print()
label = tf.cast(example['label'], tf.int32)
return frames, label
구체적으로는 tf.reshape 부분에서 오류가 발생했다. reshape 메소드는 첫 번째 인자를 두번째 인자의 shape 으로 바꿔주는 역할을 한다. (예를 들면 [2, 8] 을 [4, 4] 로 변환) 이때 당연히 변환이 되려면 그 shape 의 element 들의 곱(product) 값이 일치해야하는데, 추측하기로 나의 경우에는 그 곱이 (에러메세지 내 value 값) 서로 달라 발생하고 있는 오류였다.
3. 해결 과정
일반적으로 shape 오류는 모델 레이어 중간 중간마다 텐서의 shape 을 print 로 찍어보면서 쉽게 고칠 수 있다. 그런데 이 경우에는 나도 이번에 처음 알게된 것인데, eager execution 이 아니라 graph execution 으로 연산이 수행되고 있어 텐서의 shape 을 [0, 0, 0, 0[ 이런 식으로 찍어볼 수가 없었다. 또한 오류가 발생하고 있는 부분이 decode 함수를 iteration 으로 next(iter(..)) 수행하고 있어서 정확히 어떠한 지점에서 오류가 발생하고 있는지 처음에는 파악하기가 어려웠다.
https://github-wiki-see.page/m/pai-plznw4me/tensorflow_basic/wiki/Eager-execution-Vs-Graph-execution
Eager execution Vs Graph execution - pai-plznw4me/tensorflow_basic GitHub Wiki
Eager execution Vs Graph execution - pai-plznw4me/tensorflow_basic GitHub Wiki Eager execution Vs Graph execution 해당 포스트에서는 Tensorflow의 Eager execution 과 Graph execution의 차이점을 아래 주제로 설명합니다. Debug 변수 관
github-wiki-see.page
결국에는 장장 3일동안 조금씩 조금씩 들여다보며, 맨 땅에 헤딩한다는 마음가짐으로 이것저것 혼자 코드를 바꿔보고 고쳐보았다. 이것저것 다 해보다 안돼서 TFRecord 공식 문서를 들여다보다 인사이트를 얻었다.
https://www.tensorflow.org/tutorials/load_data/tfrecord?hl=ko
TFRecord 및 tf.Example | TensorFlow Core
TFRecord 및 tf.Example 컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요. 데이터를 효율적으로 읽으려면 데이터를 직렬화하여 각각을 선형적으로 읽을 수 있는 파
www.tensorflow.org
문제의 원인은 프레임을 decode 하는 tf.io.decode_raw(example['frames'], tf.float64) 에서 두번째 인자의 data type 을 잘못 설정해준 것이었다. 자꾸 expected value 보다 8배 큰 값이 나와서, 저 8 이 어디서 나왔을까 했는데, 내가 type 을 uint8 로 잘못 설정해준 것이 화근이었다. 타입을 float 으로 지정해주어야 했다.
데이터타입이 이렇게 텐서의 shape 에 영향을 미치는지 처음 알았다. 그리고 Pytorch 를 자주 쓰지, TensorFlow 는 오랜만이라 더욱 헤맨 듯 하다. 또한 TFRecord 나 TFDataset 도 이번에 처음 사용해보았고, Video 처리도 처음이었어서 새로운 것이 많았다.
마지막으로는 이렇게 고친 데이터파이프라인으로 학습시킨 S3D 모델의 테스트 결과를 첨부하며 마친다. 뿌듯
이상 끝.
'studyLog. AI > 오늘의 디버깅' 카테고리의 다른 글
[Pytorch Lightning] GPU memory keeps increasing during training (0) | 2024.06.09 |
---|---|
[Pytorch Lightning] Inconsistent Batch Size in Training (0) | 2024.05.29 |