通过遍历train_test_split训练模型,而无需循环训练

时间:2020-02-03 08:58:50

标签: python tensorflow machine-learning keras data-science

我是python和Keras的新手,请回答我的问题。

  1. 我最近在Keras创建了一个模型,对其进行了训练,并获得了“均方误差MSE”后期预测。我在使用的数据集上使用了train_test_split函数。

  2. 接下来,我创建了一个带有50次迭代的while循环,并将其应用于上述模型。但是,我在循环内保留了train_test_split函数(未指定* random_number),这样在每次迭代中我都会拥有一组新的X_train,y_train,X_test和y_test值。我获得了50个MSE值作为输出,并计算了它们的“均值”和“标准差”。 我的查询是通过将train_test_split函数放入循环中来做对的事情吗?会影响我的目标,即查看为我的数据集生成的不同MSE值吗?

  3. 如果我已经将train_test_split函数放置在while循环之外并执行了上述活动,那么在我的50次迭代中,X_train,y_train,X_test和y_test的值会保持不变吗?这不会对我的模型造成过度拟合的问题吗?

非常感谢您的反馈。

我的代码段:

from sklearn.model_selection import train_test_split
from sklearn import metrics
import numpy as np

MSE=np.zeros(50)

for i in range(50):
    predictors_train,predictors_test,target_train,target_test=train_test_split(predictors,target,test_size=0.3)
    model=regression_model()
    model.fit(predictors_train,target_train,validation_data=(predictors_test,target_test),epochs=50,verbose=0)
    model.evaluate(predictors_test,target_test, verbose=0)
    target_predicted=model.predict(predictors_test)
    MSE[i]=metrics.mean_squared_error(target_test, target_predicted)
    print("Test set MSE for {} cycle:{}".format(i+1,MSE[i]))

2 个答案:

答案 0 :(得分:2)

您正在实现的方法称为交叉验证,它使您的模型可以更好地“查看”数据,并减少训练数据“太完美”或“太吵”的机会。

因此,将train_test_set放入循环中将根据原始数据生成新的训练批次,并通过含义输出将获得所需的内容。 如果将train_test_set放在外面,则所有训练循环的训练数据批次都将保持不变,从而导致过拟合,如您所说。

但是train_test_split是随机的,因此您可能会有两个非常可能的随机批处理,因此此方法不是最佳方法。

更好的方法是使用k倍交叉验证:

from sklearn.model_selection import StratifiedKFold

kfold = StratifiedKFold(n_splits=10, shuffle=True, random_state=seed)

MSE = []

for train, test in kfold.split(X, Y):

   model = regression_model()
   model.fit(X[train],y[train],validation_data= (X[test],y[test]),epochs=50,verbose=0)
   model.evaluate(X[test],y[test], verbose=0)
   target_predicted = model.predict(predictors_test)
   MSE.append(metrics.mean_squared_error(y[test], target_predicted))
   print("Test set MSE for {} cycle:{}".format(i+1,MSE[i]))

print("Mean MSE for {}-fold cross validation : {}".format(len(MSE), np.mean(MSE)) 

此方法将创建10倍的训练数据,并在每次迭代中使用不同的模型来拟合模型。

您可以在此处获得更多信息:https://scikit-learn.org/stable/modules/generated/sklearn.model_selection.StratifiedKFold.html

希望这对您有帮助!

精确修改

实际上不要在您的TEST数据上使用此方法,而仅在您的VALIDATION数据上使用! 您的模特绝对不能在之前看到您的TEST数据!

答案 1 :(得分:0)

您根本不想在训练期间使用测试仪。您将对模型进行调整,使其甚至开始“过度拟合”测试集,并且您的误差估计将过于乐观。

是的,如果将train_test_split放置在for循环之外,则在整个训练过程中您的集合将保持不变,这可能会导致过拟合。因此,您有一个验证集,该验证集不用于训练,而是用于验证,主要是为了确定您的模型是否适合训练集。如果过拟合,则应通过调整模型来解决(使其变得不那么复杂,实施正则化,提前停止...)。

但是不要在用于测试的相同数据上训练模型。在验证集上训练数据是另一回事,通常在实施K折交叉验证时使用。

因此要遵循的一般步骤是:

  1. 将您的数据集分为测试集和“其他”集,将测试集放开,直到准备好进行最终测试时才将其显示在模型中=>仅当您已经训练和调整完之后您的模型

  2. 选择是否要执行k倍交叉验证。如果不是,那么将您的数据分为训练和验证集,并在整个训练中使用它们=>用于训练的训练集和用于验证的验证集

  3. 如果要实施k倍交叉验证,请按照步骤2进行操作,测量要跟踪的错误指标,再次选择另一组,将其分为不同的训练集和验证集,然后再次进行整个训练。重复多次,并取这些周期中测得的误差指标的平均值,以获得更好的(平均)误差估计

  4. 调整模型并重复步骤2和3,直到对结果满意为止

  5. 在测试集上测量最终模型的误差,以查看其推广是否很好

请注意,尽管通常执行k倍交叉验证是一个好主意,但这种方法对于大型神经网络可能不可行,因为它会大大增加训练它们的时间。在这种情况下,您可能只想保留一个训练集和一个验证集,或者将k(以k倍表示)设置为一个较低的数字,例如3。