이번 세미나에서는 KERAS를 이용하여 개와 고양이를 분류해보는 시간을 가져보도록 하겠습니다.
1. 이론편
분류하기에 앞서 keras가 무엇인지, 인공지능은 무엇인지, 또 딥러닝은 무엇인지에 대해서 먼저 소개하는 시간을 가져보록 하겠습니다. 약 25분 정도의 동영상 강의입니다!
목차는 다음과 같습니다.
- AI의 역사와 출현
- 머신러닝과 딥러닝의 차이
- 딥러닝
- 분류
- About KERAS
+) 10:28초경 비선형 함수인 것은 쓸모가 없다-> 선형 함수인 것은 효율적이지 못하다로 바꿉니다!
2. 실전편
2.1. 데이터 가져오기
- 01. 구글 코렙을 구글 드라이브와 연동하기
01. 구글 코렙을 구글 드라이브와 연동하기
이제부터 본격적으로 고양이, 개 이진분류를 시작해보도록 하겠습니다. 이번 세미나에서는 Google Colab환경에서 keras를 사용할 것입니다.
세미나를 본격적으로 시작하기에 앞서, 세미나에 필요한 데이터를 미리 다운로드 해주세요.
개와 고양이 사진을 kaggle에서 다운로드 받아도 되지만 혹시 모를 용량 문제를 대비해 사진 개수가 더 적은 파일로 세미나를 진행하겠습니다.
다운로드 받은 dogs-vs-cats.zip 파일을 구글 드라이브에 deeplearning이라는 폴더를 만들어서 해당 폴더 안에 파일을 넣어주세요.
파일을 google drive에 옮겼으면 google colab을 열어줍니다.
(지금부터 나타나는 소스 코드는 각 묶음 단위로 google colab에서 한줄에 넣어 실행시키는 것을 권장드립니다!)
진행하기에 앞서 colab에서 '런타임'-'런타임 유형 변경' - 'GPU'로 바꾸어주시기 바랍니다.
구글드라이브에 저장한 파일을 가져오기 위해 먼저 colab과 google drive를 연동시켜주겠습니다.
from google.colab import drive
drive.mount('/content/gdrive')
위의 코드를 돌리고 난후, 아래와 같이 링크와 함께 코드를 입력하라는 표시가 뜰 것입니다.
그러면 해당 링크를 눌러 계정을 선택하고 구글 계정에 엑세스한다는 창이 뜨면 '허용'버튼을 누른 다음 코드를 복사해 붙여줍니다.
다음과 같이 나온다면 성공적으로 colab과 google drive가 연동된 것입니다.
- 02. 구글 드라이브에서 데이터 가져오기1
02. 구글 드라이브에서 데이터 가져오기1
구글 드라이브에서 파일에 접근해 데이터를 가져오기 위해 우선 드라이브의 디렉토리 목록을 먼저 살펴보겠습니다.
!ls /content/gdrive -la
ls [옵션] 디렉터리*파일* (*표시는 디렉터리 혹은 파일 이름이 0개 이상 올 수 있음을 의미합니다.)
여기서 ls는 디렉토리의 목록을 보여주는 명령어입니다.
-a는 모든 파일과 디렉토리를 표시해주고 -l은 자세히 출력해주어, 숨긴 파일까지 표시해주는 명령어입니다.
따라서 만약에 모든 파일과 디렉토리를 자세히 출력하고 싶다면 ls -al 또는 ls -la를 입력하면 됩니다.
해당 코드를 입력하면 다음과 같은 출력이 나옵니다.
방금 전 만들어준 deeplearning폴더는 'My Drive'에 존재하기 때문에 아래와 같이 ls 명령어를 이용해 폴더 안의 목록을 확인해줍니다.
!ls /content/gdrive/'My Drive'/deeplearning -la
출력 결과를 통해 dogs-vs-cats.zip이 안에 들어있는 것을 확인할 수 있습니다.
우리는 이제부터 dogs-vs-cats데이터 처리를 위해 현재위치로 가져오겠습니다.
!cp /content/gdrive/'My Drive'/deeplearning/dogs-vs-cats.zip .
cp 파일 디렉터리
여기서 cp는 복사 기능 명령어입니다. 그리고 코드의 맨 마지막 부분에 있는 . 은 현재 위치를 의미합니다.
cp 명령어 다음에 복사하고자 하는 파일을 지정하고 그 뒤에 자신이 복사할 위치를 지정하면 파일을 원하는 위치에 복사할 수 있습니다.
따라서 해당 코드는 지정한 파일을 현재 위치로 복사한다는 의미입니다.
조금 더 구체적인 예시를 들자면
abc에 def라는 파일이 있는데 이를 ghi에 jkl라는 폴더에 복사하고 싶으면 cp /abc/def /ghi/jkl 이렇게 입력하시면 됩니다.
위에서 dogs-vs-cats.zip을 현재 위치로 복사하였으니 현재 위치에서의 디렉터리 내용을 확인하기 위해
!ls라는 명령어를 입력하면 아래와 같은 결과가 나오는 것을 확인할 수 있습니다.
!ls
unzip 압축을 해제할 파일 -d 압축해제폴더위치
현재 이 파일은 압축이 되어있으니 압축을 풀어보도록 하겠습니다.
아래의 코드는 특정폴더(여기서는 catdog1)에 압축을 풀기 위해
unzip 명령어를 사용하였습니다. 압축을 해제할 파일은 dogs-vs-cats.zip이고
압축해제폴더위치는 catdog1 입니다.
!unzip dogs-vs-cats.zip -d catdog1
cd 디렉터리
방금 만든 catdog1 폴더로 이동하기 위해 cd 명령어를 이용하겠습니다. cd 명령어는 특정폴더로 이동할 수 있는 명령어입니다.
!cd catdog1을 통해 catdog1으로 이동 후 방금 압축을 해제한 폴더 안에 또 다른 train, test1이라는 압축파일이 있어 이 파일들을 dogs-vs-cats라는 폴더에 압축을 풀도록 하겠습니다.
!cd catdog1
!unzip catdog1/dogs-vs-cats/train.zip -d dogs-vs-cats
!unzip catdog1/dogs-vs-cats/test1.zip -d dogs-vs-cats
위의 명령어를 실행하면 아래와 같이 파일들이 압축해제되는 모습을 확인할 수 있습니다.
(아래의 사진은 일부 결과만 캡쳐한 모습입니다. 실제 결과는 이보다 더 길게 나옵니다.)
아래의 명령어를 통해 train 파일이 제대로 압축이 해제되었는지 확인해봅니다.
!ls dogs-vs-cats/train/train -la
동일하게 test1의 파일도 확인해봅니다.
!ls dogs-vs-cats/test1/test1 -la
- 03. 구글 드라이브에서 데이터 가져오기2
03. 구글 드라이브에서 데이터 가져오기2
압축된 파일들이 모두 해제가 되었으면 고양이 사진들은 cats라는 폴더에 강아지 사진들은 dogs라는 폴더로 이동시켜보겠습니다.
여기서 사진들을 고양이와 강아지로 분류할 수 있는 이유는 train 폴더 안에 있는 사진들은 고양이 또는 강아지에 따라 이름을 cat 또는 dog로 붙여주었기에 가능합니다.
mkdir [옵션] 디렉터리
아래의 코드를 보기 전에 사용된 명령어를 먼저 확인해봅시다.
cd라는 명령어는 지정한 디렉터리로 이동하는 명령어이고, mkdir 명령어는 디렉터리를 만드는 명령어입니다.
그리고 ;를 이용하면 여러 개의 명령어를 한 줄에 입력하여 처리가 가능하도록 해줍니다.
이제 아래의 코드를 보면 cd라는 명령어를 통해 dogs-vs-cats 폴더 안의 train 폴더 안의 train폴더로 이동한 후
해당 위치에서 dogs 라는 파일과 cats라는 파일을 만들어 주고 있습니다.
!cd dogs-vs-cats/train/train; mkdir dogs; mkdir cats
폴더를 만들어주었으니 사진들을 각각의 폴더로 이동시켜보겠습니다.
여기서 새롭게 등장하는 명령어는 | 과 grep, xargs 그리고 mv라는 명령어입니다.
| 명령어는 '명령어1 | 명령어2' 이렇게 사용할 수 있습니다. 이는 명령어1의 표준 출력이 파이프(|)를 통해 명령어2의 표준입력이 될 수 있도록 해주는 기능을 가지고 있습니다.
grep [옵션] 패턴
grep 명령어는 특정 파일 내에서 찾고 싶은 키워드를 검색하는 명령어입니다. -e 옵션을 사용해 매칭을 위한 패턴을 전달할 수 있도록 하였습니다.
xargs 명령어는 표준 출력값을 이용하여 명령을 실행할 수 있도록 해줍니다. 여기서 -t 옵션을 통해 상세한 정보를 화면에 출력할 수 있도록 해줍니다.
mv 파일 디렉터리
mv 명령어는 파일 이동을 위한 명령어입니다.
아래의 코드에서 첫 번째 코드를 살펴보면 train 폴더로 이동 후,
현재 위치(train 폴더로 이동한 후의 위치)에서의 목록을 리스트하기 위해 ls 명령어를 사용하였습니다.
ls의 출력이 grep의 입력으로 들어와 이름에 cat이라는 패턴을 가진 사진들을 선택하였고,
이를 cats라는 폴더로 이동해주기 위해 mv라는 명령어를 사용하였습니다.
2번째 코드도 이와 동일하고 다른 점은 dog 라는 이름을 가진 사진들을 분류해 dogs 폴더에 이동시킨 점입니다.
!cd dogs-vs-cats/train/train; ls | grep -e cat | xargs mv -t cats
!cd dogs-vs-cats/train/train; ls | grep -e dog | xargs mv -t dogs
ls를 통해 dogs-vs-cats/train/train 위치의 파일 목록을 확인해보면 cats와 dogs 파일이 성공적으로 만들어진 것을 확인할 수 있습니다.
!ls dogs-vs-cats/train/train -la
2.2. Keras Model 만들기
- 01. 데이터 전처리 과정1
01.데이터 전처리 과정1
데이터 처리를 완료했다면 이제부터는 이미지 데이터를 학습시키기 위한 모델을 만들어보겠습니다.
아래의 코드에서 ImageDataGenerator는 keras에서 제공하는 이미지데이터 학습을 위한 라이브러리입니다.
from keras.preprocessing.image import ImageDataGenerator
이번에 사용할 함수는 flow_from_directory() 함수입니다.
flow_from_directory() 함수는 폴더에 저장된 데이터를 불러오는 함수입니다.
이 함수는 이미지를 불러올 때 폴더명에 맞춰 자동으로 labelling 을 해주기 때문에 전의 강의 자료에서 강아지와 고양이에 따라서 각각의 맞는 폴더로 사진을 저장해준 것입니다.
아래의 코드에서 하나씩 살펴보겠습니다.
우선 첫 번째 파라미터에는 이미지를 읽어올 경로명을 적어주었습니다.
dogs-vs-cats/train/train 경로에서 이미지를 읽어오고, target_size=(64,64)를 통해 사이즈를 resize 해주었습니다.
그리고 한번에 32장의 사진을 읽기 위해 batch_size를 32로 지정해 주었습니다.
마지막 파라미터인 class_mode는 폴더명에 따라 labelling을 할 때 어떤 방식으로 할지 정해주는 파라미터입니다.
아래 코드에서는 class_mode = 'binary'를 통해 0 또는 1로 labelling을 합니다.
generator = ImageDataGenerator()
# ImageDataGenerator() : 주어진 데이터 이용해 변형된 이미지 만드는 함수이다.
train_gen = generator.flow_from_directory('dogs-vs-cats/train/train', target_size=(64,64),
batch_size = 32, class_mode = 'binary')
train_gen 을 입력하고 아래와 같이 결과가 나오면 됩니다.
train_gen
아래의 코드를 실행하면 방금 적용한 조건들에 맞추어 각 이미지에 해당하는 label들을 출력해줍니다.
아래의 출력 결과는 일부분만 캡쳐한 것이고 실제로는 이보다 더 길게 결과가 나옵니다.
next(train_gen)
x_batch, y_batch에 next(train_gen)의 값을 주어 이를 출력해보면 아래와 같은 결과가 나오게 됩니다.
첫 번째 줄의 32는 총 32개의 배치 데이터를 의미하고,
그 다음의 64, 64는 크기를 조정했을 때의 가로, 세로 크기를 의미합니다.
마지막 3은 컬러 이미지를 사용했기 때문에 RGB 3이 출력된 것입니다.
두 번째 줄은 0 또는 1로 나온 label 이 총 32개가 있다는 것을 의미합니다.
x_batch, y_batch = next(train_gen)
print(x_batch.shape)
print(y_batch.shape)
아래의 코드를 통해 모델을 만들기 전, 데이터를 확인해 보면 0과 255 사이로 지정되어 있는 것을 확인해볼 수 있습니다.
x_batch.max()
x_batch.min()
다음으로 이미지랑 label이 제대로 일치하는지 확인하기 위해
첫번째 index(index[0])의 이미지를 불러와 확인해보겠습니다.
위에서 class_mode = 'binary' 했을 때 이는 디렉터리 명들을 사전 순으로 나열하고 난 뒤 0과 1의 값을 매기기 때문에
강아지이면 1로 되어있고 고양이이면 0으로 되어있을 것입니다.
데이터 시각화를 위해 matplotlib.pyplot을 import 합니다.
next(train_gen)의 결과와 x_batch.max(), x_batch.min()의 값을 통해
데이터(배열)가 0-255 사이의 정수 값을 가지고 있는 것을 확인했습니다.
따라서 이미지를 보여줄 때 존재하는 배열의 데이터 타입을 변경하는 함수인 astype()함수를 이용해 int32(4바이트의 정수)로 설정해주었습니다.
import matplotlib.pyplot as plt
%matplotlib inline
plt.imshow(x_batch[0].astype('int32'))
plt.title(y_batch[0])
아래와 같이 이미지가 성공적으로 출력된다면 여기까지 잘 따라오고 계십니다.
하지만 저희는 label 을 0 또는 1로 잡았기 때문에 0-255의 값을 0-1로 rescale을 해주어야 합니다.
관련 내용은 다음 슬라이드에서 이어서 진행하겠습니다.
- 02. 데이터 전처리 과정2
02.데이터 전처리 과정2
우리는 label을 0 또는 1로 잡았기 때문에 0 - 255 를 0 - 1 사이로 줄이기 위해
ImageDataGenerator 함수의 옵션인 rescale을 통해 이를 처리해줍니다. 이를 제외한 나머지 코드는 아까와 동일합니다.
generator = ImageDataGenerator(rescale=1/255.)
train_gen = generator.flow_from_directory('dogs-vs-cats/train/train', target_size=(64,64),
batch_size = 32,
class_mode = 'binary')
아래 코드를 통해 내용을 다시 확인합니다.
x_batch, y_batch = next(train_gen)
print(x_batch.shape)
print(y_batch.shape)
이후 max 값을 출력하면 1로 바뀐 것을 확인할 수 있습니다.
x_batch.max()
그리고 다시 이미지를 출력해봅니다. 여기서 0 - 1로 조정을 했기 때문에 아래 코드에서는 astype('int32')를 사용하지 않습니다.
import matplotlib.pyplot as plt
%matplotlib inline
plt.imshow(x_batch[0])
plt.title(y_batch[0])
- 03. 모델 만들기
03. 모델 만들기
데이터 전처리를 완료했다면 이제는 모델을 구축할 차례입니다.
우선 모델을 구축하기 위해 keras.layers와 keras.models를 사용합니다.
모델의 기본단위는 층(layer)이며 즉, 모델은 layer로 이루어져 있기 때문에
모델이 구축되면 손실 함수(loss function) 값이 최소가 될 때까지
즉, 예측한 결과와 실제 값의 차이인 손실을 최대한 줄일 수 있을 때까지 데이터를 입력하고 실행시키는 과정을 반복하며
최적의 가중치(weight)와 바이어스(bias)값을 찾는 학습 과정이 진행됩니다.
구글 드라이브에서 가져온 데이터에서 train폴더안에 있었던 train data는 학습에 사용되는 데이터이고,
가중치와 바이어스를 최적화하기 위해 사용됩니다.
그리고 test1폴더에 있는 test data는 학습 후 정확도를 평가할 때 사용되는 데이터입니다.
이제 모델을 만들어볼텐데요. 모델을 만들기 전 모델의 기본적인 구조에 대해 살펴봅시다.
모델은 입력층, 은닉층, 출력층으로 이루어져 있습니다. 모델을 만든다는 것을 각 층에 대해 구현을 해주는 것을 의미합니다.
아래의 코드에서 build_model 함수를 살펴보면 먼저 입력 값으로는 shape(64,64,3)를 줍니다.
그 아래의 Flatten은 입력으로 들어오는 다차원 데이터를 1차원으로 정렬하기 위해 사용되는 layer입니다.
즉, 입력층은 Flatten을 통해 구현을 합니다.
Dense는 각 층의 입력과 출력 사이에 있는 모든 노드가 서로 연결되어 있는 완전 연결층을 나타내며, 첫번째 인자는 출력 노드수를 의미합니다.
Dense는 1차원 벡터에 대해서만 사용할 수 있기 때문에 모든 코드를 한줄로 펼쳐야 합니다.
따라서 위에서 out=Flatten()(out)를 해준 것입니다.
그리고 Dense 안의 activation은 노드의 활성화 함수를 의미합니다.
대표적인 활성화 함수는 일반적인 classification인 경우에 sigmoid, relu 등이 있습니다.
전에 다차원 데이터를 1차원으로 정렬하는 부분이 있었는데요, 입력 값인 shape=(64,64,3)을 한줄로 펼치면
64*64*3이기 때문에 약 12000짜리의 크기가 나옵니다. 이를 Dense를 이용해 원하는 크기로 줄입니다.
첫번째 Dense의 첫번째 파라미터는 512이기 때문에 512개의 노드로 줄여주는 것이고 각 층을 지날때마다 이에 대한 결과를 out에 저장해줍니다.
여기서는 총 4층짜리 모델을 만들어주었습니다. 주로 활성화함수는 'relu'가 많이 쓰이고 마지막은 0과 1사이로 매핑해주어야 하기 때문에 'sigmoid'를 사용하겠습니다.
마지막으로 model = Model(x,out)은 입력 값이 x이고 나가는 값이 out을 의미합니다.
from keras.layers import*
from keras.models import Model
def build_model():
x = Input(shape=(64,64,3))
out = x
out = Flatten()(out)
out = Dense(512, activation='relu')(out)
out = Dense(256,activation='relu')(out)
out = Dense(64, activation='relu')(out)
out = Dense(1, activation='sigmoid')(out)
model = Model(x,out)
return model
model.summary()를 통해 만든 내용을 요약해 볼 수 있습니다.
model = build_model()
model.summary()
결과는 아래와 같이 나오게 됩니다.
2.3. Model 학습시키기
- 01. 모델 학습하기
01.모델 학습하기
모델을 구축하였다면 구축된 모델을 기계가 이해할 수 있도록 컴파일을 해주어야 합니다.
이에 대한 최적화 방법,오차함수를 학습과정 중에 모니터링 할 지표로 나타내보겠습니다.
여기서는 compile()함수를 이용하여 모델 학습 과정을 설정합니다.
즉, 모델을 빌드하고 실행하기 전, 훈련 준비 단계라고 생각하시면 됩니다.
이 함수에서 첫 번째 파라미터는 optimizer로, 훈련과정을 설정하는 파라미터입니다.
여기서 최적화알고리즘(optimizer)은 sgd로 설정합니다.
그리고 두 번째 파라미터는 loss 로, 최적화 과정에서 최소화 될 손실함수를 설정하는 것으로
MSE, binary_crossentropy가 자주 사용됩니다.
우리는 label을 0과 1로 설정해놓았기 때문에 이진 분류인 binary_crossentropy를 사용합니다.
손실함수 값이 최소가 될 때까지 각 층의 가중치와 바이어스를 업데이트 하기 위해 model.fit 함수를 이용합니다.
첫번째 파라미터는 입력데이터이고, 그 다음 epochs를 통해 전체 데이터를 10번 진행하도록 설정해줍니다.
마지막 파라미터는 epoch 한번에 입력으로 주는 데이터를 몇으로 할 것인지 지정해주는 파라미터이며 train_gen 만큼을 steps_per_epoch에 저장해주었습니다.
아래의 결과를 보시면 학습을 할수록 성능이 점점 좋아지기 때문에 loss가 점점 줄어드는 것을 확인할 수 있습니다.
하지만 이는 오버피팅(overfitting)에 의한 결과일 수도 있다는 점을 유념해두어야 합니다.
# 이 모델을 학습
model.compile(optimizer='sgd', loss='binary_crossentropy')
history = model.fit(train_gen, epochs=10, steps_per_epoch = len(train_gen))
- 02. 모델 평가하기
02. 모델 평가하기
모델을 구축하고 학습을 시켰으면 이번에는 만든 모델을 평가해보도록 하겠습니다.
모델을 평가하기 위해 이번에는 test1의 사진들을 이용하겠습니다.
아까와 같이 flow_from_directory 함수를 이용하고 이번에는 classes=['test1']이라고 해주었습니다.
test1은 train 데이터와 다르게 label이 없기 때문에 class는 test1 한 개로 지정해주었습니다.
test_gen = generator.flow_from_directory('dogs-vs-cats/test1', target_size=(64,64),
batch_size = 32,
classes = ['test1'])
데이터를 예측하기 위해 model.predict 메소드를 불러오겠습니다.
이 메소드의 첫 번째 파라미터에는 예측하고자 하는 데이터가 들어와야 합니다.
저희는 test_gen을 예측하기 위해 첫번째 파라미터 값으로 test_gen을 주었습니다.
이에 대한 결과는 (400,1)로 나오게 됩니다.
pred = model.predict(test_gen)
pred.shape
pred를 입력하면 아래의 결과와 같이 예측한 모델 결과들을 0과 1 사이의 sigmoid 값으로 나오게 됩니다.
pred
- 03. 모델 테스트하기
03. 모델 테스트하기
이제는 사진과 함께 예측 결과를 확인해보도록 하겠습니다.
next(test_gen)을 x_test, y_test으로 받은 뒤, x_test 크기만큼의 사진들을 출력해 예측 결과를 확인해보겠습니다.
아래의 코드는 인덱스가 서로 맞아야 하기 때문에 코드를 작성하실 때 오류없이 작성하셔서 한번에 실행하는 것을 권장드립니다.
0은 고양이를 의미하고 1이 개를 의미하니 0.5를 기준으로
고양이 사진일 경우에 0.5보다 작게 나오거나
개 사진일 경우에는 0.5보다 크게 값이 나오면 잘맞춘 것입니다.
하지만 이번 실습은 학습을 많이 시키지도 않았고, 데이터도 충분하지 않은 점을 고려해
대부분의 예측 결과가 좋지 않을 수 있습니다.
아래의 코드를 실행시켜보고 각자의 예측 결과가 어떻게 나오는지 확인해봅시다!
x_test, y_test = next(test_gen)
for i in range(len(x_test)):
plt.imshow(x_test[i])
plt.title(pred[i])
plt.show()
3. 강의 참고 자료
① 데이터(사진) : www.kaggle.com/c/dogs-vs-cats/data
② 딥러닝 내용 :kyubot.tistory.com/96,kyubot.tistory.com/97
③ 활성화 함수 : https://reniew.github.io/12/
④ 케라스 :cyc1am3n.github.io/2018/11/02/introduction-to-keras.html
⑤ 전체 틀 : https://yjoo0913.tistory.com/12
'❤25기 > 25기 세미나' 카테고리의 다른 글
[25기 세미나] Pygame 모듈로 눈송이게임 만들기 (0) | 2021.03.03 |
---|---|
[25기 세미나] PyQt5로 그림판 만들기(2) (0) | 2021.03.03 |
[25기 세미나] PyQt5로 그림판 만들기(1) (0) | 2021.03.03 |
[25기 세미나] 국내가요 TOP 100 가사 크롤링해서 워드 클라우드 만들기(2) (0) | 2021.03.03 |
[25기 세미나] Selenium으로 솔룩스 공식 사이트에 자동으로 댓글 달기(2) (0) | 2021.03.03 |