我想像Keras那样为我的训练集和验证集绘制损失曲线,但使用Scikit。我选择了具体数据集,这是一个回归问题,数据集可以在以下位置找到:
http://archive.ics.uci.edu/ml/machine-learning-databases/concrete/compressive/
因此,我已将数据转换为CSV格式,我的程序的第一个版本如下:
模型1
df=pd.read_csv("Concrete_Data.csv")train,validate,test=np.split(df.sample(frac=1),[int(.8*len(df)),int(.90*len(df))])Xtrain=train.drop(["ConcreteCompStrength"],axis="columns")ytrain=train["ConcreteCompStrength"]Xval=validate.drop(["ConcreteCompStrength"],axis="columns")yval=validate["ConcreteCompStrength"]mlp=MLPRegressor(activation="relu",max_iter=5000,solver="adam",random_state=2)mlp.fit(Xtrain,ytrain)plt.plot(mlp.loss_curve_,label="train")mlp.fit(Xval,yval) #疑问plt.plot(mlp.loss_curve_,label="validation") #疑问plt.legend()
生成的图表如下:
在这个模型中,我对标记的部分表示怀疑,因为据我所知,应该将验证集或测试集分开,因此这里的fit函数可能不正确。我得到的分数是0.95。
模型2
在这个模型中,我尝试使用验证分数如下:
df=pd.read_csv("Concrete_Data.csv")train,validate,test=np.split(df.sample(frac=1),[int(.8*len(df)),int(.90*len(df))])Xtrain=train.drop(["ConcreteCompStrength"],axis="columns")ytrain=train["ConcreteCompStrength"]Xval=validate.drop(["ConcreteCompStrength"],axis="columns")yval=validate["ConcreteCompStrength"]mlp=MLPRegressor(activation="relu",max_iter=5000,solver="adam",random_state=2,early_stopping=True)mlp.fit(Xtrain,ytrain)plt.plot(mlp.loss_curve_,label="train")plt.plot(mlp.validation_scores_,label="validation") #更改的行plt.legend()
对于这个模型,我不得不添加提前停止设置为true,并绘制validation_scores_,但图表结果有点奇怪:
我得到的分数是0.82,但我读到,当模型发现预测验证集中的数据比训练集中的数据更容易时,就会发生这种情况。我认为这是因为我在使用validation_scores_部分,但我无法找到任何关于这个特定指令的在线参考资料。
在Scikit中调整我的超参数时,绘制这些损失曲线的正确方法是什么?
更新我按照建议编写了模块,如下所示:
mlp=MLPRegressor(activation="relu",max_iter=1,solver="adam",random_state=2,early_stopping=True)training_mse = []validation_mse = []epochs = 5000for epoch in range(1,epochs): mlp.fit(X_train, Y_train) Y_pred = mlp.predict(X_train) curr_train_score = mean_squared_error(Y_train, Y_pred) # 训练性能 Y_pred = mlp.predict(X_valid) curr_valid_score = mean_squared_error(Y_valid, Y_pred) # 验证性能 training_mse.append(curr_train_score) # 用于绘图的训练性能列表 validation_mse.append(curr_valid_score) # 用于绘图的验证性能列表plt.plot(training_mse,label="train")plt.plot(validation_mse,label="validation")plt.legend()
但得到的图表是两条平坦的线:
看起来我在这里遗漏了一些东西。
回答:
你不应该在验证集上拟合你的模型。验证集通常用于决定使用哪些超参数,而不是参数的值。
训练的标准方法是将你的数据集分为三部分
- 训练
- 验证
- 测试
例如,以80、10、10%的比例分割
通常,你会选择一个神经网络(多少层,节点数,使用什么激活函数),然后只在训练集上训练,检查验证集上的结果,然后在测试集上进行测试
我将展示一个伪算法以便更清楚:
for model in my_networks: # 超参数选择 model.fit(X_train, Y_train) # 参数拟合 model.predict(X_valid) # 不训练,只检查性能
保存model
在验证集上的性能,并选择最佳模型(在验证集上得分最高的模型),然后在测试集上检查结果:
model.predict(X_test) # 这将是你的模型的预估性能
如果你的数据集足够大,你也可以使用类似交叉验证的方法。
无论如何,请记住:
- 参数是网络权重
- 你用训练集拟合参数
- 超参数是定义网络架构的(层,节点,激活函数)
- 你通过检查模型在验证集上的结果来选择最佳超参数
- 在进行此选择(最佳参数,最佳超参数)后,你通过在测试集上测试模型来获得模型性能
为了获得与Keras相同的结果,你应该明白,当你在模型上调用fit()
方法时使用默认参数,训练会在固定数量的轮次后停止(200次),或者使用你定义的轮次数(在你的例子中是5000次),或者当你定义early_stopping
时停止。
max_iter: int, default=200
最大迭代次数。求解器会迭代直到收敛(由‘tol’决定)或达到这个迭代次数。对于随机求解器(‘sgd’, ‘adam’),请注意,这决定了轮次的数量(每个数据点会被使用多少次),而不是梯度步骤的数量。
检查你的模型定义和参数在scikit页面
为了获得与Keras相同的结果,你可以固定训练轮次(例如,每次训练一步),检查验证集上的结果,然后再次训练直到达到所需的轮次数
例如,如果你的模型使用均方误差(mse),可以这样做:
epochs = 5000mlp = MLPRegressor(activation="relu", max_iter=1, solver="adam", random_state=2, early_stopping=True)training_mse = []validation_mse = []for epoch in epochs: mlp.fit(X_train, Y_train) Y_pred = mlp.predict(X_train) curr_train_score = mean_squared_error(Y_train, Y_pred) # 训练性能 Y_pred = mlp.predict(X_valid) curr_valid_score = mean_squared_error(Y_valid, Y_pred) # 验证性能 training_mse.append(curr_train_score) # 用于绘图的训练性能列表 validation_mse.append(curr_valid_score) # 用于绘图的验证性能列表