GOAL
- overfitting 을 피하기 위한 dropout 효과를 주는 keras layer type 을 마스터 해보자 !
- keras API 를 통해 transfer learning 을 해보자.
- Sequential mdoel 대신 keras functional API 로 모델을 코딩해보자.
- 성공적인 transfer learning 을 구현하기 위해 존재하는 모델로 부터 later 를 freeze 하는 방법을 알아보자.
- 대형 dataset으로 부터 학습된 다른 모델의 convolutions 를 사용하기 위한 transfer learning 개념 학습
L2 : Understanding transfer learning: the concepts
훨씬 많은 데이터로 학습된 모델을 활용하는 방법 :
transfer learning
Dense layer 만 새롭게 학습
시켜 사용하는 방법
( 실습 )
140만개의 데이터 셋을 1,000개의 class 로 분류하는imagenet
의 dataset 으로 훈련된inception
모델을 이용해 transfer learning 을 배워보자
import os
from tensorflow.keras import layers
from tensorflow.keras import Model
아래 링크에서 사전에 훈련해둔 가중치의 사본을 다운받을 수 있다.
keras 에는 inception_v3 모델이 내재되어 있다.
기존에 학습된 가중치를 이용하여 모델을 학습시켜 보자.
include_top
: inception_v3 상단에 있는 fully connected layer 를 사용할지에 대한 여부from tensorflow.keras.applications.inception_v3 import InceptionV3
local_wights_file = 'tmp/inception_v3_weights_tf_dim_ordering_tf_kernels_notop.h5'
pre_trained_model = InceptionV3(input_shape = ( 150,150,3 ),
include_top = False ,
weights = None )
for layer in pre_trained_model.layers:
layer.trainable = False
pre_trained_model.summary()
Now, you'll need to add your own DNN at the bottom of these, which you can retrain to your data.
pre-trained model 에 DNN 을 추가하여 학습하고자 하는 dataset 에 대한 분류 모델로 사용할 수 있다.
last_layer = pre_trained_model.get_layer('mixed7')
last_output = last_layer.output
from tensorflow.keras.optimizers import RMSprop
x = layers.Flatten()(last_output)
x = layers.Dense( 1024, activation = 'relu')(x)
x = layers.Dense( 1 , activation = 'sigmoid')(x)
model = Model( pre_trained_model.input , x )
model.compile( optimizer = RMSprop(learning_rate = 0.0001 ),
loss = 'binary_crossentropy',
metrics = ['acc'])
# Add our data-augmentation parameters to ImageDataGenerator
train_datagen = ImageDataGenerator( rescale = 1./255.,
rotation_range = 40,
width_shift_range = 0.2 ,
height_shift_range = 0.2 ,
shear_range = 0.2 ,
zoom_range = 0.2 ,
horizontal_flip = True )
flow_from_directory
로 데이터 얻기train_generator = train_datagen.flow_from_directory( train_dir,
batch_size = 20 ,
class_mode = 'binary',
target_size = (150,150))
history = model.fit(
train_generator ,
validation_data = validation_generator ,
steps_per_epoch = 100,
epochs = 100,
validation_steps = 50,
verbose = 2 )
이런 형태의 overfitting 을 방지하기 위해서는 어떻게 해야할까 ? :
dropout
: to remove a random number of neurons in your neural networkdropout
이overfitting
방지에 효과적인 이유
- 인접한 neuron들은 비슷한 weight 를 가져 overfitting 을 야기한다. random drop out 을 이용하면 해당 부분을 방지할 수 있다.
- neuron 은 이전 layer의 neuron 의 input 을 over-weight 하는 경향이 있어 overfitting 을 야기한다.
dropout
: neural network 에서 random 으로 몇몇 neuron 을 제거하는 것
- 인접한 neuron 들이 서로 영향을 주지 못하게 연결고리를 끊는다. →
overfitting
방지 효과
- 20% 의 확률로 dropout 하는 코드
x = layers.Dropout(0.2)(x)
from tensorflow.keras.optimizers import RMSprop
x = layers.Flatten()(last_output)
x = layers.Dense( 1024, activation='relu')(x)
x = layers.Dropout(0.2)(x) # 20%의 확률로 dropout
x = layers.Dense( 1 , activation = 'sigmoid')(x)
model = Model( pre_trained_model.input , x )
model.compile( optimizer = RMSprop(lr = 0.001) ,
loss = 'binary_crossentropy',
metrics = ['acc'])
C2_W3_Lab_1_transfer_learning 코드 보기
( 참고 )
예시 basemodel : InceptionV3
- 내 application 에 맞는
input shape
설정하기- output으로 사용할 것과 freeze 할 convolution layer 고르기 ( 이전 학습으로 부터 이점이 될만한 방향으로 생각해서 고르자 )
- train 시킬 dense layer 추가하기
from tensorflow.keras.applications.inception_v3 import InceptionV3
from tensorflow.keras import layers
# Set the weights file you downloaded into a variable
local_weights_file = '/tmp/inception_v3_weights_tf_dim_ordering_tf_kernels_notop.h5'
# Initialize the base model.
# Set the input shape and remove the dense layers
pre_trained_model = InceptionV3( input_shape = ( 150,150,3),
include_top = False ,
weights = None )
# Load the pre-trained weights you downloaded
pre_trained_model.load_weights(local_weights_filie)
# Freeze the weights of the layers.
for layer in pre_trained_model.layers
layer.trainable = False
pre_trained_model.summary()
- Inceptionnet_V3는 아주 깊은 모델이다.
- layer 가 깊어질수록 특정 데이터에 specialize 되기 때문에 , 강의에서는
mixed_7
layer 의 output value 를 사용한다.( todo )
output value 를 가져올 layer 의 이름을 바꾸면서 실험해보자 ! `
mixed_7
layer 확인# Choose 'mixed_7' as the last layer of your base model
last_layer = pre_trained_model.get_layer('mixed7')
print('last layer output shape : ' , last_layer.output_shape)
last_output = last_layer.output
from tensorflow.keras.optimizers import RMSprop
from tensorflow.keras import Model
# Flatten the output layer to 1 dimension
x = layers.Flatten()(last_output)
# Add a fully connected layer with 1,024 hidden units and ReLU activation
x = layers.Dense(1024,activation='relu')(x)
# Add a dropout rate of 0.2
x = layers.Dropout(0.2)(x)
# Add a final sigmoid layer for classificatoin
x = layers.Dense( 1, activation = 'sigmoid')(x)
# Append the dense network to the base model
model = Model(pre_trained_model.input,x)
# Print the model summary. See your dense network connected at the end.
model.summary()
# Set the training parameters
model.compile( optimizer = RMSprop( learning_rate = 0.0001) ,
loss = 'binary_crossentropy',
metrics = ['accuracy'])
ImageDataGenerator 를 이용하여 데이터를 준비해보자.
test_datagen
은 augmentation 을 적용하지 않음에 주의
import os
import zipfile
from tensorflow.keras.preprocessing.image import ImageDataGenerator
# Extract the archive
zip_ref = zipfile.ZipFile("./cats_and_dogs_filtered.zip", 'r')
zip_ref.extractall("tmp/")
zip_ref.close()
# Define our example directories and files
base_dir = 'tmp/cats_and_dogs_filtered'
train_dir = os.path.join( base_dir , 'train' )
validation_dir = os.path.join( base_dir , 'validation' )
# Directory with training cat pictures
train_cats_dir = os.path.join(train_dir , 'cats')
# Directory with training dog pictures
train_dogs_dir = os.path.join(train_dir,'dogs')
# Directory with validation cat pictures
validation_cats_dir = os.path.join( validation_dir , 'cats')
# Directory with validation dog pictures
validation_dogs_dir = os.path.join( validation_dir , 'dogs' )
# Add our data-augmentation parameters to ImageDataGenerator
train_datagen = ImageDataGenerator( rescale = 1./255.,
rotation_range = 40,
width_shift_range = 0.2,
height_shift_range = 0.2,
shear_range = 0.2,
zoom_range = 0.2,
horizontal_flip = True )
# Note that the validation data should not be augmented!
test_datagen = ImageDataGenerator( rescale = 1.0/255. )
# Flow training images in batches of 20 using train_datagen generator
train_generator = train_datagen.flow_form_directory( train_dir ,
batch_size = 20,
class_mode = 'binary',
target_size = ( 150,150) )
# Flow validation images in batches of 20 using test_datagen generator
validation_generator = test_datagen.flow_from_directory( validation_dir,
batch_size = 20 ,
class_mode = 'binary',
target_size = ( 150,150))
20 epochs 학습하고 plot 그려보기
# Train the model. history = model.fit( train_generator, validation_data = validation_generator, steps_per_epoch = 100, # 20*100 = 2,000 epochs = 20, validation_steps = 50 , verbose = 2 )
training accuracy 와 validation accuracy 를 그래프로 그려보자.
- validation accuracy 가 training accuracy 를 추종하는 면이 있다.
This is a good sign that your model is no longer overfitting!
import 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(len(acc))
plt.plot(epochs , acc , 'r', label = 'Training accuracy')
plt.plot(epochs , val_acc , 'b' , label = 'Validation accuarcy')
plt.title('Training and Validation accuracy')
plt.legend(loc = 0 )
plt.figure()
plt.show()
How did you lock or freeze a layer from retraining?
layer.trainable = false
Why do dropouts help avoid overfitting?
Because neighbor neurons can have similar weights, and thus can skew the final training
Week 3: Transfer Learning 코드 바로가기
Transfer learning
기존에 학습된 모델에 DNN 을 추가하여 가지고 있는 dataset 에 맞는 분류 모델을 생성하는 것
- overfitting 이 발생했을 때는
dropout
을 생각해보자.