본문 바로가기
네이버클라우드/AI

AI 2일차 (2023-05-09) 인공지능 기초 - 인공지능 기초개념과 훈련 테스트 데이터 셋

by prometedor 2023. 5. 9.

퍼셉트론

ㄴ 다수의 신호(Input)를 입력으로 받아 하나의 신호(Output)를 출력하는 알고리즘
ㄴ 인공신경망(ANN)의 한 종류로, 1957년에 Frank Rosenblatt이 발명
ㄴ 각 입력값에 대해 가중치(Weight)를 곱한 값들의 합과 편향(Bias)을 더한 후, 이 값이 어떤 임계값(Threshold)을 넘으면 1을 출력하고, 그렇지 않으면 0을 출력 
= > y = wx + b
 
ㄴ 활성화 함수를 통해 입력값이 일정한 임계치를 넘어설 경우 출력값이 1에 가까워지고, 그렇지 않은 경우에는 0에 가까워지도록 하여 입력값을 0 또는 1로 변환
ㄴ 계산된 출력값은 정답과 비교하여 오차를 계산하고, 이 오차를 줄이는 방향으로 가중치(w)와 편향(b)을 업데이트함 
ㄴ 최적의 가중치(w)와 편향(b)을 찾는 것이 최종 목표
ㄴ 퍼셉트론의 학습원리 : 손실함수
ㄴ 손실함수의 최소점을 찾는 기법 --> 경사 하강법

 
 

다층 퍼셉트론 (Multilayer Perceptron, MLP)

ㄴ 여러 개의 은닉층을 가지고 있는 인공신경망 구조 (성능은 좋아지지만 시간이 많이 소요됨)
ㄴ 각 은닉층은 여러 개의 노드(node)를 가지며, 이전 층의 노드와 연결되어 있는 가중치(weight)를 가짐
ㄴ 입력층(input layer), 은닉층(hidden layer), 출력층(output layer)으로 구성됨
ㄴ 각 층의 노드는 활성화 함수를 거쳐 출력값을 계산함
ㄴ 이렇게 출력층의 결과를 기준으로 오차를 계산하고, 역전파 알고리즘을 통해 각 층의 가중치를 조정하여 손실 함수를 최소화하는 방향으로 학습함

 

** 역전파 알고리즘
ㄴ 입력 데이터를 모델에 주입하여 나온 결과값과 정답을 비교하면서 오차를 계산하고, 이 오차를 이용하여 가중치를 업데이트
ㄴ 이 때, 역전파는 먼저 출력층에서 시작하여 입력층으로 이동하면서 각 층에서의 오차를 계산하고, 이 오차를 가지고 가중치를 업데이트 함
ㄴ 정해진 학습 횟수나 일정한 기준치 이상으로 오차가 줄어들 때까지 과정 반복


훈련 테스트 데이터 셋

데이터 셋 - Train, Test

https://pozalabs.github.io/assets/images/Dataset_Splitting/data_split.jpg

 
ㄴ 보편적으로 Train : Test 비율을 7 : 3 을 사용
ㄴ Train : Test 비율을 8 : 2 을 사용하면 과적합 위험이 있음
ㄴ Train : Validation : Test 비율을 6 : 2 : 2 로 사용하기도 함

 

** 과적합이란?
ㄴ 모델이 학습 데이터에 너무 잘 적합되어 새로운 데이터에 대해 일반화(generalization) 성능이 떨어지는 현상
ㄴ 간단한 모델이 복잡한 데이터를 모델링하려고 할 때 발생
ㄴ 모델이 학습 데이터에 매우 민감하게 반응하여 잡음(noise)까지 학습하는 경우, 새로운 데이터에 대한 예측력이 떨어지게 됨

 

Train Set

ㄴ 모델의 학습만을 위해 사용
ㄴ parameter 나 feature 등을 모델의 성능을 높이는 작업에 사용

 

Test Set

ㄴ 최종적으로 모델의 성능을 평가
ㄴ 모델의 학습에는 전혀 사용되지 않음
ㄴ 실사용 되었을 때 모델이 얼마나 좋은 성능을 발휘 할 수 있을지 알아보는 것

 

Validation Set

ㄴ 모델의 학습에 직접적으로 관여하지 않음
ㄴ 학습이 끝난 모델에 적용
ㄴ 최종적으로 모델을 fine tuning 하는 데에 사용
ㄴ 학습이 완료된 모델이라고 하더라도 epoch을 몇번 돌릴 것인지, 또는 learning rate의 설정은 어떻게 할 것인지 등에 따라 모델의 성능이 달라질 수 있기 때문에,  validation set을 통해 만든 모델이 test set 에서, 그리고 실제로 배포 되었을때 높은 성능을 낼 수 있도록 만들어 줌

 
 

 

train_test_split()

ㄴ scikit-learn 라이브러리
ㄴ 데이터를 무작위로 섞어서 훈련 데이터와 검증 데이터를 분리

 
 

실습

직접 데이터 비율 나누기

tf04_train_test_split01.py

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

#1. 데이터 
x = np.array([1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20])	# data 20개
y = np.array([1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20])

# x = np.array(range(1,21)) #range함수로도 가능

# print(x.shape)
# print(y.shape)
# print(x)

x_train = np.array([1,2,3,4,5,6,7,8,9,10,11,12,13,14])	# train 14개 
y_train = np.array([1,2,3,4,5,6,7,8,9,10,11,12,13,14])

x_test = np.array([15,16,17,18,19,20])	# test 6개
y_test = np.array([15,16,17,18,19,20])

# 비율 => train : test = 14 : 6 (7 : 3 비율로 만듦)


# 2. 모델 구성
model = Sequential()
model.add(Dense(14, input_dim = 1))
model.add(Dense(50))
model.add(Dense(1))


# 3. 컴파일, 훈련
model.compile(loss ='mse' , optimizer='adam')
model.fit(x_train, y_train, epochs=100, batch_size = 1)


# 4. 평가 , 예측
loss = model.evaluate(x_test, y_test)
print('loss : ', loss)

result  = model.predict([21])
print('21의 예측값 : ', result)

# loss :  1.01626937976107e-07
# 21의 예측값 :  [[20.999578]]

 
 

range 이용하여 데이터 비율 나누기

tf04_train_test_split02.py

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

#1. 데이터 
x = np.array([1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20])
y = np.array([1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20])

# x = np.array(range(1,21)) #range함수로도 가능

# print(x.shape)
# print(y.shape)
# print(x)

# x_train = np.array([1,2,3,4,5,6,7,8,9,10,11,12,13,14])
# y_train = np.array([1,2,3,4,5,6,7,8,9,10,11,12,13,14])

# x_test = np.array([15,16,17,18,19,20])
# y_test = np.array([15,16,17,18,19,20])

# [실습] x와 y 데이터를 파이선 리스트 스플릿으로 분리하기
# x_train = x[0:14]
# y_train = y[0:14]
# x_test = x[14:20]
# y_test = y[14:20]
x_train = x[:14]
y_train = y[:14]
x_test = x[14:]
y_test = y[14:]

print(x_train)
print(x_test)

# 2. 모델 구성
model = Sequential()
model.add(Dense(14, input_dim = 1))
model.add(Dense(50))
model.add(Dense(1))


# 3. 컴파일, 훈련
model.compile(loss ='mse' , optimizer='adam')
model.fit(x_train, y_train, epochs=100, batch_size = 1)


# 4. 평가 , 예측
loss = model.evaluate(x_test, y_test)
print('loss : ', loss)

result  = model.predict([21])
print('21의 예측값 : ', result)


# loss :  1.840210900327932e-10
# 21의 예측값 :  [[20.999985]]

 
 

train_test_split  - 7 : 3 비율로 데이터 나누기

tf04_train_test_split03.py

import numpy as np
from keras.models import Sequential
from keras.layers import Dense
from sklearn.model_selection import train_test_split

#1. 데이터 
x = np.array([1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20])
y = np.array([1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20])

x_train, x_test, y_train, y_test = train_test_split(
    x, y,               # x, y 데이터
    test_size=0.3,      # test의 사이즈 보통 30%
    train_size=0.7,     # train의 사이즈는 보통 70%
    random_state=100,   # 데이터를 난수값에 의해 추출한다는 의미, 중요한 하이퍼 파라미터 (random_state : 난수 값 지정)
    shuffle=True        # 데이터를 섞을 것인지 정함 (shuffle : True 가 default)
)

# 2. 모델 구성
model = Sequential()
model.add(Dense(14, input_dim = 1))
model.add(Dense(50))
model.add(Dense(1))


# 3. 컴파일, 훈련
model.compile(loss ='mse' , optimizer='adam')
model.fit(x_train, y_train, epochs=100, batch_size = 1)


# 4. 평가 , 예측
loss = model.evaluate(x_test, y_test)
print('loss : ', loss)

result  = model.predict([21])
print('21의 예측값 : ', result)

 
 

matplotlib - Scatter (산점도)

import numpy as np
from keras.models import Sequential
from keras.layers import Dense
from sklearn.model_selection import train_test_split

#1. 데이터 
x = np.array([1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20])
y = np.array([1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20])

x_train, x_test, y_train, y_test = train_test_split(    # 사이킷런에 있는 train_test_split
    x, y,               # x, y 데이터
    test_size=0.3,      # test의 사이즈 보통 30%
    train_size=0.7,     # train의 사이즈는 보통 70%
    random_state=100,   # 데이터를 난수값에 의해 추출한다는 의미, 중요한 하이퍼 파라미터 (random_state : 난수 값 지정)
    shuffle=True        # 데이터를 섞을 것인지 정함 (shuffle : True 가 default)
)

# 2. 모델 구성
model = Sequential()
model.add(Dense(14, input_dim = 1))
model.add(Dense(50))
model.add(Dense(1))


# 3. 컴파일, 훈련
model.compile(loss ='mse' , optimizer='adam')
model.fit(x_train, y_train, epochs=100, batch_size = 1)


# 4. 평가 , 예측
loss = model.evaluate(x_test, y_test)
print('loss : ', loss)

y_predict = model.predict(x)

##### scatter 시각화 #####
import matplotlib.pyplot as plt

plt.scatter(x, y)   # 산점도 그리기
plt.plot(x, y_predict, color='red')
plt.show()

 

실행 결과

 
 

R2 score (결정계수)

https://velog.velcdn.com/images%2Fgooook%2Fpost%2F38b370c1-015d-40ba-81f1-920781ade8c9%2FRegression-terminologies-Page-3.png

 
ㄴ R-squared 는 선형 회귀 모델에 대한 적합도 측정값
ㄴ 선형 회귀 모델을 훈련한 후, 모델이 데이터에 얼마나 적합한지 확인하는 통계 방법 중 하나
ㄴ r2 score 는 0 과 1 사이의 값을 가지며 1에 가까울 수록 선형회귀 모델이 데이터에 대하여 높은 연관성을 가지고 있다고 해석함
ㄴ 1 로 정확하게 떨어지면 과적합일 가능성 있음
 

tf06_r2score.py

import numpy as np
from keras.models import Sequential
from keras.layers import Dense
from sklearn.model_selection import train_test_split

#1. 데이터 
x = np.array([1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20])
y = np.array([1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20])

x_train, x_test, y_train, y_test = train_test_split(    # sklearn 에 있는 train_test_split
    x, y,               # x, y 데이터
    test_size=0.3,      # test의 사이즈는 보통 30%
    train_size=0.7,     # train의 사이즈는 보통 70%
    random_state=100,   # 데이터를 난수값에 의해 추출한다는 의미, 중요한 하이퍼 파라미터 (random_state : 난수 값 지정)
    shuffle=True        # 데이터를 섞을 것인지 정함 (shuffle : True 가 default)
)

# 2. 모델 구성
model = Sequential()
model.add(Dense(14, input_dim = 1))
model.add(Dense(50))
model.add(Dense(1))


# 3. 컴파일, 훈련
model.compile(loss ='mse' , optimizer='adam')
model.fit(x_train, y_train, epochs=100, batch_size = 1)


# 4. 평가 , 예측
loss = model.evaluate(x_test, y_test)
print('loss : ', loss)              # 훈련 잘 되어있는지 체크

y_predict = model.predict(x)

##### R2score #####
from sklearn.metrics import r2_score, accuracy_score    # metrics --> 분석(r2_score 회귀, accuracy_score 분류)
r2 = r2_score(y, y_predict)
print('r2스코어 : ', r2)

# result(1)
# loss :  1.276703187613748e-10
# r2스코어 :  0.99999999999226

 
 

성능 떨어뜨려보기 실습

tf06_r2_bad.py

# [실습]
# 1. R2score 를 음수가 아닌 0.5 이하로 만들어 보기
# 2. 데이터는 건드리지 말기
# 3. 레이어는 인풋, 아웃풋 포함 7개(히든레이어 5개 이상) 이상으로 만들기
# 4. batch_size=1
# 5. 히든레이어의 노드 개수는 10개 이상 100개 이하
# 6. train_size = 0.7
# 7. ephocs = 100 이상
# 8. [실습시작]

import numpy as np
from keras.models import Sequential
from keras.layers import Dense
from sklearn.model_selection import train_test_split

#1. 데이터 
x = np.array([1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20])
y = np.array([1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20])

x_train, x_test, y_train, y_test = train_test_split(    # 사이킷런에 있는 train_test_split
    x, y,               # x, y 데이터
    test_size=0.3,      # test의 사이즈 보통 30%
    train_size=0.7,     # train의 사이즈는 보통 70%
    random_state=100,   # 데이터를 난수값에 의해 추출한다는 의미, 중요한 하이퍼 파라미터 (random_state : 난수 값 지정)
    shuffle=False        # 데이터를 섞을 것인지 정함 (shuffle : True 가 default)
)

# 2. 모델 구성
model = Sequential()
model.add(Dense(14, input_dim = 1))      # 노드 수, 히든 레이어 수 영향
model.add(Dense(100))       # 히든 레이어 많이 쌓으면 성능 저하
model.add(Dense(100))
model.add(Dense(100))
model.add(Dense(100))
model.add(Dense(100))
model.add(Dense(100))
model.add(Dense(100))
model.add(Dense(100))
model.add(Dense(100))
model.add(Dense(100))
model.add(Dense(100))
model.add(Dense(100))
model.add(Dense(100))
model.add(Dense(100))
model.add(Dense(100))
model.add(Dense(100))
model.add(Dense(100))
model.add(Dense(100))
model.add(Dense(100))
model.add(Dense(100))
model.add(Dense(100))
model.add(Dense(100))
model.add(Dense(100))
model.add(Dense(100))
model.add(Dense(100))
model.add(Dense(100))
model.add(Dense(100))
model.add(Dense(100))
model.add(Dense(100))
model.add(Dense(100))
model.add(Dense(100))
model.add(Dense(100))
model.add(Dense(100))
model.add(Dense(100))
model.add(Dense(100))
model.add(Dense(100))
model.add(Dense(100))
model.add(Dense(100))
model.add(Dense(1))


# 3. 컴파일, 훈련
model.compile(loss ='mse' , optimizer='adam')
model.fit(x_train, y_train, epochs=100, batch_size = 1)


# 4. 평가 , 예측
loss = model.evaluate(x_test, y_test)
print('loss : ', loss)              # 훈련 잘 되어있는지 체크

y_predict = model.predict(x)

##### R2score #####
from sklearn.metrics import r2_score, accuracy_score    # metrics --> 분석(r2 회귀, accuracy 분류)
r2 = r2_score(y, y_predict)
print('r2스코어 : ', r2)

# result(1)
# loss : 62.93217849731445
# r2스코어 : 0.1696187048801573
# 노드수를 많게, 히든레이어의 개수를 많게 하면 r2score 가 좋지 않음