티스토리 뷰

Study/AI

[DL] 해보면서 배우는 딥러닝 - ANN 구현 (3)

생각많은 소심남 2017. 4. 25. 01:59
* 여기에 담긴 내용은 Udemy에서 진행되는 DeepLearning A-Z(https://www.udemy.com/deeplearning)의 일부를 발췌했습니다.

지난 포스트까지 했던 작업은 Artificial Neural Network의 토대를 잡고 그 안에 들어갈 Layer의 정의, 특히 1개의 Input Layer와 2개의 Hidden Layer, 그리고 마지막 output Layer를 만들고 각각에 적용할 Activation function까지 정의했다. 이제 만들어진 Layer를 ANN로 묶어서 처리하는 과정이 필요하다. Keras에서는 이 과정을 compile이라고 말하는 것 같다. compile 함수의 인자로는 다음 내용이 들어간다.


여기서 필요한 인자는 optimizer, loss, metrics 이다. optimizer는 말그대로 Neural Network을 구성하는 알고리즘을 최적화시켜주는 도구이다. 우리가 사용하고 있는 Stochastic Gradient Descent 알고리즘에는 adam optimizer라는 것을 사용한다. 이게 궁금한 사람은 논문을 참조하고 다른 optimizer를 찾고 싶다면 링크를 살펴보면 좋을거 같다.

 loss function은 우리가 앞에서 소개한 Cost function과 유사한데, 예측값과 실제값간의 차이를 표현한 일종의 수식이다. 수식적으로 설명하기엔 복잡하기에 우리가 사용하는 loss function은 binary_crossentropy라는 log형식의 cost function이라고만 설명하겠다. (참고로 binary가 아닌 3 이상의 결과에 대한 loss function은 categorical_crossentropy를 사용하면 된다.)

 마지막으로 metrics 이라는 것이 있는데, 이건 실제 화면상으로 출력되는 output을 표현한다. 사실 우리가 뭔가를 학습시키는데 있어, 잘된다, 안된다를 판단하는 기준이 뭘까? 바로 정확성(accuracy)가 아닐까? 이값을 넣어주면 된다. 물론 여기에 들어가는 인자의 형식은 list이므로 더 얻고 싶은 데이터가 있다면 추가해줘도 된다.

 위에서 표현한 내용을 코드로 구현하면 다음과 같다.

56
57
# Compiling the ANN
classifier.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])
cs

여기까지가 Artificial Neural Network을 만드는 과정이었다. 이제 가장 마지막으로 해야 될 내용이 바로 학습이 되겠다. 이전포스트에서 우리는 사전에 10000개의 정보중 8000개의 training set과 2000개의 test set을 구별했다. 그럼 8000개의 data를 가지고 우리가 만든 ANN에 집어넣고, 반복과정을 거쳐 cost function을 minimize 시킬 수 있는 최적의 weight를 찾아야 한다.(물론 우리가 이 weight을 실제로 알 필요도 없고, 이 모든 과정을 이 keras가 자동으로 해준다) 이 학습 과정을 수행하는 함수가 Fit이다. 이 함수도 정의와 필요 인자를 보면 다음과 같다.

첫번째와 두번째 인자인 x와 y는 우리가 학습 시킬 데이터의 x, y, 앞에서 정한대로라면 X_train과 y_train이 들어가면 된다. 그리고 추가로 더 정해줘야 할 인자가 바로 batch_size와 epochs다. batch_size는 말그대로 학습시킬 군집의 단위를 말한다. 그리고 epochs란 전체 단위가 학습되는 횟수를 말한다. 가령 epoch가 10이라면 batch_size만큼 10번 돌리겠다는 의미로 인식하면 된다. 

 사실 이런 인자들은 딱히 어떤 것을 넣으라고 정형화된 식이 없다. 그렇기 때문에 이런 걸 하면서 어떤 size가 좋을까 경험적으로 겪고, 집어넣은게 좋을 수 있다. 보통 이런식으로 값을 조절하면서 최적의 accuracy를 뽑아내는 과정을 parameter tuning이라고 한다. 물론 눈썰미가 있는 사람이라면 이런게 금방되면서 accuracy를 높게끔 수치를 적절히 수정할 것이다. 

 이번 예제에서는 batch_size를 10, epochs를 100으로 정의했다. 이말은 10개의 집단을 100씩 학습하겠다는 말이다. 그래서 이 코드를 수행하게 되면 IPython console로 100번 수행되는 과정이 출력된다. 그리고 앞에서 정의했던 accuracy가 나타나는 형태로 출력된다. 코드는 다음과 같다.

56
57
58
59
60
# Compiling the ANN
classifier.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])
 
# Fitting the ANN to the Training set
classifier.fit(X_train, y_train, batch_size=10, epochs=100)
cs

실제 실행은 다음과 같이 진행된다.

(* 사실 난 지금 환경에서 gpu 관련 library까지 같이 설치했었는데, 이렇게 하고 실행하니까. CUDA Library에서 cuDNN을 읽어올수 없다는 오류가 많이 출력되었다. 이걸 해결하려면 CUDA Driver와 cuDNN 전용 Driver를 받아서 설치한 후 환경변수로 해당 경로를 PATH로 잡아줘야 한다. 나같은 경우에는 3월에 Release된 CUDA Driver v8.0 를 설치하니까 정상적으로 인식되었다. 그런데 왠지 gpu로 처리하는게 cpu보다 느린거 같다는 느낌... 나중에 jetson tx1에다가 올려보고 test해볼 필요가 있겠다.)

여기까지 하면 accuracy가 대략 83.4%로 수렴하는 것을 확인할 수 있다. 시간은 대략 4분정도 걸렸는데, 이상했다. 내가 내 랩탑으로 했을때는 더 빨랐던거 같은데... 아무튼 이렇게 한게 Neural Network로 일종의 학습 모델을 생성한 것이다. 이제 이게 정상적으로 생성된건지 test를 해봐야 되고, 이때 사용되는게 이전에 만들어둔 test set이다. 이때 predict 함수를 사용한다.

56
57
58
59
60
61
62
63
# Compiling the ANN
classifier.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])
 
# Fitting the ANN to the Training set
classifier.fit(X_train, y_train, batch_size=10, epochs=100)
 
# Predicting the Test set results
y_pred = classifier.predict(X_test)
cs

이렇게 하고 Variable Explorer상으로 살펴보면 각각의 output에 대한 확률이 출력되는 것을 확인할 수 있다.

 그런데 이것만 가지고 정확히 예측이 되었는지 안되었는지를 확인할 수 없으니까 0.5보다 높은 확률이면 1, 아니면 0의 형식으로 위의 y_pred를 바꾼다. python으로는 간단하게 한줄로 위의 형태를 바꿀 수 있다.

56
57
58
59
60
61
62
63
64
# Compiling the ANN
classifier.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])
 
# Fitting the ANN to the Training set
classifier.fit(X_train, y_train, batch_size=10, epochs=100)
 
# Predicting the Test set results
y_pred = classifier.predict(X_test)
y_pred = (y_pred > 0.5)
cs

그러면 위의 형태가 이렇게 변한다.

그러면 이거만 가지고는 정확히 예측을 한 확률을 따질 수 없으니까 일종의 시각화 작업을 거치는 것이 필요하다. 보통 위와 같이 binary value를 비교할 때 많이 사용되는 형식이 바로 confusion matrix이다. 그래서 0과 1을 x,y축으로 두고 정확히 예측한 경우의 수와 아닌 수를 구분해준다. 

56
57
58
59
60
61
62
63
64
65
66
67
# Compiling the ANN
classifier.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])
 
# Fitting the ANN to the Training set
classifier.fit(X_train, y_train, batch_size=10, epochs=100)
 
# Predicting the Test set results
y_pred = classifier.predict(X_test)
y_pred = (y_pred > 0.5)
 
from sklearn.metrics import confusion_matrix
cm = confusion_matrix(y_test, y_pred)
cs

이렇게 해주면 결과는 다음과 같이 나온다.

여기서 우리가 눈여겨봐야 할 값은 (0,0)과 (1,1)이다. 이게 바로 학습된 Neural Network가 정상적으로 예측한 case가 되는 것이다. 이걸 토대로 예측 정확성을 계산해보면

이라는 결과가 나오게 된다. 10개를 물어보면 8.5개 정도는 맞춘다는 의미니까 얼추 맞는다고 할 수 있겠다.

이런식으로 Neural Network를 사용해서 학습시키고 예측하는 예제를 다뤄보았다. 물론 위의 결과는 아주 formal하고 쉬운 예제를 위해 많은 이론을 생략하고, 넘어갔기 때문에 결과가 저렇게 나온 것이고, 잠깐잠깐 설명했던 data cleaning이나 parameter tuning같은 것을 더 하면 정확성을 조금더 높힐 수 있다.

 전체 코드는 아래를 통해 전달해드립니다.

ann_part3.py

댓글