= 컨브넷(Convnet)
🔸 mnist로 컨브넷(+풀링) 살펴보기
import keras
from keras.datasets import mnist
from keras import layers
(train_images, train_labels), (test_images, test_labels) = mnist.load_data()
train_images = train_images.reshape((60000, 28, 28, 1))
train_images = train_images.astype("float32") / 255
test_images = test_images.reshape((10000, 28, 28, 1))
test_images = test_images.astype("float32") / 255
#----------------------------------#
inputs = keras.Input(shape=(28, 28, 1))
x = layers.Conv2D(filters=32, kernel_size=3, activation="relu")(inputs) # == kernel_size=(3,3)
x = layers.MaxPooling2D(pool_size=2)(x)
x = layers.Conv2D(filters=64, kernel_size=3, activation="relu")(x)
x = layers.MaxPooling2D(pool_size=2)(x)
x = layers.Conv2D(filters=128, kernel_size=3, activation="relu")(x)
x = layers.Flatten()(x)
outputs = layers.Dense(10, activation="softmax")(x)
model = keras.Model(inputs=inputs, outputs=outputs)
#----------------------------------#
model.compile(optimizer="rmsprop",
loss="sparse_categorical_crossentropy",
metrics=["accuracy"])
model.fit(train_images, train_labels, epochs=5, batch_size=64)
model.summary()
test_loss, test_acc = model.evaluate(test_images, test_labels)
print(f"Test accuracy: {test_acc:.3f}")
Test accuracy: 0.992
Dense는 전역패턴(global)학습, Convnet은 지역패턴(local) 학습
학습된 패턴은 평행이동 불변
공간적 계층구조 학습
🔸 특성맵 입력
🔸 특성맵 출력 = 응답맵
합성곱으로 특성추출(위의 화면에서 convolved feature)한 filter가 model의 Conv2D에서 설정한 개수만큼 존재 = 합성곱커널(convolution kernel)
패치: 3x3 혹은 5x5의 크기의 윈도우가 특성맵 위를 슬라이딩하면서 특성을 추출할 때, 추출 값을 지닌 한 장의 필터
🔸 Conv2D층
layers.Conv2D(
filters,
kernel_size,
strides=(1, 1),
padding='valid',
activation=None,
use_bias=True,
두 번의 연속적인 윈도우 사이의 거리
이러한 이유로 합성곱 연산을 통해 출력된 특성맵(feature map)의 경우 일반적으로 ReLU 활성화 함수를 거치게 되며, ReLU 함수가 양의 값만을 활성화하여 특징을 좀 더 두드러지게 표현한다.
합성곱층(Convolutional Layer)과 유사하게 특성맵(feature map)의 차원을 다운 샘플링하여 연산량을 감소시키고 주요한 특징 벡터를 추출하여 학습을 효과적으로 하는 것
🔸 pooling을 하지 않으면?
🔸 pooling 종류
🔸 대부분의 ConvNet에서는 Avg Pooling이 아닌 Max Pooling 사용: 평균으로 할 경우 주요한 가중치를 갖는 value의 특성이 희미해질 수 있음
https://www.kaggle.com/competitions/dogs-vs-cats/data
🔸 colab 이용
import gdown
url = "https://drive.google.com/uc?id=1ipzN9okFFT3oieklsrfr6iUHzjPAbT9i"
gdown.download(url, "cats_and_dogs.tar")
!tar -xvf cats_and_dogs.tar
# 1. 캐글사용하기
!pip install kaggle --upgrade
# 2. 캐글사이트>Account>API>Create New API Token( 참고로 약관동의가 필요하므로 www.kaggle.com/c/dogs-vs-cats/rules에서 약관동의 후 API 다운로드하기)
# 3. API 다운로드한거 코랩에 업로드: 파일선택
from google.colab import files
files.upload()
# 4. (!mkdir).kaggle폴더만들기 (!cp)파일복사 (!chmod 600)보안설정
!mkdir ~/.kaggle
!cp kaggle.json ~/.kaggle/
!chmod 600 ~/.kaggle/kaggle.json
# 5. 데이터 내려받기 실행
!kaggle competitions download -c dogs-vs-cats
# 6. 압축 해제
!unzip -qq dogs-vs-cats.zip
!unzip -qq train.zip
import os,shutil,pathlib
original_dir = pathlib.Path('./data/train')
new_base_dir = pathlib.Path('./data/cats_vs_dogs')
def make_subset(subset_name, start_index, end_index):
for category in ('cat','dog'):
dir = new_base_dir / subset_name / category
os.makedirs(dir)
fnames = [f'{category}.{i}.jpg' for i in range(start_index, end_index)]
for fname in fnames:
shutil.copyfile(src= original_dir / fname, dst= dir / fname)
make_subset('train', start_index = 0, end_index = 1000)
make_subset('validation', start_index = 1000, end_index = 1500)
make_subset('test', start_index = 1500, end_index = 2500)
🔸 다른 방법
train_dir = './cats_and_dogs/train'
validation_dir = './cats_and_dogs/validation'
test_dir = './cats_and_dogs/test'
import os
# 훈련용 고양이 사진 디렉터리
train_cats_dir = os.path.join(train_dir, 'cats')
# 훈련용 강아지 사진 디렉터리
train_dogs_dir = os.path.join(train_dir, 'dogs')
# 검증용 고양이 사진 디렉터리
validation_cats_dir = os.path.join(validation_dir, 'cats')
# 검증용 강아지 사진 디렉터리
validation_dogs_dir = os.path.join(validation_dir, 'dogs')
# 테스트용 고양이 사진 디렉터리
test_cats_dir = os.path.join(test_dir, 'cats')
# 테스트용 강아지 사진 디렉터리
test_dogs_dir = os.path.join(test_dir, 'dogs')
from keras.utils import image_dataset_from_directory
train_dataset = image_dataset_from_directory(new_base_dir / 'train',
image_size=(180,180),
batch_size=32)
validation_dataset = image_dataset_from_directory(new_base_dir / 'validation',
image_size=(180,180),
batch_size=32)
test_dataset = image_dataset_from_directory(new_base_dir / 'test',
image_size=(180,180),
batch_size=32)
🔸 다른 방법
import keras
import scipy
from keras import layers
from keras.preprocessing.image import ImageDataGenerator
# 모든 이미지를 1/255 부동소수점으로 스케일을 조정
train_datagen = ImageDataGenerator(rescale=1./255)
validation_datagen = ImageDataGenerator(rescale=1./255)
test_datagen = ImageDataGenerator(rescale=1./255)
train_generator = train_datagen.flow_from_directory(
train_dir, # 타깃 디렉터리
target_size=(150, 150), # 모든 이미지를 150 × 150 크기로
batch_size=20, # 20개씩 배치로 생산
class_mode='binary') # 이진 레이블. 만약 다중클래스라면 'categorical'
validation_generator = validation_datagen.flow_from_directory(
validation_dir,
target_size=(150, 150),
batch_size=20,
class_mode='binary')
test_generator = test_datagen.flow_from_directory(
test_dir,
target_size=(150, 150),
batch_size=20,
class_mode='binary')
inputs= keras.Input(shape=(180,180,3))
x = layers.Rescaling(1./255)(inputs) #스케일 조정
x = layers.Conv2D(filters=32, kernel_size=3, activation='relu')(x)
x = layers.MaxPooling2D(pool_size=2)(x)
x = layers.Conv2D(filters=64, kernel_size=3, activation='relu')(x)
x = layers.MaxPooling2D(pool_size=2)(x)
x = layers.Conv2D(filters=128, kernel_size=3, activation='relu')(x)
x = layers.MaxPooling2D(pool_size=2)(x)
x = layers.Conv2D(filters=256, kernel_size=3, activation='relu')(x)
x = layers.MaxPooling2D(pool_size=2)(x)
x = layers.Conv2D(filters=256, kernel_size=3, activation='relu')(x)
x = layers.Flatten()(x)
outputs = layers.Dense(1, activation='sigmoid')(x)
model = keras.Model(inputs=inputs, outputs=outputs)
model.compile(loss='binary_crossentropy',
optimizer='rmsprop',
metrics=['accuracy'])
model.summary()
callbacks = [keras.callbacks.ModelCheckpoint(
filepath='convnet_from_scratch.keras',
save_best_only=True,
monitor='val_loss')]
history = model.fit(train_dataset, epochs=30,
validation_data=validation_dataset,
callbacks=callbacks)
🔸 그래프로 확인
import matplotlib.pyplot as plt
accuracy = history.history["accuracy"]
val_accuracy = history.history["val_accuracy"]
loss = history.history["loss"]
val_loss = history.history["val_loss"]
epochs = range(1, len(accuracy) + 1)
plt.plot(epochs, accuracy, "bo", label="Training accuracy")
plt.plot(epochs, val_accuracy, "b", label="Validation accuracy")
plt.title("Training and validation accuracy")
plt.legend()
plt.figure()
plt.plot(epochs, loss, "bo", label="Training loss")
plt.plot(epochs, val_loss, "b", label="Validation loss")
plt.title("Training and validation loss")
plt.legend()
plt.show()
🔸 모델평가
test_model = keras.models.load_model('convnet_from_scratch.keras')
test_loss, test_acc = test_model.evaluate(test_dataset)
print(f'정확도: {test_acc:.3f}')
정확도: 0.702
🔸 Sequential모델로 데이터 증식층 정의
data_augmentation = keras.Sequential([
layers.RandomFlip('horizontal'),
layers.RandomRotation(0.1),
layers.RandomZoom(0.2)
])
- 참고: 사진 확인
plt.figure(figsize=(10,10))
for image, _ in train_dataset.take(1):
for i in range(9):
a_image = data_augmentation(image)
ax = plt.subplot(3,3,i+1)
plt.imshow(a_image[0].numpy().astype('uint8'))
plt.axis('off')
🔸 모델 재 정의(데이터증식+Dropout)
inputs= keras.Input(shape=(180,180,3))
x = data_augmentation(inputs) #데이터증식
x = layers.Rescaling(1./255)(inputs)
x = layers.Conv2D(filters=32, kernel_size=3, activation='relu')(x)
x = layers.MaxPooling2D(pool_size=2)(x)
x = layers.Conv2D(filters=64, kernel_size=3, activation='relu')(x)
x = layers.MaxPooling2D(pool_size=2)(x)
x = layers.Conv2D(filters=128, kernel_size=3, activation='relu')(x)
x = layers.MaxPooling2D(pool_size=2)(x)
x = layers.Conv2D(filters=256, kernel_size=3, activation='relu')(x)
x = layers.MaxPooling2D(pool_size=2)(x)
x = layers.Conv2D(filters=256, kernel_size=3, activation='relu')(x)
x = layers.Flatten()(x)
x = layers.Dropout(0.5)(x) #과대적합 더 억제
outputs = layers.Dense(1, activation='sigmoid')(x)
model = keras.Model(inputs=inputs, outputs=outputs)
model.compile(loss='binary_crossentropy',
optimizer='rmsprop',
metrics=['accuracy'])
🔸 모델 재 훈련
callbacks = [keras.callbacks.ModelCheckpoint(
filepath="convnet_from_scratch_with_augmentation.keras",
save_best_only=True,
monitor="val_loss")]
history = model.fit(
train_dataset,
epochs=40, #교재는 100
validation_data=validation_dataset,
callbacks=callbacks)
🔸 모델 평가
test_model = keras.models.load_model('convnet_from_scratch_with_augmentation.keras')
test_loss, test_acc = test_model.evaluate(test_dataset)
print(f'정확도: {test_acc:.3f}')
정확도: 0.729
→ 참고: epochs=100으로 했을때(교재), 약 90%
** 이미지 출처