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

AI 2일차 (2023-05-09) 인공지능 기초 - 회귀분석과 분류분석

by prometedor 2023. 5. 9.

회귀분석과 분류분석

https://velog.velcdn.com/images%2Fskm0626%2Fpost%2Fdebf2e8b-71eb-4c8f-b870-72dab5452a79%2Fclassificationregression2.png

 

 

구분 회귀분석 분류
이진분류 다중분류
평가지표
Loss
mse, mae
R2
Binary_Crossentropy

accuracy
Catergorical_Crossentropy

accuracy
Last Layer
Activation
Default
(Linear)
Simoid Softmax
Last Layer
node 의 개수
1이상 1 y 레벨의 수 만큼
Metrics mse, mae mse, mae + acc mse, mae + acc
One Hot Encoding X X X

 

 

회귀분석 (Regression)

ㄴ 연속된 값을 예측 (계속해서 변하는 값)
ㄴ 과거의 주가 데이터를 가지고 미래 주가를 예측하거나, 자동차 배기량이나 연식 등 중고차 정보를 이용하여 가격을 예측

 
 

분류분석 (Classification)

ㄴ 종류를 예측
ㄴ 클래스 0 또는 1 중에서 선택하는 이진분류(binary classification) 또는 3개 이상의 클래스 중에서 하나를 선택하는 다중 분류(multi classification)


 

이진분류

https://machinethink.net/images/tensorflow-on-ios/LogisticRegression@2x.png

 
ㄴ 이진분류의 경우 참(True) 또는 거짓(False)을 판별하기 때문에 출력 값이 1개
ㄴ 출력 값을 sigmoid 함수(활성화 함수 종류)를 이용하여 0과 1로 가공
로지스틱 회귀(Logistic Regression)는 이진 분류 모델을 분석하기 좋은 모델

** 로지스틱 회귀는 Regression 이지만 분류분석에 사용되는 모델임

= > 직선(Linear)보다 적절한 곡선(Logistic)을 통해 분류를 함

 

https://velog.velcdn.com/images/73syjs/post/9ece82c2-0abb-4379-b0a7-74ed203eaf8d/image.png

 
ㄴ 그림을 보면 선형 회귀 모델(Linear Regression)은 독립 변수의 값이 증가할수록 종속 변수의 값도 증가/감소 하는 형태를 가짐
ㄴ 반면에 로지스틱 회귀 모델(Logistic Regression)은 독립변수 값이 아무리 크게 변해도 종속 변수는 0과 1사이의 값으로 나타남
 
 

다중 분류

https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbku1Ai%2FbtriSLS9kCa%2F0oQjP2UFUnIQlTKQire061%2Fimg.png

 
ㄴ 타깃의 종류가 여러 개이기 때문에 출력 값도 여러 개
     = > 각각의 출력 값은 그에 대응하는 타깃과 매칭 될 확률을 나타냄
ㄴ 다중 분류는 softmax 함수를 사용하여 0과 1 사이의 값으로 가공
ㄴ 다중 분류 모델에서는 one-hot encoding 이라는 기법을 사용
 

https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbeCcNQ%2FbtriCFSQ9nF%2FpJxaBlDozg75dwgTuAJmXk%2Fimg.png


ㄴ 다중 분류 모델의 Softmax 함수
ㄴ 그림의 softmax함수를 통과한 값들의 합은 1
ㄴ  첫 번째 그림은 두 번째 타깃일 가능성이 높고, 두 번째 그림은 두 번째 타깃일 가능성이 높으므로 두 번째 데이터가 좀 더 높은 신뢰성을 가지고 있음
ㄴ  softmax함수를 통과한 값들 중 가장 높은 값에 대응하는 클래스가 모델의 예측값이 됨
ㄴ One-hot encoding  = > 단 하나의 값만 True(1)이고 나머지는 False(0) 으로 인코딩하는 것 (softmax를 통과한 값 중 가장 높은 값을 1로 남겨두고, 나머지 값들은 모두 0으로 만듦)

 

 

** One-hot encoding

ㄴ why?

       = > 데이터 형태가 0, 1로 이루어졌기 때문에 컴퓨터가 인식하고 학습하기에 용이함

       = > 각 클래스 간의 차이를 균등하게 취급하도록 함 (즉, 큰 값을 가진 클래스가 중요하다고 인식하지 않도록 함)

 

** softmax 함수

ㄴ 각 클래스가 정답일 확률을 표현하도록 0에서부터 1사이의 값으로 정규화(Normalization)를 해주는 함수

= >  정규화를 해주는 이유

        ㄴ 큰 값을 갖는 변수에 편향되지 않을 수 있음

        ㄴ X값을 특정 범위로 제한하기 때문에 최적화를 더 빠르게 만듦 (학습 속도 향상)


 

손실함수 (Loss Function)

binary_crossentropy (이항교차 엔트로피)

y 값이 0과 1인 이진 분류기를 훈련할 때 자주 사용되는 손실함수
ㄴ 활성화 함수(activation) : sigmoid 사용 (출력값이 0과 1 사이의 값)
 

이진분류
tf09_cancer_sigmoid.py

import numpy as np
from keras.models import Sequential
from keras.layers import Dense
from sklearn.model_selection import train_test_split
from sklearn.metrics import r2_score, accuracy_score    # 적합도 / 정확도
from sklearn.datasets import load_breast_cancer
import time

# 1. 데이터
datasets = load_breast_cancer()
print(datasets.DESCR)
print(datasets.feature_names)
# ['mean radius' 'mean texture' 'mean perimeter' 'mean area'
#  'mean smoothness' 'mean compactness' 'mean concavity'
#  'mean concave points' 'mean symmetry' 'mean fractal dimension'
#  'radius error' 'texture error' 'perimeter error' 'area error'
#  'smoothness error' 'compactness error' 'concavity error'
#  'concave points error' 'symmetry error' 'fractal dimension error'
#  'worst radius' 'worst texture' 'worst perimeter' 'worst area'
#  'worst smoothness' 'worst compactness' 'worst concavity'
#  'worst concave points' 'worst symmetry' 'worst fractal dimension']
x = datasets.data
y = datasets.target
print(x.shape, y.shape) # (569, 30) (569,)  --> input_dim : 30

x_train, x_test, y_train, y_test = train_test_split(
    x, y, train_size=0.7, random_state=100, shuffle=True
)

# 2. 모델구성
model = Sequential()
model.add(Dense(100, input_dim=30))
model.add(Dense(100))
model.add(Dense(50))
model.add(Dense(1, activation='sigmoid'))   # 이진분류는 무조건 아웃풋 레이어의 활성화 함수를 sigmoid 로 해줘야 함

# 3. 컴파일 훈련
# model.compile(loss='binary_crossentropy', optimizer='adam', 
#               metrics='mse')
model.compile(loss='binary_crossentropy', optimizer='adam', 
              metrics=['accuracy', 'mse'])

start_time = time.time()    # 시작 시간
model.fit(x_train, y_train, epochs=100, batch_size=200,
          verbose=1)        # verbose : 0 일 경우 표시 안 됨 / 2 일 경우 막대기 없어짐
end_time = time.time() - start_time     # 걸린 시간


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

# [실습] accuracy_score 를 출력하라
# y_predict 반올림하기

# np.where
'''
y_predict = np.where(y_predict > 0.5, 1, 0)
acc = accuracy_score(y_test, y_predict)
print('loss : ', loss)  # loss :  [0.23969072103500366, 0.06037144735455513] --> loss, mse
print('acc : ', acc)    # acc :  0.9239766081871345
'''
# np.round
y_predict = np.round(y_predict)
acc = accuracy_score(y_test, y_predict)
print('loss : ', loss)  # loss :  [0.26926353573799133, 0.056343384087085724] --> loss, mse
print('acc : ', acc)    # acc :  0.935672514619883
print('걸린 시간 : ', end_time)
# 걸린 시간 :  1.1122465133666992


# 걸린 시간 :  1.1031553745269775
# loss :  [0.35699227452278137, 0.9415204524993896, 0.06094878911972046]
# acc :  0.9415204678362573

 

categorical_crossentropy (범주형 교차 엔트로피)

ㄴ y 클래스가 3개 이상일 경우, 즉 다중 분류에서 사용
ㄴ 활성화 함수(activation) : softmax 사용 (모든 벡터 요소의 값은 0 과 1 사이의 값이 나오고, 모든 합이 1이 됨)
ㄴ 라벨이 (0,0,1,0,0), (0,1,0,0,0) 과 같이 one-hot encoding 된 형태로 제공될 때 사용 가능
 
tf10_iris_onehotencoding.py

import numpy as np
from keras.models import Sequential
from keras.layers import Dense
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
from sklearn.datasets import load_iris
import time

# 1. 데이터
datasets = load_iris()
print(datasets.DESCR)
print(datasets.feature_names)
# ['sepal length (cm)', 'sepal width (cm)', 'petal length (cm)', 'petal width (cm)']

# x = datasets.data --> x = datasets['data'] 와 같음
x = datasets['data']    
y = datasets.target     
print(x.shape, y.shape) # (150, 4) (150,)  --> input_dim : 4 / 다중분류 : Class(분류)

### one hot encoding ###
from keras.utils import to_categorical
y = to_categorical(y)
print(y)
print(y.shape)  # (150, 3)

x_train, x_test, y_train, y_test = train_test_split(
    x, y, train_size=0.7, random_state=100, shuffle=True
)
print(x_train.shape, y_train.shape)     # (105, 4) (105, 3)
print(x_test.shape, y_test.shape)       # (45, 4) (45, 3)
print(y_test)

# 2. 모델 구성
model = Sequential()
model.add(Dense(100, input_dim=4))
model.add(Dense(50))
model.add(Dense(50))
model.add(Dense(10))
model.add(Dense(3, activation='softmax'))   # 다중 분류

# 3. 컴파일, 훈련
model.compile(loss='categorical_crossentropy', optimizer='adam',
              metrics=['accuracy'])   # sparse_categorical_crossentropy : one-hot encoding 하지 않고 가능
start_time = time.time()
model.fit(x_train, y_train, epochs=500, batch_size=100) # 훈련 시킴
end_time = time.time() - start_time
print('걸린 시간 : ', end_time)

# 4. 평가, 예측
loss, acc = model.evaluate(x_test, y_test)
print('loss : ', loss)
print('acc : ', acc)    # acc 1.0 -> 과적합일 확률 높음

# 걸린 시간 :  2.4981889724731445
# loss :  0.041628070175647736
# acc :  0.9777777791023254

### argmax 로 accuracy score 구하기
y_predict = model.predict(x_test)
y_predict = y_predict.argmax(axis=1)
y_test = y_test.argmax(axis=1)
argmax_acc = accuracy_score(y_test, y_predict)
print('argmax_acc', argmax_acc)

 

sparse_categorical_crossentropy

ㄴ categorical crossentropy와 같이 다중 분류에서 사용
one-hot encoding 된 상태일 필요 없이 정수 인코딩 된 상태에서 수행 가능
ㄴ 라벨이 (1,2,3,4) 와 같이 정수형태로 사용
 
tf10_iris_softmax.py

import numpy as np
from keras.models import Sequential
from keras.layers import Dense
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
from sklearn.datasets import load_iris
import time

# 1. 데이터
datasets = load_iris()
print(datasets.DESCR)
print(datasets.feature_names)
# ['sepal length (cm)', 'sepal width (cm)', 'petal length (cm)', 'petal width (cm)']

# x = datasets.data
x = datasets['data']    
y = datasets.target     
print(x.shape, y.shape) # (150, 4) (150,)  --> input_dim : 4 / 다중분류 : Class(분류)

x_train, x_test, y_train, y_test = train_test_split(
    x, y, train_size=0.7, random_state=100, shuffle=True
)
print(x_train.shape, y_train.shape)     # (105, 4) (105,)
print(x_test.shape, y_test.shape)       # (45, 4) (45,)
print(y_test)

# 2. 모델 구성
model = Sequential()
model.add(Dense(100, input_dim=4))
model.add(Dense(50))
model.add(Dense(50))
model.add(Dense(10))
model.add(Dense(3, activation='softmax'))   # 다중 분류

# 3. 컴파일, 훈련
model.compile(loss='sparse_categorical_crossentropy', optimizer='adam',
              metrics=['accuracy'])   # sparse_categorical_crossentropy : one-hot encoding 하지 않고 가능
start_time = time.time()
model.fit(x_train, y_train, epochs=500, batch_size=100)
end_time = time.time() - start_time
print('걸린 시간 : ', end_time)

# 4. 평가, 예측
loss, acc = model.evaluate(x_test, y_test)
print('loss : ', loss)
print('acc : ', acc)    # acc 1.0 -> 과적합일 확률 높음

# 걸린 시간 :  2.4981889724731445
# loss :  0.041628070175647736
# acc :  0.9777777791023254

 
 

평균 제곱 오차 손실 (means squared error, MSE)

회귀 문제에서 널리 사용됨
     ㄴ 회귀문제에 사용될 수 있는 다른 손실 함수
         (1) 평균 절대값 오차 (Mean absolute error, MAE)
         (2) 평균 제곱근 오차 (Root mean squared error, RMSE)

ㄴ 예측값과 실제값의 차이를 제곱하여 평균한 값 (모두 실수값으로 계산)
MSE가 크면 = > 평균 사이에 차이가 크다는 뜻
ㄴ MSE가 작으면 = > 데이터와 평균사이의 차이가 작다는 뜻


난수값(random_state)

ㄴ 머신러닝 모델을 학습할 때 데이터를 무작위로 섞을 때 사용되는 값
ㄴ 이 값을 지정하면 모델을 다시 실행해도 동일한 결과를 얻을 수 있음 --> 재현성을 보장
ㄴ train_test_split() 함수 사용 시 random_state 값을 지정하면 동일한 난수 시퀀스가 생성되므로 다른 사용자가 동일한 코드를 실행해도 동일한 데이터 분리 결과를 얻을 수 있음
ㄴ 이때 random_state에는 어떤 숫자를 적든 그 기능은 같기 때문에 어떤 숫자를 적든 상관없음
ㄴ 모델의 초기 가중치를 무작위로 설정할 때도 사용
ㄴ random_state 값을 지정하면 다른 모델을 학습할 때와 동일한 초기 가중치를 설정할 수 있으므로 재현성을 보장할 수 있음
ㄴ 모델의 하이퍼파라미터를 튜닝할 때는 여러 가지 random_state 값을 사용하여 검증 데이터의 성능을 평균 내는 것이 좋음