본문 바로가기
studyLog. AI/오늘의 디버깅

[TensorFlow] Datatype 과 Tensor shape

by 브라이티_ 2024. 2. 18.
반응형

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 모델의 테스트 결과를 첨부하며 마친다. 뿌듯

이상 끝.

반응형