상세 컨텐츠

본문 제목

[PLAYDATA] 데이터 엔지니어링 9월 3주차 9/15

PLAYDATA/PLAYDATA데일리노트

by Na느님 2023. 9. 15. 06:03

본문

  • 9월 15일
딥러닝, 인공신경망,심층신경망에 대해 배운다

 

 

딥러닝이란?

딥러닝은 머신러닝의 하위 분류로, 머신러닝 중에서 특히 인공신경망 이라는 기술을 이용한 머신러닝 방법이다.

다층 구조의 은닉층(중간층)으로 네트워크를 연결한 모습을 띄고 있다.

 

 

MNIST

딥러닝에서 가장 대표적인 데이터셋은 MNIST(Modified National Institute of Standards and Technology database)으로, 많은 숫자 손글씨들로 이루어진 데이터셋이다.

-> 숫자 대신 의상으로 이루어져 있는 패션MNIST도 있다.

 

 

텐서플로우와 케라스

텐서플로우는 구글에서 공개한 머신러닝 라이브러리이다.

케라스는 거의 모든 종류의 딥러닝 모델을 간편하게 만들고 훈련시킬 수 있는 패키지이다.

텐서플로우에는 high-level API가 있고, low-level API가 있다. 켈라스는 high-level API이다.

 

 

패션MNIST 데이터셋 세팅하기

from tensorflow import keras

(train_feature, train_target), (test_feature, test_target) = keras.datasets.fashion_mnist.load_data()

(주의!) keras의 load_data함수는 sklearn의 train_test_split과는 달리 반환형이 2개의 튜플 형태이다!

-> Tuple of Numpy arrays: `(x_train, y_train), (x_test, y_test)`.

 

 

인공신경망(ANN)

인공신경망의 기본 구조. 출처: 위키피디아

인공신경망이란, 인간의 뉴런 구조를 본따서 만든 머신러닝 기법 중 하나이고, 딥러닝의 핵심 기법이다.

위의 그림처럼, 입력값을 직접 받는 뉴런들의 층을 입력층,

최종 값을 받는 뉴런들의 층을 출력층,

그리고 중간값들을 받는 뉴런들의 층을 은닉층 이라고 한다.

 

Tip) 특정 층의 개별 뉴런들은 이전 층의 뉴런들의 선형회귀 구조(좀 더 정확히는 sigmoid가 추가된 로지스틱 회귀)를 따른다!

그래서 인공신경망의 선수개념 중 하나가 선형회귀&로지스틱 회귀인 것이다.

 

(주의!) 인공신경망의 뉴런은 실제 뉴런과는 많은 차이가 존재한다. 실제 뉴런은 인공신경망처럼 가중치를 입력값과 곱하여 출력값을 만드는게 아니다.

인공신경망은 정말 뇌 속에 있는 무언가를 만드는 일이 아니라는 것을 꼭 기억하자.

 

 

인공신경망으로 모델 만들기

 

Tip) 인공신경망은 교차 검증을 잘 사용하지 않는다. 딥러닝에서 교차검증을 하기엔 너무 오래 걸리기 때문이다.

 

이전 층의 각 뉴런마다 현재 층의 모든 뉴런들을 전부 연결하고 있을 때, 이 층을 완전 연결층 이라고 한다.

keras에서 완전연결층은 Dense함수를 이용한다.

dense = keras.layers.Dense(<num_of_neuron>[, activation = <str>][, input_shape = <dimensions>][, name = <str>])

num_of_neuron: 출력층(입력층의 다음 층)의 뉴런의 갯수

activation: 출력층(입력층의 다음 층) 뉴런에 적용할 함수(예를 들면 "softmax")

input_shape: 입력층의 뉴런의 갯수(차원 형태로 입력). 예를들면 (512, )

 

Tip) 출력값들 간의 확률분포를 표현하려면 softmax함수를 적용한다.

 

Sequential함수를 사용하여 모델 객체를 만든다. (Dense함수와 혼동 주의!)

model = keras.Sequential(dense)

 

 

모델 객체 설정하기

sklearn과는 달리 keras는 학습 명령을 내리기 전에 설정을 먼저 해 줘야할 필요가 있다.

-> fit함수를 호출하기 전에 compile함수를 먼저 호출해야 한다.

 

model.compile(loss = <str>[, optimizer = <str>][metrics = <list>])

metrics옵션은 keras로 학습중일 때, 지정한 학습척도를 보여주는 기능이다. 예를들어 ['accuracy']의 경우, 매 epoch마다 추정값이 원래값과 얼마나 동일한 지를 0~1 사이의 수치로 보여준다.

일반적으로 인공신경망의 loss함수는 cross entropy함수를 사용한다. (target데이터는 one-hot encoding 거쳐야 함)

 

크로스 엔트로피

cross entropy

mid-side 공식은 이해하기 어려우니 right-side 공식을 보자.

여기서 Q함수는 이산확률변수 x의 확률분포를 말한다.

P함수는 일정 확률 이상의 값은 1로 표현하고 그 미만은 0으로 표현되는 함수이다.

예를들어 임계값이 0.5인 확률분포를 보자.

확률변수 Q(x) P(x)
x1 0.7 1
x2 0.2 0
x3 0.1 0

cross entropy는 Q에 log를 취한뒤 P함수를 곱한다음, 모든 변수에 대해 합하고, 마지막으로 부호를 반전시키면 된다.

(log1 값은 0이다)

따라서 위의 cross entropy는 -(1xlog0.7 + 0xlog0.2 + 0xlog0.1) 이다.

 

(주의!) 다중 분류에서 cross entropy를 사용하려면 원-핫 인코딩을 수행해야 한다.

one-hot encoding이란 정수 자료형을 하나만 1이고 나머지는 전부 0인 바이너리 형태로 표현하고, 각 정수값을 1의 위치로 구별할 수 있도록 변환하는 것이다.

 

keras에서 이진 분류에는 "binary_crossentropy" 손실함수를 사용한다.

다중 분류에는 "categorical_crossentropy" 손실함수를 사용한다.

one-hot encoding없이 정수값의 target데이터로 학습하려고 한다면 "sparse_categorical_crossentropy"를 사용한다.

 

 

모델 훈련 및 평가

compile함수로 모델을 설정했으니 이제 본격적으로 훈련시켜보자.

model.fit(<train_data>, <train_target>, epochs = <n>)

epochs 옵션은 전체 데이터 셋을 얼마나 반복시킬지 정하는 옵션이다.

 

모델 평가는 evaluate함수를 사용한다.

model.evaluate(<val_scaled>, <val_target>)

 

 

심층 신경망

입력층, 출력층 뿐 만 아니라 은닉층까지 포함된 인공신경망을 심층신경망(DNN) 이라고 부른다.

출력층의 활성화 함수는 sigmoid나 softmax등 거의 제한된 종류로 사용된다.

그러나 은닉층의 활성화 함수는 이 둘 뿐만 아니라 ReLU와 같은 다양한 활성화 함수가 사용된다.

 

Why?) 왜 은닉층에 활성화 함수를 적용하는가?

일단 활성화 함수는 비선형 함수이다. 만약 활성화 함수가 없다면, 입력부터 출력층까지 모두 선형연산만 하게 되는데, 선형 연산을 여러번 하는 것은, 입/출력이 동일한 하나의 선형 연산으로 치환되기 때문에 은닉층이 의미가 없어지기 때문이다.

예를들어 두 연산이 있다고 해 보자.

x2 = 3 x (x1) + 5

y = 2 x (x2) + 1

이것은 아래의 하나의 선형 연산과 동치이다.

y = 6 x (x1) + 11

따라서 선형연산을 여러번 한 의미가 없어진다.

 

심층 신경망의 구현

앞에서 보았듯이, Dense함수를 통해 dense객체를 만들고, dense객체들을 Sequential함수에 넣어서 인공신경망 객체를 생성했다.

여기서 Sequential함수에 인자를 dense객체들의 list형태로 넣어준다면 층이 여러개인 인공신경망을 만들 수 있다.

dense1 = keras.layers.Dense(<num_of_neuron>[, activation = <str>][, input_shape = <dimensions>][, name = <str>])

dense2 = keras.layers.Dense(<num_of_neuron>[, activation = <str>][, input_shape = <dimensions>][, name = <str>])

model = keras.Sequential(<dense_obj_list>)

 

(주의!) 출력층이 항상 list의 마지막 인덱스에 위치해야 한다.

 

e.g.)

dense1 = keras.layers.Dense(150, activation = "sigmoid", input_shape = (400, ))

dense2 = keras.layers.Dense(5, activation = "softmax")

model = keras.Sequential([dense1, dense2])

위 예제의 경우, 입력층은 400개, 은닉층은 150개, 출력층은 5개의 뉴런이 있다. 첫번째 코드에서 해당 층의 다음층의 뉴런갯수를 150개로 하면서 sigmoid함수를 지정했기 때문에, 입력층의 다음 층인 은닉층 뉴런에서 sigmoid함수가 적용된다.

마찬가지로 두번째 코드에서 softmax함수를 적용했기 때문에, 두번째의 다음 층인 출력층 뉴런에서 softmax함수가 적용된다.

 

심층 신경망의 구현2

만약 층이 많아진다면 위와 같은 방식으로 코드를 짤 때 Sequential의 list길이가 너무 길어지는 문제가 있다.

여기서는 원리는 동일하되, add함수를 사용하는 방법을 보여준다.

model = keras.Sequential()

model.add(keras.layers.Dense(...))

model.add(keras.layers.Dense(...))

...

 

이제 만든 DNN을 학습시키는 것은 이전에 설명한 것과 동일하게 compile, fit함수를 사용한다.

 

 

ReLU 함수

ReLU 함수란 활성화 함수 중 하나로, 음수일 경우 0을 반환하고, 0이상의 값은 그대로 출력하는 함수이다.

 

Why?) 왜 DNN에서 ReLU를 쓰는가?

초창기에는 심층신경망에서 sigmoid함수를 사용하였다. 그러나 sigmoid특성상 뉴런의 출력값이 0에서 멀어질 수록 기울기가 극단적으로 작아져 다음 층의 입력값들이 거의 동일해진다(분산이 거의 0이된다). 입력값들이 서로 거의 차이가 없어지게 되면, 처음 입력의 입력값들이 서로 많이 차이가 나도 마지막에는 다 비슷비슷하게 출력되기 때문에 학습이 제대로 되지 않는다.

따라서 sigmoid함수를 대체할 함수가 필요했고 여기 중에서 ReLU함수가 사용된다.

 

ReLU함수는 activation옵션을 "relu"로 지정하면 사용된다.

 

 

옵티마이저

keras 패키지는 다양한 종류의 경사하강법을 제공한다. 이것들을 옵티마이저 라고 부른다.

<추후 추가>

 

Tip) model.summary()함수를 사용하면 인공신경망 모델의 정보를 출력한다.

 

 

 

관련글 더보기