- 완전 쌩 이미지를 이용하여 CNN 모델을 만들어보자
- 현재 노트북 환경(NoneGPU)이기 때문에 Colab을 사용할 것임
이미지 준비
- kaggle에서 이미지를 가져온다.
- kaggle 을 사용하려면 토큰이 필요함
- Account>API에서 CreateNewToken으로 .json 다운
- colab에 업로드
import os
os.environ['KAGGLE_CONFIG_DIR'] = '/content/'
!kaggle competitions download -c dogs-vs-cats-redux-kernels-edition
압축해제
!unzip -q train.zip -d .
데이터셋 만들기
- 데이터셋 폴더 만들기
import os
import tensorflow as tf
import shutil
print(len(os.listdir('/content/train/')))
for i in os.listdir('/content/train'):
if 'cat' in i:
shutil.copyfile('/content/train/'+i, '/content/dataset/cat/'+i)
if 'dog' in i:
shutil.copyfile('/content/train/'+i, '/content/dataset/dog/'+i)
train_ds = tf.keras.preprocessing.image_dataset_from_directory(
'/content/dataset',
image_size=(64,64),
batch_size=64,
subset='training',
validation_split=0.2,
seed=1234
)
val_ds = tf.keras.preprocessing.image_dataset_from_directory(
'/content/dataset',
image_size=(64,64),
batch_size=64,
subset='validation',
validation_split=0.2,
seed=1234
)
print(train_ds)
- 클래스가 2개가 아닌 3개가 나온다.
- 전처리로 처리해보자
전처리 및 모델만들기
- 폴더 일단 비우기
- 리눅스 명령어로 다시 만들기
os.mkdir('/content/dataset')
os.mkdir('/content/dataset/cat')
os.mkdir('/content/dataset/dog')
- 다시 처리하고 결과
- Dropout(0.n) : 오버피팅방지를 위해 레이어 하나 추가해봄.
model = tf.keras.Sequential([
tf.keras.layers.Conv2D(32, (3,3), padding="same",activation='relu', input_shape=(64,64,3)),
tf.keras.layers.MaxPooling2D( (2,2) ),
tf.keras.layers.Conv2D(64, (3,3), padding="same",activation='relu'),
tf.keras.layers.MaxPooling2D( (2,2) ),
tf.keras.layers.Dropout(0.2),
tf.keras.layers.Conv2D(128, (3,3), padding="same",activation='relu'),
tf.keras.layers.MaxPooling2D( (2,2) ),
tf.keras.layers.Dense(128, activation="relu"),
tf.keras.layers.Flatten(),
tf.keras.layers.Dense(1, activation="softmax")
])
model.summary()
model.compile(loss="binary_crossentropy", optimizer="adam", metrics=['accuracy'])
model.fit(train_ds, validation_data=val_ds, epochs=5)
- 너무 느리다..
- 데이터 전처리를 안해서 느린것임
전처리
train_ds = tf.keras.preprocessing.image_dataset_from_directory(
'/content/dataset',
image_size=(64,64),
batch_size=64,
subset='training',
validation_split=0.2,
seed=1234
)
val_ds = tf.keras.preprocessing.image_dataset_from_directory(
'/content/dataset',
image_size=(64,64),
batch_size=64,
subset='validation',
validation_split=0.2,
seed=1234
)
print(train_ds)
def 전처리함수(i, 정답):
i = tf.cast(i/255.0, tf.float32)
return i, 정답
train_ds = train_ds.map(전처리함수)
val_ds = val_ds.map(전처리함수)
for i, 정답 in train_ds.take(1):
print(i)
print(정답)
plt.imshow(i[0].numpy().astype('uint8'))
plt.show()
model = tf.keras.Sequential([
tf.keras.layers.Conv2D(32, (3,3), padding="same",activation='relu', input_shape=(64,64,3)),
tf.keras.layers.MaxPooling2D( (2,2) ),
tf.keras.layers.Conv2D(64, (3,3), padding="same",activation='relu'),
tf.keras.layers.MaxPooling2D( (2,2) ),
tf.keras.layers.Dropout(0.2),
tf.keras.layers.Conv2D(128, (3,3), padding="same",activation='relu'),
tf.keras.layers.MaxPooling2D( (2,2) ),
tf.keras.layers.Dense(128, activation="relu"),
tf.keras.layers.Flatten(),
tf.keras.layers.Dense(1, activation="softmax")
])
model.summary()
model.compile(loss="binary_crossentropy", optimizer="adam", metrics=['accuracy'])
model.fit(train_ds, validation_data=val_ds, epochs=1)
결과
pb, ckpt 저장하기
- 체크포인트로 저장하기
- 교육을 이어하 할 수 있게 해줌
방법
model.save('./model1')
- pb 파일로 모델 전체가 폴더내에 저장된다.
- 모델 불러오기
불러온모델 = tf.keras.models.load_model('./model1')
불러온모델.summary()
불러온모델.evaluate(testX,testY)
- ckpt :w값만 저장
- ckpt는 epoch 완료시 (중간중간에) 저장 가능.
import tensorflow as tf
import numpy as np
(trainX, trainY), (testX, testY) = tf.keras.datasets.fashion_mnist.load_data()
trainX = trainX / 255.0
testX = testX / 255.0
trainX = trainX.reshape( (trainX.shape[0], 28,28,1) )
testX = testX.reshape( (testX.shape[0], 28,28,1) )
model = tf.keras.Sequential([
tf.keras.layers.Flatten(),
tf.keras.layers.Dense(128, activation='relu'),
tf.keras.layers.Dense(10, activation='softmax'),
])
콜백함수 = tf.keras.callbacks.ModelCheckpoint(
filepath='ckpt/mnnist',
monitor='val_acc',
mode='max',
save_weights_only=True,
save_freq='epoch'
)
model.compile(loss='sparse_categorical_crossentropy', optimizer='adam', metrics=['acc'])
model.fit(trainX, trainY, validation_data=(testX, testY), epochs=3, callbacks=[콜백함수])
model.evaluate(testX,testY)
model2 = tf.keras.Sequential([
tf.keras.layers.Flatten( input_shape=(28,28,1) ),
tf.keras.layers.Dense(128, activation='relu'),
tf.keras.layers.Dense(10, activation='softmax'),
])
model2.summary()
model2.compile(loss='sparse_categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
model2.load_weights('ckpt/mnnist')
model2.evaluate(testX,testY)
이미지 증강
- 이미지 비틀기, 이미지 수 뻥튀기
- 효과 : 오버피팅 방지효과, 정확도 상승
- 방법
- 증강데이터 사본 생성
- 초기데이터 적으면 효과 X
- 초기데이터 너무 많으면 X
- 모델에 넣기 전에 이미지 증강
모델에 넣기 전에 이미지 증강
...
model = tf.keras.Sequential([
tf.keras.layers.experimental.preprocessing.RandomFlip('horizontal', input_shape=(64,64,3)),
tf.keras.layers.experimental.preprocessing.RandomRotation(0.1),
tf.keras.layers.experimental.preprocessing.RandomZoom(0.1),
tf.keras.layers.Conv2D(32, (3,3), padding="same",activation='relu'),
tf.keras.layers.MaxPooling2D( (2,2) ),
...
imageDataGenerator : tensorflow 정통방식 이미지 증강
- 코드
- 이미지를 생성할때부터 꼬아서 만든다.
- class_mode : 두개면 binary, 몇개더면 categorical
- train은 만드는데, val은 안 뒤틀어도 됨.
테스트 자동화
TensorBoard 확인
- 텐서보드를 이용하여 log 파일 받아오기(시간도 적었음)
...
model = tf.keras.Sequential([
tf.keras.layers.Flatten(),
tf.keras.layers.Dense(128, activation='relu'),
tf.keras.layers.Dense(10, activation='softmax'),
])
model.compile(loss='sparse_categorical_crossentropy', optimizer='adam', metrics=['acc'])
from tensorflow.keras.callbacks import TensorBoard
import time
tensorboard = TensorBoard( log_dir= 'logs/{}'.format('첫모델'+str(int(time.time()))))
model.fit(trainX, trainY, validation_data=(testX, testY), epochs=3, callbacks=[tensorboard])
...
log 열어보기
%load_ext tensorboard
%tensorboard --logdir logs
모델 함수화 하기
def 모델만들기(덴스값):
model = tf.keras.Sequential([
tf.keras.layers.experimental.preprocessing.RandomFlip('horizontal', input_shape=(64,64,3)),
tf.keras.layers.experimental.preprocessing.RandomRotation(0.1),
tf.keras.layers.experimental.preprocessing.RandomZoom(0.1),
tf.keras.layers.Conv2D(32, (3,3), padding="same",activation='relu'),
tf.keras.layers.MaxPooling2D( (2,2) ),
tf.keras.layers.Conv2D(64, (3,3), padding="same",activation='relu'),
tf.keras.layers.MaxPooling2D( (2,2) ),
tf.keras.layers.Dropout(0.2),
tf.keras.layers.Conv2D(128, (3,3), padding="same",activation='relu'),
tf.keras.layers.MaxPooling2D( (2,2) ),
tf.keras.layers.Dense(덴스값, activation="relu"),
tf.keras.layers.Flatten(),
tf.keras.layers.Dense(1, activation="softmax")
])
return model
NEW_model = 모델만들기(128)
EarlyStopping
- 더 이상 진전이 없을 경우 epoch 알아서 스탑
tensorboard = TensorBoard( log_dir= 'logs/{}'.format('첫모델'+str(int(time.time()))))
from tensorflow.keras.callbacks import EarlyStopping
es = EarlyStopping(monitor='val_accuracy', patience=5, mode='max')
model.fit(trainX, trainY, validation_data=(testX, testY), epochs=3, callbacks=[tensorboard, es])
Sequential 말고 FunctionalAPI
- 레이어를 유연하게 연결가능
- 일단 모델 미리 보기 함수_plot_model
레이어 함수화
input1 = tf.keras.layers.Input(shape=[28,28])
flatten1 = tf.keras.layers.Flatten()(input1)
dense1 = tf.keras.layers.Dense(28*28, activation='relu')(flatten1)
reshape1= tf.keras.layers.Reshape((28,28))(dense1)
concat1 = tf.keras.layers.Concatenate()([input1,reshape1])
flatten2 = tf.keras.layers.Flatten()(concat1)
output = tf.keras.layers.Dense(10,activation='softmax')(flatten2)
model = tf.keras.Model(input1, output)
model.compile(loss='sparse_categorical_crossentropy', optimizer='adam', metrics=['acc'])
from tensorflow.keras.utils import plot_model
plot_model(model, to_file='model.png', show_shapes=True,show_layer_names=True)
- 결과를 이렇게 볼 수 있다.
- 함수화 하면 이렇게 유연하게 레이어를 붙였다 땠다 할수 있다.
- 데이터 쉐잎이 잘 꼬이니까 잘 만져주기
전이학습
- 모델을 배껴서 사용하자~
- 구글모델은 심지어 오픈소스!!
- 실무자들도 다 사용한다.
- 모델사용 방법
- 전부쓰기(GoogleNet을 쓰면 1천개 사진 분류가능)
- 일부레이어만 씀 (구글이 학습했던 Conv 레이어만 사용)
- 결과 : 너무 사기적이다.. 교육 몇시간 돌린거보다 훨씬좋은 데이터가 나와버렸다. (에포크1회가 무슨 ac:0.97가 나오냐