超参数调整(Hyperas)和带有管道预处理的交叉验证

时间:2020-05-18 21:47:49

标签: python tensorflow keras scikit-learn hyperas

tl; dr我尝试使用Hyperas优化和交叉验证我的超参数,但无法使用KerasClassifier进行预处理(缩放,过度/欠采样)管道

我使用Hyperas(hyperopt的包装器)调整我的神经网络(使用Keras / Tensorflow构建)的超参数,并尝试实现kfold-cross验证以获得最佳参数。但是,我也对数据进行了预处理(Standardscaler和MinMaxScaler),然后使用SMOTETOMEK进行过/欠采样。

read不应对整个数据集进行特征缩放和重采样,而应仅对用于训练以避免溢出的部分进行。仅在交叉验证的训练折叠中尝试在hyperopt内部实现此方法有些困难,因为在使用df1 <- structure(list(old = c("z1", "z2", "z3", "z4", "z5", "z6", "z7", "z8"), new = c("D1", "D1", "D1", "D4", "D4", "D6", "D7", "D7" )), class = "data.frame", row.names = c(NA, -8L)) m1 <- structure(c(1L, 2L, 3L, 0L, 1L, 2L, 1L, 0L, 1L, 2L, 3L, 0L, 1L, 2L, 1L, 0L, 1L, 2L, 3L, 0L, 1L, 2L, 1L, 0L, 1L, 2L, 3L, 0L, 1L, 2L, 1L, 0L, 1L, 2L, 3L, 0L, 1L, 2L, 1L, 0L, 1L, 2L, 3L, 0L, 1L, 2L, 1L, 0L, 1L, 2L, 3L, 0L, 1L, 2L, 1L, 0L, 1L, 2L, 3L, 0L, 1L, 2L, 1L, 0L), .Dim = c(8L, 8L), .Dimnames = list(c("z1", "z2", "z3", "z4", "z5", "z6", "z7", "z8"), c("z1", "z2", "z3", "z4", "z5", "z6", "z7", "z8"))) 之类的管道时,该管道仅与仅具有模型功能的KerasClassifier一起使用。我不能给他那个模型函数,因为hyperopt中的整个验证过程都发生在一个函数中。

您对如何进行此类工作有任何建议吗?我可以在imblearn中进行所有预处理并优化/交叉验证整个数据集上的参数吗?这是否会损害正确的参数查找过程? (我的最终模型还有其他测试数据集)

有没有办法使其手动工作?

def data()

1 个答案:

答案 0 :(得分:0)

解决了。如果有人感兴趣,这是解决方案:

def data():
    import pandas as pd
    import feather

    df_hyper_X = feather.read_dataframe('df_hyper_X_train.feather')
    df_hyper_Y = feather.read_dataframe('df_hyper_Y_train.feather')

    return df_hyper_X, df_hyper_Y

def hyper_model(df_hyper_X,df_hyper_Y):

  ct = ColumnTransformer([('ct_std', StandardScaler(), ['pre_grade', 'math']),('ct_minmax', MinMaxScaler(), ['time'])
  ], remainder='passthrough')

  metrics = [
            tf.keras.metrics.TruePositives(name='tp'),
            tf.keras.metrics.FalsePositives(name='fp'),
            tf.keras.metrics.TrueNegatives(name='tn'),
            tf.keras.metrics.FalseNegatives(name='fn'), 
            tf.keras.metrics.BinaryAccuracy(name='accuracy'),
            tf.keras.metrics.Precision(name='precision'),
            tf.keras.metrics.AUC(name='auc'),
             ]

  model = tf.keras.Sequential()
  model.add(Dense({{choice([2,4,8,16,32,64])}}, activation={{choice(['relu', 'sigmoid', 'tanh', 'elu', 'selu'])}}, kernel_initializer={{choice(['lecun_uniform','glorot_normal', 'glorot_uniform', 'he_normal', 'he_uniform'])}}
                  , input_shape=(20,)))
  model.add(Dropout({{uniform(0, 0.5)}}))

  if ({{choice(['one', 'two'])}}) == 'two':
      model.add(Dense({{choice([2,4,8,16,32,64])}}, activation={{choice(['relu', 'sigmoid', 'tanh', 'elu', 'selu'])}}))
      model.add(Dropout({{uniform(0, 0.5)}}))

  model.add(Dense(1, activation='sigmoid'))

  adam = tf.keras.optimizers.Adam(lr={{choice([0.0001, 0.001, 0.01, 0.1])}})
  nadam = tf.keras.optimizers.Nadam(lr={{choice([0.0001, 0.001, 0.01, 0.1])}})
  adamax = tf.keras.optimizers.Adamax(lr={{choice([0.0001, 0.001, 0.01, 0.1])}})
  adagrad = tf.keras.optimizers.Adagrad(lr={{choice([0.0001, 0.001, 0.01, 0.1])}})
  adadelta = tf.keras.optimizers.Adadelta(lr={{choice([0.0001, 0.001, 0.01, 0.1])}})
  sgd = tf.keras.optimizers.SGD(lr={{choice([0.0001, 0.001, 0.01, 0.1])}})
  rmsprop = tf.keras.optimizers.RMSprop(lr={{choice([0.0001, 0.001, 0.01, 0.1])}})

  opti_choice = {{choice(['adam', 'nadam', 'adamax','adagrad', 'adadelta', 'sgd','rmsprop'])}}
  if opti_choice == 'adam':
      optimizer = adam
  elif opti_choice == 'nadam':
      optimizer = nadam
  elif opti_choice == 'adamax':
      optimizer = adamax
  elif opti_choice == 'adagrad':
      optimizer = adagrad
  elif opti_choice == 'adadelta':
      optimizer = adadelta
  elif opti_choice == 'sgd':
      optimizer = sgd
  else:
      optimizer = rmsprop

  model.compile(loss='binary_crossentropy', optimizer=optimizer, metrics=metrics)

  smt = SMOTETomek(sampling_strategy='auto', random_state=2)
  kfold = KFold(n_splits=10, shuffle=True, random_state=3)  
  scores = []

  for train_fold_index, val_fold_index in kfold.split(df_hyper_X,df_hyper_Y):

    X_train_fold, y_train_fold = df_hyper_X.iloc[train_fold_index], df_hyper_Y.iloc[train_fold_index]

    X_val_fold, y_val_fold = df_hyper_X.iloc[val_fold_index], df_hyper_Y.iloc[val_fold_index]

    X_train_fold = ct.fit_transform(X_train_fold)
    X_val_fold = ct.transform(X_val_fold)

    X_train_smtk, y_train_smtk = smt.fit_resample(X_train_fold, y_train_fold)

    model.fit(X_train_smtk, y_train_smtk, epochs={{choice([20,30,40,50,60,70])}}, batch_size={{choice([16,32, 64, 128])}})

    predicts = model.predict(X_val_fold)
    score = precision_score(y_val_fold, predicts.round())
    scores.append(score)

  avg_score = np.mean(scores)    
  print('Precision', avg_score)
  return {'loss': -avg_score, 'status': STATUS_OK, 'model': model}

if __name__ == '__main__':
    best_run, best_model = optim.minimize(model=hyper_model,
                                          data=data,
                                          algo=tpe.suggest,
                                          max_evals=2,
                                          trials=Trials(),
                                          notebook_name = 'drive/My Drive/Colab Notebooks/final_NL_EU_Non-EU')
    df_hyper_X, df_hyper_Y = data()
    print("Best performing model chosen hyper-parameters:")
    print(best_run)