텐서플로
이전 내용
케라스의 전처리 층
[신경망에 사용할 데이터 전처리]
신경망에 사용할 데이터를 준비하려면 일반적으로 수치 특성 정규화, 범주형 특성이나 텍스트 인코딩, 이미지 자르기와 크기 조정 등의 작업이 필요하며, 이러한 작업을 위한 방법은 아래와 같다.
- 훈련 데이터 파일을 준비 시, 넘파이, 판다스, 사이킷런과 같은 도구를 사용하여 미리 전처리를 수행한다. 제품에 투입한 모델이 훈련할 때와 비슷하게 전처리된 입력을 받으려면 제품 환경에 정확히 동일한 전처리 단계를 적용해야 한다.
- 데이터셋의 map() 메서드를 사용하여 데이터셋의 모든 원소에 전처리 함수를 적용하여 tf.data로 데이터를 로드하는 동안 바로 전처리할 수 있으며, 여기서도 제품 환경에서 동일한 전처리 단계를 적용해야 한다.
- 모델 내부에 전처리 층을 직접 포함시켜 훈련 중에 즉시 모든 입력 데이터를 전처리하고, 제품 환경에서 동일한 전처리 층을 사용한다.
Normalization 층
케라스는 입력 특성을 표준화할 수 있는 Normalization 층을 제공한다. 이 층을 만들 때 각 특성의 평균과 분산을 지정할 수 있거나, 모델을 훈련하기 전에 이 층의 adapt() 메서드에 훈련 세트를 전달하여 특성의 평균과 분산을 계산할 수 있다.
먼저 필요한 모듈을 import 하고, 캘리포니아 주택 가격 데이터셋 로드
import tensorflow as tf
from sklearn.datasets import fetch_california_housing
from sklearn.model_selection import train_test_split
housing = fetch_california_housing()
X_train_full, X_test, y_train_full, y_test = train_test_split(
housing.data, housing.target.reshape(-1, 1), random_state=42)
X_train, X_valid, y_train, y_valid = train_test_split(
X_train_full, y_train_full, random_state=42)
Normalization 층 생성
norm_layer = tf.keras.layers.Normalization()
model = tf.keras.models.Sequential([
norm_layer,
tf.keras.layers.Dense(1)
])
model.compile(loss='mse', optimizer=tf.keras.optimizers.SGD(learning_rate=2e-3))
norm_layer.adapt(X_train) # 모든 특성의 평균과 분산 계산
model.fit(X_train, y_train, validation_data=(X_valid, y_valid), epochs=5)
▶ 모델에 Normalization 층을 포함했기 때문에 정규화에 대해 신경 쓰지 않고 이 모델을 제품에 배포할 수 있으며, 모델이 정규화를 알아서 처리한다.
이 방식은 전처리 불일치 위험을 완전히 제거하는 데, 전처리 불일치는 훈련과 제품에 사용하는 전처리 코드를 별도로 유지하다가 한 쪽은 업데이트되고 다른 쪽은 업데이트 되지 않을 때 일어나며 그로인해 제품 모델은 기대하는 것과 다르게 전처리된 데이터를 받는 것을 말한다.
모델에 전처리 층을 포함시키는 것은 간단하지만 훈련 속도를 느리게 만들며, 실제로 전처리가 훈련하는 동안 즉시 적용되기 때무넹 에포크마다 매번 수행된다. 이보다는 훈련 전체 훈련 세트를 딱 한 번 전처리하는 것이 좋은 데, 이를 위해 사이킷런의 StandardScaler 처럼 Normalization 층을 독립적으로 사용할 수 있다.
norm_layer = tf.keras.layers.Normalization()
norm_layer.adapt(X_train)
X_train_scaled = norm_layer(X_train)
X_valid_scaled = norm_layer(X_valid)
▶ 이제 스케일이 조정된 데이터로 모델을 훈련할 수 있다.
모델을 훈련 시키는 데, 이번에는 Normalization 층을 포함시키지 않는다.
model = tf.keras.models.Sequential([tf.keras.layers.Dense(1)])
model.compile(loss='mse', optimizer=tf.keras.optimizers.SGD(learning_rate=2e-3))
model.fit(X_train_scaled, y_train, validation_data=(X_valid_scaled, y_valid), epochs=5)
▶ 이렇게 하면 훈련 속도가 조금 빨라지긴 하나, 모델을 제품에 배포했을 때 입력을 전처리하지 못한다.
이 문제를 해결하기 위해 adapt() 메서드를 호출한 Normalization 층과 훈련된 모델을 포함하는 새로운 모델을 만들고, 이 최종 모델을 제품에 배포한다. 이 모델은 입력을 전처리하여 예측을 만들 수 있다.
final_model = tf.keras.Sequential([norm_layer, model])
X_new = X_test[:3] # 스케일을 조정하지 않은 새로운 샘플
y_pred = final_model(X_new) # 데이터를 전처리하고 예측 생성
y_pred
▶ 이 모델은 훈련 전에 데이터를 한 번만 전처리하기 때문에 속도가 빠르고, 최종 모델이 입력 데이터를 바로 전처리할 수 있어 전처리 불일치에 대한 위험이 없다.
케라스 전처리 층은 tf.data API와 함께 쓸 수 있다.
예를 들어 tf.data.Dataset 객체를 전처리 층의 adapt() 메서드에 전달 할 수 있다.
또는 tf.data.Dataset 객체의 map() 메서드에 케라스 전처리 층을 적용할 수도 있다.
아래는 adapt() 메서드를 호출한 Normalization 층을 데이터셋에 있는 각 배치의 입력 특성에 적용하는 예이다.
# map()을 사용하여 norm_layer에 적용하는 데모용 데이터 세트 생성.
dataset = tf.data.Dataset.from_tensor_slices((X_train, y_train)).batch(5)
dataset = dataset.map(lambda X, y: (norm_layer(X), y))
# 첫 번째 배치 표시
list(dataset.take(1))
케라스 전처리 층이 제공하는 것보다 더 많은 기능이 필요하다면 언제든지 자신만의 케라스 층(사용자 정의 층)을 만들 수 있는 데, 예를 들어 Normalization 층이 없다고 가정하면 아래와 같은 사용자 정의 층을 만들어 비슷한 작업을 수행할 수 있다.
import numpy as np
class MyNormalization(tf.keras.layers.Layer):
def adapt(self, X):
self.mean_ = np.mean(X, axis=0, keepdims=True)
self.std_ = np.std(X, axis=0, keepdims=True)
def call(self, inputs):
eps = tf.keras.backend.epsilon() # 0 나눗셈을 방지하기 위한 작은 값
return (inputs - self.mean_) / (self.std_ + eps)
my_norm_layer = MyNormalization()
my_norm_layer.adapt(X_train)
X_train_scaled = my_norm_layer(X_train)
Discretization 층
Discretization 층의 목적은 구간(bin)이라 부르는 값 범위를 범주로 매핑하여 수치 특성을 범주형 특성으로 변환하는 것이다. 다중모드 분포를 가진 특성이나 타깃과의 관계가 매우 비선형적인 특성에 유용할 때가 있다.
예를 들어 다음 코드는 수치 특성 age를 18보다 작음, 18~50 (50 미포함) 사이, 50 이상의 세 범주로 매핑한다.
age = tf.constant([[10.], [93.], [57.], [18.], [37.], [5.]])
discretize_layer = tf.keras.layers.Discretization(bin_boundaries=[18., 50.])
age_categories = discretize_layer(age)
age_categories
위 예시처럼 원하는 구간 경계를 제공하는 게 아니라, 원하는 구간 개수를 전달하고 adapt() 메서드를 호출하여 백분위수 기반으로 적절한 구간 경계를 찾게 만들 수도 있다.
discretize_layer = tf.keras.layers.Discretization(num_bins=3)
discretize_layer.adapt(age)
age_categories = discretize_layer(age)
age_categories
▶ num_bins=3 으로 지정하면 구간 경계는 33번째와 66번째 백분위수 바로 아래에 있는 값이 된다.
이런 범주 식별자는 비교하는 것이 의미가 없어 일반적으로 바로 신경망으로 주입해서는 안 되며, 대신 원-핫 인코딩을 사용해 인코딩되어야 한다.
CategoryEncoding 층
범주의 개수가 적다면 (10 또는 20개 미만) 원-핫 인코딩이 좋은 옵션이다. 이를 위해 케라스는 CategoryEncoding 층을 제공한다. 예를 들어 앞서 만든 age_categories 특성을 원-핫 인코딩 해본다.
onehot_layer = tf.keras.layers.CategoryEncoding(num_tokens=3)
onehot_layer(age_categories)
동일한 범주를 사용한다고 가정할 때 동시에 한 개 이상의 범주형 특성을 인코딩하면 CategoryEncoding 클래스는 기본적으로 멀티-핫 인코딩 즉, 입력 특성에 있는 범주에 해당하는 위치마다 출력 텐서의 값이 1이 되도록 수행한다.
two_age_categories = np.array([[1, 0], [2, 2], [2, 0]])
onehot_layer(two_age_categories)
각 범주가 얼마나 많이 등장하는지 알고 싶다면 CategoryEncoding 층을 만들 때 output_mode='count'를 추가한다. 이렇게 하면 출력 텐서에 각 범주의 등장 횟수가 포함된다.
onehot_layer = tf.keras.layers.CategoryEncoding(num_tokens=3, output_mode="count")
onehot_layer(two_age_categories)
멀티-핫 인코딩과 카운트 인코딩은 범주를 활성화한 특성이 어떤 것인지 알 수 없기 때문에 정보에 손실이 있다. 이를 피하려면 특성마다 별도로 원-핫 인코딩을 한 다음 출력을 합쳐야 한다. 범주 식별자가 겹치지 않도록 조정하면 동일한 결과를 얻을 수 있다.
onehot_layer = tf.keras.layers.CategoryEncoding(num_tokens=3+3)
onehot_layer(two_age_categories + [0, 3]) # 두 번째 특성에 3을 더함
▶ 이 출력에서 처음 세 개의 열은 첫 번째 특성에 해당하고 마지막 세 개의 열은 두 번째 특성에 해당한다.
이렇게 하면 모델이 두 특성을 구별할 수 있으나, 모델에 주입할 특성의 개수를 증가시키기 때문에 모델의 파라미터가 더 필요해진다.
하나의 멀티-핫 인코딩과 특성별 원-핫 인코딩 중 어떤 게 더 나을지 작업에 따라 다르기 때문에 미리 아는 것이 어려워 두 방식을 모두 테스트해 봐야 한다.
StringLookup 층
텍스트로 된 범주형 특성을 인코딩하기 위해서는 StringLookup 층을 사용할 수 있다.
그 예로 cities 특성을 원-핫 인코딩 해본다.
cities = ['Aukland', 'Paris', 'Paris', 'San Francisco', 'Seoul', 'Tokyo']
str_lookup_layer = tf.keras.layers.StringLookup()
str_lookup_layer.adapt(cities)
str_lookup_layer([['Paris'], ['Auckland'], ['Paris'], ['Seoul'], ['Berlin']])
[코드 설명]
- StringLookup 층을 만들고 adapt() 메서드에 데이터를 전달하여 5개의 고유한 범주를 찾음
- 이 층을 사용해 몇 개의 도시를 인코딩 (정수로 인코딩)
- 알 수 없는 범주는 0으로 매핑 (여기서는 'Belrin')
- 이미 알고 있는 범주는 가장 자주 등장하는 범주에서 드물게 등장하는 범주순으로 1부터 매핑
StringLookup 층을 만들 때 output_mode='one_hot'으로 지정하면 정수 대신 범주마다 원-핫 벡터를 출력한다.
str_lookup_layer = tf.keras.layers.StringLookup(output_mode='one_hot')
str_lookup_layer.adapt(cities)
str_lookup_layer([['Paris'], ['Auckland'], ['Paris'], ['Seoul'], ['Berlin']])
훈련 세트가 매우 크면 훈련 세트에서 랜덤하게 일부를 추출하여 adapt() 메서드에 전달하는 것이 편리할 수 있다. 이런 경우 이 층의 adapt() 메서드는 일부 드문 범주를 놓칠 수 있는데, 기본적으로 이런 범주를 모두 범주 0으로 매핑하기 때문에 모델이 구별할 수 없다. 이런 위험을 줄이기 위해 num_oov_indices를 1보다 큰 정수로 지정할 수 있다.
이 값은 OOV(out_of_vocabulary) 버킷 개수이며, 알 수 없는 범주는 해시 함수를 사용해 OOV 버킷 중 하나로 랜덤하게 매핑된다. 이렇게 하면 모델이 적어도 드문 범주 중 일부를 구별할 수 있다.
str_lookup_layer = tf.keras.layers.StringLookup(num_oov_indices=5)
str_lookup_layer.adapt(cities)
str_lookup_layer([['Paris'], ['Auckland'], ['Foo'], ['Bar'], ['Baz']])
▶ 다섯 개의 OOV 버킷이 있으므로 알려진 첫 번째 범주 'Paris'의 ID는 5가 되었다. 그러나 'Foo', 'Bar' ,'Baz'는 알 수 없는 범주이므로 OOV 버킷 중 하나에 매핑된다.
'Bar'는 독립적인 버킷에 매핑되었지만, 'Auckland', 'Foo'와 'Baz'는 같은 버킷에 매핑되어 모델이 이 셋을 구분할 수 없는데, 이를 해싱 충돌(hashing collision)이라고 부르며, 해싱 충돌의 위험을 줄이는 유일한 방법은 OOV 버킷의 수를 늘리는 것이다. 그러나 이렇게 하면 범주의 전체 개수도 증가되어 필요한 메모리가 늘어나고 범주마다 원-핫 인코딩 되기 때문에 모델 파라미터도 증가한다.
Hashing 층
케라스 Hashing 층은 범주마다 해시를 계산하고 버킷 또는 구간 개수로 나눈 나머지를 구한다. 이 매핑은 재현 가능한 랜덤이므로 구간의 개수가 바뀌지 않는다면 동일한 범주는 항상 같은 정수로 매핑되어 안정적이다.
예를 들어 Hashing 층으로 몇 개의 도시를 인코딩해본다.
hashing_layer = tf.keras.layers.Hashing(num_bins=10)
hashing_layer([["Paris"], ["Tokyo"], ["Auckland"], ["Montreal"]])
▶ 이 층의 장점은 adapt() 메서드를 호출할 필요가 없다는 것이며, 특히 데이터셋이 너무 커서 메모리에 들어가지 않는 외부 메모리 환경에서 유용하게 쓰인다. 그러나 여기에서도 해싱 충돌('Tokyo', 'Montreal')이 일어나 모델이 이 둘을 구분할 수 없다.
따라서 일반적으로 StringLookup 층을 사용하는 것이 좋다.
임베딩을 사용해 범주형 특성 인코딩하기
※ 임베딩(embedding): 범주나 어휘 사전의 단어와 같은 고차원 데이터의 밀집 표현이며, 상대적으로 작은 밀집 벡터이다. 예를 들어 50,000개의 범주가 있다면 원-핫 인코딩은 대부분이 0으로 채워진 50,000 차원의 회소 벡터를 만드나, 임베딩은 100 차원의 벡터를 만든다.
딥러닝에서 임베딩은 일반적으로 랜덤하게 초기화되고 다른 모델 파라미터와 함께 경사 하강법으로 훈련된다.
케라스는 임베딩 행렬을 감싼 Embedding 층을 제공한다. 이 행렬은 범주마다 하나의 행을, 임베딩 차원마다 하나의 열을 가지며, 기본적으로 랜덤하게 초기화된다.
범주 ID를 임베딩으로 변환하기 위해 Embedding 층이 범주에 해당하는 행을 찾아 반환하는 것이 전부이다.
그 예로 5개의 행과 2D 임베딩으로 구성된 Embedding 층을 만들어 몇 개의 범주를 인코딩해본다.
tf.random.set_seed(42)
embedding_layer = tf.keras.layers.Embedding(input_dim=5, output_dim=2)
embedding_layer(np.array([2, 4, 2]))
범주형 텍스트 특성을 임베딩하기 위해 StringLookup 층과 Embedding 층을 아래와 같이 연결 할 수 있다.
tf.random.set_seed(42)
ocean_prox = ['<1H OCEAN', 'INLAND', 'NEAR OCEAN', 'NEAR BAY', 'ISLAND']
str_lookup_layer = tf.keras.layers.StringLookup()
str_lookup_layer.adapt(ocean_prox)
lookup_and_embed = tf.keras.Sequential([
tf.keras.layers.InputLayer(input_shape=[], dtype=tf.string), # WORKAROUND
str_lookup_layer,
tf.keras.layers.Embedding(input_dim=str_lookup_layer.vocabulary_size(),
output_dim=2)
])
lookup_and_embed(np.array(['<1H OCEAN', 'ISLAND', '<1H OCEAN']))
임베딩 행렬의 행 개수는 어휘 사전의 크기(알려진 범주와 OOV 버킷 개수를 포함한 총 범주 개수)와 같아야 한다. StingLookup 클래스의 vocabulary_size() 메서드는 이 숫자를 반환한다.
이를 모두 연결하면 일반적인 수치 특성과 함께 범주형 텍스트 특성을 처리하고 각 범주와 각 OOV 버킷을 위한 임베딩을 학습하는 케라스 모델을 만들 수 있다.
# 시드 설정 및 랜덤 데이터 생성
tf.random.set_seed(42)
np.random.seed(42)
ocean_prox = ['<1H OCEAN', 'INLAND', 'NEAR OCEAN', 'NEAR BAY', 'ISLAND']
# 훈련 세트 로드
X_train_num = np.random.rand(10_000, 8).astype(np.float32)
X_train_cat = np.random.choice(ocean_prox, size=10_000)
y_train = np.random.rand(10_000, 1).astype(np.float32)
# 검증 세트 로드
X_valid_num = np.random.rand(2_000, 8).astype(np.float32)
X_valid_cat = np.random.choice(ocean_prox, size=2_000)
y_valid = np.random.rand(2_000, 1).astype(np.float32)
# tf.data.Dataset를 사용하여 데이터셋 생성
train_dataset = tf.data.Dataset.from_tensor_slices(((X_train_num, X_train_cat), y_train))
valid_dataset = tf.data.Dataset.from_tensor_slices(((X_valid_num, X_valid_cat), y_valid))
# batch 및 shuffle 설정
train_dataset = train_dataset.shuffle(buffer_size=10000).batch(32)
valid_dataset = valid_dataset.batch(32)
# lookup_and_embed 함수 정의
def lookup_and_embed(cat_input):
lookup = tf.keras.layers.StringLookup(vocabulary=ocean_prox, output_mode='int')
cat_indices = lookup(cat_input)
embedding = tf.keras.layers.Embedding(input_dim=len(ocean_prox) + 1, output_dim=4)
cat_embeddings = embedding(cat_indices)
return cat_embeddings
# 모델 구성
num_input = tf.keras.layers.Input(shape=[8], name="num")
cat_input = tf.keras.layers.Input(shape=[], dtype=tf.string, name="cat")
cat_embeddings = lookup_and_embed(cat_input)
# 수치형 입력과 임베딩된 범주형 입력 합치기
encoded_inputs = tf.keras.layers.concatenate([num_input, cat_embeddings])
outputs = tf.keras.layers.Dense(1)(encoded_inputs)
model = tf.keras.models.Model(inputs=[num_input, cat_input], outputs=[outputs])
model.compile(loss="mse", optimizer="sgd")
# 모델 훈련
history = model.fit(train_dataset, epochs=5, validation_data=valid_dataset)
텍스트 전처리
케라스는 기본적인 텍스트 전처리를 위한 TextVectorization 층을 제공한다. StringLookup 층과 매우 비슷하게 층을 만들 때 vocabulary 매개변수로 어휘 사전을 전달하거나 adapt() 메서드를 사용해 훈련 데이터로부터 어휘 사전을 학습할 수 있다.
train_data = ["To be", "!(To be)", "That's the question", "Be, be, be."]
text_vec_layer = tf.keras.layers.TextVectorization()
text_vec_layer.adapt(train_data)
text_vec_layer(["Be good!", "Question: be or be?"])
▶ 두 문장 "Be good!"과 "Question: be or be?"가 각각 인코딩되었다.
훈련 데이터에 있는 네 개의 문장으로부터 학습한 어휘 사전은 "be"=2, "to"=3 등이다. 어휘 사전을 구성하기 위해 adapt() 메서드는 먼저 훈련 텍스트를 소문자로 바꾸고 구두점을 삭제하고, 문장을 공백으로 나누고 만들어진 단어를 빈도에 따라 정렬하여 최종 어휘 사전을 만든다. 문장을 인코딩할 때 알 수 없는 단어는 1로 인코딩되고, 첫 번째 문장이 두 번째 문장보다 짧기 때문에 0으로 패딩된다.
TextVectorization 층의 output_mode 매개변수를 'mult_hot' 또는 'count'로 지정하여 멀티-핫 인코딩이나 카운트 인코딩을 얻을 수 있다. 카운트 인코딩과 비슷하지만 훈련 데이터에 자주 등장하는 단어의 가중치를 줄이고 드물게 등장하는 단어의 가중치를 높이는 TF-IDF를 의미하는 'tf_idf'로 설정하는 것이 더 좋다.
text_vec_layer = tf.keras.layers.TextVectorization(output_mode='tf_idf')
text_vec_layer.adapt(train_data)
text_vec_layer(["Be good!", "Question: be or be?"])
텍스트 인코딩 방법은 사용하기 쉽고 기초적인 자연어 처리 작업에서 꽤 좋은 결과를 내지만 몇 가지 중요한 제약 사항이 있다.
- 공백으로 단어가 구분되는 언어에만 사용 가능
- 동음이의어 구별 불가
- 같은 단어의 관계에 대한 힌트를 모델에게 주지 못함.
- 멀티-핫, 카운트, TF-IDF 인코딩을 사용하면 단어의 순서가 사라짐.
사전 훈련된 언어 모델 구성 요소 사용하기
텐서플로 허브 라이브러리를 사용하면 텍스트, 이미지, 오디오 등을 위해 사전 훈련된 모델의 구성 요소를 수비게 재사용할 수 있으며, 이런 모델의 구성 요소를 모듈이라고 부른다.
https://www.tensorflow.org/hub?hl=ko
텐서플로 허브 저장소를 둘러보고 필요한 것을 찾아 코드 예제를 프로젝트에 복사해 넣으면 자동으로 모듈이 다운로드되어 케라스 층으로 제공되므로 모델에 바로 추가할 수 있다.
모듈은 일반적으로 전처리 코드와 사전 훈련된 가중치를 모두 가지며 추가 훈련이 필요 없다.
그 예로 원시 텍스트를 입력받아 50차원 문장 임베딩을 출력하는 nnlm-en-dim50 모듈 버전 2를 사용하기 위해 텐서플로 허브를 import 하고 모듈을 로드한 다음, 모듈을 사용해 두 개의 문장을 벡터로 인코딩해본다.
그 전에 먼저 텐서플로 허브 저장소를 설치한다.
!pip install --upgrade tensorflow_hub
import tensorflow_hub as hub
hub_layer = hub.KerasLayer("https://tfhub.dev/google/nnlm-en-dim50/2")
sentence_embeddings = hub_layer(tf.constant(["To be", "Not to be"]))
sentence_embeddings.numpy().round(2)
▶ 과정 설명
- hub.KerasLayer 층은 주어진 URL에서 모듈을 다운로드한다. (이 모듈은 문장 인코더이다.)
- 문자열을 입력으로 받아 하나의 벡터로 인코딩한다. (여기서는 50차원 벡터)
- 내부적으로 문자열을 공백을 기준으로 단어로 나누고(파싱)
- 70억 단어 길이의 대규모 말뭉치 구글 뉴스에서 사전 훌년된 임베딩 행렬을 사용해 각 단어를 임베딩
- 모든 단어 임베딩의 평균 계산 (그 결과가 문장 임베딩)
이 모델은 영어에서 훈련 되었으나 다른 언어와 다국어 모델도 있다.
허깅 페이스에서 만든 오픈 소스 라이브러리인 트랜스포머를 사용하면 강력한 언어 모델의 구성 요소를 손쉽게 모델에 추가할 수 있다.
https://huggingface.co/docs/transformers/ko/index
허깅 페이스 허브에서 원하는 모델을 찾아 여기에서 제공하는 예제 코드를 사용할 수 있다. (예전에는 언어 모델만 제공했으나, 이제는 이미지 모델 등으로 확장되었다.)
이미지 전처리 층
케라스 전처리 API에는 세 개의 이미지 전처리 층이 포함되어 있다.
- tf.keras.layers.Resizing: 입력 이미지를 원하는 크기로 변경. tf.keras.layers.Resizing(height=100, width=200) ▶ 이미지 크기를 100 * 200 으로 바꿈. crop_to_aspect_ratio=True 로 설정하면 왜곡을 피하기 위해 목표 이미지 비율에 맞게 이미지 자름.
- tf.keras.layers.Rescaling: 픽셀값의 스케일 조정. Rescaling(scale=2/255, offset=-1)은 0~255 사이의 값을 -1~1 사이의 값으로 변경.
- tf.keras.layers.CenterCrop: 원하는 높이와 너비의 중간 부분만 유지하면서 이미지 자름.
from sklearn.datasets import load_sample_images
images = load_sample_images()["images"]
crop_image_layer = tf.keras.layers.CenterCrop(height=100, width=100)
cropped_images = crop_image_layer(images)
plt.imshow(images[1])
plt.axis("off")
plt.show()
plt.imshow(cropped_images[1] / 255)
plt.axis("off")
plt.show()
▶ 샘플 이미지를 로드한 후, 중앙 부분만 남도록 잘랐다.
※ 사이킷런의 load_sample_images() 함수를 사용하면 중국 사원 이미지와 꽃 이미지를 로드할 수 있다.
케라스는 RandomCrop, RandomFlip, RandomTranslation, RandomRotation, RandomZoom, RandomHeight, RandomWidth, RandomContrast와 같은 데이터 증식에 관한 층도 포함하고 있다.
이런 층들은 훈련 중에만 활성화되며 입력 이미지에 랜덤한 변형을 적용한다.
데이터 증식은 인공적으로 훈련 세트의 크기를 증가시켜 변형된 이미지가 실제 증식되지 않은 이미지처럼 보이는 한 종종 성능을 증가시킨다.
내부적으로 케라스 전처리 층은 텐서플로 저수준 API를 기반으로 한다. 케라스 전처리 API로 충분하지 않다면 텐서플로 저수준 API를 바로 사용할 수 있다.
케라스 전처리 층 | 텐서플로 저수준 API |
Normalization 층 | tf.nn.moments() 를 사용해 평균과 분산 계산 |
Discretization 층 | tf.raw_ops.Bucketize() 사용 |
CategoryEncoding 층 | tf.math.bincount() 사용 |
IntegerLookup, StringLookup 층 | tf.lookup() 사용 |
Hashing, TextVectorization 층 | tf.strings 패키지에 있는 여러 연산 사용 |
Embedding 층 | tf.nn.embedding_lookup() 사용 |
이미지 전처리 층 | tf.image 패키지에 있는 연산 사용 |
다음 내용
[출처]
핸즈 온 머신러닝
텐서플로 허브 라이브러리
허깅페이스 트랜스포머
'[파이썬 Projects] > <파이썬 딥러닝, 신경망>' 카테고리의 다른 글
[딥러닝] 합성곱 신경망을 사용한 컴퓨터 비전 (0) | 2024.11.27 |
---|---|
[딥러닝] 텐서플로 데이터셋 프로젝트 (0) | 2024.11.27 |
[딥러닝] 심층 신경망 훈련 - 4 (1) | 2024.11.26 |
[딥러닝] 텐서플로를 사용한 데이터 적재와 전처리 (0) | 2024.11.25 |
[딥러닝] 텐서플로 함수와 그래프 (0) | 2024.11.25 |