ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [IMLP] Chapter 5. 모델 평가와 성능 향상
    Machine Learning/Intro to Machine Learning with Python 2022. 5. 23. 14:35

    - 데이터를 훈련 세트와 테스트 세트로 나누는 이유는 새로운 데이터에 모델이 얼마나 잘 일반화되는지 측정하기 위함

     

    [교차 검증]

    - cross-validation

    - 일반화 성능 재기 위해 훈련 세트/테스트 세트로 나누는 것보다 더 안정적이고 뛰어난 통계적 평가 방법

    - 데이터를 여러 번 반복해서 나누고 여러 모델을 학습하며 가장 널리 사용되는 방법은 k-겹 교차 검증

     

    #. scikit-learn의 교차 검증

    from sklearn.model_selection import cross_val_score
    form sklearn.datasets import load_iris
    from sklearn.linear_model import LogisticRegression
    
    iris = load_iris()
    logreg = LogisticRegression()
    
    scores = cross_val_score(logreg, iris.data, iris.target)

    - cross_val_sore 함수로 교차 검증 구현 가능하며 기본값은 3-겹 교차 검증

    - 보통 교차 검증의 정확도를 간단하게 나타내려면 평균 사용함

     

    #. 교차 검증의 장점

    - 테스트 세트에 각 샘플이 정확하게 한 번씩 들어감

    - 단점은 연산 비용 증가

     

    #. 계층별 k-겹 교차 검증과 그외 전략들

    - 단순한 k-겹 교차 검증은 나열 순서대로 k개의 폴드로 나눔

    - 계층별 교차 검증은 폴드 안의 클래스 비율이 전체 데이터셋의 클래스 비율과 같도록 데이터를 나눔

    - scikit-learn은 회귀에서 기본 k-겹 교차 검증 사용함.. 회귀에서도 폴드가 서로 다른 타깃값 포함하도록 만들 수 있지만 보통 생소한 일이고 일반적으로 사용하는 방법은 아님

     

    <교차 검증 상세 옵션>

    - scikit-learn에서 사용 시 cv 매개변수에 교차 검증 분할기 전달함

    from sklearn.model_selection import KFold
    
    # 5-겹 교차 검증
    kfold = KFold(n_splits=5)
    cross_val_score(logreg, iris.data, iris.target, cv=kfold)
    
    # 3-겹 교차 검증
    kfold = KFold(n_splits=3)
    cross_val_score(logreg, iris.data, iris.target, cv=kfold)
    
    # 샘플의 순서 바꾸기
    kfold = KFold(n_splits=3, shuffle=True, random_state=0)
    cross_val_score(logreg, iris.data, iris.target, cv=kfold)

     

    <LOOCV>

    - Leave-one-out cross-validation

    - 각 반복에서 하나의 데이터 포인트를 선택해 테스트 세트로 사용함

    from sklearn.model_selection import LeaveOneOut
    loo = LeaveOneOut()
    scores = cross_val_score(logreg, iris.data, iris.target, cv=loo)

     

    <임의 분할 교차 검증>

    - shuffle-split cross-validation

    - train_size만큼의 포인트로 훈련 세트를, test_size만큼의 포인트로 테스트 세트를 만들어 분할하는데 n_splits 횟수만큼 반복함 (정수 입력 시 포인트 절대 개수, 실수 입력 시 전체 데이터에서의 비율)

     

    <그룹별 교차 검증>

    - GroupKFold 사용

    - groups 배열 사용하는데 훈련/테스트 세트 만들 때 분리되지 않아야 할 그룹 지정

    - 예시: 의료 애플리케이션.. 같은 환자로부터 얻은 여러 샘플로 새로운 환자에게 일반화하는 것

    scores = cross_val_score(logreg, X, y, groups, cv=GroupKFold(n_splits=3))

     

    [그리드 서치]

    - 관심 있는 매개변수들을 대상으로 가능한 모든 조합 시도

     

    #. 간단한 그리드 서치

    from sklearn.svm import SVC
    
    X_train, X_test, y_train, y_test = train_test_split(iris.data, iris.target, random_state=0)
    
    best_score = 0
    for gamma in [0.001, 0.01, 0.1, 1, 10, 100]:
    	for C in [0.001, 0.01, 0.1, 1, 10, 100]:
        	svm = SVC(gamma=gamma, C=C)
            svm.fit(X_train, y_train)
            score = svm.score(X_test, y_test)
            if score> best_score:
            	best_score = score
                best_parameters = {'C':C, 'gamma':gamma}

     

    #. 매개변수 과대적합과 검증 세트

    - 매개변수 조정을 위해 이미 테스트 세트 이용한 위의 예제!

    from sklearn.svm import SVC
    
    X_trainval, X_test, y_trainval, y_test = train_test_split(iris.data, iris.target, random_state=0)
    X_train, Xvalid, y_train, y_valid = train_test_split(X_trainval, y_trainval, random_state=1)
    
    best_score = 0
    for gamma in [0.001, 0.01, 0.1, 1, 10, 100]:
    	for C in [0.001, 0.01, 0.1, 1, 10, 100]:
        	svm = SVC(gamma=gamma, C=C)
            svm.fit(X_train, y_train)
            score = svm.score(X_valid, y_valid)
            if score> best_score:
            	best_score = score
                best_parameters = {'C':C, 'gamma':gamma}
    
    svm = SVC(**best_parameters)
    svm.fit(X_trainval, y_trainval) 
    terst_score = svm.score(X_test, y_test)

     

    #. 교차 검증을 사용한 그리드 서치

    best_score = 0
    for gamma in [0.001, 0.01, 0.1, 1, 10, 100]:
    	for C in [0.001, 0.01, 0.1, 1, 10, 100]:
        	svm = SVC(gamma=gamma, C=C)
            scores = cross_val_score(svm, X_trainval, y_trainval, cv=5)
            score = np.mean(scores)
            if score> best_score:
            	best_score = score
                best_parameters = {'C':C, 'gamma':gamma}
    
    svm = SVC(**best_parameters)
    svm.fit(X_trainval, y_trainval) 
    terst_score = svm.score(X_test, y_test)

    - 일반화 성능을 더 잘 평가하려면 훈련/검증 세트를 한 번만 나누지 않고 교차 검증 사용해서 각 매개변수 조합의 성능 평가할 수 있음

    - scikit-larn은 추정기 형태로 구현된 GridSearchCV 제공함

    param_grid = {'C': [0.001, 0.01, 0.1, 1, 10, 100], 'gamma': [0.001, 0.01, 0.1, 1, 10, 100]}
    
    from sklearn.model_selection import GridSearchCV
    from sklearn.svm import SVC
    grid_search = GridSearchCV(SVC(), param_grid, cv=5)
    
    # 매개변수 과대적합되는 것을 피하기 위해 데이터를 훈련/테스트 세트로 나누기
    X_train, X_test, y_train, y_test = train_test_split(iris.data, iris.target, random_state=0)
    
    grid_search.fit(X_train,y_train)
    
    grid_search.best_params_ #최적 매개변수
    grid_search.best_score_ #최상 교차 검증 점수
    pd.DataFrame(grid_search.cv_result) #cv results을 DataFrame으로 변환

     

    <비대칭 매개변수 그리드 탐색>

    param_grid = [{'kernel': ['rbf'],
    			'C': [0.001, 0.01, 0.1, 1, 10, 100], 'gamma': [0.001, 0.01, 0.1, 1, 10, 100]},
    			{'kernl': [linear'],
                'C': [0.001, 0.01, 0.1, 1, 10, 100]}]
                
    grid_search = GridSearchCV(SVC(), param_grid, cv=5)
    grid_search.fit(X_train, y_train)
    
    grid_search.best_params_
    grid_search.best_score_
    results = pd.DataFrame(grid_search.cv_results_)

     

    <그리드 서치에 다양한 교차 검증 적용>

    - 훈련 세트와 검증 세트를 한 번만 분할하려며 n_splits = 1, ShuffleSplit나 StratifiedShuffleSplit 사용

     

    <중첩 교차 검증>

    - 원본 데이터를 훈련 세트와 테스트 세트로 한 번만 나누느 방식 대신 더 나아가 교차 검증 분할 방식 사용 가능

    - nested cross-validation

    - 바깥쪽 루프에서 훈련/테스트 세트로 나누고 각 훈련 세트에 대해 그리드 서치를 실행

    - 미래의 데이터에 적용하기 위한 예측 모델을 찾는 데에 거의 사용하지 않음

    - 특정 데이터셋에서 주어진 모델이 얼마나 잘 일반화되는지 평가하는 데 유용한 방법

     

    [평가 지표와 측정]

    - 분류 성능 평가에는 정화가도, 회귀 성능 평가에는 R^2 사용했음

     

    #. 최종 목표를 기억하라

    - 머신러닝 애플리케이션에서 특정 알고리즘을 선택하여 나타난 결과를 비즈니스 임팩트라고 함

     

    #. 이진 분류의 평가 지표

    - 거짓 양성 (FP, False Positive, 타입 1 에러): 건강한 사람을 양성이라 분류

    - 거짓 음성 (FN, False Negative, 타입 2 에러): 암에 걸린 사람을 음성으로 분류

     

    #. 불균형 데이터셋

    - imbalanced datasets

     

    #. 오차 행렬

    - confusion matrix

    from sklearn.metrics import confusion_matrix
    
    confusion = confusion_matrix(y_test, pred_logreg)

     

    #. 정확도와의 관계

    - 정확도 = (TP+TN)/ (TP+TN+EP+FN) : 정확히 예측한 수 / 전체 샘플 수

     

    #. 정밀도, 재현율, f-점수

    - 정밀도 = TP/(TP+FP) (혹은 양성 예측도)

    - 재현율 = TP/(TP+FN) (혹은 민감도, 적중률, 진짜 양성 비율)

    - (f-score) F = 2*(정밀도 x 재현율) / (정밀도+재현율)

    - classification_report 함수는 정밀도, 재현율, f1-점수 모두 계산하여 출력함

     

    <불확실성 고려>

    - decision_function 혹은 predict_proba

     

    <정밀도-재현율 곡선과 ROC 곡선>

    - 정밀도-재현율 곡선

    from sklearn.metrics import precision_recall_curve
    precision, recall, thresholds = precision_recall_curve(y_test, svc.decision_function(X_test))

    - 정밀도-재현율 아랫부분 면적 계산할 수 잇는데 이를 평균 정밀도 (average precisions)

     

    <ROC와 AUC>

    - ROC 곡선은 여러 임계값에서 분류기 특성 분석하는 데 널리 사용하는 도구

    - 정밀도와 재현율 대신 진짜 양성 비율(TPR)에 대한 거짓 양성 비율(FPR)을 나타냄 : 진짜 양성 비율은 재현율, 거짓 양성 비율은전체 음성 샘플 중 거짓 양성으로 잘못 분류한 비율

    from sklearn.metrics import roc_curve
    fpr, tpr, thresholds = roc_curve(y_test, svc.decision_function(X_test))
    
    plt.plot(fpr, trp, label ="ROC Curve")
    plt.xlabel("FPR")
    plt.ylabel("TPR (재현율)")

    - 곡선 아래의 면적값 하나로 ROC 곡선 요약하기도 하는데 이 면적을 보통 AUC(Area Under the Curve)라고 함

    from sklearn.metrics import roc_auc_core
    rf_auc = roc_auc_score(y_test, rf.predict_proba(X_test)[:,1]) # random forest의 AUC
    svc_aud = roc_auc_score(y_test, svc.decision_+function(X_test)) # SVM의 AUC

    - 불균형한 데이터셋에서 모델 평가 시 AUC 사용하라고 강력히 권고됨

     

    #. 다중 분류의 평가 지표

    - 다중 클래스용 f1-점수는 한 클래스를 양성 클래스로 두고 나머지 클래스들을 음성 클래스로 간주하여 클래스마다 f1-점수 계산함.. macro, weighted, micro 전략 중 하나 사용

     

    #. 회귀의 평가 지표

    - R^2 만으로 충분함

     

Designed by Tistory.