ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 머신러닝 04 - sklearn 알아 보기 (분류 - 3, 회귀 - 1)
    빅데이터/Machine-Learning 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()

    Malignant - 악성인지, Benign - 양성인지 판단하는 데이터
    어떤 키들로 나눠져 있는지 볼 수 있고 각각의 데이터 또한 찍어보는게 가능하다
    일반적인 데이터와 각각의 데이터값에 맞는 타겟값들이 있다. 악성과 양성의 종류를 0,1로 표현한듯 하다

     

      • 이 키들을 합쳐서 데이터프레임화를 해보면..
        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, 즉 모델의 학습도는 완벽에 가깝다. 하지만 아래처럼 내 임의대로 모든것이 양성이다라고 하고 돌려보자
      my_prediction = np.ones(shape=y_test.shape)
      
      (my_prediction == y_test).mean()
      1.0​
      이 데이터는 현재 악성 데이터를 5개나 들고 있음에도 불구하고 아무런 지식이 없는 내가 모든것은 양성이다 라고 선언해도 데이터 정확도는 1과 똑같이 나온다.
    •  
    • 즉 어떤 의사가 모델의 정확도만 믿고 저는 음성과 양성을 완벽히 구분합니다 라고 하면 과연 그 의사는 좋은 의사일까? 당연히 이렇게 정확도의 함정에 빠질 수 있는데 이를 보완하고 생겨난 지표들이 몇개 있다

     

     

     

    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

    - 절대값 참조 링크(https://nous-temperature.tistory.com/431#:~:text='%EC%A0%88%EB%8C%80%EA%B0%92'%EC%9D%B4%EB%9E%80%20%EC%88%98%EC%A7%81%EC%84%A0%20%EC%9C%84,%EB%96%A8%EC%96%B4%EC%A1%8C%EB%82%98%EB%A5%BC%20%EB%82%98%ED%83%80%EB%82%B4%EB%8A%94%20%EB%A7%90%EC%9E%85%EB%8B%88%EB%8B%A4.&text=%EC%A0%88%EB%8C%80%EA%B0%92%EC%9D%80%20%EA%B1%B0%EB%A6%AC%EC%9D%B4%EB%AF%80%EB%A1%9C,3%EC%9D%80%20%EC%96%91%EC%88%98%EC%9E%85%EB%8B%88%EB%8B%A4.)

     

     

    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)
Designed by Tistory.