독서 목록

딥러닝 이론 공부 기록

곽가누 2023. 9. 23. 02:10

내가 보려고 만든 기억 상기용 글

책 <모두의 딥러닝>을 혼자 공부하면서 간단한 개념 정도로 정리하려 한다. 

책을 보고 옮겨 적는 것이 아닌, 기억나는 개념을 키워드 정도 인용하고 그 외에는 본인이 창작해서 쓸 것이다.

수식은 워드에서, 그래프 그림은 지오지브라나 노타빌리티에서, 표는 주피터 노트북에서 제작했다.(아직까지는)

제작하지 않은 자료는 출처를 따로 기재할 것이다. 

문제가 된다면 비공개로 전환하겠다. 


2023.9.20

3-6. 시그모이드 함수

딥러닝은 입력받은 신호를 얼마나 출력할 지 계산하는 과정이 반복되는데, 이 때 출력 값으로 얼마나 내보낼지를 계산하는 함수를 활성화 함수라고 한다. 활성화 함수 중 하나가 시그모이드 함수이다.

시그모이드 함수 수식
시그모이드 함수 그래프

 0 또는 1, 두개의 값 중 하나를 고를 때 유용하게 쓰인다.

x가 큰 값을 가지면 f(x)는 1에 가까워지고, x가 작은 값을 가지면 f(x)는 0에 가까워진다.

나중에 로지스틱 회귀분석에서 사용될 중추적인 개념이다. 

 

4. 딥러닝의 가장 말단에서 이루어지는 기본적인 두 가지 계산 원리 : 선형 회귀와 로지스틱 회귀


2023.9.22

4-3. 최소 제곱법

선형 회귀의 원리는 최소 제곱법을 따른다. 

y = ax + b의 형태로 선형 회귀를 한다면, 기울기인 a와 y절편 b를 최소 제곱법을 사용하여 구해보자. 

 

다음과 같은 자료가 있을 때, 

기울기 a는 ((x-x평균)(y-y평균))/∑((x-x평균)^2 의 합)으로 구할 수 있으며,

y절편 b는 y의 평균 - (x의 평균*기울기 a)로 구할 수 있다. 

 

계산하면

x의 평균은 35,  y의 평균은 54.25이므로

 

a = ((20-35)(33-54.25) + (30-35)(47-54.25) +(40-35)(66-54.25) +(50-35)(71-54.25)) /

((20-35)^2 +(30-35)^2 +(40-35)^2 +(50-35)^2) 이다.

 

4-5. 평균 제곱 오차

최소 제곱법을 사용하여 만들어진 일차함수가 대부분의 경우에는 완벽하게 들어맞지 않을 것이다.

실제 값과 계산 값과의 차이가 생기기 마련인데, 이 차이를 제곱하여 경우의 수로 나누는 방법이 평균 제곱 오차 계산법이다. 


2023.09.25

5-1. 경사 하강법

앞서 배운 최소 제곱법과 평균 제곱 오차를 사용하여 기울기 a를 구할 수 있다. 만약 a가 지나치게 커지거나(양의 무한대로 발산) 지나치게 작아지면(음의 무한대로 발산한다면), 오차 또한 커질 것이다. 이러한 관계를 우리는 이차함수로 표현할 수 있다. 그리고 적절한 기울기를 찾았을 때, 오차는 최소화된다. 

그렇다면 최소화된 오차의 지점을 구해야 한다. 이를 경사 하강법을 통해 구할 수 있다. 경사 하강법은 이차함수의 기울기가 0인 지점(미분했을때, 0이 나오는 지점)을 찾는 것이다. 

그림으로 표시하면 이런 느낌..? 기울기가 a다.

이차함수를 미분했을 때, 기울기가 양수면 음의 방향으로 이동시켜서 다시 미분해보고, 기울기가 음수면 양의 방향으로 이동시켜 미분해보는 과정이다. 

 

물론 단점도 존재한다. 선형 회귀에만 사용할 수 있다. 

그래프가 복잡해지면 기울기가 0인 지점을 찾아도 오차가 정말로 최소인 지점인건지,

아니면 기울기가 0인 단순 극솟값인 지점(최소값 아님)인건지 알수가 없다. 

 


2023.09.26

5-3. 다중 선형 회귀

이전까지의 선형 회귀는 x값도 하나, y값도 하나였다. (식품 첨가물과, 소비자 선호도)

그런데 소비자 선호도가 식품 첨가물 변수 하나만을 토대로 도출되진 않을 것이다. 살균 온도에도 영향을 받을 수 있다. 

이처럼 고려해야 할 변수가 여러개일 때는 다중 회귀 분석을 사용해야 한다. 

그리고, 수식은 y = a1*x1 + a2*x2 + b와 같이 나타날 것이다. 

 

5-4. 텐서플로우에서 선형 회귀, 다중 선형 회귀 구현 

코드 짜기 전에, 용어를 익히고 가자.

1. 우리가 y = ax + b 라던가  y = a1*x1 + a2*x2 + b로 수식을 세운 것 처럼 문제를 해결하기 위해 가정하는 식을 머신 러닝에서는 가설 함수라고 한다. 

2. 기울기 a는 지금부터 가중치이다. y절편인 b는 데이터의 특성에 따라 따로 부여되는 값이므로 편향이라고 일컫는다. 

3. 평균 제곱 오차처럼 실제 값과 예측값 사이의

오차에 대한 식을 손실 함수라고 한다. 

4. 경사 하강법처럼 '최적의' 기울기와 절편을 찾는 법을 이제 옵티마이저라고 부른다.

옵티마이저가 경사 하강법보다 더 큰 개념.

 

선형 회귀 구현

1. 모듈을 불러온다

import pandas as pd
import matplotlib.pyplot as plt #데이터 시각화 할때 씀
from tensorflow.keras.models import Sequential #딥러닝 층 생성
from tensorflow.keras.layers import Dense #각 층을 촘촘히 연결

 

2. 데이터를 생성하거나 불러온다. 

df = pd.DataFrame({'식품 첨가물(g)': [2, 3, 4, 5], '소비자 선호도(%)': [33, 47, 66, 71]})

3. 모델을 생성한다. 

#신경망 모델을 정의
model = Sequential()

#결과 데이터 개수 : 1, 입력 데이터 개수: 1, 선형 회귀이므로
model.add(Dense(1, input_dim=1, activation='linear'))

# 최적화 알고리즘을 수정하여 학습률을 조절합니다.
from tensorflow.keras.optimizers import SGD #경사 하강법(sgd) 사용
custom_optimizer = SGD(learning_rate=0.03)  # 학습률을 0.03으로 조절
model.compile(optimizer=custom_optimizer, loss='mse') #손실 함수(mse)는 평균 제곱 오차 사용

4. 모델을 학습시킨다.

model.fit(df['식품 첨가물(g)'], df['소비자 선호도(%)'], epochs=1000) #1000회 반복

5. 시각화한다.

plt.scatter(df['식품 첨가물(g)'], df['소비자 선호도(%)'])
plt.plot(df['식품 첨가물(g)'], model.predict(df['식품 첨가물(g)']), 'r')
plt.show()

>>>

 

다중 선형 회귀 구현

1. 모듈을 불러온다.(선형 회귀랑 동일)

import pandas as pd
import matplotlib.pyplot as plt #데이터 시각화 할때 씀
from tensorflow.keras.models import Sequential #딥러닝 층 생성
from tensorflow.keras.layers import Dense #각 층을 촘촘히 연결

2. 데이터를 생성하거나 불러온다.(다중 선형 회귀이므로 독립 변수가 2개 이상이어야 한다.)

본인은 수분 활성도 변수를 추가하였다. 

df = pd.DataFrame({'식품 첨가물(g)': [2, 3, 4, 5], '수분 활성도(Aw)': [0.97, 0.63, 0.83, 0.9], '소비자 선호도(%)': [33, 47, 66, 71]})

3. 모델을 생성한다. 

#신경망 모델을 정의
model = Sequential()

#결과 데이터 개수 : 1, 입력 데이터 개수: 2, 선형 회귀이므로
model.add(Dense(1, input_dim=1, activation='linear'))

# 최적화 알고리즘을 수정하여 학습률을 조절합니다.
from tensorflow.keras.optimizers import SGD #경사 하강법(sgd) 사용
custom_optimizer = SGD(learning_rate=0.03)  # 학습률을 0.03으로 조절
model.compile(optimizer=custom_optimizer, loss='mse') #손실 함수(mse)는 평균 제곱 오차 사용

4. 모델을 학습시킨다.

# 다변수이므로 변수들을 x로 묶어서 학습
x = df[['식품 첨가물(g)','수분 활성도(Aw)']]
model.fit(x, df['소비자 선호도(%)'], epochs=1000)

5. 시각화 대신 예측 함수를 생성해보았다. 

다중 선형 회귀분석은 시각화가 어렵다. (3차원으로 나타남)

foodAdditive = float(input('식품 첨가물 g 단위로 입력'))
waterActivity = float(input('수분 활성도 Aw 단위로 입력'))
prediction = model.predict([[foodAdditive, waterActivity]])
print('예상되는 소비자 선호도는 ' + str(prediction[0][0]) + '입니다.')  # 숫자를 문자열로 변환하여 출력

>>>


2023.10.01

6-2. 시그모이드 함수

로지스틱 회귀분석의 기반이 되는 시그모이드 함수는

a값이 커지면 경사가 커지고, a값이 작아지면 경사가 작아진다.

a값이 작아지면 오차는 무한대로 늘어난다.

그러나 a값이 커지면 오차가 줄어드는 건 맞지만 오차가 0이 되는 것은 아니다. 

궁금하면 책 찾아보기.. 자료 넣기 빡세다. 

 

b는 그래프의 좌우 이동이다. 

b값은 적정한 값에 맞춰주어야 한다. b값이 너무 커지거나 작아지면 오차는 증가한다. 

 

2023.10.5

6-5. 텐서플로에서 실행하는 로지스틱 회귀

1. 모듈을 불러온다

import pandas as pd
import matplotlib.pyplot as plt
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense

2. 데이터를 만들거나 불러온다. 

df = pd.DataFrame({'우유 소비기한(일)' : [5,10,15,20,25,30,35], '식중독 여부' : [0,0,0,0,1,1,1]})

3. 모델을 생성한다.

model = Sequential()
#활성 함수 activation을 'linear'에서 'sigmoid'로 바꾼다.
model.add(Dense(1, input_dim= 1, activation='sigmoid')) 
#경사 하강법 sgd를 옵티마이저로, 손실 함수는 교차 엔트로피 오차 함수를 사용한다. 
model.compile(optimizer='sgd', loss='binary_crossentropy')
model.fit(df['우유 소비기한(일)'], df['식중독 여부'], epochs = 5000)

4. 학습시킨다.

model.fit(df['우유 소비기한(일)'], df['식중독 여부'], epochs = 5000)

5. 그래프로 시각화한다. 

plt.scatter(df['우유 소비기한(일)'],df['식중독 여부'])
plt.plot(df['우유 소비기한(일)'], model.predict(df['우유 소비기한(일)']), 'r')
plt.show()

>>>

epochs = 2000
epochs = 5000

정정한다. 소비기한이 아니라 소비기간이 맞다. 잘못씀..

6. 설정하고 싶은 소비기간을 입력받아 식중독이 발생할 확률을 예측해본다. 

day = int(input('설정할 소비기한을 입력하세요: '))
prediction = model.predict([day])
print("%.f일을 소비기간으로 설정할 경우, 식중독이 발생할 확률은 %.01f%%입니다." % (day, prediction*100))

2023.11.6

7. 퍼셉트론과 인공지능의 시작

인간의 뇌에는 뉴런이 있음. 뉴런들이 보낸 전기적 신호들을 통합하면 생각이 됨

이걸 컴퓨터에서도 구현하면 딥러닝을 구현하지 않을까 싶었음

퍼셉트론 : 여러 개의 입력값을 받아 가중치를 조절하여 하나의 출력값을 만드는 것

아달라인 : 경사 하강법을 도입한 퍼셉트론 

 

퍼셉트론으로 모든 문제를 해결할 수 있을 것이라 생각했으나, 아니었음

XOR 문제같은 걸 해결할 수 없었기 때문

XOR 문제란?

AND(논리곱)
두개가 1이어야 1
OR(논리합)
하나라도 1이면 1
XOR(배타적 논리합)
하나만 1이어야 1
x1 x2 결과 x1 x2 결과 x1 x2 결과
0 0 0 0 0 0 0 0 0
0 1 0 0 1 1 1 0 1
1 0 0 1 0 1 0 1 1
1 1 1 1 1 1 1 1 0

 

이를 그래프로 나타내면 다음과 같이 나타낼 수 있다.

첫번째 그래프와 두번째 그래프는 경사 하강법 등을 사용하여 흰색 점과 검정색 점을 구분하는 결론을 도출할 수가 있음

그러나 세번째 그래프는 선 하나로는 어떻게 해도 구분할 수가 없음

이런 문제를 해결하지 못하여 딥러닝은 뜨지 못함

그러나, 다층 퍼셉트론과 오차 역전파를 이용하여 해결이 가능해짐

 

8. 다층 퍼셉트론

다층 퍼셉트론은 말 그대로 퍼셉트론을 여러개 사용하는 것

방법 : 은닉층을 만들어 퍼셉트론 두개를 각각 한번에 처리

 

 

117p 가 이해가 안 되어 집합 그림으로 그려 보았다. 

가운데는 결괏값, 왼쪽 벤다이어그램과 오른쪽 벤다이어그램을 논리곱하면 가운데가 된다.

여기서 왼쪽 벤다이어그램과 오른쪽 벤다이어그램이 은닉층이라고 생각하면 된다.

 

은닉층을 이용하여 XOR 문제는 해결했으나, 이때 가중치를 어떻게 해야할 지에 대한 과제가 남아있었다. 

데이터 과학자들은 이를 두 부류로 해결하고자 함. 

1. 일단 한거를 발전시키자 : 아달라인을 발전시켜 SVM이나 로지스틱 회귀 모델을 만듦

2. 가중치 방법 생각하자 :  다층 퍼셉트론 학습 방법을 찾으며 오차 역전파 구현

 

2023.11.7

9. 오차 역전파에서 딥러닝으로

아까 2번의 이야기가 오차 역전파

오차 역전파란 다층 퍼셉트론에서의 최적화 과정

가중치는 전에 배웠던 경사 하강법 사용 (=다층 퍼셉트론 역시 결괏값과 실제값의 차이를 고려하여 구현)

오차 역전파

다음 그림의 과정을 계속 반복하여 오차가 작아지는 방향으로 업데이트한다.

이 과정을 다른 말로 하면, 가중치에서 기울기를 뺐을 때 가중치의 변화가 없는 상태이다. 

각각의 과정을 자세히 설명하면 다음과 같다. 

1. 환경 변수 지정 : 환경 변수에는 입력값, 결괏값이 포함된 데이터셋, 학습률 등등.

                               여기서 활성화 함수와 가중치 등도 선언되어야 함

2. 신경망 실행

3. 결과를 비교하여 오차 측정

4. 역전파 실행

5. 결과 출력 

 

9-1. 오차 역전파의 시그모이드 함수 외의 다른 함수들 

그런데, 오차 역전파를 사용하면 기울기 소실 발생.

시그모이드 함수의 최대 기울기는 0.3 정도밖에 되지 않음. 그런데 이 기울기를 가지고 계속 오차 역전파 기법을 사용하다 보면 기울기의 값이 점점 작아져 맨 처음 층까지 전달되지 않음

빨간색은 시그모이드 함수, 파란색은 시그모이드의 도함수

 

따라서, 활성화 함수를 다른 함수로 대체해 보기로 결정

지금은 렐루 함수, 소프트플러스 함수를 많이 사용. 

 

렐루 함수

(x<0 이면 y = 0 , x>=0 이면 y = x)

단순하지만 여러 은닉층을 거쳐도 맨 처음 층이 사라지지 않음

 

소프트플러스 함수 

렐루 함수의 변형 함수로, x=0일때의 순간을 부드럽게 만듦

 

9-2. 고급 경사 하강법

경사 하강법의 문제 등장 : 정확한 가중치를 찾을 수 있지만 한번 업데이트 할 때마다 전체 데이터 미분하므로 계산량이 매우 많음. 따라서 고급 경사 하강법 등장

 

1. 확률적 경사 하강법 Stochastic Gradient Descent(SGD)

랜덤하게 추출한 데이터를 사용하여 더 빨리 업데이트함

중간 결과의 진폭이 크고 불안정해보일 수 있으나 근사값을 빨리 찾아낸다는 장점

 

2. 모멘텀

확률적 경사 하강법은 불안정해보이는 상태로 진행되기에, 이를 개선하고자 하였음

모멘텀이란, 바로 앞 수정 방향을 참고하여 같은 방향으로 수정되게끔 하는 방법

즉, 수정 방향이 지그재그로 일어나는 현상 줄어들게 함 

 

이 외에도, 네스테로프 모멘텀, 아다그라드, 알엠에스포롭, 아담 등 많은 방법

 

2023.11.14

10. 딥러닝 모델 설계하기

1. 모듈 불러오기

from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense
import numpy as np

2. 데이터 불러오기

!git clone https://github.com/taehojo/data.git

데이터 예시 : 빨간선을 기준으로 16개의 진찰 기록 X, 생존 여부 Y

3. 데이터 x값 y값 정하기

Data_set = np.loadtxt("./data/ThoraricSurgery3.csv", delimiter=",")
X = Data_set[:,0:16]
y = Data_set[:,16]

 

4. 모델 생성 

model = Sequential() #딥러닝의 구조를 짜고 층을 설정하는 부분
model.add(Dense(30, input_dim=16, activation='relu')) #은닉층 생성, 노드 30개, 16개 데이터 
model.add(Dense(1, activation='sigmoid')) #출력층 생성, 노드 1개

데이터에서 값을 16개 받아 은닉층의 노드 30개로 보낸다는 뜻

출력 값은 1개이므로 출력층의 노드 수는 1개 

 

활성화 함수를 은닉층과 출력층에서 둘 다 사용하는 이유:

하나만 사용하면 결과가 하나의 선형 변환으로만 나오기 때문

은닉층에선 ReLU, sigmoid, tanh이 사용됨

출력층에선 이진 분류할땐 sigmoid, 다중 클래스 분류는 softmax

5. 모델 컴파일 

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

모델이 효과적으로 구현될 수 있게 여러가지 환경을 설정하며 컴파일하는 부분

손실 함수는 선형 회귀에선 평균 제곱 오차, 로지스틱 회귀에선 교차 엔트로피 오차를 사용한다. 

metrics는 모델 컴파일 시에 모델 수행의 결과를 나타내게끔 설정하는 부분

 

6. 모델 실행

history = model.fit(X, y, epochs=5, batch_size=16)

에포크는 샘플이 다섯 번 재사용 될 때 까지 실행하시오

batch_size는 샘플을 한번에 몇 개씩 처리할 지 입력하는 부분,

너무 크면 속도가 느려지고 너무 작으면 각 실행값의 편차가 커짐. 

 

 2023.11.28

11. 데이터 다루기

1. 모듈과 데이터 불러오기

import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns 
!git clone https://github.com/taehojo/data.git
df = pd.read_csv('./data/pima-indians-diabetes3.csv')

 

2.데이터 정보 알아내기

df['diabetes'].value_counts() #정상인 500명과 환자 268명

>>>

diabetes
0    500
1    268
Name: count, dtype: int64
df.corr() #정보 간 상관관계, 피어슨 상관계수나 스피어만 상관계수 사용

>>>

당뇨병은 공복혈당과 가장 큰 상관관계가 있음을 알 수 있다. 

 

3. 시각화하기

plt.hist(x=[df.plasma[df.diabetes==0], df.plasma[df.diabetes==1]], bins=30, histtype='barstacked', label=['normal', 'diabetes'])
plt.legend()

>>>

당뇨가 없는 사람을 추출하고 싶을 때는 df.plasma[df.diabetes==0]과 같이 나타낸다는것을 기억하자. 

조건을 추가하고 싶으면

df.plasma[(df.insulin >= 100) & (df.insulin <= 200)]

다음과 같이 &로 나타낸다. 

 

딥러닝 돌려보기

1. 독립변수 종속변수 지정

X = df.iloc[:,0:8]
y = df.iloc[:,8]

 

2. 모델 제작

from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense
model = Sequential()
model.add(Dense(12, input_dim = 8, activation = 'relu', name = 'Dense_1'))
model.add(Dense(8, activation = 'relu', name = 'Dense_2'))
model.add(Dense(1, activation = 'sigmoid', name = 'Dense_3'))
model.summary()

>>>

Model: "sequential"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 Dense_1 (Dense)             (None, 12)                108       
                                                                 
 Dense_2 (Dense)             (None, 8)                 104       
                                                                 
 Dense_3 (Dense)             (None, 1)                 9         
                                                                 
=================================================================
Total params: 221 (884.00 Byte)
Trainable params: 221 (884.00 Byte)
Non-trainable params: 0 (0.00 Byte)

설명하자면 층을 Dense_1, Dense_2, Dense_3 3개 만든 것이고

아까 데이터 0:8개를 X에 넣었으므로 input_dim 을 8로 지정한 것이다. 

Dense_1, Dense_2, Dense_3은 각각 은닉층이 12,8,1인 것이다. 

param은 파라미터수 = 가중치 수 + 바이어스 수 이다. 

Dense_1의 경우 입력 값 8개가 12개의 노드로 분산되므로 가중치가 96이 되고, 각 노드에 바이어스가 한개씩 있으므로 바이어스가 12이다. 따라서 96+12 = 108인 것. 

 

3. 모델 컴파일

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

 

4. 딥러닝 실행

history = model.fit(X, y, epochs = 100, batch_size = 5)

>>>

Epoch 100/100
154/154 [==============================] - 0s 3ms/step - loss: 0.5133 - accuracy: 0.7747

77%의 정확도가 나왔다. 

'독서 목록' 카테고리의 다른 글

밑바닥부터 시작하는 데이터 과학  (0) 2023.03.06