개발로 자기계발
728x90

CNN은 Convolutional Neural Network의 약자로, 이미지, 음성 등의 다양한 유형의 데이터를 처리하는 데 특화된 딥러닝 모델이다.

 

CNN은 일반적인 신경망과는 달리, 합성곱(Convolution)과 풀링(Pooling) 레이어를 사용하여 이미지의 특징을 추출한다.

이를 통해 공간 정보를 보존하면서 이미지 데이터를 처리할 수 있다.

 

합성곱 레이어는 이미지의 특징을 추출하는 역할을 수행한다. 필터(Filter) 또는 커널(Kernel)이라는 작은 윈도를 이미지의 픽셀 데이터에 대해 일정 간격으로 이동시키면서 합성곱을 계산한다.

이를 통해 이미지의 여러 특징(선, 모서리, 질감 등)을 추출하게 된다.

 

풀링 레이어는 합성곱 레이어를 통해 추출된 특징 맵의 크기를 줄이는 역할을 수행한다.


이러한 합성곱과 풀링 과정을 반복하여 이미지의 특징을 추출한 뒤, 마지막에는 일반적인 신경망에서와 같이 완전 연결층(Fully Connected Layer)을 사용하여 최종 출력을 계산한다.


GitHub 코드

https://github.com/seokcode/Simple_CNN_Model

 

seokcode/Simple_CNN_Model

개와 고양이 분류하는 CNN 모델 만들어보기. Contribute to seokcode/Simple_CNN_Model development by creating an account on GitHub.

github.com

자료는 여기서 참고!

훈련 데이터 set과 테스트 데이터 set은 데이터가 많아서 첨부가 안된다..

GitHub에서도 최대 1000장만 가능하다.

 

훈련 데이터 set 4000장

테시트 데이터 set 1000장


라이브러리 import

import tensorflow as tf
from keras.preprocessing.image import ImageDataGenerator

tensor flow사용 간에 주의점은 Python버전을 3.7 ~ 3.9를 지원하는데 3.8을 추천!

 

Tensor flow 버전 확인

tf.__version__

 

데이터 전처리

part1 - 훈련 데이터 set을 전처리한다.

# 이미지 데이터를 학습하기 전에 데이터 증강을 수행하는 코드
train_datagen = ImageDataGenerator(rescale = 1./255,    # 이미지의 픽셀값을 0과 1 사이의 값으로 조정
                                   shear_range = 0.2,    # 이미지를 변형시키는 시어링(Shearing) 강도를 지정(회전)
                                   zoom_range = 0.2,     # 이미지를 확대 또는 축소하는 줌(Zoom) 범위를 지정
                                   horizontal_flip = True)   # 이미지를 좌우로 뒤집는 수평방향 뒤집기를 수행

# flow_from_directory() 함수를 사용하여 디렉토리에서 이미지 데이터를 읽어와 배치(batch) 단위로 학습할 수 있도록 설정
training_set = train_datagen.flow_from_directory('dataset/training_set',   # 학습 데이터셋 디렉토리 경로를 지정
                                                 target_size = (64, 64),   # 이미지를 지정된 크기(64x64)로 리사이즈
                                                 batch_size = 32,          # 한 번에 학습할 배치(batch) 크기를 지정(이미지의 장수 32는 기본값)
                                                 class_mode = 'binary')     # 이진 분류(Binary classification) 문제로 설정

 

part2 - 테스트 데이터 set을 전처리한다.

test_datagen = ImageDataGenerator(rescale = 1./255)

test_set = test_datagen.flow_from_directory('dataset/test_set',
                                            target_size = (64, 64),
                                            batch_size = 32,
                                            class_mode = 'binary')

* 테스트 set은 이미지 증강을 해주지 않는 이유는?

테스트 셋에서는 데이터 증강(augmentation)을 수행하지 않는 이유는 모델의 일반화 성능을 평가하기 위해서다.

 

데이터 증강은 훈련 데이터셋을 늘리기 위해 사용하는 기술로, 이미지를 회전, 확대/축소, 이동, 반전 등의 다양한 방법으로 변형시켜 데이터의 다양성을 증가시키는 것이다.

이를 통해 모델이 좀 더 일반화된 특징을 학습하게 되며, 과적합(overfitting)을 방지할 수 있다.

반면에, 테스트 셋은 모델의 일반화 성능을 평가하는 데 사용되는 데이터셋이므로, 훈련 데이터와 최대한 비슷한 분포를 가져야 한다.

따라서, 테스트 셋에서 데이터 증강을 수행하게 되면, 테스트 데이터와 훈련 데이터 간의 분포 차이가 커지게 되어 모델의 성능 평가 결과가 왜곡될 수 있다.

따라서 테스트 셋에서는 데이터 증강을 수행하지 않고, 이미지의 크기를 조정하는 정도의 간단한 전처리만을 수행한다.

 

CNN 모델 빌딩

part1 - CNN 모델 초기화

# 각 레이어가 정확히 하나의 입력 텐서와 하나의 출력 텐서를 갖는 단일 입력 및 출력으로 간단한 모델을 만들 때 유용
# cnn 모델 초기화

cnn = tf.keras.models.Sequential()

 

part2 - 합성곱(Convolution): 이미지의 특징을 추출

# Sequential 모델에 컨볼루션 레이어를 추가 계층에는 커널 크기가 3x3인 32개의 필터가 있으며 사용된 활성화 함수는 ReLU
# 레이어의 입력 모양은 [64, 64, 3]이며 크기가 64x64이고 3개의 색상 채널(RGB)이 있는 입력 이미지

cnn.add(tf.keras.layers.Conv2D(filters=32, kernel_size=3, activation='relu', input_shape=[64, 64, 3]))

* relu 사용하는 이유: 입력 값이 0 이상일 때는 그대로 출력하고, 0 이하일 때는 0을 출력하는 함수

* 비선형성(Nonlinearity)을 도입하여, 모델이 더 복잡한 패턴을 학습할 수 있도록 돕는다.

* 그래서 주로 합성곱과 많이 쓰인다.

 

part3 - 풀링(Pooling): 합성곱(Convolution) 레이어의 출력 결과를 간소화하는 연산

# cnn에 최대 풀링 계층을 추가
# MaxPool2D 계층은 pool_size 및 strides 매개변수로 정의된 크기 창 내에서 최대값을 취하여 입력의 공간적 차원을 줄인다.
# 이 경우 pool_size=2는 풀링 작업에 2x2 윈도우가 사용됨을 의미하고 strides=2는 윈도우가 한 번에 2 단위 이동됨을 의미
# 이 계층의 출력은 입력의 다운샘플링된 버전이며 공간 차원은 2배로 줄었다.
# padding의 기본값은 valid이고 2칸씩 띄었을 때 없는 숫자 칸은 무시 할 수 있고
# padding의 same은 없는 숫자 칸은 0인 가짜 픽셀을 추가 한다.

cnn.add(tf.keras.layers.MaxPool2D(pool_size=2, strides=2))

 

part3 - 두 번째 합성곱 레이어 추가

cnn.add(tf.keras.layers.Conv2D(filters=32, kernel_size=3, activation='relu'))
# 풀링 연산을 수행하여 입력 이미지를 축소하는 레이어를 생성
cnn.add(tf.keras.layers.MaxPool2D(pool_size=2, strides=2))

 

part4 - 플래튼(Flattening): 입력된 다차원 배열을 1차원 벡터로 변환

# cnn에 평탄화 레이어를 추가
# Flatten 레이어는 이전 레이어의 출력을 가져와 완전 연결 레이어로 전달할 수 있는 1차원 배열로 변환
# 이는 일반적으로 이전 레이어에서 추출한 기능 간의 관계를 학습하고 모델링할 수 있는 네트워크에 조밀한 레이어를 추가하기 전에 수행

cnn.add(tf.keras.layers.Flatten())

 

part5 - 완전 연결(Full Connection): 입력층과 출력층 사이에 위치하며, 입력층의 모든 뉴런이 출력층의 모든 뉴런과 연결

# 완전히 연결된 계층을 신경망에 추가

cnn.add(tf.keras.layers.Dense(units=128, activation='relu'))

 

part6 - 출력층

# 완전히 연결된 계층을 신경망에 추가
# 이진 분류 문제이므로 마지막 계층의 뉴런 수는 1로 설정

cnn.add(tf.keras.layers.Dense(units=1, activation='sigmoid'))

* sigmoid 사용 이유: 함수는 출력 값이 0과 1 사이에 위치하는 S자 모양의 함수이다.

* 이 함수는 이진 분류 문제에서 출력층에 사용된다.

* 이 함수를 사용하면 모델이 예측한 값을 확률로 해석할 수 있으며, 이를 기반으로 클래스를 구분할 수 있다.

 

※ 합성곱과 출력층의 activation

CNN 모델에서는 ReLU 함수를 사용하여 입력 이미지에서 추출한 특징을 비선형으로 변환하고, 마지막에 sigmoid 함수를 사용하여 이진 분류 문제를 해결한다.

이렇게 함으로써 모델이 더 복잡한 패턴을 학습하고, 이를 바탕으로 입력 이미지를 더욱 정확하게 분류할 수 있다.

 

CNN 모델 훈련

part1 - CNN 컴파일

#  'adam' 옵티마이저는 손실 함수의 기울기에 따라 네트워크 가중치를 업데이트하는 데 사용
#  'binary_crossentropy' 손실 함수는 이진 분류 문제에 사용되며 잘못된 예측에 대해 모델에 페널티를 줌
#  학습 및 테스트 중에 모델의 성능을 평가하는 데 사용되는 메트릭은 모델에서 수행한 올바른 예측의 백분율인 정확도
#  compile() 함수는 모델을 컴파일하고 학습을 위해 준비하는 데 사용

cnn.compile(optimizer = 'adam', loss = 'binary_crossentropy', metrics = ['accuracy'])

 

part2 - 학습 데이터셋으로 CNN 모델 훈련 및 테스트 데이터셋으로 모델 평가

# training_set에 지정된 훈련 데이터에서 컴파일된 CNN 모델 cnn을 훈련하고 총 25 에포크 동안 test_set에 지정된 테스트 데이터에서 검증
# 교육 과정에서 모델은 Adam 옵티마이저를 사용하여 이진 교차 엔트로피 손실을 최소화하려고 시도하고 '정확도' 메트릭을 사용하여 모델의 정확도를 모니터링한다.

# 'fit()' 메서드는 모델을 교육 데|이터에 맞추고 지정된 에포크 수 동안 테스트 데이터에서 유효성을 검사하는 데 사용
# 각 에포크 동안 모델은 지정된 배치 크기(이 경우 32개)의 배치에 대해 학습되며 유효성 검사 정확도 및 손실은 각 에포크 후에 계산
# 'fit()' 메서드의 출력은 각 시대의 모델 손실 및 정확도와 같은 교육 프로세스에 대한 정보를 포함하는 'History' 개체

cnn.fit(x = training_set, validation_data = test_set, epochs = 25)

 

part3 - 단일 예측 결과 확인

#  훈련된 CNN 모델을 사용하여 단일 이미지에 대한 예측을 하기 위한 것
import numpy as np
from keras.utils import load_img, img_to_array

# cnn모델에 입력할 크기로 조절 하면서 이미지를 불러온다.
test_image = load_img('dataset/prediction/dog.jpg', target_size = (64, 64))
# 이미지를 numpy배열로 변환
test_image = img_to_array(test_image)
# 배열의 차원을 cnn 모델의 입력 차원에 맞추기 위해 확장
test_image = np.expand_dims(test_image, axis = 0)
# cnn 모델을 사용하여 이미지에 대한 예측 수행
result = cnn.predict(test_image)
# 에측 결과를 레이블로 매핑하기 위해 훈련 데이터의 클래스 인덱스 를 가져온다.
training_set.class_indices
# 예측 결과가 1 이상인 경우 'dog' 그렇지 않은 경우 'cat'
if result[0][0] == 1:
  prediction = 'dog'
else:
  prediction = 'cat'

print(prediction)

 

728x90
SMALL

'인공지능' 카테고리의 다른 글

머신러닝과 딥러닝 개념과 데이터 종류 비교  (0) 2023.04.17
profile

개발로 자기계발

@김잠봉

틀린부분이나 조언이 있다면 언제든 환영입니다:-)