출처 : https://www.kaggle.com/amadeus1996/fruits-360-transfer-learning-using-keras/data
Transfer Learning
(원래 코드는 Kaggle Kernels을 사용, 또한 현재 데이터는 업데이트됨)
import os
from os import listdir, makedirs
from os.path import join, exists, expanduser
cache_dir = expanduser((join('~','.keras'))
if not exists(cache_dir):
makedirs(cache_dir)
models_dir = join(cache_dir, 'models')
if not exists(models_dir):
makedirs(models_dir)
!cp ../input/keras-pretrained-models/*notop* ~/.keras/models
!cp ../input/keras-pretrained-models/imagenet_class_index.json ~/.keras/models/
!cp ../input/keras-pretrained-models/resnet50* ~/.keras/models
print("Available Pretrained Models:\n")
!ls ~/.keras/models
- expanduser : 입력받은 경로안의 '~'를 현재 사용자 디렉터리의 절대경로로 대체
- join : 해당 os 형식에 맞도록 입력받은 경로를 연결
- makedirs : 폴더/경로 생성 → 경로가 없는 경우 중간에 지정한 폴더 생성(mkdir과 비슷)
[결과]
Available Pretrained Models:
imagenet_class_index.json inception_resnet_v2_weights_tf_dim_ordering_tf_kernels_notop.h5 inception_v3_weights_tf_dim_ordering_tf_kernels_notop.h5 resnet50_weights_tf_dim_ordering_tf_kernels.h5 resnet50_weights_tf_dim_ordering_tf_kernels_notop.h5 vgg16_weights_tf_dim_ordering_tf_kernels_notop.h5 xception_weights_tf_dim_ordering_tf_kernels_notop.h5
from keras import applications
from keras.preprocessing.image import ImageDataGenerator
from keras import optimizers
from keras.models import Sequential, Model
from keras.layers import Dense, GlobalAveragePooling2D
from keras.layers import Activation, Dropout, Flatten, Dense
from keras import backend as K
import tensorflow as tf
Reading the Data
# dimensions of images
img_width, img_height = 224, 224 # The input size for ResNet-50 is (224,224,3)
train_data_dir = '../input/fruits/fruits-360_dataset_2018_06_03/fruits-360/Training/'
validation_data_dir = '../input/fruits/fruits-360-dataset_2018_06_03/fruits-360/Validation/'
nb_train_samples = 3168
nb_validation_samples = 10657
batch_size = 16
- train_data_dir, validation_data_dir : 데이터 저장 경로이기 때문에, 본인 경로에 맞게 쓰면 됨
- nb_train_samples : total number of train samples
- nb_validation_samples : total number of validation samples
train_datagen = ImageDataGenerator(rescale = 1./255,
shear_range = 0.2,
zoom_range = 0.2,
horizontal_flip=True)
test_datagen = ImageDataGenerator(rescale = 1./255)
train_generator = train_datagen.flow_from_director(train_data_dir,
target_size = (img_height, img_width),
batch_size = batch_size,
class_mode = 'categorical')
validation_generator = test_datagen.flow_from_director(validation_data_dir,
target_size=(img_height, img_width),
batch_size = batch_size,
class_mode = 'categorical')
Found 32426 images belonging to 65 classes.
Found 10903 images belonging to 65 classes.
ImageDataGenerator 클래스를 통해 객체를 생성할 때 파라미터를 전달해주는 것을 통해 데이터의 전처리를 쉽게 할 수 있다.
출처: https://3months.tistory.com/199 [Deep Play]
ImageDataGenerator
: 실시간 데이터 증강을 사용해서 텐서 이미지 데이터 배치를 생성
- rescale : 크기 재조절 인수. 디폴트 값은 None
- shear_range: 부동소수점. 층밀리기의 강도
- zoom_range : 무작위 줌의 범위, 부동소수점인 경우 [하한, 상한] = [1-zoom_range, 1+zoom_range]
- horizontal_flip: 불리언. 인풋을 무작위로 가로로 뒤집음
- 참고 : https://keras.io/ko/preprocessing/image/
ImageDataGenerator.flow_from_directory
: 폴더 형태로 된 데이터 구조를 바로 가져와서 사용 가능
Visualizing the Data
import pandas as pd
from plotly.offline import init_notebook_mode, iplot
import plotly.graph_objs as go
init_notebook_mode(conneted=True) # 이걸 써야 주피터 노트북에서 plotly 그림을 그릴 수 있음
training_data = pd.DataFrame(train_generator.classes, columns=['classes'])
testing_data = pd.DataFrame(validation_generator.classes, columns=['classes'])
def create_stack_bar_data(col, df):
aggregated = df[col].values_counts().sort_index() # 인덱스를 기준으로 정렬
x_values = aggregated.index.tolist()
y_value s= aggregated.values.tolist()
return x_values, y_values
x1, y1 = create_stack_bar_data('classes', training_data)
x1 = list(train_generator.class_indices.keys())
trace1 = go.Bar(x=x1, y=y1, opacity=0.75, name="Class Count")
layout = dict(height=400, widht=1200, title='Class Distribution in Training Data',
legend=dict(orientation='h')), yaxis=dict(title='Class Count'))
fig = go.Figure(data=[trace1], layout=layout)
iplot(fig)
go.Bar
- opacity : 불투명도 조절
- 출처 : https://plotly.com/python/marker-style/#opacity
x1, y1 = create_stack_Bar_data('classes', testing_data)
x1= list(validation_generator.class_indices.keys())
trace1 = go.Bar(x=x1, y=y1, opacity=0.75, name="Class Count")
layout = dict(hegiht=400, width=1100, title='Class Distribution in Validation Data',
legend=dict(orientation='h'), yaxis=dict(title='Class Count'))
fig = go.Figure(data=[trace1], layout=layout);
iplot(fig);
모든 클래스는 train, validation에서 균형이 잘 잡혀있다.
Building the Models
We remove the top so that we can add our own layer according to the number of our classes. We then add our own layers to complete the model architecture.
1. Pretrained Model
# import inception with pre-trained weights
inception_base = applications.ResNet50(weigths='imagenet', inclue_top=False)
# add a global spatial average pooling layer
x = inception_base.output
x = GlobalAveragePooling2D()(x)
# add a fully-connected layer
x = Dense(512, activation='relu')(x)
# and a fully connected output/classification layer
prediction = Dense(65, activation='softmax')(x)
# create the full network so we can train on it
inception_transfer = Model(inputs=inception_base.input, outputs=predictions)
ResNet50
: 대표적인 사전학습 모델
- 위의 코드를 보면 ResNet50을 사용한 ImageNet 분류라는 것을 알 수 있다.
- weights = 'imagenet' : ImageNet에 대한 선행학습 → ImageNet으로 훈련된 모델을 불러올 수 있다.
- inclued_top : network의 최상단에 fully connected layer를 넣을지 여부를 결정한다.
2. Vanilla Model
# import inception with pre-trained weights
inceptinos_base_vanilla = applications.ResNet50(weights=None, include_top=False)
# add a global spatial average pooling layer
x = inception_base_vanilla_output
x = GlobalAveragePooling2D()(x)
# add a fully-connected layer
x = Dense(512, activation='relu')(x)
# and a fully connected output/classification layer
predictions = Dense(65, activation='softmax')(x)
# create the fully network so we can train on it
inception_transfer_vanilla = Model(inputs=inceptino_base_vanilla.input, outpus=predictions)
Vanilla Model
: 오리지널 상태, 순수한 상태
- 어떤 모델을 사용할지 결정하기 위해
- 기준이 되는 모델로 사용하기 위해
- 출처 : https://lv99.tistory.com/30
Compiling the Models
inception_transfer.compile(loss='categorical_crossentropy',
optimizer=optimizers.SGD(lr=1e-4, momentum=0.9),
metrics=['accuracy'])
inception_transfer_vanilla.compile(loss='categorical_crossentropy',
optimizer=optimizers.SGD(lr=1e-4, momentum=0.9),
metrics=['accuracy'])
from tensorflow.python.client import device_lib
print(device_lib.list_local_devices())
[결과]
[name: "/device:CPU:0"
device_type: "CPU"
memory_limit: 268435456
locality {
}
incarnation: 5772340684690380691
, name: "/device:GPU:0"
device_type: "GPU"
memory_limit: 11145828762
locality {
bus_id: 1
links {
}
}
incarnation: 6102347138481656910
physical_device_desc: "device: 0, name: Tesla K80, pci bus id: 000
0:00:04.0, compute capability: 3.7"
]
device_lib
: Tensorflow에서 GPU 이용가능한지 여부를 따짐
출처 : https://needneo.tistory.com/43
Training and Validating the Pretrained Model
import tensorflow as tf
with tf.device("/device:GPU:0"):
history_pretrained = inception_transfer.fit_generator(
train_generator,
epochs=5, shuffle = True, verbose = 1, validation_data = validation_generator)
[결과]
Epoch 1/5
2027/2027 [==============================] - 1117s 551ms/step - loss: 1.1785 - acc: 0.7857 - val_loss: 0.1525 - val_acc: 0.9695
Epoch 2/5
2027/2027 [==============================] - 1100s 543ms/step - loss: 0.1199 - acc: 0.9800 - val_loss: 0.0530 - val_acc: 0.9819
Epoch 3/5
2027/2027 [==============================] - 1102s 544ms/step - loss: 0.0586 - acc: 0.9890 - val_loss: 0.0466 - val_acc: 0.9848
Epoch 4/5
362/2027 [====>.........................] - ETA: 13:30 - loss: 0.0465 - acc: 0.9900
with tf.device("/device:GPU:0"):
history_vanilla = inception_transfer_vanilla.fit_generator(
train_generator,
epochs=5, shuffle = True, verbose = 1, validation_data = validation_generator)
[결과]
Epoch 1/5
2027/2027 [==============================] - 1112s 549ms/step - loss: 2.6697 - acc: 0.3113 - val_loss: 0.8495 - val_acc: 0.7829
Epoch 2/5
2027/2027 [==============================] - 1103s 544ms/step - loss: 0.9162 - acc: 0.7384 - val_loss: 0.3252 - val_acc: 0.8996
Epoch 3/5
2027/2027 [==============================] - 1101s 543ms/step - loss: 0.4894 - acc: 0.8548 - val_loss: 0.1886 - val_acc: 0.9402
Epoch 4/5
2027/2027 [==============================] - 1102s 544ms/step - loss: 0.3215 - acc: 0.9062 - val_loss: 0.1548 - val_acc: 0.9454
Epoch 5/5
2027/2027 [==============================] - 1104s 545ms/step - loss: 0.2334 - acc: 0.9320 - val_loss: 0.0852 - val_acc: 0.9762
import matplotlib.pyplot as plt
# summarize history for accuracy
plt.plot(history_pretrained.history['val_acc'])
plt.plot(history_vanilla.history['val_acc'])
plt.title('model accuracy')
plt.ylabel('accuracy')
plt.xlabel('epoch')
plt.legend(['Pretrained', 'Vanilla'], loc='upper left')
plt.show()
# summarize history for loss
plt.plot(history_pretrained.history['val_loss'])
plt.plot(history_vanilla.history['val_loss'])
plt.title('model loss')
plt.ylable('loss')
plt.xlabel('epoch')
plt.legend(['Pretrained', 'Vanilla'], loc='upper left')
plt.show()
위 코드를 실행시키던 중 용량이 너무 커서 그런가, 중간에 계속 오류가 발생하고 제대로 실행이 안됐다.. 그리고 출처 코드의 dataset과 현재 dataset이 달라서 똑같이 나오는 것 같지는 않다. 다른 데이터로 다시 필사해야겠다.
'데이터 분석 > kaggle' 카테고리의 다른 글
[kaggle] Fashion MNIST 필사 ① (0) | 2021.08.31 |
---|---|
[kaggle] image classification 필사 목록 (0) | 2021.08.25 |
[kaggle] Statoil/C-CORE Iceberg Classifier Challenge(수정중) (0) | 2021.08.25 |
댓글