Python 通过随机搜索CV在Keras(MLP)中进行超参数调谐

Python 通过随机搜索CV在Keras(MLP)中进行超参数调谐,python,keras,time-series,grid-search,hyperparameters,Python,Keras,Time Series,Grid Search,Hyperparameters,一段时间以来,我一直在尝试调整神经网络,但不幸的是,我无法从中获得良好的性能。我有一个时间序列数据集,我正在使用RandomizedSearchCV进行二元分类。我的代码如下。如有任何建议或帮助,将不胜感激。有一件事是,我仍在努力找出如何合并的方法,但我很早就停止了 编辑:忘了添加我是根据F1宏度量来衡量性能的,我无法获得高于0.68的分数。我注意到的另一件事是,我一次尝试估计的参数越多(增加我的网格),我的得分就越差 train_size = int(0.70*X.shape[0]) X_tr

一段时间以来,我一直在尝试调整神经网络,但不幸的是,我无法从中获得良好的性能。我有一个时间序列数据集,我正在使用RandomizedSearchCV进行二元分类。我的代码如下。如有任何建议或帮助,将不胜感激。有一件事是,我仍在努力找出如何合并的方法,但我很早就停止了

编辑:忘了添加我是根据F1宏度量来衡量性能的,我无法获得高于0.68的分数。我注意到的另一件事是,我一次尝试估计的参数越多(增加我的网格),我的得分就越差

train_size = int(0.70*X.shape[0])
X_train, X_test, y_train, y_test = X[0:train_size], X[train_size:],y[0:train_size], y[train_size:]


from numpy.random import seed
seed(3)
from tensorflow import set_random_seed
set_random_seed(4)

from imblearn.pipeline import Pipeline

def create_model(activation_1='relu', activation_2='relu', 
                 neurons_input = 1, neurons_hidden_1=1,
                 optimizer='adam',
                 input_shape=(X_train.shape[1],)):

  model = Sequential()
  model.add(Dense(neurons_input, activation=activation_1, input_shape=input_shape, kernel_initializer='random_uniform'))

  model.add(Dense(neurons_hidden_1, activation=activation_2, kernel_initializer='random_uniform'))


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

  model.compile (loss = 'sparse_categorical_crossentropy', optimizer=optimizer)
  return model


clf=KerasClassifier(build_fn=create_model, verbose=0)

param_grid = {
    'clf__neurons_input':[5, 10, 15, 20, 25, 30, 35],
    'clf__neurons_hidden_1':[5, 10, 15, 20, 25, 30, 35],
    'clf__optimizer': ['Adam', 'Adamax','Adadelta'],
    'clf__activation_1': ['softmax', 'softplus', 'softsign', 'relu', 'tanh', 'sigmoid', 'hard_sigmoid', 'linear'],
    'clf__activation_2': ['softmax', 'softplus', 'softsign', 'relu', 'tanh', 'sigmoid', 'hard_sigmoid', 'linear'],
    'clf__batch_size': [40,60,80,100]}


pipe = Pipeline([
    ('oversample', SMOTE(random_state=12)),
    ('clf', clf)
    ])

my_cv = TimeSeriesSplit(n_splits=5).split(X_train)

rs_keras = RandomizedSearchCV(pipe, param_grid, cv=my_cv, scoring='f1_macro', refit='f1_macro', verbose=3, n_jobs=1,random_state=42)
rs_keras.fit(X_train, y_train)

print("Best: %f using %s" % (rs_keras.best_score_, rs_keras.best_params_))

from sklearn.metrics import classification_report, confusion_matrix
y_pred=rs_keras.predict(X_test)
clfreport = classification_report(y_test, y_pred)
cm = confusion_matrix(y_test, y_pred)
print (clfreport)
print (cm)
scores_test = rs_keras.score(X_test,y_test)
print ("Testing:", scores_test)
我关于早起的分数

clf=KerasClassifier(build_fn=create_model, verbose=0)

stop = EarlyStopping(monitor='your_metric', min_delta=0, 
                         patience=5, verbose=1, mode='auto',
                         baseline=None, restore_best_weights=True)
.
.
.
grid.fit(x_train_sc, y_train_sc, callbacks = [stop])
它应该会起作用。(我在没有管道结构的情况下进行了测试。)

顺便说一句,当我尝试使用管道结构的数据集时,它并没有像我所想的那样起作用。在我的例子中,我试图标准化缩放数据,但gridsearch没有首先缩放数据,因此它进入分类器而没有缩放。这对我来说是个问题


我建议您在gridsearch之前转换数据,并尝试不使用管道。我知道数据泄漏问题,但我找不到任何其他方法。

您的数据似乎非常不平衡。你怎么办?可能问题是,由于不平衡,而不是由于超参数优化,您的所有模型都无法找到好的解决方案?通过管道使用SMOTE。好的,有道理,我现在可以在代码中找到它。在没有数据的情况下,我想到的下一个问题是:为什么你认为0.68的F1已经不太好了?也许您的网络架构不适合这个问题?(时间序列通常使用RNN而不是完全连接的网络进行处理)或者可能
类1
的统计数据波动很大(因为它的分数很小),并且您的测试样本与培训非常不同?(培训集的性能如何?您是否使用EDA来比较培训集和测试集之间的分布?)我将再次查看测试集。我想知道SMOTE是否真的将底层分布搞得如此混乱,以至于测试集不再是平衡训练集的表示。为了消除
SMOTE
瑕疵,您还可以尝试在训练中使用权重,而不是重新采样。有一些相关的问题,我试图提前停止,但它似乎只考虑到训练损失。对于val_损失,它抛出了一个类似“这不是一个可接受的指标”的错误。我倾向于使用l1_l2正则化器或添加辍学者;我来看看。这应该不会有太大的区别,但无论如何我都会尝试。谢谢。val_损失是默认的监控指标,它应该接受它。可能,早期停止func只关心KerasClassifier。(即由gridsearchCV进行验证)。您可以尝试使用**fit_参数通过fit函数的“validation_split=x.x”,但我怀疑这是最佳方式。如果您有时间,可以将搜索功能用作一般情况。我的意思是,你可以选择最好的参数,用它们来训练网络并调整它们。(增加批量可能会加快过程…。@eemamedo用于正则化: