본문 바로가기

Study/class note

딥러닝 / LeNet, cifar10, VGG16

8장 딥러닝의 역사와 기술들

1  CNN LeNet - p.257

LeNet은 손글씨 숫자를 인식하는 신경망으로 1998년에 제안됨.

CNN알고리즘의 시초 신경망

MNIST데이터를 만든 얀르쿤 교수에 의해 개발되었다. 현재는 28x28을 사용하는데 그 당시에는 32x32 사이즈로 신경망에 넣음.

[이미지(32x32) -> conv -> maxpooling -> conv -> maxpooling -> fully connected1 -> fully connected2 -> fully connected3(출력층) -> output]

 

ㅇcifar10

32x32픽셀의 60000개의 컬러 이미지로 구성되어 있고 10개의 클래스로 라벨링 되어 있음.

6만개 중 5만개가 훈련 데이터이고 1만개가 테스트 데이터.

 

 

ㅇcifar10데이터셋을 lenet신경망에 넣고 분류하는 모델 만들기

1. cnn없이 완전 연결계층으로만 학습 시킨 결과

# 1. cifar10 데이터를 불러옵니다.

from  tensorflow.keras.datasets  import  cifar10
import  tensorflow  as  tf 

(x_train, y_train), (x_test, y_test) = cifar10.load_data()

x_train_gray = tf.image.rgb_to_grayscale(x_train)
x_test_gray = tf.image.rgb_to_grayscale(x_test)

x_train_gray_3dim = tf.reshape( x_train_gray, [50000, 32, 32] )
x_test_gray_3dim = tf.reshape( x_test_gray, [10000, 32, 32] )

x_train_gray_3dim = np.array(x_train_gray_3dim)
x_test_gray_3dim = np.array(x_test_gray_3dim)

x_train= x_train_gray_3dim # 3차원으로 변경한 데이터
x_test =  x_test_gray_3dim

# 2.1  32x32 의 shape 를 1 x 1024 로 변경합니다.

x_train = x_train.reshape(50000,32*32)  # 2차원으로 변경
x_test  = x_test.reshape(10000, 32*32)

x_train = x_train/255.0
x_test = x_test/255.0

# 2.2 정답 데이터를 준비합니다. (p98 원핫인코딩을 해야합니다.)
 
from  tensorflow.keras.utils import  to_categorical

y_train = to_categorical(y_train)
y_test = to_categorical(y_test)

# 3. 모델을 구성합니다.

from  tensorflow.keras.models  import  Sequential
from  tensorflow.keras.layers    import  Dense

model = Sequential()
model.add(Dense(50, activation='sigmoid', input_shape=(32*32, ) ) ) # 은닉1층
model.add(Dense(50, activation='sigmoid') ) # 2층  
model.add(Dense( 10, activation='softmax') ) # 출력층

# 4. 모델을 설정합니다. (경사하강법과 오차함수를 정의해줍니다. 4장에서 배웁니다)

model.compile(optimizer='adam',  # 경사하강법 
                     loss='categorical_crossentropy',  #오차함수
                     metrics=['acc'] )  # 학습과정에서 정확도를 보려고 지정

# 5. 모델을 훈련 시킵니다.

model.fit( x_train, y_train, epochs=30, batch_size=100)

#model.fit( 훈련데이터, 정답, 에폭수, 배치사이즈) 
# 에폭수 :  학습횟수 (책을 몇번 볼건지)
# 배치사이즈:  한번에 학습할 양 ( 사람은 책을 한번에 한페이지 밖에 못보지만 컴퓨터는 한번에
#                  여러 페이지를 볼 수 있다)

# 6. 모델을 평가합니다. (시험을 봅니다.)

model.eval‎uate(x_test, y_test)

정확도 40으로 아주 별로임

 

 

문제204. 위의 신경망 앞에 합성곱층을 하나만 넣어 구현하시오.

# 1. cifar10 데이터를 불러옵니다.(텐서플로우에 내장)
from  tensorflow.keras.datasets  import  cifar10
import  tensorflow  as  tf 
import numpy as np

(x_train, y_train), (x_test, y_test) = cifar10.load_data()  #훈련 데이터, 테스트 데이터 구성

x_train = x_train/255.0  #(50000, 32, 32, 3)
x_test = x_test/255.0

# 2.2 정답 데이터를 준비합니다. (p98 원핫인코딩을 해야합니다.)
from  tensorflow.keras.utils import  to_categorical

y_train = to_categorical(y_train)
y_test = to_categorical(y_test)

# 3. 모델을 구성합니다.

from  tensorflow.keras.models  import  Sequential
from  tensorflow.keras.layers    import  Dense, Flatten, Conv2D, MaxPooling2D, BatchNormalization, Dropout

model = Sequential()
model.add(Conv2D(100, activation = 'relu', kernel_size = (5,5), padding = 'same', input_shape = (32,32,3)))  #컨볼루션 층
model.add(BatchNormalization())
model.add(MaxPooling2D(pool_size =(2,2), padding = 'same'))

model.add(Flatten())
model.add(Dense(50, activation='relu') ) # 완전연결계층 은닉1층
model.add(BatchNormalization())
model.add(Dense(50, activation='relu') ) # 은닉 2층  
model.add(BatchNormalization())
model.add(Dense(10, activation='softmax') ) # 출력층

# 4. 모델을 설정합니다. (경사하강법과 오차함수를 정의해줍니다. 4장에서 배웁니다)

model.compile(optimizer='adam',  # 경사하강법 
                     loss='categorical_crossentropy',  #오차함수
                     metrics=['acc'] )  # 학습과정에서 정확도를 보려고 지정

# 5. 모델을 훈련 시킵니다.

model.fit( x_train, y_train, epochs=30, batch_size=100)

#model.fit( 훈련데이터, 정답, 에폭수, 배치사이즈) 
# 에폭수 :  학습횟수 (책을 몇번 볼건지)
# 배치사이즈:  한번에 학습할 양 ( 사람은 책을 한번에 한페이지 밖에 못보지만 컴퓨터는 한번에
#                  여러 페이지를 볼 수 있다)

# 6. 모델을 평가합니다. (시험을 봅니다.)

model.evaluate(x_test, y_test)

오버피팅이 심하게 발생한 것을 확인할 수 있음.

 

 

문제205. 고전 cnn인 LeNet신경망 설계도로 다시 cifar10데이터를 학습 시키시오.

conv -- maxpooling -- conv -- maxpooling -- fc1 -- fc2 -- fc3

# 1. cifar10 데이터를 불러옵니다.(텐서플로우에 내장)
from  tensorflow.keras.datasets  import  cifar10
import  tensorflow  as  tf 
import numpy as np

(x_train, y_train), (x_test, y_test) = cifar10.load_data()  #훈련 데이터, 테스트 데이터 구성

x_train = x_train/255.0  #(50000, 32, 32, 3)
x_test = x_test/255.0

# 2.2 정답 데이터를 준비합니다. (p98 원핫인코딩을 해야합니다.)
from  tensorflow.keras.utils import  to_categorical

y_train = to_categorical(y_train)
y_test = to_categorical(y_test)

# 3. 모델을 구성합니다.

from  tensorflow.keras.models  import  Sequential
from  tensorflow.keras.layers    import  Dense, Flatten, Conv2D, MaxPooling2D, BatchNormalization, Dropout

model = Sequential()
model.add(Conv2D(100, activation = 'relu', kernel_size = (5,5), padding = 'same', input_shape = (32,32,3)))  #컨볼루션 층
model.add(BatchNormalization())
model.add(MaxPooling2D(pool_size =(2,2), padding = 'same'))

model.add(Conv2D(100, activation = 'relu', kernel_size = (5,5), padding = 'same'))  #컨볼루션 층
model.add(BatchNormalization())
model.add(MaxPooling2D(pool_size =(2,2), padding = 'same'))

model.add(Flatten())
model.add(Dense(50, activation='relu') ) # 완전연결계층 은닉1층
model.add(BatchNormalization())
model.add(Dense(50, activation='relu') ) # 은닉 2층  
model.add(BatchNormalization())
model.add(Dense(10, activation='softmax') ) # 출력층

# 4. 모델을 설정합니다. (경사하강법과 오차함수를 정의해줍니다. 4장에서 배웁니다)

model.compile(optimizer='adam',  # 경사하강법 
                     loss='categorical_crossentropy',  #오차함수
                     metrics=['acc'] )  # 학습과정에서 정확도를 보려고 지정

# 5. 모델을 훈련 시킵니다.

model.fit( x_train, y_train, epochs=30, batch_size=100)

#model.fit( 훈련데이터, 정답, 에폭수, 배치사이즈) 
# 에폭수 :  학습횟수 (책을 몇번 볼건지)
# 배치사이즈:  한번에 학습할 양 ( 사람은 책을 한번에 한페이지 밖에 못보지만 컴퓨터는 한번에
#                  여러 페이지를 볼 수 있다)

# 6. 모델을 평가합니다. (시험을 봅니다.)

model.evaluate(x_test, y_test)

 

 

2  VGG신경망 - p.270

잘 분류하는 신경망 설계도 대표적으로 VGG신경망과 inception 신경망이 있음.

 

VGG신경망은 옥스포드 대학의 연구팀 vgg에 의해 개발된 모델로써, 2014년 이미지넷 이미지 인식대회에서 준우승한 모델.

VGGnet은 16개 또는 19개 층으로 구성된 모델. 처음에는 8개의 층으로 구성되었는데 나중에는 22층까지 구성되었음. 그 중 16개의 층으로 구성한 vgg16이 가장 정확도가 좋은 모델. 층을 더 깊게 쌓는다고 더 좋은 효과를 보이지 않아서 보통 vgg16을 많이 사용함.

이 설계도가 텐서플로우에 내장되어 있음. 그래서 그냥 내장된 걸 가져오기만 하면 됨.

from tensorflow.keras.applications import VGG16

model = VGG16(weights = 'imagenet', input_shape = (32,32,3), include_top = False)

weights = 'imagenet' --> 이미지넷 대회에서 준우승한 가중치를 사용하겠다

weights = 'None' --> 이미지넷 대회에서 준우승한 가중치를 사용하지 않겠다.

include_top은 완전연결계층 모델의 분류기를 내가 직접 기술할지 말지를 결정. False로 하게 되면 완전연결계층을 직접 설계해야함.

 

from tensorflow.keras.applications  import  * 

vgg16 = VGG16(weights='imagenet', input_shape=(32, 32, 3), include_top=False)

vgg16.summary()

 

 

ㅇ VGG신경망 구현하기

1. 필요한 패키지를 임폴트 받습니다.

# 필요한 패키지 임폴트 받기
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Conv2D, MaxPool2D, Dense, Flatten, BatchNormalization, Activation, Dropout
from tensorflow.keras.optimizers import Adam
from tensorflow.keras.applications import VGG16

 

 

2. cifar10 데이터를 준비합니다.

# 데이터 준비하기
from tensorflow.keras.datasets import cifar10
import numpy as np

(x_train, y_train), (x_test, y_test) = cifar10.load_data()

# 평균과 표준편차는 채널별로 구해줍니다.
x_mean = np.mean(x_train, axis = (0, 1, 2))
x_std = np.std(x_train, axis = (0, 1, 2))

x_train = (x_train - x_mean) / x_std
x_test = (x_test - x_mean) / x_std
 

3. 훈련 데이터를 검정 데이터로 나눕니다.

from sklearn.model_selection import train_test_split

x_train, x_val, y_train, y_val = train_test_split(x_train, y_train, test_size = 0.1, random_state = 777)​

 

4. vgg16 신경망을 가져옵니다.

# imagenet을 학습한 모델을 불러옵니다.
vgg16 = VGG16(weights = 'imagenet', input_shape = (32, 32, 3), include_top = False)
vgg16.summary()​

 

5. vgg16 신경망을 동결시키고 싶으면 아래의 코드를 주석을 풀고 실행합니다.

#for layer in vgg16.layers[:14]:
#    layer.trainable = False

## 가중치 초기값 : imagenet
# layer.trainable=True : 동결 해제 (default)
# layer.trainable=False : 동결 (option)
 

vgg16모델을 가져올때 weight = 'None'으로 가져와도 되지만, 일부 층의 가중치를 바꾸고 싶다면 위의 코드를 실행하여 동결해제해서 가중치 수정할 수 있음.

 

6. 동결을 풀었을때의 훈련 시킬수 있는 파라미터의 갯수를 확인합니다. 

vgg16.summary()
 

 

7. vgg16 신경망에 완전 연결계층을 붙입니다. 

 
model = Sequential()

# vgg16 모델을 사용합니다.

model.add(vgg16)

# 분류기를 직접 정의합니다.
model.add(Flatten())
model.add(Dense(256))
model.add(BatchNormalization())
model.add(Dropout(0.4))
model.add(Activation('relu'))
model.add(Dense(10, activation = 'softmax'))

model.summary()

 

8. 모델을 설정합니다.

model.compile(optimizer = Adam(1e-4),
             loss = 'sparse_categorical_crossentropy',
             metrics = ['acc'])​

 

9. 조기종료 옵션을 지정합니다. 

from keras.callbacks import ModelCheckpoint, EarlyStopping

callbacks = [ EarlyStopping(monitor='val_acc', patience=10, verbose=1) ]​

 

10. 모델을 훈련시킵니다. 

history = model.fit(x_train, y_train,epochs = 200, batch_size=100,validation_data = (x_val, y_val),callbacks=callbacks)
model.save('cifar10_model.h5')
 

 

11. 모델을 평가합니다.

 
model.eval‎uate(x_test,y_test)

 

+) 전체코드

# 필요한 패키지 임폴트 받기
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Conv2D, MaxPool2D, Dense, Flatten, BatchNormalization, Activation, Dropout
from tensorflow.keras.optimizers import Adam
from tensorflow.keras.applications import VGG16  #텐서플로우에 내장된 vgg신경망

# 데이터 준비하기
from tensorflow.keras.datasets import cifar10
import numpy as np

(x_train, y_train), (x_test, y_test) = cifar10.load_data()

# 평균과 표준편차는 채널별로 구해줍니다.
x_mean = np.mean(x_train, axis = (0, 1, 2))
x_std = np.std(x_train, axis = (0, 1, 2))

x_train = (x_train - x_mean) / x_std
x_test = (x_test - x_mean) / x_std

from sklearn.model_selection import train_test_split
#훈련 데이터 0.1를 떼어서 테스트 데이터(검정 데이터)로 사용
x_train, x_val, y_train, y_val = train_test_split(x_train, y_train, test_size = 0.1, random_state = 777)

print('data ready~')

# imagenet을 학습한 모델을 불러옵니다.
vgg16 = VGG16(weights = 'imagenet', input_shape = (32, 32, 3), include_top = False)
vgg16.summary() #vgg 층 확인


#vgg16 신경망을 동결시키고 싶으면 아래의 코드를 주석을 풀고 실행합니다.
#for layer in vgg16.layers[:14]:
#    layer.trainable = False

## 가중치 초기값 : imagenet
# layer.trainable=True : 동결 해제 (default)
# layer.trainable=False : 동결 (option)

model = Sequential()

# vgg16 모델을 사용합니다.

model.add(vgg16)

# 분류기를 직접 정의합니다.
model.add(Flatten())
model.add(Dense(256))
model.add(BatchNormalization())
model.add(Dropout(0.4))
model.add(Activation('relu'))
model.add(Dense(10, activation = 'softmax'))

model.summary() 

model.compile(optimizer = Adam(1e-4),
             loss = 'sparse_categorical_crossentropy',
             metrics = ['acc'])

from keras.callbacks import ModelCheckpoint, EarlyStopping

callbacks = [ EarlyStopping(monitor='val_acc', patience=10, verbose=1) ]

history = model.fit(x_train, y_train,epochs = 200, batch_size=100,validation_data = (x_val, y_val),callbacks=callbacks)
model.save('cifar10_model.h5')

훈련데이터의 정확도 약 0.98, 테스트 데이터 정확도 0.85

1000개의 이미지에 속하지 않은 다른 이미지를 분류하는 vgg신경망을 만들고 싶다면 가중치 동결을 전부 해제하고 사용하면 됨.

 

 

반응형