ℹ️ <혼자 공부하는 머신러닝+딥러닝> 책을 읽고 정리한 내용입니다.
뉴런을 아는가?
인공 신경망은 뉴런에서 영감을 받아 만들어진 머신러닝 알고리즘이다. (그렇다고 해서 실제 우리네 뇌를 모델링 한 것은 아니고)
신경망은 기존의 머신러닝 알고리즘으로 다루기 어려웠던 이미지, 음성, 텍스트 분야에서 뛰어난 성능을 발휘하면서 크게 주목받고 있다.
인공 신경망 알고리즘을 종종 딥러닝이라고 부르기도 한다. (거의 동의어로 사용되는 경우가 많다.)
머신러닝 내에 선형 모델도 있고, 앙상블 모델도 있고, 트리 모델도 있고, 군집 알고리즘도 있고, 여기에 더해 딥러닝(=인공 신경망)도 있다고 보면 된다.
가장 기본적인 인공 신경망은 확률적 경사 하강법을 사용하는 로지스틱 회귀와 같다. (로지스틱 회귀는 3주차에 공부했었다 - 링크)
만약 우리가 옷 데이터셋(MNIST)을 기반으로 어떤 옷인지 판단할 때에 로지스틱 회귀를 쓴다면 아래와 같이 각 옷에대해 z값을 구할 수 있도록 각각 서로 다른 가중치를 가진 공식이 완성된다.
z_티셔츠 = w1*픽셀1 + w2*픽셀2 + ... + w784*픽셀784 + b
z_바지 = w1'*픽셀1 + w2'*픽셀2 + ... + w784'*픽셀784 + b'
... (10개 클래스만큼 반복)
이게 실은 인공 신경망 구조다. 각 픽셀들은 각각의 가중치가 곱해져 z값으로 모이고, 가중치가 모두 곱해진 픽셀값에 b를 더하면 z다.
이처럼 레이어(층)는 공장의 작업대와 비슷하다. 입력층은 원재료 투입구로 픽셀값들이 들어오고, 출력층은 완제품 출구로 분류 결과가 나온다. 나중에 배울 은닉층은 중간 가공 단계들이다.
각 층의 뉴런들은 동시에 병렬로 계산을 수행한다. 여러 명의 작업자가 동시에 각자의 판단을 내리는 것과 같다.
밀집층에서는 뉴런들이 모두 연결되어 있기 때문에 완전 연결층이라고도 부른다.
앞 층의 모든 뉴런이 다음 층의 모든 뉴런과 연결되어 있다는 뜻이다.
예를 들어 입력층에 784개 픽셀이 있고 출력층에 10개 뉴런이 있다면, 784개의 픽셀 각각이 10개의 뉴런 각각과 연결되어 있다. 즉, 784 × 10 = 7,840개의 연결선(가중치)이 있는 셈이다.
연결선이 빽빽하게 모여있어서 마치 밀집한 것처럼 보이기 때문에 "밀집"층이라고 부른다.
특별히 출력층에 밀집층을 사용할 때는 분류하려는 클래스와 동일한 개수의 뉴런을 사용한다. 10종류 옷 분류라면 10개 뉴런, 2종류 분류라면 2개 뉴런을 사용한다.
딥러닝 라이브러리로는 텐서플로가 가장 인기가 높다. 텐서플로는 구글이 2015년 11월 오픈소스로 공개한 딥러닝 라이브러리이다.
CPU와 GPU를 사용해 인공 신경망 모델을 효율적으로 훈련하며 모델 구축과 서비스에 필요한 다양한 도구를 제공하기 때문이다.
실제로 인턴할 때에도 TF Serving? 이런 용어를 많이 들어봤던 기억이 난다. 확실히 많이 쓰이는 기술인듯 하다.
딥러닝 라이브러리가 다른 머신러닝 라이브러리와 다른 점 중 하나는 GPU를 사용하여 인공 신경망을 훈련한다는 것이다.
CPU는 복잡한 계산을 순차적으로 빠르게 처리하는 반면, GPU는 단순한 계산을 병렬로 대량 처리한다. 마치 요리사 1명이 정교한 요리를 하는 것과 요리사 1000명이 동시에 간단한 작업을 하는 것의 차이다.
GPU는 벡터와 행렬 연산에 매우 최적화되어 있기 때문에 곱셈과 덧셈이 많이 수행되는 인공 신경망에 큰 도움이 된다. 뉴런의 계산인 z = w1*x1 + w2*x2 + ... + w784*x784 + b
를 수만 번, 수백만 번 반복해야 하기 때문이다.
코랩에서 런타임 유형을 GPU로 바꾸어 실습할 수 있다.
고수준 API를 제공하는 라이브러리.
저수준 API는 모든 세부사항을 직접 코딩해야 한다. 가중치 초기화, 순전파, 역전파, 경사하강법 등을 직접 구현해야 한다.
반면 고수준 API는 복잡한 부분을 라이브러리가 알아서 처리해준다. 간단한 명령어로 모델 생성과 훈련이 가능하다.
사실상 케라스 API만 익히면 다양한 딥러닝 라이브러리(텐서플로, 씨아노, CNTK 등)를 골라서 백엔드로 두고 사용할 수 있다. (여기서 백엔드로 둔다는 것은, GPU연산을 케라스 라이브러리가 아닌, 해당 라이브러리에게 맡긴다는 의미)
이제는 텐서플로가 케라스 API를 남기고는 나머지 고수준 API를 모두 정리했기 때문에, 케라스가 텐서플로를 쓸 수 있는 거의 유일한(?) 고수준 API인 셈이다. 그러니 이걸 실습에서 사용해보자.
import tensorflow as tf
tf.keras.utils.set_random_seed(42)
tf.config.experimental.enable_op_determinism()
from tensorflow import keras
# Fashion-MNIST 데이터셋 로드
(train_input, train_target), (test_input, test_target) = keras.datasets.fashion_mnist.load_data()
import matplotlib.pyplot as plt
fig, axs = plt.subplots(1, 10, figsize=(10,10))
for i in range(10):
axs[i].imshow(train_input[i], cmap='gray_r')
axs[i].axis('off')
plt.show()
# 데이터 전처리: 0-255 범위를 0-1 범위로 정규화
train_scaled = train_input / 255.0
# 28×28 이미지를 784개의 1차원 배열로 변환
train_scaled = train_scaled.reshape(-1, 28*28)
# 기존 sklearn과 성능 비교
from sklearn.model_selection import cross_validate
from sklearn.linear_model import SGDClassifier
sc = SGDClassifier(loss='log_loss', max_iter=5, random_state=42)
scores = cross_validate(sc, train_scaled, train_target, n_jobs=-1)
print(np.mean(scores['test_score'])) # 0.8194166666666666
# 텐서플로/케라스로 신경망 구현
import tensorflow as tf
from tensorflow import keras
from sklearn.model_selection import train_test_split
train_scaled, val_scaled, train_target, val_target = train_test_split(
train_scaled, train_target, test_size=0.2, random_state=42)
# 밀집층 생성: 10개 뉴런, softmax 활성화 함수, 입력 크기 784
dense = keras.layers.Dense(10, activation='softmax', input_shape=(784,))
model = keras.Sequential([dense])
# 모델 컴파일: 손실함수와 평가지표 설정
model.compile(loss='sparse_categorical_crossentropy', metrics=['accuracy'])
# 모델 훈련
model.fit(train_scaled, train_target, epochs=5)
# 모델 평가
model.evaluate(val_scaled, val_target)
# [0.4444445073604584, 0.8458333611488342]
0.845 정도의 평가 결과가 나온다! 기존 sklearn의 SGDClassifier가 0.819의 성능을 보였는데, 케라스로 구현한 신경망이 약간 더 좋은 성능을 보인다.
학습한 내용을 확인 문제 기반으로 정리해보자.
1. 어떤 인공 신경망의 입력 특성이 100개이고 밀집층에 있는 뉴런 개수가 10개일 때 필요한 모델 파라미터의 개수는 몇 개인가요?
정답: 1,010개
계산 과정은 다음과 같다.
2. 케라스의 Dense 클래스를 사용해 신경망의 출력층을 만들려고 합니다. 이 신경망이 이진 분류 모델이라면 activation 매개변수에 어떤 활성화 함수를 지정해야하나요?
1) 'binary'
2) 'sigmoid' ✅
3) 'softmax'
4) 'relu'
이진 분류에서는 sigmoid 함수를 사용한다. sigmoid는 출력값을 0과 1 사이로 압축해서 확률로 해석할 수 있게 해준다.
자세한 내용은 3주차에서 배웠으니, 이 링크를 참조하기
3. 케라스 모델에서 손실 함수와 측정 지표 등을 지정하는 메서드는 무엇인가요?
1) configure()
2) fit()
3) set()
4) compile() ✅
compile() 메서드는 모델을 훈련하기 전에 손실 함수, 옵티마이저, 평가 지표를 설정하는 역할을 한다. 실제 훈련은 fit() 메서드로 진행한다.
4. 정수 레이블을 타깃으로 가지는 다중 분류 문제일 때 케라스 모델의 compile() 메서드에 지정할 손실 함수로 적절한 것은 무엇인가요?
1) 'sparse_categorical_crossentropy' ✅
2) 'categorical_crossentropy'
3) 'binary_crossentropy'
4) 'mean_square_error'
정수 레이블(0, 1, 2, ...)을 사용할 때는 'sparse_categorical_crossentropy'를 사용한다. 만약 원-핫 인코딩된 레이블([1,0,0], [0,1,0], ...)을 사용한다면 'categorical_crossentropy'를 사용한다.
드디어 혼공학습단 6주간의 대장정이 막을 내렸다!
'이번엔 정말 많은 것을 배워가겠어!'라는 열정으로 시작했지만, 솔직히 그 과정이 쉽지만은 않았다. 1~2주차에는 익숙한 용어들을 접하며 재미있게 학습했지만, 3주차부터는 어려운 알고리즘들을 따라가는 데 버거움을 느끼기도 했다.
하지만 혼공 학습단 활동 덕분에 포기하지 않고 6주를 완주할 수 있었다. 학교에서 교양 수업으로 인공지능을 들었을 때는 '신경망, 은닉층' 같은 용어들을 그저 외우기만 했는데, 이번에 이 책을 통해 다양한 머신러닝 알고리즘과 딥러닝을 직접 구현해보니 이제는 어떤 개념인지 어렴풋하게나마 이해할 수 있게 되어 뿌듯했다.
물론 어떤 알고리즘이 있었는지 세세하게 설명하긴 어렵겠지만, 피처, 머신러닝, 딥러닝이 무엇이고 이들이 어떤 원리로 작동하는지 큰 그림은 확실히 잡은 것 같다. 언젠가 프로젝트에 머신러닝 기능을 활용하거나 관련 분야에서 일하게 된다면, 그때는 거기서 들려오는 말들을 이전보다 훨씬 선명하게 알아들을 수 있으리라.
매주 힘내라고 응원해주고, 맛있는 간식까지 챙겨준 혼공족장님께도 진심으로 감사드린다!
찐 끝.