首页 文章

Keras的交叉验证

提问于
浏览
8

我正在Keras中实现一个多层感知器并使用scikit-learn来执行交叉验证 . 为此,我受到了问题中的代码的启发Cross Validation in Keras

from sklearn.cross_validation import StratifiedKFold

def load_data():
    # load your data using this function

def create model():
    # create your model using this function

def train_and_evaluate__model(model, data[train], labels[train], data[test], labels[test)):
    # fit and evaluate here.

if __name__ == "__main__":
    X, Y = load_model()
    kFold = StratifiedKFold(n_splits=10)
    for train, test in kFold.split(X, Y):
        model = None
        model = create_model()
        train_evaluate(model, X[train], Y[train], X[test], Y[test])

在我对神经网络的研究中,我了解到神经网络的知识表示是在突触权重和网络跟踪过程中,更新的权重,从而降低网络错误率并改善其性能 . (就我而言,我正在使用监督学习)

为了更好地训练和评估神经网络性能,一种常用的方法是交叉验证,它返回数据集的分区,用于训练和评估模型 .

我怀疑是......

在此代码段中:

for train, test in kFold.split(X, Y):
    model = None
    model = create_model()
    train_evaluate(model, X[train], Y[train], X[test], Y[test])

我们为每个生成的分区定义,训练和评估一个新的神经网络?

如果我的目标是为整个数据集微调网络,为什么定义单个神经网络并使用生成的分区对其进行训练是不正确的?

也就是说,为什么这段代码是这样的?

for train, test in kFold.split(X, Y):
    model = None
    model = create_model()
    train_evaluate(model, X[train], Y[train], X[test], Y[test])

而不是这样?

model = None
model = create_model()
for train, test in kFold.split(X, Y):
    train_evaluate(model, X[train], Y[train], X[test], Y[test])

我对代码如何工作错误的理解是什么?还是我的理论?

谢谢!

3 回答

  • 5

    如果我的目标是为整个数据集微调网络

    目前尚不清楚“微调”是什么意思,甚至不清楚你进行交叉验证的目的是什么(CV);通常,CV服务于以下目的之一:

    • 模型选择(选择超参数的值)

    • 模型评估

    由于您没有在代码中为超参数选择定义任何搜索网格,因此您似乎使用CV来获得模型的预期性能(错误,准确性等) .

    无论如何,无论出于什么原因你使用简历,第一个片段都是正确的;你的第二个片段

    model = None
    model = create_model()
    for train, test in kFold.split(X, Y):
        train_evaluate(model, X[train], Y[train], X[test], Y[test])
    

    将按顺序在不同的分区上训练您的模型(即在分区#1上训练,然后继续训练分区#2等),这基本上只是对您的整个数据集进行训练,并且肯定不是交叉验证...

    也就是说,简历之后的最后一步,通常只暗示(并且经常被初学者忽略)是,在您对所选择的超级参数和/或模型表现感到满意之后,您可以返回并再次训练您的模型,这次是整个可用数据 .

  • 1

    注释掉的功能使这一点变得不那么明显,但我们的想法是在迭代折叠时跟踪模型性能,最后提供较低级别的性能指标或平均全局性能 . 例如:

    理想情况下, train_evaluate 函数会为每个分割输出一些准确度分数,这些分数可以在最后组合 .

    def train_evaluate(model, x_train, y_train, x_test, y_test):
        model.fit(x_train, y_train)
        return model.score(x_test, y_test)
    
    X, Y = load_model()
    kFold = StratifiedKFold(n_splits=10)
    scores = np.zeros(10)
    idx = 0
    for train, test in kFold.split(X, Y):
        model = create_model()
        scores[idx] = train_evaluate(model, X[train], Y[train], X[test], Y[test])
        idx += 1
    print(scores)
    print(scores.mean())
    

    所以是的,您确实想为每个折叠创建一个新模型,因为本练习的目的是确定您的模型设计如何对数据的所有部分执行,而不仅仅是一个可能允许或不允许该模型的特定部分表现良好 .

    当与超参数一起应用网格搜索时,这种方法变得特别强大 . 在这种方法中,您使用交叉验证拆分训练具有不同超参数的模型,并跟踪拆分和整体上的性能 . 最后,您将能够更好地了解哪些超参数允许模型表现最佳 . 有关更深入的解释,请参阅sklearn Model Selection并特别注意交叉验证和网格搜索的各个部分 .

  • 1

    测试模型性能的主要思想是执行以下步骤:

    • 在训练集上训练模型 .

    • 在训练过程中未使用的数据上评估模型,以模拟新数据到达 .

    基本上 - 您最终应该测试模型的数据应该模仿您从客户端/应用程序获得的第一个数据部分以应用您的模型 .

    这就是交叉验证如此强大的原因 - 它使整个数据集中的每个数据点都可以用作新数据的模拟 .

    现在 - 回答你的问题 - 每个交叉验证都应遵循以下模式:

    for train, test in kFold.split(X, Y
         model = training_procedure(train, ...)
         score = evaluation_procedure(model, test, ...)
    

    因为毕竟,您将首先训练您的模型,然后将其用于新数据 . 在您的第二种方法中 - 您不能将其视为培训过程的模仿,例如,在第二次折叠中,您的模型将保留第一次折叠的信息 - 这不等同于你的训练程序 .

    当然 - 你可以应用一个训练程序,使用10倍的连续训练来微调网络 . 但这不是交叉验证 - 您需要使用上面的某种模式来评估此过程 .

相关问题