-
[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
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)
그 다음 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/
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() 메서드로 미리 층을 적응시켜야 합니다.
ㅠ 막차끊기겠다... 집에가야지....
'[도서완독]Hands On Machine Learning' 카테고리의 다른 글
[HandsOn]15. RNN과 CNN을 사용해 시퀀스 처리하기 - 내용 정리1 (0) 2022.08.08 [HandsOn]14. 합성곱 신경망을 사용한 컴퓨터 비전 - 내용 정리1 (0) 2022.08.01 [HandsOn]13. 텐서플로에서 데이터 적재와 전처리하기 - 내용 정리2 (0) 2022.07.29 [HandsOn]13. 텐서플로에서 데이터 적재와 전처리하기 - 내용 정리1 (0) 2022.07.26 [HandsOn]12. 텐서플로를 사용한 사용자 정의 모델과 훈련 - 연습문제 풀이 (0) 2022.07.21