코드스테이츠 AI 부트캠프/Section 4

AIB_411_복습정리 : 딥러닝 인트로 / 인공신경망(ANN)

yourhm 2022. 1. 18. 09:15

'퍼셉트론' 이해하기

• 다수의 신호를 입력(input)받아서, 하나의 신호를 출력(output)한다.

• 예측값과 실제값의 차이가 최소가 되는 가중치를 찾는 과정이 퍼셉트론이 학습하는 과정.

• 퍼셉트론의 구조

     - 가중합(가중치-편향 연산) + 활성화함수

     - 가중합: 입력 신호와 각각의 가중치를 곱한 뒤 모두 합한 뒤,

     - 활성화함수: 가중합 결과 값에 활성화 함수를 적용하여 값을 출력한다.

• 퍼셉트론의 종류

     - 단층 퍼셉트론 (입력층과 출력층만 존재)

     - 다층 퍼셉트론 (입력층과 출력층사이에 은닉층이 존재)

• 퍼셉트론의 가장 단순한 형태는 AND, NAND, OR 과 같은 논리 게이트(Logic Gate)이다.

• 퍼셉트론 1개로 해결할 수 없는 Gate는? XOR Gate

• 퍼셉트론 1개로는 오직 직선 한개만 그릴 수 있다. (분류 분포도에서 나눌 때)

     - AND Gate: 두 조건 모두 만족할때만 동작하는 것.

     - NAND Gate(=Not AND): 두 조건 모두 만족할때만 동작하지 않는 것.

       => AND Gate 결과값과 반대 결과

     - OR Gate: 두 조건중 최소 하나만 만족하더라도 동작하는 것.

     - XOR Gate: 두 조건중 단 하나만 만족할 때만 동작하는것.

 

 

예제 1. 실생활에 비유해보기

예를 들어, 야식을 먹는데 아래와 같은 조건이 있다고 하자.

- 저녁을 안먹은 경우

- 내일 출근을 안하는 경우

 

앤드류는 AND Gate처럼 동작하는 사람이다. (두 조건을 모두 만족해야만 야식을 먹는다.)

벨라는 OR Gate처럼 동작하는 사람이다. (두 조건중 하나만 만족해도 야식을 먹는다.)

캐롤은 NAND Gate처럼 동작하는 사람이다. (두 조건을 모두 만족하면 야식을 먹지 않는다.) 청개구리같은 사람...

 

 

예제 2. 논리 구조로 XOR을 표현하면?
x1, x2는 각각 (0, 0), (1, 0), (0, 1), (1, 1) 형태로 입력된다고 하자.

XOR <= AND(NAND(x1, x2), OR(x1, x2))

 

 

 

인공신경망 (Artificial Neural Network, ANN)

신경망의 기본 단위? 퍼셉트론

 

입력층

• 입력층의 노드 수: 데이터셋의 피쳐(특성)의 갯수

• 신경망 층수를 셀 때 얘는 포함하지 X, 보통 자동으로 입력되서 코딩할때 굳이 안써줘도됨

은닉층

• 입력층과 출력층 사이에 있는 모든 층을 은닉층이라고 부른다.

• 인공신경망의 강력한 성능은 은닉층을 추가하여 입력 데이터에 대해 연속적인 학습을 진행하는 능력에서 나온다.

은닉층의 노드 수: 사용자가 정하는 것. 단, 적어도 출력층의 노드보다는 많게 만들어야 한다. 예를 들어 다중분류 문제로, 클래스 10개에 대한 확률을 예측해야 하는데 이전 은닉층의 노드가 10개보다 적다면 부족한 정보가 전달될 것이다. (몇 개를 두어야 할지 판단하기 위해서는 상당한 경험이 필요함)

은닉층의 레이어 갯수: 이것도 정해진 바는 없다. 사용자 정의임 (단, 은닉층이 2개 이상인 신경망을 심층 신경망(Deep Neural Network, DNN) 또는 딥러닝이라고 한다. 인공 신경망의 층을 깊게(Deep) 쌓아서 학습하기 때문에)

• 은닉층의 활성화 함수: 이것도 정해진 바는 없다. 출력층에 적용하는 활성화 함수에 비하면 선택에 대해 비교적 자유로운 편이다. 대표적으로는 sigmoid함수와 relu함수 등을 많이 사용한다.

 

출력층

출력층의 노드 수, 활성화함수는 어떤 문제인지에 따라 다르다.

 

문제 출력층의 노드 수 출력층의 활성화 함수
이진 분류 1 시그모이드
다중 분류 타겟의 클래스 갯수 소프트맥스
회귀 몇 개의 수를 출력할 건지에 따라 그 숫자대로 (보통 하나의 수를 예측하기때문에 1) 분류문제는 클래스에 대한 확률을 출력하기 위해 활성화함수가 사용하지만, 회귀의 출력은 임의의 어떤 숫자이므로 활성화함수를 적용할 필요가 없다. 즉 출력층의 선형 방정식의 계산을 그대로 출력한다. (코딩할 때, Dense층의 activation 매개변수에 아무런 값을 지정하지 않으면 됨)

 

 

 

활성화 함수 종류

만약 활성화 함수에 아무 것도 지정해주지 않으면, 계산된 가중합 값에 어떠한 활성화 함수도 적용되지 않고 출력된다. 이 것을 굳이 표현하면 "linear" activation: a(x) = x 이라고 할 수 있는 것. → 가중합 값에 어떤 활성화 함수도 적용되지 않았으므로 그냥 그 값 그대로 나온다는 의미.

 

1) Step(계단 함수)

• 임계값 지점에서 미분이 불가능하고, 나머지 지점에서는 미분값이 0이 나온다.
• 단점: 그렇기 때문에 실제로 계단 함수를 활성화 함수로 사용하면 학습이 제대로 이루어지지 않는다.

 

2) Sigmoid(시그모이드 함수)

• 계단 함수처럼 임계값보다 작은 부분은 0에 가까워지고, 큰 부분은 1에 가까워진다.

• 계단함수와는 달리 모든 지점에서 미분이 가능하며, 미분값도 0이 아니다.

장점: 계단 함수의 단점이 보완되기 때문에 이진 분류 문제의 신경망 출력층에서 활성화 함수로 사용할 수 있다.

단점: 시그모이드 함수를 중복으로 사용하면 '기울기 소실(Vanishing Gradient)' 문제가 발생하게 된다.

 

3) ReLU(렐루 함수)

시그모이드 함수의 '기울기 소실' 문제를 해결하기 위해 등장한 함수.

• 양의 값이 입력되면 그 값을 그대로 출력하고, 음의 값이 입력되면 0을 반환한다.

장점: 특히 이미지 처리에서 좋은 성능을 낸다고 알려져 있다.

 

4) Softmax(소프트맥스 함수)

다중 분류(Multi Classification) 문제에 적용할 수 있도록 시그모이드 함수를 일반화한 활성화 함수.

가중합 값을 소프트맥스 함수에 통과시키면, 모든 클래스의 값의 합이 1이되는 확률값으로 변환된다. 

 

 

 

[참고] TensorFlow/Keras Built-in activation functions.내장 활성화 함수 종류 더보기

https://www.tensorflow.org/api_docs/python/tf/keras/activations

 

Module: tf.keras.activations  |  TensorFlow v2.11.0

Built-in activation functions.

www.tensorflow.org

 

 

활성화 레이어는 뭐지? (Activation Layer)

단순한 텐서플로우 함수보다 더 복잡한 활성화는 'Advanced Activation layers'를 사용하면 가능하다. 단 활성화 레이어 인스턴스는 일반 레이어안에 있는 activation function 인자로 전달하면 안되고, 활성화 레이어는 일반적인 레이어처럼 사용해야한다.(아래 예시처럼)  ft.keras.layers.advanced_activations 모듈에서 찾을 수 있다.

 

x = layers.Dense(10)(x)    # regular layer
x = layers.LeakyReLU()(x)  # activation layer

 

[참고] 케라스 공식문서: About "advanced activation" layers

https://keras.io/api/layers/activations/#about-advanced-activation-layers

 

Keras documentation: Layer activation functions

Layer activation functions Usage of activations Activations can either be used through an Activation layer, or through the activation argument supported by all forward layers: model.add(layers.Dense(64, activation=activations.relu)) This is equivalent to:

keras.io

 

 


파이썬 코딩 연습하기💬

 

STEP 0. 데이터 불러오기

STEP 1. 데이터 전처리

인공 신경망 모델에 주입하려면, 2차원 -> 1차원 배열로 만들어줘야함

 

🔽 2차원 이미지 데이터 전처리하는 방법

방법 1.

전처리 단계 reshape 사용: 직접 1차원으로 만들기

train_scaled = train_input / 255.0  # 픽셀정규화
train_scaled = train_scaled.reshape(-1, 28*28)  # 1차원으로 만들기(reshape)

model = tf.keras.models.Sequential()
model.add(tf.keras.layers.Dense(100, activation='relu', input_shape=(784,)))
model.add(tf.keras.layers.Dense(10, activation='softmax')

 

방법 2.

전처리 단계 reshape 사용X: 전처리 단계에서는 그냥 픽셀정규화만 하기

모델 구축 단계 Flatten 사용: 모델 구축하는 과정 안에서 1차원으로 만들기

train_scaled = train_input / 255.0  # 픽셀정규화

model = keras.Sequential()
model.add(keras.layers.Flatten(input_shape=(28, 28)))  # 1차원으로 만들기(Flatten)
model.add(keras.layers.Dense(100, activation='relu'))
model.add(keras.layers.Dense(10, activation='softmax'))

입력 데이터에 대한 전처리 과정을 방법2 처럼 가능한 모델에 포함시키는 것이 케라스 API의 철학 중 하나라고 한다.

 

 

STEP 2. 케라스 인공 신경망 모델 만들기

🔽 이중분류 문제 (입력층 , 출력층)

방법1. Dense 클래스의 객체를 만든 후, Sequential 클래스에 전달하기.

dense = tf.keras.layers.Dense(1, activation='sigmoid')
model = tf.keras.models.Sequential(dense)

 

방법 2. Sequential( ) 클래스 생성자 안에서 바로 Dense 클래스의 객체를 만들기

model = tf.keras.models.Sequential([
    tf.keras.layers.Dense(1, activation='sigmoid')
])

 

방법 3. Sequential( ) 객체를 먼저 만든 후, model의 add( ) 메소드 사용하여 층 추가하기

model = tf.keras.models.Sequential()
model.add(tf.keras.layers.Dense(1, activation='sigmoid'))

 

 

🔽 다중분류 문제 (입력층, 출력층)

방법 1.

dense = tf.keras.layers.Dense(10, activation='softmax', input=(784,))
model = tf.keras.Sequential(dense)


방법 2.

model = tf.keras.models.Sequential([
    tf.keras.layers.Dense(10, activation='softmax')
])

 

방법 3.

model = tf.keras.models.Sequential()
model.add(tf.keras.layers.Dense(1, activation='softmax'))

 

 

🔽 다중분류 문제 (입력층, 은닉층1개, 출력층)

방법 1.

dense1 = tf.keras.layers.Dense(100, activation='sigmoid', input_shape=(784,))
dense2 = tf.keras.layers.Dense(10, activation='softmax')
model = tf.keras.models.Sequential([dense1,dense2])

 

방법 2.

model = tf.keras.models.Sequential([
  tf.keras.layers.Dense(100, activation='sigmoid', input_shape=(784,))
  tf.keras.layers.Dense(10, activation='softmax')
  ])

 

방법 3.

model = tf.keras.models.Sequential()
model.add(tf.keras.layers.Dense(100, activation='sigmoid', input_shape=(784,)))
model.add(tf.keras.layers.Dense(10, activation='softmax')

 

 

STEP 3. 모델 컴파일

model.compile(optimizer='sgd',
              loss='binary_crossentropy',
              metrics=['accuracy'])

이진분류

  • loss = 'binary_crossentropy'

다중분류

  • loss = 'categorical_crossentropy' ← 타겟값이 원핫인코딩되었을 때
  • loss = 'sparse_categorical_crossentropy' ← 타겟값이 정수일 때

 

 

STEP 4. 모델 학습

model.fit(X_train, y_train, epochs=30)

케라스 모델의 fit( ) 메소드에 훈련 데이터를 주입하면, 한번에 모두 사용하지 않고 잘게 나누어 여러번에 걸쳐 경사 하강법 단계를 수행한다. 즉 기본적으로 '미니배치 경사하강법'을 사용하여 학습함. 

  • batch_size = Integer or None.
    : 아무것도 쓰지 않으면 Default 값은 32개.

검증 데이터 셋에 대한 유효성 평가도 가능하다. 

  • validation_data = (X_val, y_val) ← train 데이터셋에서 미리 validation 데이터셋을 떼어둔 경우 (train, valid, test)
  • validation_split = 0.2 ← train 데이터셋에서 마지막 20% 데이터를 validation 데이터셋으로 사용 (train, test)

 

[참고자료] 내장 메서드를 이용한 학습 및 평가 Tensorflow Documentation

https://www.tensorflow.org/guide/keras/train_and_evaluate?hl=ko

 

 

STEP 5. 모델 평가

model.evaluate(X_test, y_test, verbose=2)

verbose 매개변수는 훈련 과정 '출력'을 조절한다. Default 값은 1.

  • verbose = 0 : 훈련과정을 출력하지 않는다.
  • verbose = 1 : 에포크마다 진행 막대와 함께 손실 등의 지표를 출력한다. (Default)
  • verbose = 2 : 에포크마다 진행 막대는 제외하고 지표만 출력한다.

 

 


Q&A

Q1. 퍼셉트론과 노드를 같다고 봐도 되는지, 아니라면 차이점이 뭔지?

퍼셉트론: 입력이 여러개, 출력이 한개.

노드: 신경망에서 연산을 하는 것.

 

Q2. 모델이 fit 과정에서 학습 중간에 loss nan 값이 나오는 이유가 궁금합니다. 

학습이 잘못 되었을 가능성이 높다. loss function을 문제에 맞게 잘 세팅했는지 확인이 필요하다.

 

Q3. 출력층 회귀에서 노드 수는 출력층의 특성 수와 동일하다는 말이 잘 이해가 안갑니다. 입력층에서 특성과 어떻게 다른 건가요?

예를 들어 여러 피쳐들로 수학 성적을 예측하는 회귀 문제가 있다.

수면시간, 나이, 공부시간, IQ => 수학 성적 (회귀문제)

4개 : 입력층의 노드 수 

1개 : 출력층의 노드 수

 

Q5. 타겟이 binary인 경우에 차원을 늘려서 최종 출력층 노드를 2개로 바꿔 소프트맥스를 쓰는 것과 또는 그냥 1차원으로 시그모이드로 출력하는 것의 두 경우 중 어떠한 방법이 더 좋다 혹은 나은 방법이다 라고 할 수 있나요?

더 좋은 방법은 없다. '나은' 방법은 있을 수 있다.

- 노드 수 1개 & sigmoid => 더 낫다!

- 노드 수 2개 & softmax => 신경망에서 학습해야하는 것은 가중치인데, 그 가중치 갯수가 더 많아진다. 학습해야할 가중치 갯수가 많아지면 신경망의 학습속도가 느려진다.

 

Q6. binary 클래스로 나눌 때 출력값을 왜 1로 잡는지 살짝 헷갈립니다. 2개라고 생각했거든요.

Section2에서 로지스틱 회귀에서 계산된 결과값(0~1)이 임계값을 기준으로 sigmoid함수를 사용하여 0/1 로 분류

0.2 => class 0

0.7 => class 1

 

즉 값 하나로도 시그모이드를 사용하면 이진분류가 가능하다.

 

Q7. '모델을 학습한다' 의미는? 무엇이 학습되는 걸까요?

가중치를 학습하는 것이다.

input 모델 output  
입력값 sum(입력값 * 가중치) + bias 출력값 출력값과 실제 타겟값의 차이가 작을수록 좋은것.

 

Q8. 여기서 각 층의 노드의 수 ?

model = tf.keras.models.Sequential([
  tf.keras.layers.Dense(64, input_shape=(100,)), 
  tf.keras.layers.Dense(128, activation='relu'),
  tf.keras.layers.Dense(5, activation='softmax') 
 ])

입력층: 100개

은닉층: 각각 64개, 128개

출력층: 5개

 

 

 

[참고자료]

layer 종류

https://ssongnote.tistory.com/13