빅데이터/Machine-Learning
머신러닝 04 - sklearn 알아 보기 (분류 - 3, 회귀 - 1)
H-V
2022. 2. 11. 21:42
패스트캠퍼스 '직장인을 위한 파이썬 데이터분석 올인원 패키치 Online' 참조
01 오차 및 정확도의 함정
- 분류함에 있어 평가지표가 중요하다. 그 중 하나가 정확도이다. 하지만 이 정확도에 함정이 있다
- 유방암 환자 데이터셋을 베이스로 알아 보자
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
import numpy as np
cancer = load_breast_cancer()
print(cancer['DESCR'])
cancer.keys()
- 이 키들을 합쳐서 데이터프레임화를 해보면..
일반적인 학습에 필요한 데이터 값들과 그 값에 맞는 이름을 데이터 프레임으로 넣으면 아래와 같다.data = cancer['data'] target = cancer['target'] feature_names = cancer['feature_names'] df = pd.DataFrame(data=data, columns = feature_names) df
- 여기서 타겟값을 합치고 타겟값을 베이스로 데이터를 짜보면..
df['target'] = cancer['target'] df.head()
- 그리고 여기서 양성인지 악성인지 나눠서 보자 (악성이 0, 양성이 1)
# .loc로 원하는 열을 집어서 원하는 값으로 만들 수 있다 pos = df.loc[df['target']==1] neg = df.loc[df['target']==0] pos
- 이제 여기서 직접 데이터들을 섞고 어떻게 정확도의 오류가 생기는지 보자
# 학습데이터에는 예측데이터가 들어 가면 안된다!, .drop(드랍하고자하는 컬럼명, axis='1 or columns') # axis=''를 반드시 선언해줘야 한 열이 다 지워진다. # axis = 0 은 행, axis = 1 은 열 x_train, x_test, y_train, y_test = train_test_split(sample.drop('target', 1), sample['target'], random_state=77)
→ 로지스틱 회귀로 체크
sample = pd.concat([pos, neg[:5]], sort=True)
# 학습데이터에는 예측데이터가 들어 가면 안된다!, .drop(드랍하고자하는 컬럼명, axis='1 or columns')
# axis=''를 반드시 선언해줘야 한 열이 다 지워진다.
# axis = 0 은 행, axis = 1 은 열
x_train, x_test, y_train, y_test = train_test_split(sample.drop('target', 1), sample['target'],random_state=1)
model = LogisticRegression()
model.fit(x_train, y_train)
pred = model.predict(x_test)
(pred == y_test).mean()
1.0
- 로지스틱에서도 1, 즉 모델의 학습도는 완벽에 가깝다. 하지만 아래처럼 내 임의대로 모든것이 양성이다라고 하고 돌려보자
이 데이터는 현재 악성 데이터를 5개나 들고 있음에도 불구하고 아무런 지식이 없는 내가 모든것은 양성이다 라고 선언해도 데이터 정확도는 1과 똑같이 나온다.my_prediction = np.ones(shape=y_test.shape) (my_prediction == y_test).mean() 1.0
- 즉 어떤 의사가 모델의 정확도만 믿고 저는 음성과 양성을 완벽히 구분합니다 라고 하면 과연 그 의사는 좋은 의사일까? 당연히 이렇게 정확도의 함정에 빠질 수 있는데 이를 보완하고 생겨난 지표들이 몇개 있다
02 오차 행렬
- Confusion Matrix로 불리는데 분류 모델이 예측을 수행하면서 얼마나 헷갈리는지를 보여주는 지표이다. 즉 이진 분류의 예측 오류가 얼마인지와 더불어 어떠한 유형의 예측 오류가 발생하고 있는지를 함께 보여주는 지표
- 오차행렬은 위와 같이 4분면 행렬에서 실제 label class와 예측 label class가 어떠한 유형을 가지고 mapping이 되는지 나타낸다.
- 예측 class와 실제 class에 따라 TN,FP,FN,TP로 4분면을 채울 수 있다. 오차가 들어가는 조건은 다음과 같다.
1. TN은 예측값을 Negative 값인 0으로 예측했고 실제값 또한 Negative 값인 0일 때
2. FP은 예측값을 Positive 값인 1으로 예측했는데 실제값은 Negative 값인 0일 때
3. FN은 예측값을 Negative 값인 0으로 예측했는데 실제값은 Positive 값인 1일 때
4. TP은 예측값을 Positive 값인 1으로 예측했고 실제값 또한 Positive 값인 1일 때
예제를 보면 다음과 같다
from sklearn.metrics import confusion_matrix
import matplotlib.pyplot as plt
import seaborn as sns
confusion_matrix(y_test, pred)
array([[ 0, 2],
[ 0, 89]], dtype=int64)
sns.heatmap(confusion_matrix(y_test, pred), annot=True, cmap='Reds')
plt.xlabel('Predict')
plt.ylabel('Actual')
plt.show()
03 정밀도와 재현율
- 정밀도와 재현율도 분류성능평가지표들 중 하나이다.
- 정밀도(Precision) - 모델이 True라고 분류한 것 중에서 실제 True인 것의 비율.
- 재현율(Recall) - 실제 True인 것 중에서 모델이 True라고 예측한 것의 비율.
- 예로 날씨 예측 모델이 맑다로 예측했는데, 실제 날씨가 맑았는지를 판별 할 수 있다
- 정밀도 TP/(TP+FP)
from sklearn.metrics import precision_score, recall_score
precision_score(y_test, pred)
0.967032967032967
88 / (88+3) = 88/91 = 0.967....
▶ 무조건 양성으로 판단하면 좋은 정밀도를 얻기 때문에 유용 하지 않다
- 재현율 TP/(TP+FN) - 민감도라고도 불린다 (True Positive Rate (TPR))
recall_score(y_test, pred)
1.0
04 F1 Score
- 정밀도와 재현율의 조화평균을 나타내는 지표, 즉 둘이 같이 보기 위해서 만들어짐
- 조화평균을 통해 비중에 따라 영향을 받는 bias가 줄어드는 효과가 있음
(참고 링크: https://sumniya.tistory.com/26)
from sklearn.metrics import f1_score
f1_score(y_test, pred)
0.9832402234636871
05 회귀 예측 준비
- 분류는 각각의 클래스를 예측한다고 보면 회귀 예측은 수치값을 예측하는 모델
- 분류모델은 말 그대로 분류를 한다. iris()를 예로보면 3개의 붓꽃 종류가 있고 어디에 해당하는지를 분류를 했다. 회귀 예측은 수치 즉 가격, 매출액 혹은 연속된 수치로 된것들을 예측하는 모델
- 샘플데이터를 준비 하고 모델을 만들어야 한다
import pandas as pd
import numpy as np
#수지형중 'e'가 찍히는걸 방지함
np.set_printoptions(suppress=True)
from sklearn.datasets import load_boston
print(data['DESCR'])
▶ 가격 예측에 필요한 기호들
- DF만들기
# data['data'] 에는 X데이터, data['feature_names'] 에는 컬럼명 df = pd.DataFrame(data['data'], columns = data['feature_names']) df
- 분류와는 다르게 data값이 x에 들어간다.
- 그리고 똑같이 y = price값도 추가로 넣어 준다
df['MEDV'] = data['target'] df
- 분류에서는 데이터와 타겟을 맞춰야하기때문에 target으로 컬럼명을하고 데이터를 넣었고
(target = cancer['target'] --> 음성/양성 (0/1) 이 타겟값으로 들어갔었음)
회귀예측에서는 수치형(가격 등등 = target)이 'MEDV'라는 컬럼명으로 데이터값이 들어감MEDV = 자가 주택의 중앙값, 즉 예측해야될 주택 가격
이제 여기서 똑같이 훈련용, 테스트용, 검증용으로 나뉜다
from sklearn.model_selection import train_test_split
x_train, x_test, y_train, y_test = train_test_split(df.drop('MEDV', 1), df['MEDV'])
x_train.shape, x_test.shape
((379, 13), (127, 13))
x_train.head()
06 회귀 모델 평가 지표 만들기
- 모델을 평가하기 위한 지표가 필요하다. 테스트 전에 선택한 모형이 데이터에 얼마나 잘 맞는지를 측정할 방법이 필요한 것.
- 회귀 모델에 대한 평가지표는 여러가지가 있지만 가장 기본적인 3가지를 알아야 한다
1) MSE(Mean Squared Error) - 예측값과 실제값의 차이에 대한 제곱에 대하여 평균을 낸 값
(실제값(y) - 예측값(x)) = 오차, 오차 전 실제값+예측값으로 전체 합을 구함
오차는 분산과 똑같은데 각 데이터가 평균으로부터 얼마나 퍼져 있는지를 나타내는 통계치
제곱을 하는 이유는 예측시에 +1, -1, +3, -3 등 평균이 0이 되는 경우가 있다.오차 제곱에 대한 평균을 낸것
2) MAE(Mean Absolute Error) - 예측값과 실제값의 차이에 대한 절대값에 대하여 평균을 낸 값
절대값은 단순히 +,- 부호만 뗀 것. 이것을 '평균 절대 오차' 라고 부른다. 일반적으로는 MSE를 더 많이 쓴다.
단지 계산이 더 쉽기 때문. MAE의 장점은, MSE 경우 오차를 제곱하면 할 수록 오차가 커지고 손실이 제곱으로 커진다. 따라서 100개의 예측 중 99개가 잘 맞았으나 하나에 크게 틀리면 영향을 엄청나게 받는다. 이 틀린것을 이상점이라 하는데 MAE는 이상점에 영향을 덜 받는다.절대값에 대한 평균
3) RMSE(Root Mean Squared Error) - 예측값과 실제값의 차이에 대한 제곱에 평균을 내고 루트를 씌운 값
쉽게 말해 모델간의 '잔차'를 비교해 볼 수 있음. 잔차는 회귀선에서 얼마나 멀리 떨어져 있는지 측정을 하는 값인데 RMSE는 이 잔차가 얼마나 분산되어 있는지 측정함. 즉 데이터가 가장 적합한 선 주위에 얼마나 집중되어 있는지 알려 줌오차 제곱에 루트를 씌움
- 코드로 보자!
import numpy as np
pred = np.array([3,4,5])
actual = np.array([1,2,3])
# MSE
def my_mse(pred, actual):
return ((pred - actual)**2).mean()
my_mse(pred, actual)
4.0
def my_mae(pred, actual):
return np.abs(pred-actual).mean() # .abs() 절대값
my_mae(pred, actual)
2.0
def my_rmse(pred, actual):
return np.sqrt(my_mae(pred, actual)) #.sqrt() 루트를 씌워줌
my_rmse(pred, actual)
1.4142135623730951 (2.0)
07 sklearn에서 지원하는 평가지표 사용해보기
- 위에서 처럼 직접 코드로 구현도 되지만 사이킷런에서 제공하는 회귀모델 평가지표가 있다
from sklearn.metrics import mean_absolute_error, mean_squared_error.
my_mae(pred, actual), mean_absolute_error(pred, actual)
(2.0, 2.0)
my_mse(pred, actual), mean_squared_error(pred, actual)
(4.0, 4.0)