交叉验证和评估:神经网络损失函数在交叉验证中不断下降

数据挖掘 神经网络 喀拉斯 交叉验证 损失函数
2022-02-28 07:45:38

我正在以两种不同的方式( A 和 B )使用交叉验证来评估神经网络模型,我认为这两种方式是等效的。

  • 评估类型 A: 对于每个交叉验证循环,都会对模型进行实例化和拟合。
  • 评估类型 B: 我将模型实例化一次,然后将该实例化模型拟合到交叉验证过程的每个循环中。

我正在使用度量平均绝对误差(MAE)。

问题:为什么在使用 B 类评估而不是使用 A 类评估时,交叉验证循环中的MAE会持续下降?

代码和细节

首先我生成合成数据:

from sklearn.datasets import make_regression

X , y = make_regression( n_samples = 1000 , n_features = 10 , n_informative = 5 , n_targets = 1 , random_state = 2 )

然后我定义一个函数来获取模型(神经网络):

from keras.models import Sequential
from keras.layers import Dense

def get_model( n_nodes_hidden_layer , n_inputs , n_outputs ) :
   model = Sequential()
   model.add( Dense( n_nodes_hidden_layer , input_dim = n_inputs , kernel_initializer = 'he_uniform' , activation = 'relu' ) )
   model.add( Dense( n_outputs ) )
   model.compile( loss = 'mae' , optimizer = 'adam' )
   return model

之后,我使用以下方法定义了 2 个评估函数:

from sklearn.model_selection import RepeatedKFold
from sklearn.metrics import mean_absolute_error

A类评价函数:

def evaluate_model_A( X , y ) :
   results = list()
   cv = RepeatedKFold( n_splits = 10 , n_repeats = 1 , random_state = 999 )

   for train_ix, test_ix in cv.split( X ) :
     X_train, X_test = X[ train_ix ] , X[ test_ix ]
     y_train, y_test = y[ train_ix ] , y[ test_ix ]

     model = get_model( 20 , 10 , 1 )
     model.fit( X_train , y_train , epochs = 100 , verbose = 0 )

     y_test_pred = model.predict( X_test )
     mae = mean_absolute_error( y_test , y_test_pred )
     results.append( mae )

     print( f'mae : {mae}' )

   return results

B类评价函数:

 def evaluate_model_B( model , X , y ) :
   results = list()
   cv = RepeatedKFold( n_splits = 10 , n_repeats = 1 , random_state = 999 )

   for train_ix, test_ix in cv.split( X ) :
     X_train, X_test = X[ train_ix ] , X[ test_ix ]
     y_train, y_test = y[ train_ix ] , y[ test_ix ]

     model.fit( X_train , y_train , epochs = 100 , verbose = 0 )

     y_test_pred = model.predict( X_test )
     mae = mean_absolute_error( y_test , y_test_pred )
     results.append( mae )

     print( f'mae : {mae}' )

   return results

在使用 B 型评估函数之前,我需要实例化模型,因为它是函数的参数:

model = get_model( 20 , 10 , 1 )

我不明白的是,在使用 B 型评估函数时,每个交叉验证循环的 MAE 都在减少,而 A 型评估函数并非如此。

这是特定于神经网络的吗?

注意:当我使用 a 时RandomForestRegressor()没有出现这种现象。

1个回答

评估类型 B方法中,您的神经网络权重和偏差不会在每个交叉验证循环之前重置。然后神经网络从一个循环学习到另一个循环,因此您会看到 MAE 不断下降。

一种解决方案是在拟合模型之前存储您的权重和偏差,并在每个循环中加载它们,以便它们具有相同的 init。

您可以使用这些方法来做到这一点:

model.save_weights('model.h5') # right after model instantiation
model.load_weights('model.h5') # in the loop before fitting

评估类型 A中,因为您在循环中实例化模型,所以会重置权重和偏差,因此您看不到这种现象。