1단계. 필요한 라이브러리 호출
2단계. 사전 훈련된 모델 내려받기
- 해당 예제에서 사용할 모델 : 사전 훈련된 ResNet50
model = ResNet50(include_top=True,
weights="imagenet",
input_tensor=None,
input_shape=None,
pooling=None,
classes=1000)
ⓐ include_top : 네트워크(사전 훈련된 모델) 상단에 '완전연결층을 포함'할지의 여부를 지정(기본값: True)
//완전연결층 : 합성곱층, 풀링층을 거쳐 차원이 축소된 특성맵을 전달받음, 이미지를 3차원 벡터에서 1차원 벡터로 펼침
ⓑ weights : 가중치
None(무작위 초기화)과 'imagenet'(ImageNet에서 사전 훈련된 값)을 지정 가능
ⓒ input_tensor : 입력 데이터의 텐서(layers.Input()의 출력)
//텐서 : 데이터의 배열
ⓓ input_shape : 입력 이미지에 대한 텐서 크기
ⓔ pooling : 풀링(sub sampling, 특징 추출)에서 사용할 수 있는 값의 종류
- None : 모델의 출력이 마지막 합성곱층
- avg : 마지막 합성곱층에 글로벌 '평균' 풀링이 추가됨(나누는 과정X, 각 특성 맵에 대해 모든 값을 더하는 단순 합으로 대체)
- max : 마지막 합성곱층에 글로벌 '최대' 풀링이 추가됨
ⓕ classes : 이미지를 분류할 클래스의 선택적 수
- weights로 'imagenet'사용하려면 classes 값이 1000이어야함
(다른 값을 사용하고 싶다면 None으로 지정)
✔ResNet50
- 계층 50개로 구성된 합성곱 신경망
- ImageNet 데이터베이스의 100만 개가 넘는 영상을 이용하여 훈련된 신경망으로, 전이 학습에 사용되도록 사전 훈련된 모델을 제공
- 단점 : 입력 제약이 매우 크고, 충분한 메모리(RAM)가 없으면 학습 속도가 느릴 수 있다
2*단계. 내려받은 ResNet50 네트워크 구조 확인
✔ResNet50 네트워크는 유지, 여기에 추가 계층을 생성해 사용할 것
model.summary()
3단계. 사전훈련된 합성곱층의 가중치 고정, 시그모이드 활성화 함수가 포함된 밀집층(완전연결층) 추가
model.trainable = False
model = Sequential([model,
Dense(2, activation='sigmoid')]) #시그모이드 함수가 포함된 밀집층 추가
model.summary()
ⓐ model.trainable : 훈련 가능/불가능(동결) 지정
ⓑ Sequential() : 순차적으로 레이어층을 더해주는 모델.
각 레이어에 정확히 하나의 입력 텐서와 하나의 출력 텐서가 있는 일반 레이어 스택에 적합
+ Dense() : 밀집층, 입력과 출력을 연결
- 첫번째 인자 : 출력 노드(뉴런)의 수
- activation : 활성화 함수를 설정. ( 'sigmoid' : 이진 분류 문제에서 출력 층에 주로 쓰임)
ⓒ model.summary() 해석
- Layer(type) : 레이어의 이름과 타입(알아서 레이어의 이름을 지정해줌)
- Output Shape: (None, 2)이라는 뜻은 None개의 행과 2개의 아웃풋 값이 주어졌다는 것.
✔행이 None으로 지정되는 이유 : 데이터의 갯수는 계속해서 추가될 수 있기 때문에
딥러닝 모델에서는 주로 행을 무시하고 열의 shape을 맞추어주는 작업을 많이 수행함
- Param: 파라미터의 수, 즉 각 입력노드와 출력노드에 대해 연결된 간선의 수
인풋이 1개, 아웃풋이 5개인 경우, 1*5=5개의 간선이 존재
인풋에 Bias(b) 노드가 추가된 경우, 입력값(1)+바이어스노드(1)=2 총 2개의 인풋 노드 ⇒ 파라미터의 갯수: 2*5 = 10개의 간선
4단계. 훈련에 사용될 환경 설정(활성화함수, 손실함수, 평가지표)
5단계. 모델 훈련(개와 고양이 이미지 데이터셋 이용)
train = ImageDataGenerator(rescale=1./255,
rotation_range=10,
width_shift_range=0.1,
height_shift_range=0.1,
shear_range=0.1,
zoom_range=0.1) ------ ①
train_generator = train.flow_from_directory(train_dir,
target_size=(image_height, image_width),
color_mode="rgb",
batch_size=BATCH_SIZE,
seed=1,
shuffle=True,
class_mode="categorical") ------ ②
valid = ImageDataGenerator(rescale=1.0/255.0)
valid_generator = valid.flow_from_directory(valid_dir,
target_size=(image_height, image_width),
color_mode="rgb",
batch_size=BATCH_SIZE,
seed=7,
shuffle=True,
class_mode="categorical")
history = model.fit(train_generator,
epochs=10,
validation_data = valid_generator,
verbose=2) ------ ③
① ImageDataGenerator : 쉽게 데이터 전처리를 할 수 있음 + 데이터를 증가시킴
(augmentation, 기존 데이터에서 새로 생성 된 합성 데이터를 추가 ⇒ 정규화 역할을하며 기계 학습 모델을 학습할 때 과적합을 줄이는 데 도움줌)
ⓐ rescale : 원본 영상은 0~255의 RGB 계수로 구성되는데, 1/255로 스케일링하여 0~1 범위로 변환
(원본 값은 모델을 효과적으로 학습시키기에 너무 높음)
Q. 왜 255로 나누는가?
A. 픽셀값이 0~255 사이의 값을 가진다할때, 0은 검은색, 255는 흰색, 1~254는 회색을 나타냄(grayscale 케이스)
Q. 왜 0~1범위의 값을 가져야하는가?
A. 머신러닝에서 scale이 큰 feature의 영향이 커지는걸 방지 + 극 값(local minima)에 빠질 확률을 감소시키며 학습속도 향상
ⓑ rotation_range : 이미지 회전 범위.
rotation_range=10은 0~10도 범위 내에서 임의로 원본 이미지를 회전하겠다는 의미
ⓒ width_shift_range, height_shift_range : 그림을 수평/수직으로 랜덤하게 평행 이동시키는 범위
값이 0.1, 전체 높이가 100일 경우, 0.1의 값을 적용하면서 10픽셀 내외로 이미지를 좌우/상하로 이동하겠다는 의미
ⓓ shear_range : 원본 이미지를 임의로 변형(전단)시키는 범위(늘이기)
shear_range.0.1은 0.1라디안 내외로 시계 반대 방향으로 이미지를 변환시키겠다는 의미
ⓔ zoom_range : 임의 확대/축소 범위. zoom_range.0.1은 0.9에서 1.1배의 크기로 이미지를 변환시키겠다는 의미
② flow_from_directory : 폴더 구조를 그대로 가져와서 ImageDataGenerator에 실제 데이터를 채워줌
ⓐ 첫번째 파라미터 : 훈련 이미지 경로
ⓑ target_size : 이미지 크기(모든 이미지에 적용)
ⓒ color_mode : 이미지가 그레이스케일이면 'grayscale', 색상이 있으면 'rgb' 사용
ⓓ batch_size : 한 배치당 generator에서 생성할 이미지 개수
ⓔ seed : 이미지를 임의로 섞기 위한 랜덤 숫자
ⓕ shuffle : 이미지를 섞어서 사용할지의 여부를 지정
ⓖ class_mode : 예측할 클래스가 두 개뿐이면 'binary', 그렇지 않으면 'categorical'을 선택
③ 모델을 훈련시키기
ⓐ 첫번째 파라미터 : 학습에 사용되는 데이터셋
ⓑ validation_data : 검증 데이터셋 설정
③ verbose : 훈련의 진행과정을 보여줌 (0: 출력X, 1: 훈련 진행도 표시위한 진행 막대 표시, 2: 미니 배치마다 훈련 정보 출력)
6단계. 모델의 정확도를 시각화
plt.rcParams["font.family"] = font_family
accuracy = history.history['accuracy'] ------ ①
val_accuracy = history.history['val_accuracy']
loss = history.history['loss']
val_loss = history.history['val_loss']
epochs = range(len(accuracy))
plt.plot(epochs, accuracy, label="훈련 데이터셋")
plt.plot(epochs, val_accuracy, label="검증 데이터셋")
plt.legend()
plt.title('정확도')
plt.figure()
plt.plot(epochs, loss, label="훈련 데이터셋")
plt.plot(epochs, val_loss, label="검증 데이터셋")
plt.legend()
plt.title('오차')
ⓐ plt.rcParams : 차트 figure의 기본 설정 지정
ⓑ plt.legend() : 그래프에 범례를 표시
① history 객체가 가진 정보(model.fit() 메서드에 대한 반환값으로 history 객체를 얻음)
- accuracy: 매 에포크에 대한 훈련의 정확도
- loss: 매 에포크에 대한 훈련의 손실값
- val_accuracy: 매 에포크에 대한 검증의 정확도
- val_loss: 매 에포크에 대한 검증의 손실값
훈련 데이터는 시간이 흐를 수록
정확도는 높아지고 오차는 낮아짐
그러나 검증 데이터는 시간이 흘러도 변동 X
=> 예측력이 좋지 못하다는 것을 의미
7단계. 훈련된 모델의 예측
class_names = ['cat', 'dog'] #개와 고양이에 대한 클래스 2개
validation, label_batch = next(iter(valid_generator)) //validation: 이미지 배열, label_batch : 정답 레이블 배열
prediction_values = model.predict_classes(validation) //이미지 배열의 예측값
fig = plt.figure(figsize=(12, 8))
fig.subplots_adjust(left=0, right=1, bottom=0, top=1, hspace=0.05, wspace=0.05)
for i in range(8):
ax = fig.add_subplot(2, 4, i+1, xticks=[], yticks=[])
ax.imshow(validation[i,:], cmap=plt.cm.gray_r, interpolation='nearest')
/* 예측값이 정답과 같으면 노란색, 다르면 빨간색으로 예측값 출력*/
if prediction_values[i] == np.argmax(label_batch[i]): //prediction_values는 0 아니면 1의 값을 가짐
ax.text(3, 17, class_names[prediction_values[i]], color='yellow', fontsize=14)
else:
ax.text(3, 17, class_names[prediction_values[i]], color='red', fontsize=14)
(Q.valid_generator 첫 인덱스(?)는 이미지가 아닌지)
ⓐ iter() : 전달된 데이터의 반복자를 꺼내 반환
· iterable 객체 - 반복 가능한 객체
· 대표적으로 iterable한 타입 - list, dict, set, str, bytes, tuple, range
ⓑ next() : 반복자를 입력으로 받아 그 반복자가 다음에 출력해야 할 요소를 반환
ⓒpredict_classes : label 제공 //predict는 probability
· predict 의 경우 [[0.22520512] [0.9520419 ] [0.9672848 ] [0.02690617]]
· predict_classes 의 경우 [[0] [1] [1] [0]]
ⓓ subplots_adjust : 배치되어 있는 subplot들의 위치를 모두 조절
· left, bottom= 0 : 경계에 둠
· right, top= 1 : 또 다른 경계에 둠
· hspace, wspace : subplot이 여러 개일때 subplot간의 간격을 의미
ⓔ interpolation : 보간법(픽셀들의 축 위치 간격을 보정하여 이미지가 자연스러운 모양으로 보일 수 있게 하는 방법)
* 'nearest'는 가장 고해상도인 보간법
ⓕ imshow 첫 파라미터 : 유사 배열 or PLI(Python Imaging Library)
ⓖ argmax : 배열에서 가장 큰 값의 인덱스 값을 반환
+ 틱(눈금) 없애기(틱이 기본적으로 약간의 텍스트 공백을 차지하기 때문에 제거)
→ plt.xticks([]) plt.yticks([])
+ 컬러맵 목록
https://scipy-cookbook.readthedocs.io/items/Matplotlib_Show_colormaps.html
텐서플로 허브 사용
텐서플로 허브
- 사전 훈련된 모델을 이용하는 방법 중 하나
- 일반화된 문제들에 대해 모델의 재사용성을 극대화하하려고 구글에서 공개한 API
1단계. 필요한 라이브러리 호출 및 ResNet50 내려받기
import tensorflow_hub as hub
model = tf.keras.Sequential([
/* ResNet50의 합성곱층의 가중치 고정 */
hub.KerasLayer("https://tfhub.dev/google/imagenet/resnet_v2_152/feature_vector/4",
input_shape=(224,224,3),
trainable=False),
/* 사전 훈련된 모델을 가져와서 밀집층 추가(완전연결층, 소프트맥스 활성화 함수가 추가된) */
tf.keras.layers.Dense(2, activation='softmax')
])
2단계. 훈련과 검증 데이터셋을 충분히 확보하기 위해 데이터 확장(augmentation)
이후 단계는 앞의 예제와 동일함
텐서플로 허브를 이용한 경우의 정확도와 손실
시간이 흐름에 따라
정확도는 높아지고
오차는 낮아짐
⇒ 훈련이 잘 됐음
개와 고양이에 대한 예측 결과
참고 자료
3단계 : https://ebbnflow.tistory.com/124
ImageDataGenerator 사진 출처 : https://ichi.pro/ko/keras-mich-tensorflowleul-sayonghan-imiji-deiteo-jeungdae-tamsaeg-184813206747204
predict_classes : https://mmresult.tistory.com/entry/predict-%EC%99%80-predictclass-%EC%99%80%EC%9D%98-%EC%B0%A8%EC%9D%B4%EC%A0%90
subplot_adjust : https://frhyme.github.io/python-lib/img_savefig_%EA%B3%B5%EB%B0%B1%EC%A0%9C%EA%B1%B0/
interpolation : https://bentist.tistory.com/23
imshow() :https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.imshow.html
argmax() : https://www.delftstack.com/ko/api/numpy/python-numpy-argmax/
정규화 이유 : https://realblack0.github.io/2020/03/29/normalization-standardization-regularization.html
'Etc > Deep Learning' 카테고리의 다른 글
5장 합성곱 신경망Ⅰ(3) 실습 - 특성맵 시각화 (0) | 2021.08.08 |
---|---|
5장 합성곱 신경망Ⅰ(3) - 미세조정기법(전이학습), 설명 가능한 CNN (0) | 2021.08.06 |
5장 합성곱 신경망Ⅰ(2) - 전이 학습 (0) | 2021.08.04 |
5장 합성곱 신경망(1) - 합성곱 신경망의 구조(입력층, 합성곱층, 풀링층, 완전연결층, 출력층) (수정, 보완必) (0) | 2021.08.04 |
4장 딥러닝(2) - 딥러닝 알고리즘(심층 신경망, 합성곱 신경망, 순환 신경망, 제한된 볼츠만 머신, 심층 신뢰 신경망) (0) | 2021.08.04 |