반응형

 

텐서플로에서 데이터 적재와 전처리하기

  • 메모리 용량에 맞지 않는 아주 큰 규모의 데이터셋으로 딥러닝 시스템을 훈련해야 하는 경우가 많음

  • 다른 딥러닝 라이브러리를 사용해서는 대규모 데이터셋을 효율적으로 로드하고 전처리하도록 구현하기가 어려움

    • 텐서플로에서 멀티스레딩, 큐, 배치, 프리페치 같은 상세한 사항을 모두 처리 해줌
  • 데이터 API는 텍스트 파일, 고정 길이의 레코드를 가진 이진 파일, 텐서플로의 TFRecord 포멧을 사용하는 이진 파일에서 데이터를 읽을 수 있음

    • 해당 포멧은 길이가 다른 레코드를 지원
    • 일반적으로 프로토콜 버퍼를 담은 유연하고 효율적인 이진 포멧
    • SQL 데이터베이스에서 읽는 기능도 지원
    • 구글 Big Query 와 같은 다양한 데이터 소스에서 읽을 수 있는 오픈소스 제공
    • TF 변환
      • 훈련 전에 전체 훈련 세트에 대해 실행하는 전처리 함수를 작성할 수 있음, 그다음 텐서플로 함수로 변환하고 상용 환경에 배포된 다음 훈련된 모델과 협업하여 새로운 샘플에 대해 동적으로 전처리를 수행
    • TF 데이터셋
      • 각종 데이터셋을 다운로드할 수 있는 편리한 함수를 제공, Imagenet과 같은 대용량 데이터셋도 포함

 

데이터 API

  • tf.data.Dataset.from_tensor_slices()를 사용하는 예제

    X = tf.range(10) # 셈플 데이터 텐서
    dataset = tf.data.Dataset.from_tensor_slices(X)
    dataset
    >> <TensorSliceDataset shapes: (), types: tf.int32>
    
    for item in dataset:
        print(item)
    >>  tf.Tensor(0, shape=(), dtype=int64)
        tf.Tensor(1, shape=(), dtype=int64)
        tf.Tensor(2, shape=(), dtype=int64)
        tf.Tensor(3, shape=(), dtype=int64)
        tf.Tensor(4, shape=(), dtype=int64)
        tf.Tensor(5, shape=(), dtype=int64)
        tf.Tensor(6, shape=(), dtype=int64)
        tf.Tensor(7, shape=(), dtype=int64)
        tf.Tensor(8, shape=(), dtype=int64)
        tf.Tensor(9, shape=(), dtype=int64)
    • from_tensor_slices() 함수는 텐서를 받아 첫 번째 차원에 따라 X의 각 원소가 아이템으로 표현되는 tf.data.Dataset을 생성.
    • 해당 텐서는 0~9 까지의 10개의 아이템을 가짐 (tf.data.Dataset.range(10)과 동일)

 

연쇄 변환

  • 데이터셋이 준비되면 변환 메서드를 호출하여 여러 종류의 변환을 수행할 수 있음

  • 각 메서드는 새로운 데이터셋을 반환하므로 다음과 같이 변환 메서드를 연결할 수 있음

    dataset = dataset.repeat(3).batch(7)
    for item in dataset:
        print(item)
    
    >>  tf.Tensor([0 1 2 3 4 5 6], shape=(7,), dtype=int64)
        tf.Tensor([7 8 9 0 1 2 3], shape=(7,), dtype=int64)
        tf.Tensor([4 5 6 7 8 9 0], shape=(7,), dtype=int64)
        tf.Tensor([1 2 3 4 5 6 7], shape=(7,), dtype=int64)
        tf.Tensor([8 9], shape=(2,), dtype=int64)
    
    dataset = dataset.map(lambda x: x * 2)
    >> 아이템 내부에 곱하기 2
    
    dataset = dataset.unbatch()
    >> batch 해제 하나의 정수 텐서로 반환
    
    dataset = dataset.filter(lambda x: x < 10) 
    >> 필터링도 적용 가능
    
    for item in dataset.take(3):
        print(item)
    
    >>  tf.Tensor(0, shape=(), dtype=int64)
        tf.Tensor(2, shape=(), dtype=int64)
        tf.Tensor(4, shape=(), dtype=int64)
    • repeat() 메서드를 호출하면 원본 데이터셋의 아이템을 세 차례 반복하는 데이터셋 생성

    • batch() 메서드를 호출하면 다시 새로운 데이터셋이 생성

      • batch 7 이여서 7개씩 묶음으로
      • drop_remainder=True를 호출하면 길이가 모자란 마지막 배치를 삭제
    • take() 메서드로 가져올 개수 지정 가능

 

데이터 셔플링

  • 경사 하강법은 훈련 세트에 있는 샘플이 독립적이고 동일한 분포일 때 최고의 성능을 발휘함

    • 간단한 방법은 shuffle() 메서드를 사용해 샘플을 섞으면 됨
    • 해당 메서드는 먼저 원본 데이터셋의 처음 아이템을 buffer_size 개수만큼 추출하여 버퍼에 채움
    • 그다음 새로운 아이템이 요청되면 이 버퍼에서 랜덤하게 하나를 반환
    • 그리고 원본 데이터셋에서 새로운 아이템을 추출하여 비워진 버퍼를 채움, 원본 데이터셋의 모든 아이템이 사용될 때 까지 반복 -> 버퍼가 비워질 때까지 계속하여 랜덤하게 아이템 반환
  • 해당 메서드를 사용하기 위해서는 버퍼 크기를 지정해야 함, 버퍼 크기 충분히 크게 잡는게 중요

    dataset = tf.data.Dataset.range(10).repeat(3)
    dataset = dataset.shuffle(buffer_size=3, seed=42).batch(7)
    for item in dataset:
        print(item)
    
    >>  tf.Tensor([1 3 0 4 2 5 6], shape=(7,), dtype=int64)
        tf.Tensor([8 7 1 0 3 2 5], shape=(7,), dtype=int64)
        tf.Tensor([4 6 9 8 9 7 0], shape=(7,), dtype=int64)
        tf.Tensor([3 1 4 5 2 8 7], shape=(7,), dtype=int64)
        tf.Tensor([6 9], shape=(2,), dtype=int64)

 

여러 파일에서 한 줄씩 번갈아 읽기

  • 캘리포니아 주택 데이터셋을 적재하고 섞은 다음 훈련 세트, 검증 세트, 테스트 세트로 나누었다고 가정

  • 각 세트를 다음과 같은 csv 파일 여러 개로 분할

    # 해당 CSV
    MedInc,HouseAge,AveRooms,AveBedrms,Population,AveOccup,Latitude,Longitude,MedianHouseValue
    3.5214,15.0,3.0499445061043287,1.106548279689234,1447.0,1.6059933407325193,37.63,-122.43,1.442
    5.3275,5.0,6.490059642147117,0.9910536779324056,3464.0,3.4433399602385686,33.69,-117.39,1.687
    3.1,29.0,7.5423728813559325,1.5915254237288134,1328.0,2.2508474576271187,38.44,-122.98,1.621
    7.1736,12.0,6.289002557544757,0.9974424552429667,1054.0,2.6956521739130435,33.55,-117.7,2.621
    
    # train_filepaths
    >>  ['datasets/housing/my_train_00.csv',
         'datasets/housing/my_train_01.csv',
         'datasets/housing/my_train_02.csv',
         ....
         ]
    
    # 입력 파이프라인 만들기
    filepath_dataset = tf.data.Dataset.list_files(train_filepaths, seed=42)
    ## 기본적으로 list_files() 함수는 파일 경로를 섞은 데이터셋을 반환
    ## 섞는 것을 방지하고 싶다면 shuffle = False 지정
    
    

iterleave() 메서드 사용해 한 번에 다섯 개의 파일을 한 줄씩 번갈아 읽음

n_readers = 5
dataset = filepath_dataset.interleave(
lambda filepath: tf.data.TextLineDataset(filepath).skip(1),
cycle_length=n_readers)

파일의 첫 줄은 header 임으로 skip으로 넘어감


  - interleave() 메서드는 filepath_dataset에 있는 다섯 개의 파일 경로에서 데이터를 읽는 데이터셋을 생성
    - 해당 메서드에 전달한 함수를 각 파일에 대해 호출하여 새로운 데이터셋을 생성
    - 총 7개의 데이터셋이 생성 (파일 경로 데이터셋, 인터리브 데이터셋, 인터리브 데이터셋에 의해 생성된 5개의 TextLineDataset)

&nbsp;

- 기본적으로 interleave() 메서드는 병렬화를 사용하지 않음

- 각 파일에서 한 번에 한 줄씩 순서대로 읽음, 여러 파일에서 병렬로 읽을때는 num_parallel_calls 매개변수에 원하는 스레드 수 지정

  - 해당 매개변수를 tf.data.experimental.AUTOTUNE으로 지정하면 텐서플로가 가용한 CPU를 기반으로 동적으로 적절한 스레드 개수를 선택할 수 있음 (아직 실험적인 기능)

  ```python
  for line in dataset.take(5):
      print(line.numpy())

  >>  b'4.6477,38.0,5.03728813559322,0.911864406779661,745.0,2.5254237288135593,32.64,-117.07,1.504'
      b'8.72,44.0,6.163179916317992,1.0460251046025104,668.0,2.794979079497908,34.2,-118.18,4.159'
      b'3.8456,35.0,5.461346633416459,0.9576059850374065,1154.0,2.8778054862842892,37.96,-122.05,1.598'
      b'3.3456,37.0,4.514084507042254,0.9084507042253521,458.0,3.2253521126760565,36.67,-121.7,2.526'
      b'3.6875,44.0,4.524475524475524,0.993006993006993,457.0,3.195804195804196,34.04,-118.15,1.625'
  • 위 내용은 CSV의 header 무시하고 첫 번째 행에 해당하며 순서는 랜덤

 

데이터 전처리

  • 전처리 수행 예제

    X_mean = scaler.mean_
    X_std = scaler.scale_
    
    n_inputs = 8 # X_train.shape[-1]
    
    @tf.function
    def preprocess(line):
        defs = [0.] * n_inputs + [tf.constant([], dtype=tf.float32)]
        fields = tf.io.decode_csv(line, record_defaults=defs)
        x = tf.stack(fields[:-1])
        y = tf.stack(fields[-1:])
        return (x - X_mean) / X_std, y
    • mean, std는 미리 개산
    • preprocess() 함수는 CSV 한 라인을 받아 파싱, 이를 위해 tf.io.decode_csv() 함수를 사용
      • tf.io.decode_csv()
        • 두 개의 매개변수를 입력 받음
        • 첫 번째는 파싱할 라인과 두 번째는 CSV파일의 각 열에 대한 기본값을 담은 배열
        • 이 배열은 텐서플로에게 각 열의 기본값뿐만 아니라 열 개수와 데이터 타입도 알려줌
        • 스칼라 텐서의 리스트를 반환
        • 1D 텐서 배열을 반환해야 하므로 마지막 열을 제외하고 모든 텐서에 대해 tf.stack() 함수를 호출
        • 해당 함수는 모든 텐서를 쌓아 1D 배열을 만듬, 그 다음 타깃값에도 동일하게 적용
    • 마지막으로 입력 특성에서 평균을 빼고 표준편차로 나누어 스케일을 조정. 그다음 스케일로 조정된 특성과 타깃을 담은 튜플을 반환

 

데이터 적재와 전처리를 합치기

  • 재사용 가능한 코드를 만들기 위해 지금까지 수행한 모든 것을 하나의 헬퍼 함수로 생성
    • 해당 함수는 CSV 파일에서 데이터를 효율적으로 적재하고 전처리, 셔플링, 반복, 배치를 적용한 데이터셋을 만들어 반환
def csv_reader_dataset(filepaths, repeat=1, n_readers=5,
                       n_read_threads=None, shuffle_buffer_size=10000,
                       n_parse_threads=5, batch_size=32):
    dataset = tf.data.Dataset.list_files(filepaths).repeat(repeat)
    dataset = dataset.interleave(
        lambda filepath: tf.data.TextLineDataset(filepath).skip(1),
        cycle_length=n_readers, num_parallel_calls=n_read_threads)
    dataset = dataset.shuffle(shuffle_buffer_size)
    dataset = dataset.map(preprocess, num_parallel_calls=n_parse_threads)
    dataset = dataset.batch(batch_size)
    return dataset.prefetch(1)

 

프리배치

  • 마지막 prefetch(1)를 호출하면 데이터셋은 항상 한 배치가 미리 준비되도록 함
    • 훈련 알고리즘이 한 배치로 작업을 하는 동안 이 데이터셋이 동시에 다음 배치를 준비
      • 해당 기능을 통해 성능을 크게 향상시킴

 

tf.keras와 데이터셋 사용하기

  • csv_reader_dataset() 함수로 훈련 세트로 사용할 데이터셋을 생성할 수 있음
  • tf.keras에서 반복을 처리하므로 반복을 지정할 필요가 없음
train_set = csv_reader_dataset(train_filepaths, repeat=None)
valid_set = csv_reader_dataset(valid_filepaths)
test_set = csv_reader_dataset(test_filepaths)

model = keras.models.Sequential([
    keras.layers.Dense(30, activation="relu", input_shape=X_train.shape[1:]),
    keras.layers.Dense(1),
])
model.compile(loss="mse", optimizer=keras.optimizers.SGD(learning_rate=1e-3))
batch_size = 32
model.fit(train_set, steps_per_epoch=len(X_train) // batch_size, epochs=10, validation_data=valid_set)

model.evaluate(test_set, steps=len(X_test) // batch_size)

new_set = test_set.map(lambda X, y: X) # we could instead just pass test_set, Keras would ignore the labels
X_new = X_test
model.predict(new_set, steps=len(X_new) // batch_size)
  • keras의 fit() 메서드에 X_train, y_train, X_valid, y_valid 대신 훈련 데이터셋과 검증 데이터셋을 전달하면 됨

  • 하지만 대규모의 복잡한 데이터 구조를 지원하지 못함

 

TFRecord 포맷

  • 대용량 데이터를 저장하고 효율적으로 읽기 위해 텐서플로가 사용하는 포멧인 TFRecord가 정의
  • TFRecord는 크기가 다른 연속된 이진 레코드를 저장하는 단순한 이진 포맷
  • tf.io.TFRecordWriter 클래스를 사용해 TFRecord를 손 쉽게 생성 가능
with tf.io.TFRecordWriter("my_data.tfrecord") as f:
    f.write(b"This is the first record")
    f.write(b"And this is the second record")
  • tf.data.TFRecordDataset을 사용해 하나 이상의 TFRecord를 읽을 수 있음
filepaths = ["my_data.tfrecord"]
dataset = tf.data.TFRecordDataset(filepaths)
for item in dataset:
    print(item)

>> tf.Tensor(b'This is the first record', shape=(), dtype=string)
   tf.Tensor(b'And this is the second record', shape=(), dtype=string)

 

압축된 TFRecord 파일

  • optopms 매개변수를 사용하여 압축된 TFRecord 파일 생성 가능
options = tf.io.TFRecordOptions(compression_type="GZIP")
with tf.io.TFRecordWriter("my_compressed.tfrecord", options) as f:
    f.write(b"This is the first record")
    f.write(b"And this is the second record")
  • 압축된 TFRecord 파일을 읽으려면 압축 형식을 지정해야 함
dataset = tf.data.TFRecordDataset(["my_compressed.tfrecord"],
                                  compression_type="GZIP")

 

텐서플로 프로토콜 버퍼

  • TFRecord 파일에서 사용하는 전형적인 주요 프로토콜 버퍼는 데이터셋에 있는 하나의 샘플을 표현하는 Example 프로토콜 버퍼

  • 프로토콜 버퍼 정의

    syntax = "proto3";
    
    message BytesList { repeated bytes value = 1; }
    message FloatList { repeated float value = 1 [packed = true]; }
    message Int64List { repeated int64 value = 1 [packed = true]; }
    message Feature {
        oneof kind {
            BytesList bytes_list = 1;
            FloatList float_list = 2;
            Int64List int64_list = 3;
        }
    };
    message Features { map<string, Feature> feature = 1; };
    message Example { Features features = 1; };
  • tf.train.Example 객체 생성후 TFRecord 파일에 저장하는 방법

    from tensorflow.train import BytesList, FloatList, Int64List
    from tensorflow.train import Feature, Features, Example
    
    person_example = Example(
        features=Features(
            feature={
                "name": Feature(bytes_list=BytesList(value=[b"Alice"])),
                "id": Feature(int64_list=Int64List(value=[123])),
                "emails": Feature(bytes_list=BytesList(value=[b"a@b.com", b"c@d.com"]))
            }))
    
    with tf.io.TFRecordWriter("my_contacts.tfrecord") as f:
        f.write(person_example.SerializeToString())

 

Example 프로토콜 버퍼를 읽고 파싱하기

  • 직렬화된 Example 프로토콜 버퍼를 읽기 위해서 tf.data.TFRecordDataset을 다시 한번 사용하고 tf.io.parse_single_example()을 사용해 Example 파싱

  • 설명 dict 정의후 TFRecordDataset을 순회하면서 데이터셋에 포함된 직렬화된 Example 프로토콜 버퍼를 파싱하는 예제

    feature_description = {
        "name": tf.io.FixedLenFeature([], tf.string, default_value=""),
        "id": tf.io.FixedLenFeature([], tf.int64, default_value=0),
        "emails": tf.io.VarLenFeature(tf.string),
    }
    for serialized_example in tf.data.TFRecordDataset(["my_contacts.tfrecord"]):
        parsed_example = tf.io.parse_single_example(serialized_example,
                                                    feature_description)
    • 고정 길이 특성은 보통의 텐서로 파싱되지만 가변 길이 특성은 희소 텐서로 파싱됨
    • tf.sparse.to_dense()로 희소 텐서를 밀집 텐서로 변환할 수 있지만 희소 텐서의 값을 바로 참조하는 것이 더 간단함
  • tf.io.parse_single_example()로 하나씩 파싱하는 대신 tf.io.parse_example()을 사용하여 배치 단위로 파싱하는 예제

    dataset = tf.data.TFRecordDataset(["my_contacts.tfrecord"]).batch(10)
    for serialized_examples in dataset:
        parsed_examples = tf.io.parse_example(serialized_examples,
                                              feature_description)

 

입력 특성 전처리

  • 신경망을 위해 데이터를 준비하기 위해 모든 특성을 수치 특성으로 변환하고 정규화 하는 과정이 필요

    • 데이터에 범주형 특성이나 텍스트 특성이 있다면 숫자로 변환해야 함
  • Lambda 층을 사용해 표준화를 수행하는 층을 구현하는 방법 예제

    means = np.mean(X_train, axis=0, keepdims=True)
    stds = np.std(X_train, axis=0, keepdims=True)
    eps = keras.models.Sequential([
        keras.layers.Lambda(lambda inputs : (inputs - means) / (stds + eps)),
        ...
    ])
    • 또는 사용자 정의 층을 생성할수도 있음
    class Standardization(keras.layers.Layer):
        def adapt(self, data_sample):
            self.means_ = np.mean(data_sample, axis=0, keepdims=True)
            self.stds_ = np.std(data_sample, axis=0, keepdims=True)
        def call(self, inputs):
            return (inputs - self.means_) / (self.stds_ + keras.backend.epsilon())
    
    std_layer = Standardization()
    std_layer.adapt(data_sample)
    
    model = keras.Sequential()
    model.add(std_layer)
    ...
    • 원하는 기능을 Layer로 만들어서 사용할 수 있음

 

원-핫 벡터를 사용해 범주형 특성 인코딩하기

  • 범주형 데이터를 신경망에 넣기전에 인코딩을 수행

    vocab = ["<1H OCEAN", "INLAND", "NEAR OCEAN", "NEAR BAY", "ISLAND"]
    indices = tf.range(len(vocab), dtype=tf.int64)
    table_init = tf.lookup.KeyValueTensorInitializer(vocab,indices)
    num_oov_buckets = 2
    table = tf.lookup.StaticVocabularyTable(table_init, num_oov_buckets)
    • 어휘 사전 정의, 범주에 해당하는 인덱스의 tensor 생성
    • 범주 리스트와 해당 인덱스를 전달하여 룩업 테이블을 위해 초기화 객체 생성
    • 초기화 객체와 OOV 버킷을 지정하여 룩업 테이블을 생성. 어휘 사전에 없는 범주를 찾으면 룩업 테이블이 계산한 이 범주의 해시값을 이용하여 oov 버킷 중 하나에 할당
  • 룩업 테이블을 사용해 몇 개의 범주 특성을 원-핫 인코딩 하는 예제

    categories = tf.constant(['NEAR BAY', 'DESERT', 'INLAND', 'INLAND'])
    cat_indices = table.lookup(categories)
    cat_one_hot = tf.one_hot(cat_indices, depth= len(vocab) + num_oov_buckets)
    • 어휘 사전이 크면 임베딩을 사용하여 인코딩하는 것이 훨씬 효율적인 방식임

 

임베딩을 사용해 범주형 특성 인코딩하기

  • 임베딩은 범주를 표현하는 훈련 가능한 밀집 벡터를 의미함

  • 처음엔 임베딩이 랜덤하게 초기화되어 있음

    • 'NEAR BAR' : [0.131, 0.890]과 같은 랜덤 벡터로 표현
    • 'NEAR OCEAN' : [0.631, 0.791]과 같은 랜덤 벡터로 표현
  • 임베딩을 훈련할 수 있기 때문에 훈련 도중에 점차 향상됨

  • 비슷한 범주들은 경사 하강법이 더 가깝게 만듬

    • 표현이 좋을수록 신경말이 정확한 예측을 만들기가 쉬움

    • 이처럼 범주가 유용하게 표현되도록 임베딩이 훈련되는 경향을 표현 학습

    • 케라스 임베딩 학습 예제

      regular_inputs = keras.layers.Input(shape=[8])
      categories = keras.layers.Input(shape=[], dtype=tf.string)
      cat_indices = keras.layers.Lambda(lambda cats : table.lookup(cats))(categories)
      cat_embed = keras.layers.Embedding(input_dim=6, output_dim=2)(cat_indices)
      encoded_inputs = keras.layers.concatenate([regular_inputs, cat_embed])
      outputs = keras.layers.Dense(1)(encoded_inputs)
      model = keras.model.Model(inputs = [regular_inputs, categories], outputs = [outputs])
      • 해당 모델은 두 개의 입력을 받음, 샘플마다 8개의 특성을 담은 입력과 하나의 범주형 입력
      • Lambda 층을 통해 범주의 인덱스를 찾음 다음 임베딩에서 해당하는 인덱스를 찾음
      • 임베딩과 일반 입력을 연결하여 신경망에 전달, 이후 완전연결층으로 끝

 

TF 변환

  • 전처리는 계산 비용이 크기 때문에 훈련과 동시에 수행하는 것보다 사전에 처리하면 속도를 크게 높일 수 있음

  • 데이터가 훈련하는 동안 epoch 마다 전처리되는 것이 아니라 훈련하기 전에 샘플마다 한 번씩 전처리 됨

  • 훈련 전에 수행한 전처리 연산과 앱이나 브라우저에서 수행하는 전처리가 차이가 날 수 있음 이를 훈련/서빙 왜곡 이라고 하고 이는 성능 감소로 이루어질수 있음

  • 전처리 연산을 딱 한번만 정의하기 위해 TF변환을 사용, TF 변환 같은 변환 함수를 사용하여 전처리 함수를 한 번만 정의, 필요시 어떤 텐서플로 연산도 사용할 수 있음

    • TF변환으로 두개의 특성을 전처리하는 함수 예제

      try:
          import tensorflow_transform as tft
      
          def preprocess(inputs):  # inputs is a batch of input features
              median_age = inputs["housing_median_age"]
              ocean_proximity = inputs["ocean_proximity"]
              standardized_age = tft.scale_to_z_score(median_age - tft.mean(median_age))
              ocean_proximity_id = tft.compute_and_apply_vocabulary(ocean_proximity)
              return {
                  "standardized_median_age": standardized_age,
                  "ocean_proximity_id": ocean_proximity_id
              }
      except ImportError:
          print("TF Transform is not installed. Try running: pip3 install -U tensorflow-transform")
      • 위 예제에서 housing_median_age 특성의 평균, 표준편차와 ocean_proximity 특성의 어휘 사전을 계산
      • 이런식의 통계를 계산하는 컴포넌트를 애널라이저라고 부름
      • 표준 데이터셋을 사용하고 싶다면 TFDS를 사용

 

텐서플로 데이터셋(TFDS) 프로젝트

  • TFDS는 tensorflow-datasets 라이브러리를 설치해야 함

  • MNIST 예제

    import tensorflow_datasets as tfds
    
    ###  데이터 로드
    datasets = tfds.load(name="mnist")
    mnist_train, mnist_test = datasets["train"], datasets["test"]
    
    ###  원하는 변환 적용
    plt.figure(figsize=(6,3))
    mnist_train = mnist_train.repeat(5).batch(32).prefetch(1)
    for item in mnist_train:
        images = item["image"]
        labels = item["label"]
        for index in range(5):
            plt.subplot(1, 5, index + 1)
            image = images[index, ..., 0]
            label = labels[index].numpy()
            plt.imshow(image, cmap="binary")
            plt.title(label)
            plt.axis("off")
        break # just showing part of the first batch
    
    

map 매서드를 통해 형태 변환

datasets = tfds.load(name="mnist")
mnist_train, mnist_test = datasets["train"], datasets["test"]
mnist_train = mnist_train.repeat(5).batch(32)
mnist_train = mnist_train.map(lambda items: (items["image"], items["label"]))
mnist_train = mnist_train.prefetch(1)
for images, labels in mnist_train.take(1):
print(images.shape)
print(labels.numpy())

해당과정으로 데이터를 바로 keras 모델에 적용하는 예제

datasets = tfds.load(name="mnist", batch_size=32, as_supervised=True)
mnist_train = datasets["train"].repeat().prefetch(1)
model = keras.models.Sequential([
keras.layers.Flatten(input_shape=[28, 28, 1]),
keras.layers.Lambda(lambda images: tf.cast(images, tf.float32)),
keras.layers.Dense(10, activation="softmax")])
model.compile(loss="sparse_categorical_crossentropy",
optimizer=keras.optimizers.SGD(learning_rate=1e-3),
metrics=["accuracy"])
model.fit(mnist_train, steps_per_epoch=60000 // 32, epochs=5)



반응형

'Study > Self Education' 카테고리의 다른 글

Pytorch 기본기 - 1  (0) 2024.07.02
핸즈온 머신러닝 - 14  (0) 2024.06.19
핸즈온 머신러닝 - 12  (0) 2024.06.19
핸즈온 머신러닝 - 11  (0) 2024.06.19
핸즈온 머신러닝 - 10  (0) 2024.06.19