반응형
오늘은 딥러닝 모델을 생성할 때 많이 사용하는 Python 라이브러리 중 Tensorflow의 기본 동작 원리와 코드, Tensorflow 2.0에서는 어떻게 변화하였는지에 대해 살펴보도록 하겠습니다!
텐서플로 1 코드를 텐서플로 2로 바꿔보자
여전히 텐서플로 1.X 버전의 코드를 수정하지 않고 텐서플로 2.0에서 실행할 수 있습니다(contrib 모듈은 제외):
import tensorflow.compat.v1 as tf
tf.disable_v2_behavior()
→ contrib 모듈의 경우 각 함수에 맞게 대체 가능한 모듈 찾아서 변경하기 (이 부분이 조금 귀찮음)
텐서플로 1 vs 2 동작원리 살펴보기
1. 텐서플로 1.x 코드
import tensorflow as tf # v1
# 1. tf.placeholder를 사용하여 그래프에 입력할 값의 형태를 미리 지정한다.
in_a = tf.placeholder(dtype=tf.float32, shape=(2))
in_b = tf.placeholder(dtype=tf.float32, shape=(2))
# 2. 그래프 생성
def forward(x):
# tf.get_variable을 사용하여 변수를 생성하고 tf.variable scope로 그 범위를 지정한다.
with tf.variable_scope("matmul", reuse=tf.AUTO_REUSE):
W = tf.get_variable("W", initializer=tf.ones(shape=(2,2)),
regularizer=tf.contrib.layers.l2_regularizer(0.04))
b = tf.get_variable("b", initializer=tf.zeros(shape=(2)))
return W * x + b
out_a = forward(in_a)
out_b = forward(in_b)
reg_loss = tf.losses.get_regularization_loss(scope="matmul")
# 3. tf.Session.run을 이용하여 그래프를 실행한다.
# The value returned by run() has the same shape as the fetches argument.
# feed_dict을 이용하여 placeholder의 실제 입력값을 넣는다.
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
outs = sess.run([out_a, out_b, reg_loss], # fetches
feed_dict={in_a: [1, 0], in_b: [0, 1]})
2. 텐서플로 2.x 코드로 변경
import tensorflow as tf # v2
# tf.variable_scope 사용하지 않음
W = tf.Variable(tf.ones(shape=(2,2)), name="W")
b = tf.Variable(tf.zeros(shape=(2)), name="b")
@tf.function
def forward(x):
return W * x + b
# tf.placeholder & tf.Session.run를 사용하지 않음
# Session.run 대신 실제 입력값의 단순 함수 호출로 변경(즉시 실행가능)
out_a = forward([1,0])
out_b = forward([0,1])
regularizer = tf.keras.regularizers.l2(0.04)
reg_loss = regularizer(W)
: TensorFlow 2 패키지에는 pip 버전 >19.0이 필요합니다. (https://www.tensorflow.org/install)
결론
source: https://www.tensorflow.org/guide/migrate#결론
전체적인 과정은 다음과 같습니다:
- 업그레이드 스크립트를 실행하세요.
- contrib 모듈을 삭제하세요.
- 모델을 객체 지향 스타일(케라스)로 바꾸세요.
- 가능한 **[tf.keras](<https://www.tensorflow.org/api_docs/python/tf/keras>)**나 **[tf.estimator](<https://www.tensorflow.org/api_docs/python/tf/estimator>)**의 훈련과 평가 루프를 사용하세요.
- 그렇지 않으면 사용자 정의 루프를 사용하세요. 세션과 컬렉션은 사용하지 말아야 합니다.
텐서플로 2.0 스타일로 코드를 바꾸려면 약간의 작업이 필요하지만 다음과 같은 장점을 얻을 수 있습니다:
- 코드 라인이 줄어 듭니다.
- 명료하고 단순해집니다.
- 디버깅이 쉬워집니다.
텐서플로 2 | Basic Model 만들어보자
→ tensorflow2라고 쓰고 tf.keras 라고 읽는다.
참고: https://www.tensorflow.org/guide/keras
- 아래의 tensorflow2 모델은 이미지 분류를 예시로 작성하였습니다.
1. dataset 생성하기
- 여러 방법이 있지만 2가지만 소개합니다.
import tensorflow as tf
# Case 1
## ex,
## x_train = [train_data_dir/file1.jpg, train_data_dir/file2.jpg, train_data_dir/file3.jpg, ...]
## y_train = [class1, class1, class2, ...]
train_dataset = tf.data.Dataset.from_tensor_slices((x_train, y_train))
# 필요에 따라 map_func 사용할 수 있음 (ex, 이미지 read, resize, ...)
train_dataset = train_dataset.map(lambda item1, item2: tf.numpy_function(
map_func, [item1, item2], [tf.float32, tf.float32]))
# Shuffle and batch
train_dataset = train_dataset.shuffle(BUFFER_SIZE, seed=2021).batch(BATCH_SIZE)
train_dataset = train_dataset.prefetch(BUFFER_SIZE//2)
# Case 2
## ex, train_data_dir/class1/file1.jpg, train_data_dir/class1/file2.jpg, train_data_dir/class2/file3.jpg, ...
train_dataset = tf.keras.preprocessing.image_dataset_from_directory(train_data_dir,
seed=2021,
image_size=(img_height, img_width),
batch_size=batch_size)
# class name 찾을 수 있음
class_names = train_dataset.class_names
train_dataset = train_dataset.cache().prefetch(BUFFER_SIZE//2)
2. model 생성하기
2.1 함수형
import tensorflow as tf
class_num = 5
def create_image_classification_model(input_shape):
# 아래의 구조의 경우, tf.keras.Model 대신 tf.keras.models.Sequential 사용 가능
# 다만, 다중 입력 및 출력, residual connection, attention 등 Model function이 활용성이 더 높음
model_input = tf.keras.Input(shape=input_shape)
embedding = tf.keras.layers.Conv2D(2, 3, padding='same', activation='relu')(model_input)
embedding = tf.keras.layers.GlobalAveragePooling2D()(embedding)
embedding = tf.keras.layers.Dense(128, activation='relu')(embedding)
embedding = tf.keras.layers.Dropout(0.2)(embedding)
embedding = tf.keras.layers.Dense(class_num, activation='softmax', name='output')(embedding)
return tf.keras.Model(model_input, embedding, name='image_classification_model')
input_shape = (256, 256, 3)
classification_model = create_image_classification_model(input_shape)
## sample test
temp_input = tf.random.uniform(input_shape, dtype=tf.float32, minval=0, maxval=256)
output = classification_model.predict(tf.expand_dims(temp_input, 0))
output.shape # (1, 5)
# model architecture(shape) & params 확인
classification_model.summary()
## (구조가 더 복잡한 경우,) model architecture(shape) ploting하여 확인 가능
# tf.keras.utils.plot_model(classification_model, "image_classification_model.png", show_shapes=True)
2.2 클래스 상속
- 모델 subclassing API 가이드
- https://www.tensorflow.org/guide/keras/custom_layers_and_models
import tensorflow as tf
class_num = 5
class ClassificationModel(tf.keras.Model):
def __init__(self, class_num, dim=128, rate=0.1):
super(ClassificationModel, self).__init__()
self.conv2d = tf.keras.layers.Conv2D(2, 3, padding='same', activation='relu')
self.dense1 = tf.keras.layers.Dense(dim, activation='relu')
self.dense2 = tf.keras.layers.Dense(class_num, activation='softmax', name='output')
self.gapooling = tf.keras.layers.GlobalAveragePooling2D()
self.dropout = tf.keras.layers.Dropout(rate)
def call(self, inputs):
embedding = self.conv2d(inputs)
embedding = self.gapooling(embedding)
embedding = self.dense1(embedding)
embedding = self.dropout(embedding)
embedding = self.dense2(embedding)
return embedding
input_shape = (256, 256, 3)
classification_model = ClassificationModel(class_num=class_num, rate=0.2)
## sample test
temp_input = tf.random.uniform(input_shape, dtype=tf.float32, minval=0, maxval=256)
output = classification_model(tf.expand_dims(temp_input, 0))
output.shape # TensorShape([1, 5])
# model architecture & params 확인
classification_model.build((None, 256, 256, 3))
classification_model.summary()
3. model 훈련하기
classification_model.compile(optimizer='adam',
loss=tf.keras.losses.CategoricalCrossentropy(from_logits=False),
metrics=['categorical_accuracy'])
history = classification_model.fit(train_dataset,
epochs=EPOCHS,
validation_data=val_dataset,
callbacks=[modelcheck],) # callbacks: modelcheckpoint, etc
- 시각화하기
source: https://www.tensorflow.org/tutorials/images/classificationimport matplotlib.pyplot as plt acc = history.history['accuracy'] val_acc = history.history['val_accuracy'] loss=history.history['loss'] val_loss=history.history['val_loss'] epochs_range = range(EPOCHS) plt.figure(figsize=(8, 8)) plt.subplot(1, 2, 1) plt.plot(epochs_range, acc, label='Training Accuracy') plt.plot(epochs_range, val_acc, label='Validation Accuracy') plt.legend(loc='lower right') plt.title('Training and Validation Accuracy') plt.subplot(1, 2, 2) plt.plot(epochs_range, loss, label='Training Loss') plt.plot(epochs_range, val_loss, label='Validation Loss') plt.legend(loc='upper right') plt.title('Training and Validation Loss') plt.show()
4. model save & load, predict 하기
model_save_path = 'image_classification_model'
# model architecture & weight 저장
classification_model.save(model_save_path)
# model architecture & weight 불러오기
new_model = tf.keras.models.load_model(model_save_path)
# new_model.trainable = False # transfer learning시 pre-trained model을 freezing할 때 사용, layer별로 설정 가능
# 불러온 모델 predict
y_pred = new_model.predict(test_dataset,
steps=STEP_SIZE_TEST
)
반응형
'PYTHON으로 딥러닝하기' 카테고리의 다른 글
Python으로 딥러닝하기|자연어 2. 단어 임베딩, Word2Vec (0) | 2021.11.04 |
---|---|
현업에서 많이 사용하는 Python 모듈 | Pytorch 튜토리얼 (0) | 2021.08.26 |
Tensorflow serving(Rest API) with Docker (0) | 2020.12.08 |
Python으로 딥러닝하기|LSTM(RNN) Part1&2. 이론 및 실습 (1) | 2019.06.25 |
Python으로 딥러닝하기|RNN(Recurrent Neural Networks) Part1. 이론 (0) | 2019.05.14 |