본문 바로가기

MLOps 개발자 양성과정/ml&dl

[Day-55] chap07.딥러닝_인공신경망

7-1. 인공신경망

 

텐서플로
Keras 케라스 _ '패션 MINIST 데이터셋 불러오기'
- 케라스 학습하기 위한 데이터 셋을 제공해줌
- from tensorflow import keras
- (train_input, train_target), (test_input, test_target) = keras.datasets.fashion_mnist.load_data()
* load_data()
: 훈련 데이터와 테스트 데이터를 나누어 반환함
( 데이터 셋 마다 불러오는 방식은 차이가 있음)

 

💡 인공신경망
- 기존의 머신러닝 알고리즘이 잘 해결하지 못했던 문제에 대해 높은 성능을 발휘하는 새로운 종류의 알고리즘
- 입력층과 출력층 최소 두 개의 층이 필요

ㆍ입력층
- 특성의 갯수만큼 받아주는 입력층
- 연산하지 않고 주는대로 받아서 다음 층에 넘겨줌

밀집층
- 가장 간단한 인공 신경망의 층
- 입력된 모든 값과 출력층의 모든 값이 하나도 빠짐없이 밀집되어 연결된 형태

=> 완전 연결 레이어
- 가중치(weight)는 특성의 갯수만큼 생성돼서 각각의 픽셀에 곱해지고 절편(bias)는 한 번만 더해짐
- 각 레이블의 확률을 계산하기 위한 가중치와 절편을 다름
- 레이블의 갯수만큼 각각 연산이 이루어짐
ex) z_바지 =w1 x (픽셀1) + w2 x (픽셀2) +... + w784 x (픽셀784) + b

ㆍ은닉층
- 입력층과 출력층 사이에 있는 모든 층
- 활성화함수 적용(선형 방정식의 계산 값에 적용하는 함수로 비교적 자유롭게 사용- 시그모이드, 렐루 등)
- 선형 계산을 적당하게 비선형적으로 비틀어주기 위해 활성화 함수 적용
- 뉴런의 갯수는 경험에 의해 지정(단, 출력 층의 뉴런보다는 많게 만든다)

ㆍ출력층
- 타깃값, 레이블의 갯수만큼 출력하는 출력층
- 활성화 함수 적용(종류 제한되어 있어 - 이진분류:시그모이드/다중분류:소프트맥스)

💡 딥러닝
- 인공신경망과 동의어로 사용되는 경우가 많음
- 혹은 심층 신경망(deepl neaural network, DNN)을 딥러닝이라고 부름
- 반드시 그래픽 처리 장치 GPU 사용(복잡한 연산을 동시에 빨리 처리하기 위해 병렬처리 필요)

 

케라스 모델

1. Dense 클래스 이용해서 층 생성
dense = keras.layers.Dense(10, activation='softmax', input_shape=(784,))

- 입력층, 출력층 동시에 생성하는 방식이지만, 일반적으로는 입력 부분 따로 만드는 경우가 많음
- Dense(출력 뉴런 갯수, ) 제일 먼저 작성 (이진분류-2개)
- 활성화 함수 입력 (이진분류-sigmoid / 다중분류 -softmax
- 입력의 크기는 특성의 갯수 반드시 튜플 형태로 작성

2. 모델 만들기(순차적 모델)
model = keras.Sequential(dense)
- 실제 학습은 신경망 모델이 하는 것(층만 만들어서는 학습 못해)
- 생성자에 layer 전달
- 층이 하나 이상일 경우 리스트 형태로 전달

3. 모델 만들었으면 훈련 전 반드시 compile
model.compile(loss='sparse_categorical_crossentropy', metrics='accuracy')​
-  loss매개변수에 내가 사용할 손실 함수 지정  (이진분류-binary / 다중분류 -categorical
-  클래스 레이블 정수일 경우 원-핫 인코딩까지 해주는 sparse_categorical_crossentropy
  (sparse_? 없으면 원핫 인코딩 작업 따로 해줘야 해)
- metrics 보고 싶은 값 지정해 ( 신경망 모델 훈련 할 때마다 정확도를 출력하겠다)

4. 모델 훈련 fit()
model.fit(train_scaled, train_target, epochs=5)​
- 입력과 타깃 데이터 전달
- epochs 훈련 반복횟수

5. 모델 성능 평가 evaluate()
model.evaluate(val_scaled, val_target)
- 따로 떼어놓은 검증 세트 사용

 


7-2. 심층 신경망

 

<키워드 정리>
심층 신경망
: 2개 이상의 층을 포함한 신경망
( 종종 다층 인공 신경망, 심층 신경망, 딥러닝을 같은 의미로 사용..)

렐루함수
: 이미지 분류 모델의 은닉층에서 많이 사용하는 활성화 함수
- 시그모이드는 층이 많을수록 활성화 함수의 양쪽 끝에서 변화가 작기 때문에 학습이 어려워짐
- 렐루함수 시그모이드를 보완
- 입력된 값이 양수일 경우 통과,  음수일 경우 0으로 셋팅

옵티마이저
: 신경망의 가중치와 절편을 학습하기 위한 알고리즘 또는 방법
- 모델 컴파일 시 어떤 하강법을 쓸 건지 optimizer 지정
- 케라스에는 다양한 경사하강법 알고리즘 구현되어 있음(SGD, 네스테로프 모멘텀, RMSprop, Adam 등)
- adam 제일 많이 사용함

 

심층 신경망 만드는 세 가지 방법

 방법1.
# 1) 각각의 dense 만들어 놓기
dense1 = keras.layers.Dense(100, activation='sigmoid', input_shape=(784,))
dense2 = keras.layers.Dense(10, activation='softmax')

# 2) Sequential 모델에 리스트 형태로 전달
model = keras.Sequential([dense1, dense2]) 
# 모델 만들 때 순서 바뀌면 안돼
# 리스트 형태로 전달​


 방법2.

# Sequential 클래스의 생성자 안에서 바로 Dense 클래스 객체 만들기
model=keras.Sequential([
	keras.layers.Dense(100, activation='sigmoid', input_shape=(784,),name='hidden'),
	keras.layers.Dense(10, activation='softmax', name='output')
	], name='패션 MNIST 모델')


 방법3. - 가장 많이 사용

# 1) 모델 객체 만들기
model = keras.Sequential()

# 2) 각각의 layer를 모델 객체에 순서대로 add()
model.add(keras.layers.Dense(100, activation='sigmoid', input_shape=(784,)))
model.add(keras.layers.Dense(10, activation='softmax'))


 

인공신경망 주입하기 위해 1차원 배열로 변환!
1. 넘파이 배열의 reshape() 


2. 케라스 2차원배열을 1차원으로 펼쳐주는 Flatten 층 제공
- Flatten층 학습하는 층이 아니야 
- 입력받은 것 전달만 하기 때문에 파라미터 값 붙을 수 없음
- flatten층 신경망 모델에 추가하면 입력값의 차원을 짐작할 수 있다는 장점
model = keras.Sequential()
model.add(keras. layers.Flatten(input_shape=(28, 28)))​

7-3. 신경망 모델 훈련

 

<키워드 정리>

드롭아웃
: 은닉층에 있는 뉴런의 출력을 랜덤하게 꺼서 과대적합을 막는 기법
- 드롭아웃 훈련 중에 적용되며 평가나 예측에서는 적용되지 않음
- 완벽하게 연결되어 있으면 과대하게 연산되기 때문에
- 은닉층에 틀정 일부 뉴런값을 다음 층에 전달 안해
- 훈련과정에서 은닉층의 일부 뉴런을 랜덤하게 출력을 0으로 만들어 과대적합을 막는 이론
- 얼마만큼 뉴런을 dropout 할 건지는 개발자가 지정 (경험에 의해...)


콜백
: 훈련 도중에 어떤 작업을 수행할 수 있도록 도와주는 도구
최상의 모델을 자동으로 저장해주거나 검증 점수가 더 이상 향상 되지 않으면 일직 종료할 수 있음
# keras.callbacks패키지 안에
# 콜백 객체를 넣어줘야 해
# 콜백 매개변수에는 객체를 리스트 형태로 전달한다.
# 콜백 조기종료하기 위해 사용
# 한 번 훈련이 끝날 때마다 계속 저장 체크포인트 콜백을 사용하기 위해서
# save_best_only = True 가장 낮은 검증 점수 = 검증 손실 점수 (낮으면 손 실값 낮아 좋아)


조기종료
: 검증 점수가 더 이상 감소하지 않고 상승하여 과대적합이 일어나면 훈련을 계속 진행하지 않고 멈추는 기법
가장 베스트인 모델에 해당하는 모델을 저장해
# epochs값이 20 훈련은 총 20번해 # 그중 15번했을 때 가장 낮은값이 들어왔어 그럼 훈련안해도 돼
# 문제는 손실값이 내려가 언제 멈출줄 몰라 튀고 내려오고 튀고 내려오고 partience
# 몇 번 튀었을 때 훈련을 멈추게 할 건지 설정
# fit callback쪽에 넣어줘야 해

#얼리스탑핑 객체 만들어(이때 몇 번 튀었을 때 멈추게 할거야?) 실제저장하는 데는 best-model.h5
# 멈출 때 가장 베스트인값을 넣어놔 restore 마지막 신규값을 저장하지 말고
# 콜백에 체크포인트와 얼리스타핑 넣어야 해

 

 

 
 

 

# 과대적합을 줄이고자 dropout
# 완벽하게 연결되어 있으면 과대하게 연산되기 때문에
# 은닉층에 틀정 일부 뉴런값을 다음 층에 전달 안해
# 훈련과정에서 은닉층의 일부 뉴런을 랜덤하게 출력을 0으로 만들어 과대적합을 막는 이론

# 얼마만큼 뉴런을 dropout 할 건지는 개발자가 지정 (경험에 의해...)

콜백

: 케라스 모델을 훈련하는 도중에 어떤 작업을 수행할 수 있도록 도와주는 도구

# 온클릭도 콜백 (클릭하고 뗐을 때 함수 불러와)
# 이벤트가 발생한 후에 바

# keras.callbacks패키지 안에
# 콜백 객체를 넣어줘야 해
# 콜백 매개변수에는 객체를 리스트 형태로 전달한다.

# 콜백 조기종료하기 위해 사용

# 한 번 훈련이 끝날 때마다 계속 저장 체크포인트 콜백을 사용하기 위해서
# save_best_only = True 가장 낮은 검증 점수 = 검증 손실 점수 (낮으면 손 실값 낮아 좋아)

조기종료

 

### 조기종료
# 가장 베스트인 모델에 해당하는 모델을 저장해
# epochs값이 20 훈련은 총 20번해 # 그중 15번했을 때 가장 낮은값이 들어왔어 그럼 훈련안해도 돼
# 문제는 손실값이 내려가 언제 멈출줄 몰라 튀고 내려오고 튀고 내려오고 partience
# 몇 번 튀었을 때 훈련을 멈추게 할 건지 설정
# fit callback쪽에 넣어줘야 해


#얼리스탑핑 객체 만들어(이때 몇 번 튀었을 때 멈추게 할거야?) 실제저장하는 데는 best-model.h5
# 멈출 때 가장 베스트인값을 넣어놔 restore 마지막 신규값을 저장하지 말고
# 콜백에 체크포인트와 얼리스타핑 넣어야 해

신경망 모델을 만들기 위해서

flatten 펼쳐주는 층

dense 밀집층

 

층은 학습 못해

모델 만들어줘야 해

우리가 배운 모델 sequential 순차적

학습하기 위해서는 compile 필요

fit

evaluate

 

함수 어느게 손실함수고 어느게 활성화함수인지 구별해야 해\\

 

하이퍼파라미터 레이어도 개발자가 순서 정해줘야 해 하이퍼파라미터야

 

케라스의 미니배치 32개

 

 

 validation_data=(val_scaled, val_target))

튜플 형태로 보내줘야 해

 

추가되는 매개변수 ㅎ

 


정리

 

 

딥러닝 하려면

신경망

 

층이 필요해

이미지 분류

이미지가 2차원 배열 => 1차원으로 펼쳐

10가지로 ㅁ분류하려고 해 

dense 대표적 밀집층

마지막 출력층 활서오하 함수가 필요해

softmax

-> 성능

은닉층 끼워놔

대표적인 레이어도 dense

 

- 훈련했더니 과대적합

=> 은닉층에 드롭아웃 레이어 넣어줘

 

내 팀원한테 모델을 전달하려고 해

모델 저장 1. 파라미터만 저장 / 2.모델구조 파라미터 다 저장

 

일반적으로 두 가지 방법 다 저장해놔

다른 사람이 층을 더 심고 싶을 때 

파라미터만 있으면

 

훈련을 시킬때 최상의 값으로 저장하고 싶어

=>checkpoint

100번 훈련시키는데 최적의 값 나오면 멈춰

=>earlystopping

이 두개는 fit()안에 callbacks=[]에 리스트 형태로 넣어줘

 


7-1. 인공신경망
###############데이터 준비#################
# keras 데이터 불러오기
from tensorflow import keras
(train_input, train_target), (test_input, test_target) = keras.datasets.fashion_mnist.load_data()

# 훈련 데이터의 크기 확인
print(train_input.shape, train_target.shape) >>> (60000, 28, 28) (60000,)

# 테스트 데이터의 크기 확인
print(test_input.shape, test_target.shape) >>> (10000, 28, 28) (10000,)

# 상위 10개 이미지를 가지고 출력
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()

# 타깃값 확인해보기
print([train_target[i] for i in range(10)]) >>> [9, 0, 0, 3, 0, 2, 7, 2, 5, 5]

# 각 레이블 당 샘플 몇 개씩 가지고 있는지 확인하기
import numpy as np
print(np.unique(train_target, return_counts=True)) >>> (array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], dtype=uint8), array([6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000]))

#######################################################

############### 로지스틱 회귀로 분류하기 #################

### SGDClassifier() 사용

# 표준화 작업
train_scaled = train_input / 255.0 # 0~1 사이의 값으로 정규화(StandardSclaer 대신에 255로 나눴어 / 각 픽셀 0~255 사이의 정숫값)
# 2차원 배열을 1차원 배열로
train_scaled = train_scaled.reshape(-1, 28*28)

print(train_scaled.shape) >>> (60000, 784) # 784개의 픽셀로 이루어진 60,000개의 샘플 준비


#### 교차검증
from sklearn.model_selection import cross_validate
from sklearn.linear_model import SGDClassifier
sc = SGDClassifier(loss='log', max_iter=5, random_state=42)
scores = cross_validate(sc, train_scaled, train_target, n_jobs=-1)
# 첫 번째값 무조건 모델명 # 어떤 값 # 어떤 정답지로 #-1 모든 자원 다 사용해
print(np.mean(scores['test_score'])) >>> 0.8196000000000001
# 교차 검증 반환값 딕셔너리야
# scores 키에서 'test_score' 검증 셋에 대한 평가 결과

# max_iter 올려도 성능 크게 향상되지 않아....

#######################################################

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

# 검증 세트 덜어내기(딥러닝 교차검증 하면 시간 너무 오래 걸려)
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)

print(train_scaled.shape, train_target.shape) >>> (48000, 784) (48000,)

###### 출력층과 입력층을 동시에 만들 때 사용하는 방법 #####
# 1. layer 층 만들기
dense = keras.layers.Dense(10, activation='softmax', input_shape=(784,)) # Dense라는 클래스를 이용해서 객체를 만들어
# 출력층 분류할 레이블 갯수(뉴런) / 뉴런의 출력에 적용할 활성화함수 / 입력층 입력의 크기 특성의 갯수(튜플 형태로 반드시 쉼표찍어야 해)

# 2. 모델 만들기(순차적 모델)
# 실제 학습을 하기 위해서는 모델을 만들어줘야 해(layer 층만 만들어 놓으면 학습 불가능)
model = keras.Sequential(dense) # 생성자에 layer 전달

# 3. 모델 만들었으면 반드시 compile
model.compile(loss='sparse_categorical_crossentropy', metrics='accuracy')
# loss매개변수에 내가 사용할 손실 함수 
# 케라스에서 손실함수 두 가지 (이진분류-binary / 다중분류 -categorical)
# 원-핫 인코딩까지 해주는 sparse_categorical_crossentropy
# 신경망 모델 훈련할 때마다 정확도를 내보내줘
# metrics 보고 싶은 값 지정해 (출력할 값 정확도를 출력하겠다)

print(train_target[:10]) >>> [7 3 5 8 6 9 3 3 9 9]

# 4. 모델 훈련 fit()
model.fit(train_scaled, train_target, epochs=5)
>>> Epoch 1/5
1500/1500 [==============================] - 3s 1ms/step - loss: 0.6091 - accuracy: 0.7920
Epoch 2/5
1500/1500 [==============================] - 2s 1ms/step - loss: 0.4745 - accuracy: 0.8391
Epoch 3/5
1500/1500 [==============================] - 2s 1ms/step - loss: 0.4506 - accuracy: 0.8472
Epoch 4/5
1500/1500 [==============================] - 2s 1ms/step - loss: 0.4373 - accuracy: 0.8518
Epoch 5/5
1500/1500 [==============================] - 2s 1ms/step - loss: 0.4291 - accuracy: 0.8553

# 5. 모델 성능 평가 evaluate()
# 따로 떼어놓은 검증 세트 사용
model.evaluate(val_scaled, val_target)
>>> 375/375 [==============================] - 1s 1ms/step - loss: 0.4438 - accuracy: 0.8493
[0.4438328742980957, 0.8492500185966492]

 

7-2. 심층 신경망
# 데이터 불러오기
from tensorflow import keras
(train_input, train_target), (test_input, test_target) = keras.datasets.fashion_mnist.load_data()
# 데이터 불러왔으면 반드시 샘플 데이터 확인하기

print(train_input.shape, train_target.shape) >>> (60000, 28, 28) (60000,)
print(test_input.shape, train_target.shape) >>> (10000, 28, 28) (60000,)

from sklearn.model_selection import train_test_split
train_scaled = train_input / 255.0
train_scaled = train_scaled.reshape(-1, 28*28)
train_scaled, val_scaled, train_target, val_target = train_test_split(train_scaled, train_target, test_size=0.2, random_state=42)

print(train_scaled.shape, train_target.shape) >>> (48000, 784) (48000,)
print(val_scaled.shape, val_target.shape) >>> (12000, 784) (12000,)

############ 인공신경망 모델에 층 2개 추가하기 ###########
# 은닉층 추가하기
# 은닉층에 활성화 함수를 적용해서 비선형으로 한 번 비틀어주고 마지막을 소프트맥스로
# 활성화함수는 정해져 있는 게 아니라 경험에 의해서...
# 은닉층의 뉴런의 갯수 출력층의 뉴런보다 많게(몇 개 정해져 있는 게 아니라 경험해 의해서...)
dense1 = keras.layers.Dense(100, activation='sigmoid', input_shape=(784,))
# 출력층 최종 레이블 갯수(10개)
dense2 = keras.layers.Dense(10, activation='softmax')
# 회귀를 할 때는 활성화 함수 지정하지 않고 출력층의 선형 방정식 그대로 출력함

############### 심층 신경망 만들기 ##############

########### 방법1 ###########

# 1) 각각의 dense 만들어 놓기
dense1 = keras.layers.Dense(100, activation='sigmoid', input_shape=(784,))
dense2 = keras.layers.Dense(10, activation='softmax')

# 2) Sequential 모델에 리스트 형태로 전달
model = keras.Sequential([dense1, dense2]) 
# 모델 만들 때 순서 바뀌면 안돼
# 리스트 형태로 전달

model.summary()
>>>
Model: "sequential"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 dense (Dense)             (None, 100)                78500     
                                                                 
 dense_1 (Dense)             (None, 10)                1010      
                                                                 
=================================================================
Total params: 79,510
Trainable params: 79,510
Non-trainable params: 0

########### 방법2 ###########

# Sequential 클래스의 생성자 안에서 바로 Dense 클래스 객체 만들기
model=keras.Sequential([
	keras.layers.Dense(100, activation='sigmoid', input_shape=(784,),name='hidden'),
	keras.layers.Dense(10, activation='softmax', name='output')
	], name='패션 MNIST 모델')
    
########### 방법3 ###########
# 가장 많이 사용
# 1) 모델 객체 만들기
model = keras.Sequential()

# 2) 각각의 layer를 모델 객체에 순서대로 add()
model.add(keras.layers.Dense(100, activation='sigmoid', input_shape=(784,)))
model.add(keras.layers.Dense(10, activation='softmax'))

########################################################

# compile
model.compile(loss='sparse_categorical_crossentropy', metrics='accuracy')
model.fit(train_scaled, train_target, epochs=5)
# 층 하나 추가했더니 정확도 2% 정도 상승

####################### 렐루 함수 ######################
model = keras.Sequential()
# 케라스에서 2차원 배열을 1차원으로 펼쳐주는 Flatten 층 제공
model.add(keras.layers.Flatten(input_shape=(28, 28)))
# 입력받은 거 전달많 하기 때문에 파라미터값 붙을 수 없어(활성화함수x)
model.add(keras.layers.Dense(100, activation='relu')) # 활성화 함수 relu
model.add(keras.layers.Dense(10, activation='softmax'))

model.summary() # flatten층 신경망 모델에 추가하면 입력값의 차원을 짐작할 수 있다는 장점
>>> 
Model: "sequential_4"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 flatten_1 (Flatten)         (None, 784)               0         
                                                                 
 dense_10 (Dense)            (None, 100)               78500     
                                                                 
 dense_11 (Dense)            (None, 10)                1010      
                                                                 
=================================================================
Total params: 79,510
Trainable params: 79,510
Non-trainable params: 0

##################################################
# 훈련 데이터 다시 준비해서 모델 훈련하기
# reshape() 적용 x
(train_input, train_target), (test_input, test_target) = keras.datasets.fashion_mnist.load_data()
train_scaled = train_input / 255.0
train_scaled, val_scaled, train_target, val_target = train_test_split(train_scaled, train_target, test_size=0.2, random_state=42)
# 컴파일
model.compile(loss='sparse_categorical_crossentropy', metrics='accuracy')
# 훈련
model.fit(train_scaled, train_target, epochs=5)
# 평가
model.evaluate(val_scaled, val_target)
# 은닉층 추가하니 성능 향상되었음

####################### 옵티마이저 ######################
# 컴파일 시 어떤 하강법 사용할 건지 optimizer 지정
#### Adam을 이용해 모델 훈련하기
model = keras.Sequential()
model.add(keras.layers.Flatten(input_shape=(28, 28)))
model.add(keras.layers.Dense(100, activation='relu'))
model.add(keras.layers.Dense(10, activation='softmax'))

model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics='accuracy')
model.fit(train_scaled, train_target, epochs=5)

model.evaluate(val_scaled, val_target)