2017-10-25 8 views
1

저는 sci-kit에서 MLPClassifier 모델을 배우고 있습니다. 모델을 채점하기 위해 roc_auc과 함께 gridSearchCV를 사용했습니다. 평균 열차와 시험 점수는 약 0.76이며 나쁘지 않습니다. cv_results_의 출력은 다음과 같습니다AUC는 어떻게 GridSearchCV AUC와 다를 수 있습니까?

Train set AUC: 0.553465272412 
Grid best score (AUC): 0.757236688092 
Grid best parameter (max. AUC): {'hidden_layer_sizes': 10} 

{ 'mean_fit_time': array([63.54, 136.37, 136.32, 119.23, 121.38, 124.03]), 
    'mean_score_time': array([ 0.04, 0.04, 0.04, 0.05, 0.05, 0.06]), 
    'mean_test_score': array([ 0.76, 0.74, 0.75, 0.76, 0.76, 0.76]), 
    'mean_train_score': array([ 0.76, 0.76, 0.76, 0.77, 0.77, 0.77]), 
    'param_hidden_layer_sizes': masked_array(data = [5 (5, 5) (5, 10) 10 (10, 5) (10, 10)], 
      mask = [False False False False False False], 
     fill_value = ?) 
, 
    'params': [ {'hidden_layer_sizes': 5}, 
        {'hidden_layer_sizes': (5, 5)}, 
        {'hidden_layer_sizes': (5, 10)}, 
        {'hidden_layer_sizes': 10}, 
        {'hidden_layer_sizes': (10, 5)}, 
        {'hidden_layer_sizes': (10, 10)}], 
    'rank_test_score': array([ 2, 6, 5, 1, 4, 3]), 
    'split0_test_score': array([ 0.76, 0.75, 0.75, 0.76, 0.76, 0.76]), 
    'split0_train_score': array([ 0.76, 0.75, 0.75, 0.76, 0.76, 0.76]), 
    'split1_test_score': array([ 0.77, 0.76, 0.76, 0.77, 0.76, 0.76]), 
    'split1_train_score': array([ 0.76, 0.75, 0.75, 0.76, 0.76, 0.76]), 
    'split2_test_score': array([ 0.74, 0.72, 0.73, 0.74, 0.74, 0.75]), 
    'split2_train_score': array([ 0.77, 0.77, 0.77, 0.77, 0.77, 0.77]), 
    'std_fit_time': array([47.59, 1.29, 1.86, 3.43, 2.49, 9.22]), 
    'std_score_time': array([ 0.01, 0.01, 0.01, 0.00, 0.00, 0.01]), 
    'std_test_score': array([ 0.01, 0.01, 0.01, 0.01, 0.01, 0.01]), 
    'std_train_score': array([ 0.01, 0.01, 0.01, 0.01, 0.01, 0.00])} 

당신은 평균 열차 점수로보고있는 동안 내가 흥미롭게도 수동으로 계산 된 기차 세트의 roc_auc_score이 0.55으로보고 3의 KFold 사용 볼 수 있듯이 ~ 0.76. 이 출력을 생성하는 코드는 다음과 같습니다

def model_mlp (X_train, y_train, verbose=True, random_state = 42): 
    grid_values = {'hidden_layer_sizes': [(5), (5,5), (5, 10), 
              (10), (10, 5), (10, 10)]} 

    # MLP requires scaling of all predictors 
    scaler = StandardScaler() 
    X_train = scaler.fit_transform(X_train) 

    mlp = MLPClassifier(solver='adam', learning_rate_init=1e-4, 
         max_iter=200, 
         verbose=False, 
         random_state=random_state) 
    # perform the grid search 
    grid_auc = GridSearchCV(mlp, 
          param_grid=grid_values, 
          scoring='roc_auc', 
          verbose=2, n_jobs=-1) 
    grid_auc.fit(X_train, y_train) 
    y_hat = grid_auc.predict(X_train) 

    # print out the results 
    if verbose: 
     print('Train set AUC: ', roc_auc_score(y_train, y_hat)) 
     print('Grid best score (AUC): ', grid_auc.best_score_) 
     print('Grid best parameter (max. AUC): ', grid_auc.best_params_) 
     print('') 
     pp = pprint.PrettyPrinter(indent=4) 
     pp.pprint (grid_auc.cv_results_) 
     print ('MLPClassifier fitted, {:.2f} seconds used'.format (time.time() - t)) 

    return grid_auc.best_estimator_ 

이 차이 나는 다음과 같은 결과에 '에뮬레이트'는 GridSearchCV 루틴을 결정하고 가지고 있기 때문에 :

Shape X_train: (107119, 15) 
Shape y_train: (107119,) 
Shape X_val: (52761, 15) 
Shape y_val: (52761,) 
     layers roc-auc 
    Seq l1 l2 train test iters runtime 
    1 5 0 0.5522 0.5488 85 20.54 
    2 5 5 0.5542 0.5513 80 27.10 
    3 5 10 0.5544 0.5521 83 28.56 
    4 10 0 0.5532 0.5516 61 15.24 
    5 10 5 0.5540 0.5518 54 19.86 
    6 10 10 0.5507 0.5474 56 21.09 

점수는 모든 주위 0.55과 일치를 위의 코드에서 수동 계산. 저를 놀라게 한 것은 결과에 변화가 없다는 것입니다. 내가 어떤 실수를하고 것처럼 나타납니다,하지만 난 하나를 찾을 코드를 볼 수 없습니다 :

def simple_mlp (X, y, verbose=True, random_state = 42): 
    def do_mlp (X_t, X_v, y_t, y_v, n, l1, l2=None): 
     if l2 is None: 
      layers = (l1) 
      l2 = 0 
     else: 
      layers = (l1, l2) 

     t = time.time() 
     mlp = MLPClassifier(solver='adam', learning_rate_init=1e-4, 
          hidden_layer_sizes=layers, 
          max_iter=200, 
          verbose=False, 
          random_state=random_state) 
     mlp.fit(X_t, y_t) 
     y_hat_train = mlp.predict(X_t) 
     y_hat_val = mlp.predict(X_v) 
     if verbose: 
      av = 'samples' 
      acc_trn = roc_auc_score(y_train, y_hat_train, average=av) 
      acc_tst = roc_auc_score(y_val, y_hat_val, average=av) 
      print ("{:5d}{:4d}{:4d}{:7.4f}{:7.4f}{:9d}{:8.2f}" 
        .format(n, l1, l2, acc_trn, acc_tst, mlp.n_iter_, time.time() - t)) 
     return mlp, n + 1 

    X_train, X_val, y_train, y_val = train_test_split (X, y, test_size=0.33, random_state=random_state) 
    if verbose: 
     print('Shape X_train:', X_train.shape) 
     print('Shape y_train:', y_train.shape) 
     print('Shape X_val:', X_val.shape) 
     print('Shape y_val:', y_val.shape) 

    # MLP requires scaling of all predictors 
    scaler = StandardScaler() 
    X_train = scaler.fit_transform(X_train) 
    X_val = scaler.transform(X_val) 

    n = 1 
    layers1 = [5, 10] 
    layers2 = [5, 10] 
    if verbose: 
     print ("  layers roc-auc") 
     print (" Seq l1 l2 train validation iters runtime") 
    for l1 in layers1: 
     mlp, n = do_mlp (X_train, X_val, y_train, y_val, n, l1) 
     for l2 in layers2: 
      mlp, n = do_mlp (X_train, X_val, y_train, y_val, n, l1, l2) 

    return mlp 

내가 정확히 두 경우 모두 동일한 데이터 (159880 명 관찰과 15 예측)를 사용합니다. 나는 GridSearchCVcv=3 (기본값)을 사용하고 수작업으로 만들어진 코드의 유효성 검사 설정에 동일한 비율을 사용합니다. 가능한 답을 찾을 때 같은 문제를 설명하는 this post on SO을 발견했습니다. 대답이 없었습니다. 어쩌면 누군가 정확히 무슨 일이 일어 났는지 이해할 수 있을까요?

감사합니다. 편집

나는 @Mohammed 제작 : Kashif가 제안 GridSearchCV 및 KFold의 코드를 확인하고 실제로 KFold 데이터를 셔플하지 않았다 명시 적 발언을 발견했다. 그래서 스케일러 전에 model_mlp하기 위해 다음과 같은 코드를 추가

np.random.seed (random_state) index = np.random.permutation (len(X_train)) X_train = X_train.iloc[index] 

및 train_test_split의 교체로 simple_mlp에

: 다음과 같은 출력 결과

np.random.seed (random_state) 
index = np.random.permutation (len(X)) 
X = X.iloc[index] 
y = y.iloc[index] 
train_size = int (2 * len(X)/3.0) # sample of 2 third 
X_train = X[:train_size] 
X_val = X[train_size:] 
y_train = y[:train_size] 
y_val = y[train_size:] 

:

Train set AUC: 0.5 
Grid best score (AUC): 0.501410198106 
Grid best parameter (max. AUC): {'hidden_layer_sizes': (5, 10)} 

{ 'mean_fit_time': array([28.62, 46.00, 54.44, 46.74, 55.25, 53.33]), 
    'mean_score_time': array([ 0.04, 0.05, 0.05, 0.05, 0.05, 0.06]), 
    'mean_test_score': array([ 0.50, 0.50, 0.50, 0.50, 0.50, 0.50]), 
    'mean_train_score': array([ 0.50, 0.51, 0.51, 0.51, 0.50, 0.51]), 
    'param_hidden_layer_sizes': masked_array(data = [5 (5, 5) (5, 10) 10 (10, 5) (10, 10)], 
      mask = [False False False False False False], 
     fill_value = ?) 
, 
    'params': [ {'hidden_layer_sizes': 5}, 
        {'hidden_layer_sizes': (5, 5)}, 
        {'hidden_layer_sizes': (5, 10)}, 
        {'hidden_layer_sizes': 10}, 
        {'hidden_layer_sizes': (10, 5)}, 
        {'hidden_layer_sizes': (10, 10)}], 
    'rank_test_score': array([ 6, 2, 1, 4, 5, 3]), 
    'split0_test_score': array([ 0.50, 0.50, 0.51, 0.50, 0.50, 0.50]), 
    'split0_train_score': array([ 0.50, 0.51, 0.50, 0.51, 0.50, 0.51]), 
    'split1_test_score': array([ 0.50, 0.50, 0.50, 0.50, 0.49, 0.50]), 
    'split1_train_score': array([ 0.50, 0.50, 0.51, 0.50, 0.51, 0.51]), 
    'split2_test_score': array([ 0.49, 0.50, 0.49, 0.50, 0.50, 0.50]), 
    'split2_train_score': array([ 0.51, 0.51, 0.51, 0.51, 0.50, 0.51]), 
    'std_fit_time': array([19.74, 19.33, 0.55, 0.64, 2.36, 0.65]), 
    'std_score_time': array([ 0.01, 0.01, 0.00, 0.01, 0.00, 0.01]), 
    'std_test_score': array([ 0.01, 0.00, 0.01, 0.00, 0.00, 0.00]), 
    'std_train_score': array([ 0.00, 0.00, 0.00, 0.00, 0.00, 0.00])} 

하는 모하메드 발언을 확인하는 것으로 보인다. 나는 순서대로 보이지 않는 거대한 데이터 세트에 무작위 화의 강한 영향을 상상할 수 없었기 때문에 나는 처음에는 상당히 회의적이었다고 말해야 만합니다.

그러나 나는 약간의 의문이 있습니다. 원래의 설정에서 GridSearchCV는 지속적으로 약 0.20만큼 높게 나타 났으며, 이제는 지속적으로 약 0.05로 너무 낮습니다. 이것은 두 방법의 편차가 4 배만큼 감소함에 따라 향상되었습니다. 마지막 발견에 대한 설명이 있습니까? 아니면 두 방법 사이의 편차가 약 0.05 정도로 간단합니까? 나는 이것을 정답으로 표시하기로 마음 먹었지 만, 누군가 내 의심의 여지를 밝힐 수 있기를 바랍니다.

답변

1

점수의 차이는 주로 데이터 집합을 GridSearchCV으로 분할하는 여러 가지 방법과이를 에뮬레이션하는 함수 때문입니다. 이것을 이렇게 생각하십시오. 데이터 집합에 9 개의 데이터 요소가 있다고 가정합니다.

그러나
train_cv_fold1_indices : 1 2 3 4 5 6 
test_cv_fold1_indices : 7 8 9 


train_cv_fold2_indices : 1 2 3 7 8 9 
test_cv_fold2_indices : 4 5 6 


train_cv_fold3_indices : 4 5 6 7 8 9 
test_cv_fold3_indices : 1 2 3 

GridSearchCV 다른 방식으로 데이터를 분할 할 수 에뮬레이트 함수, 예를 들어 말 : : 이제

train_indices : 1 3 5 7 8 9 
test_indices : 2 4 6 

로 이제 GridSearchCV 3 개 주름은 분포가 다음과 같이 가정하자로 당신은 볼 수 있습니다. 이것은 데이터 집합의 다른 분할과 이에 따라 훈련 된 분류 자의 동작이 상당히 다를 수 있습니다. (심지어 똑같이 행동 할 수도 있습니다. 데이터 포인트와 관련성이 얼마나 다른지, 데이터 포인트 간 차이를 확인하는 데 도움이되는지 등의 다양한 요인에 따라 달라집니다).

그래서 GridSearchCV를 완벽하게 에뮬레이션하려면 동일한 방법으로 분할을 수행해야합니다.

확인 GridSearchCV Source 당신은 호선 (592)에서, 그 중위는 CV를 수행 할 것을, 그들이 at this link 지정 check_cv에서 다른 함수를 호출 발견 할 것이다. 실제로 Kfold CV 또는 startified CV 중 하나를 호출합니다.

실험을 바탕으로 고정 랜덤 시드와 위에 언급 된 함수 (Kfold CV 또는 startified CV)를 사용하여 데이터 세트에서 CV를 명시 적으로 수행 할 것을 제안합니다. 그런 다음 에뮬레이션 함수에서 동일한 CV 객체를 사용하여보다 유사한 분석을 얻습니다. 그런 다음 더 많은 가치있는 정보를 얻을 수 있습니다.

+0

감사합니다. @mohammed kashif, 내가 언급 한 코드를 살펴보고 다시보고하겠습니다. – Arnold

+0

@Arnold 환영합니다! 도움이 필요하면 알려주세요. –