ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [HandsOn]13. 텐서플로에서 데이터 적재와 전처리하기 - 연습문제
    [도서완독]Hands On Machine Learning 2022. 7. 29. 23:02

    코드는 여기를 참고하였다.

    https://github.com/rickiepark/handson-ml2/blob/master/13_loading_and_preprocessing_data.ipynb

     

    GitHub - rickiepark/handson-ml2: 핸즈온 머신러닝 2/E의 주피터 노트북

    핸즈온 머신러닝 2/E의 주피터 노트북. Contribute to rickiepark/handson-ml2 development by creating an account on GitHub.

    github.com

     

    9. 10장에서 소개한 패션 MNIST 데이터셋을 적재하고 훈련 세트, 검증세트, 테스트 세트로 나눕니다.

    훈련 세트를 섞은 다음 각 데이터셋을 TFRecord 파일로 저장합니다.

    각 레코드는 두 개의 특성을 가진 Example 프로토콜 버퍼, 즉 직렬화된 이미지(tf.io.serialize_tensor() 를 사용해 이미지를 직렬화하세요) 와 레이블입니다. 

     

    (X_train_full, y_train_full), (X_test, y_test) = keras.datasets.fashion_mnist.load_data()
    X_valid, X_train = X_train_full[:5000], X_train_full[5000:]
    y_valid, y_train = y_train_full[:5000], y_train_full[5000:]
    train_set = tf.data.Dataset.from_tensor_slices((X_train, y_train)).shuffle(len(X_train))
    valid_set = tf.data.Dataset.from_tensor_slices((X_valid, y_valid))
    test_set = tf.data.Dataset.from_tensor_slices((X_test, y_test))

    훈련세트를 tf.data.Dataset 를 생성하는 함수인 from_tensor_slice를 통해 Dataset으로 생성. 예를 들어 MNIST의 학습데이터 (60000, 28, 28)가 입력되면, 60000개의 slices로 만들고 각각의 slice는 28×28의 이미지 크기를 갖게 됨.

     

    def create_example(image, label):
        image_data = tf.io.serialize_tensor(image)
        #image_data = tf.io.encode_jpeg(image[..., np.newaxis])
        return Example(
            features=Features(
                feature={
                    "image": Feature(bytes_list=BytesList(value=[image_data.numpy()])),
                    "label": Feature(int64_list=Int64List(value=[label])),
                }))

    기록할 데이터를 함수의 파라미터로 받고 이들을 python dictionary 형태로 묶어 tf.train.Example 객체로 변환한다. 

    for image, label in valid_set.take(1):
        print(create_example(image, label))

    slice 된 validation set 을 한개만 뽑아서 함수에 통과시켜 보자. 

     

    from contextlib import ExitStack
    
    def write_tfrecords(name, dataset, n_shards=10):
        paths = ["{}.tfrecord-{:05d}-of-{:05d}".format(name, index, n_shards)
                 for index in range(n_shards)]
        with ExitStack() as stack:
            writers = [stack.enter_context(tf.io.TFRecordWriter(path))
                       for path in paths]
            for index, (image, label) in dataset.enumerate():
                shard = index % n_shards
                example = create_example(image, label)
                writers[shard].write(example.SerializeToString())
        return paths
    train_filepaths = write_tfrecords("my_fashion_mnist.train", train_set)
    valid_filepaths = write_tfrecords("my_fashion_mnist.valid", valid_set)
    test_filepaths = write_tfrecords("my_fashion_mnist.test", test_set)

    각각의 세트가 10개로 분할되어 저장됨

    그 다음 tf. data로 각 세트를 위한 효율적인 데이터셋을 만듭니다.

    def preprocess(tfrecord):
        feature_descriptions = {
            "image": tf.io.FixedLenFeature([], tf.string, default_value=""),
            "label": tf.io.FixedLenFeature([], tf.int64, default_value=-1)
        }
        example = tf.io.parse_single_example(tfrecord, feature_descriptions)
        image = tf.io.parse_tensor(example["image"], out_type=tf.uint8)
        #image = tf.io.decode_jpeg(example["image"])
        image = tf.reshape(image, shape=[28, 28])
        return image, example["label"]
    
    def mnist_dataset(filepaths, n_read_threads=5, shuffle_buffer_size=None,
                      n_parse_threads=5, batch_size=32, cache=True):
        dataset = tf.data.TFRecordDataset(filepaths,
                                          num_parallel_reads=n_read_threads)
        if cache:
            dataset = dataset.cache()
        if shuffle_buffer_size:
            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)
    #%%
    train_set = mnist_dataset(train_filepaths, shuffle_buffer_size=60000)
    valid_set = mnist_dataset(valid_filepaths)
    test_set = mnist_dataset(test_filepaths)

    아니 진짜... 다 이해는 못하겠다 ㅠ 여튼 경로에 저장된 tfrecord를 다시 불러오는 함수임... 쥬륵....

     

    마지막으로 이 데이터셋으로 입력 특성을 표준화하는 전처리 층을 포함한 케라스 모델을 훈련합니다. 

    standardization = keras.layers.Normalization(input_shape=[28, 28])
    
    sample_image_batches = train_set.take(100).map(lambda image, label: image)
    sample_images = np.concatenate(list(sample_image_batches.as_numpy_iterator()),
                                   axis=0).astype(np.float32)
    standardization.adapt(sample_images)

    표준화하는 층을 불러오자.

     

    그리고 트레인 셋에서 100개 뽑아서, numpy 형식으로 만들고 다 합쳐서 표준화 객체에 피팅시킨다. 평균이랑 표준편차를 구하게 되겠지. 

     

    model = keras.models.Sequential([
        standardization,
        keras.layers.Flatten(),
        keras.layers.Dense(100, activation="relu"),
        keras.layers.Dense(10, activation="softmax")
    ])
    model.compile(loss="sparse_categorical_crossentropy",
                  optimizer="nadam", metrics=["accuracy"])

    아주 간단한 모델을 만들자. 처음에 전처리 층을 넣는다. 

    model.fit(train_set, epochs=5, validation_data=valid_set,

    집에 가고싶다....

     

    10. 데이터셋을 다운로드 및 분할하고 tf.data.Dataset 객체를 만들어 데이터를 적재하고 효율적으로 전처리하겠습니다. 그 다음 Embedding 층을 포함한 이진 분류 모델을 만들고 훈련시킵니다.

     

    a. 인터넷 영화 데이터베이스의 영화 리뷰 50,000개를 담은 영화 리뷰 데이터셋을 다운로드 합니다. 이 데이터는 train과 test라는 두 개의 디렉터리로 구성되어 있습니다. 각 디렉터리에는 12,500개의 긍정 리뷰를 담은 pos 서브디렉터리와 12,500개의 부정 리뷰를 담은 neg 서브디렉터리가 있습니다. 리뷰는 각각 별도의 텍스트 파일에 저장되어 있습니다.

    (전처리 된 bow를 포함해) 다른 파일과 디렉터리가 있지만 이 연습문제에서는 무시합니다.

     

    https://ai.stanford.edu/~amaas/data/sentiment/

     

    Sentiment Analysis

    Publications Using the Dataset Andrew L. Maas, Raymond E. Daly, Peter T. Pham, Dan Huang, Andrew Y. Ng, and Christopher Potts. (2011). Learning Word Vectors for Sentiment Analysis. The 49th Annual Meeting of the Association for Computational Linguistics (A

    ai.stanford.edu

    from pathlib import Path
    
    DOWNLOAD_ROOT = "http://ai.stanford.edu/~amaas/data/sentiment/"
    FILENAME = "aclImdb_v1.tar.gz"
    filepath = keras.utils.get_file(FILENAME, DOWNLOAD_ROOT + FILENAME, extract=True)
    path = Path(filepath).parent / "aclImdb"
    path

    다운중...

    def review_paths(dirpath):
        return [str(path) for path in dirpath.glob("*.txt")]

    파일이 저장된 경로의 모든 txt파일을 리스트로 반환. 

     

    train_pos = review_paths(path / "train" / "pos")
    train_neg = review_paths(path / "train" / "neg")
    test_valid_pos = review_paths(path / "test" / "pos")
    test_valid_neg = review_paths(path / "test" / "neg")
    
    len(train_pos), len(train_neg), len(test_valid_pos), len(test_valid_neg)

    데이터가 있는 경로에다가 문자열을 더해줘서 세부 경로를 만들고 그 경로 안의 txt 파일을 리스트로 반환!

    최종적으로 (12500, 12500, 12500, 12500) 개가 나왔다.

     

    b. 테스트 세트를 검증 세트(15,000개)와 테스트 세트(10,000개)로 나눕니다.

     

    np.random.shuffle(test_valid_pos)
    
    test_pos = test_valid_pos[:5000]
    test_neg = test_valid_neg[:5000]
    valid_pos = test_valid_pos[5000:]
    valid_neg = test_valid_neg[5000:]

    세트를 섞고 나서 나눠준다. 

     

    c.tf.data를 사용해 각 세트에 대한 효율적인 데이터셋을 만듭니다.

     

    def imdb_dataset(filepaths_positive, filepaths_negative):
        reviews = []
        labels = []
        for filepaths, label in ((filepaths_negative, 0), (filepaths_positive, 1)):
            for filepath in filepaths:
                with open(filepath) as review_file:
                    reviews.append(review_file.read())
                labels.append(label)
        return tf.data.Dataset.from_tensor_slices(
            (tf.constant(reviews), tf.constant(labels)))

    pos 경로 리스트와 neg 경로 리스트를 받는 함수를 만든다. 이 함수는 review, 그리고 그에 맞는 긍부정(0,1) 을 쌍으로 하여 dataset에 적재한다. 

     

    for X, y in imdb_dataset(train_pos, train_neg).take(3):
        print(X)
        print(y)
        print()

    함수에 train set 두 개 를 넣고, 3개를 뽑아보면, 

    이런 식으로 리뷰와 레이블이 보이는 걸 알수 있음.

     

    batch_size = 32
    
    train_set = imdb_dataset(train_pos, train_neg).shuffle(25000).batch(batch_size).prefetch(1)
    valid_set = imdb_dataset(valid_pos, valid_neg).batch(batch_size).prefetch(1)
    test_set = imdb_dataset(test_pos, test_neg).batch(batch_size).prefetch(1)

    모든 set에 대해 똑같이 해서 dataset에 적재해준다. 

     

    d. 리뷰를 전처리하기 위해 TextVectorization 층을 사용한 이진 분류 모델을 만드세요. TextVectorization 층을 아직 사용할 수 없다면 (또는 도전을 좋아한다면) 사용자 전처리 층을 만들어보세요. tf.strings 패키지에 있는 함수를 사용할 수 있습니다. 예를 들어 lower()로 소문자로 만들거나 regex_replace()로 구두점을 공백으로 바꾸고 split()로 공백을 기준으로 단어를 나눌 수 있습니다. 룩업 테이블을 사용해 단어 인덱스를 출력하세요. adapt() 메서드로 미리 층을 적응시켜야 합니다.

    ㅠ 막차끊기겠다... 집에가야지....

     

     

Designed by Tistory.