앞선 글에서 구글 이미지 크롤링을 했다.
durian9s-coding-tree.tistory.com/56
드론과 새의 이미지를 크롤링하여 저장했는데, 필요없는 사진은 제거하고 1:9의 비율로 트레이닝 셋과 테스트 셋으로 나누었다.
CNN을 통한 드론/새 분류기를 만들어 보도록 하겠다.
CNN의 설명을 내가 잘하면 좋겠는데.. 설명을 잘 못하니까 정말 정리가 잘되어있는 블로그를 첨부하겠다.
라이브러리 import
import random
import tensorflow as tf
from tensorflow.keras.optimizers import RMSprop
from tensorflow.keras.preprocessing.image import ImageDataGenerator
from shutil import copyfile
import tensorflow as tf
from tensorflow.keras.datasets import fashion_mnist
import tensorflow.keras
from keras.models import Sequential
from keras.layers import Dense, Flatten, Dropout
from keras.optimizers import Adam
from keras.utils import np_utils
from keras.layers import Conv2D, MaxPool2D
model=Sequential()
model = Sequential()
model.add(Conv2D( filters =16, kernel_size= (2,2), activation= 'relu', input_shape=(512,512,3)))
model.add( MaxPool2D( 2 , 2 ) )
model.add( Conv2D ( 32,(3,3), activation='relu' ) )
model.add( MaxPool2D( 2 , 2 ) )
model.add( Conv2D ( 64,(3,3), activation='relu' ) )
model.add( MaxPool2D( 2 , 2 ) )
model.add( Flatten() )
model.add(Dense( units = 512, activation= 'relu'))
model.add(Dense( units = 128, activation= 'relu'))
model.add(Dense(units = 1, activation='sigmoid'))
모델을 구축해준다.
여기서 문제가 하나 생겼는데,, input shape가 일정해야 하는데 내 사진들은 제각각이었다.
도와줘요 구글님!
검색을 했더니 알씨로 일괄변경 하면 된다고 하여 512 x 512로 변경하였다.
model.summary()
model.summary를 통해 모델을 살펴보았다.
cnn을 할 때 더 효율적으로 학습하기 위해 이미지 증강도 해주었다.
그리고 모델 컴파일까지.
from keras.preprocessing.image import ImageDataGenerator
TRAINING_DIR = '/content/drive/MyDrive/Colab Notebooks/drone_bird/training'
train_datagen = ImageDataGenerator(rescale = 1/255.0,
rotation_range=40,
width_shift_range=0.2,
height_shift_range = 0.2,
shear_range = 0.2,
zoom_range = 0.2,
horizontal_flip = True,
vertical_flip = True,
fill_mode = 'nearest')
train_generator = train_datagen.flow_from_directory(TRAINING_DIR, batch_size = 10, class_mode = 'binary', target_size=(512,512))
VALIDATION_DIR = '/content/drive/MyDrive/Colab Notebooks/drone_bird/testing'
validation_datagen = ImageDataGenerator(rescale = 1/255.0)
validation_generator =validation_datagen.flow_from_directory(VALIDATION_DIR, batch_size = 10, class_mode = 'binary', target_size=(512,512))
model.compile(loss='binary_crossentropy',optimizer = RMSprop(lr=0.001), metrics=['accuracy'])
모델을 학습한다.
처음 학습을 시킬때는 집 컴퓨터로 작업을 해서 엄청 느렸고, 에포크를 15로 설정했다.
테스트의 정확성이 최대 68% 까지 나온다.
history = model.fit(train_generator,
epochs=15,
verbose=1,
validation_data = validation_generator)
이제 차트로 확인을 해보자.
def learning_curve(history, epoch):
# 정확도 차트
plt.figure(figsize = (10, 5))
epoch_range = np.arange(1, epoch + 1)
plt.subplot(1, 2, 1)
# history는 fit 결과값을 저장하는 변수
plt.plot( epoch_range, history.history["accuracy"])
plt.plot( epoch_range, history.history["val_accuracy"])
plt.title("Model Accuracy")
plt.xlabel("Epoch")
plt.ylabel("Accurach")
plt.legend( ["Train", "Val"] )
# loss 차트
plt.figure(figsize = (10, 5))
plt.subplot(1, 2, 2)
plt.plot( epoch_range, history.history["loss"])
plt.plot( epoch_range, history.history["val_loss"])
plt.title("Model Loss")
plt.xlabel("Epoch")
plt.ylabel("Loss")
plt.legend( ["Train", "Val"] )
plt.show()
learning_curve(history, 15)
에포크 15개로는 만족스럽지 못해서 피씨방으로 가서 epoch 75로 설정하고 새로 학습시켜봤다.
앞의 컴파일까지의 과정은 동일하므로 생략하고 학습 코드만 기록하겠다.
history = model.fit(train_generator,
epochs=75,
verbose=1,
validation_data = validation_generator)
ㅎㅎㅎ 에포크가 많다고 학습이 잘 되는것은 아니지만 73.42%까지 정확도가 높아졌다.
정확도 차트도 다시 확인해보자.
이 또한 에포크의 숫자만 달리하였기에 차트만 첨부한다.
그래프와 에포크 를 보게 되면 59번째 에포크에 정확도가 최대로 올라간 뒤 이후에는 계속 낮은 정확도를 보인다.
조금 더 공부를 하고나서 이미지를 넣으면 드론인지 아닌지 판별하는 코드를 사용해보겠다.
오늘도 재밌었다.
===================================================================
오류를 발견했다.
풀링의 경우 상관없지만 커널 사이즈는 (3,3)이나 (5,5)같이 홀수여야 하기 때문에 피씨방을 다시 방문했다.
왜 저것만 (2,2)로 했지..?
모델링부터 다시~
model=Sequential()
model = Sequential()
model.add(Conv2D( filters =16, kernel_size= (3,3), activation= 'relu', input_shape=(512,512,3)))
model.add( MaxPool2D( 2 , 2 ) )
model.add( Conv2D ( 32,(3,3), activation='relu' ) )
model.add( MaxPool2D( 2 , 2 ) )
model.add( Conv2D ( 64,(3,3), activation='relu' ) )
model.add( MaxPool2D( 2 , 2 ) )
model.add( Flatten() )
model.add( Dropout( 0.4 ) )
model.add(Dense( units = 512, activation= 'relu'))
model.add(Dense( units = 128, activation= 'relu'))
model.add(Dense(units = 1, activation='sigmoid'))
model.summary()
이미지 증강
from keras.preprocessing.image import ImageDataGenerator
TRAINING_DIR = '/content/drive/MyDrive/Colab Notebooks/drone_bird/training'
train_datagen = ImageDataGenerator(rescale = 1/255.0,
rotation_range=40,
width_shift_range=0.2,
height_shift_range = 0.2,
shear_range = 0.2,
zoom_range = 0.2,
horizontal_flip = True,
vertical_flip = True,
fill_mode = 'nearest')
train_generator = train_datagen.flow_from_directory(TRAINING_DIR, batch_size = 10, class_mode = 'binary', target_size=(512,512))
VALIDATION_DIR = '/content/drive/MyDrive/Colab Notebooks/drone_bird/testing'
validation_datagen = ImageDataGenerator(rescale = 1/255.0)
validation_generator =validation_datagen.flow_from_directory(VALIDATION_DIR, batch_size = 10, class_mode = 'binary', target_size=(512,512))
model.compile(loss='binary_crossentropy',optimizer = RMSprop(lr=0.001), metrics=['accuracy'])
학습
history = model.fit(train_generator,
epochs=75,
verbose=1,
validation_data = validation_generator)
적중률이 크게 높아졌다.
오류를 일찍발견해서 다행이다.ㅎㅎ
집에서는 CNN을 계속 못돌리니 모델을 저장하겠다.
from keras.models import load_model
model.save('bird_and_drone.h5')
파일이 생겼음.
나중에 언제라도 꺼내쓸 수 있다.
아 그리고 마지막으로
import numpy as np
from google.colab import files
from keras.preprocessing import image
uploaded = files.upload()
for fn in uploaded.keys():
# predicting images
path = '/content/drive/MyDrive/Colab Notebooks/drone_bird/' + fn
img = image.load_img(path, target_size=(512,512))
x = image.img_to_array(img)
x = np.expand_dims(x, axis=0)
images = np.hstack([x])
classes = model.predict(images, batch_size=10)
print(classes[0])
if classes[0]>0.5:
print(fn + " is a drone")
else:
print(fn + " is a bird")
이미지를 입력해서 사진이 새인지, 드론인지 판별하는 코드이다.
처음엔 위의 사진을 사용하려했는데 (512,512,3)으로 일괄 학습시켜서인지 (512,512,3)이 아니면 사용이 불가능했다.
그래서 늘렸다.
이미지의 크기가 다르기 때문인지는 모르지만 정확한 분류가 되진 않는 것 같다.
if classes[0]>0.5:
print(fn + " is a drone")
else:
print(fn + " is a bird")
이상으로 길었던 드론과 새를 구별하는 CNN을 마치도록 하겠다.
'미니프로젝트' 카테고리의 다른 글
OpecCV를 통해 차선 인식하기 (0) | 2021.04.20 |
---|---|
구글에서 파이썬 셀레니움을 통한 이미지 크롤링 (0) | 2021.04.02 |
SVM을 통해 구매 가능성이 있는 고객 분류하기 (0) | 2021.04.01 |
공항 기상 시각화 (0) | 2021.04.01 |
인천 1호선 일자 및 시간대별 승하차 현황 시각화/prophet을 통한 승객 수요 예측 (0) | 2021.04.01 |