Python sklearn 在训练期间显示损失值

Posted

技术标签:

【中文标题】Python sklearn 在训练期间显示损失值【英文标题】:Python sklearn show loss values during training 【发布时间】:2017-11-10 15:02:31 【问题描述】:

我想在训练期间检查我的损失值,以便观察每次迭代的损失。到目前为止,我还没有找到一种简单的方法让 scikit learn 给我一个损失值的历史,我也没有找到 scikit 中已有的功能来为我绘制损失。

如果没有办法绘制这个,如果我可以简单地在分类器.fit 的末尾获取最终的损失值,那就太好了。

注意:我知道某些解决方案是封闭形式的。我正在使用几个没有分析解决方案的分类器,例如逻辑回归和 svm。

有人有什么建议吗?

【问题讨论】:

你能解释一下你到底想要什么吗? 这是否接近您的要求? scikit-learn.org/stable/modules/generated/… 【参考方案1】:

所以我找不到很好的文档来直接获取每次迭代的损失值,但我希望这对未来的人有所帮助:

old_stdout = sys.stdout
sys.stdout = mystdout = StringIO()
clf = SGDClassifier(**kwargs, verbose=1)
clf.fit(X_tr, y_tr)
sys.stdout = old_stdout
loss_history = mystdout.getvalue()
loss_list = []
for line in loss_history.split('\n'):
    if(len(line.split("loss: ")) == 1):
        continue
    loss_list.append(float(line.split("loss: ")[-1]))
plt.figure()
plt.plot(np.arange(len(loss_list)), loss_list)
plt.savefig("warmstart_plots/pure_SGD:"+str(kwargs)+".png")
plt.xlabel("Time in epochs")
plt.ylabel("Loss")
plt.close()

此代码将采用普通的 SGDClassifier(几乎是任何线性分类器),并拦截 verbose=1 标志,然后将拆分以从详细打印中获取损失。显然这比较慢,但会给我们带来损失并打印出来。

【讨论】:

你有逻辑回归的实现吗?【参考方案2】:

使用model.loss_curve_

您可以使用verbose 选项在每次迭代时打印值,但如果您想要实际值,这不是最好的方法,因为您需要做一些麻烦的事情来解析它们。

确实,文档没有提及任何关于此属性的内容,但如果您查看源代码,您可能会注意到 MLPClassifier 基类之一 (BaseMultilayerPerceptron) 实际上是 defines an attribute loss_curve_ 存储每个迭代的值。

当您获取列表中的所有值时,使用任何库进行绘图都应该是微不足道的。

请注意,此属性仅在使用随机求解器时存在(即sgdadam)。

【讨论】:

【参考方案3】:

我刚刚改编并更新了@OneRaynyDay 的答案。使用context manager 更优雅。

定义上下文管理器:

import sys
import io
import matplotlib.pyplot as plt

class DisplayLossCurve(object):
  def __init__(self, print_loss=False):
    self.print_loss = print_loss

  """Make sure the model verbose is set to 1"""
  def __enter__(self):
    self.old_stdout = sys.stdout
    sys.stdout = self.mystdout = io.StringIO()
  
  def __exit__(self, *args, **kwargs):
    sys.stdout = self.old_stdout
    loss_history = self.mystdout.getvalue()
    loss_list = []
    for line in loss_history.split('\n'):
      if(len(line.split("loss: ")) == 1):
        continue
      loss_list.append(float(line.split("loss: ")[-1]))
    plt.figure()
    plt.plot(np.arange(len(loss_list)), loss_list)
    plt.xlabel("Epoch")
    plt.ylabel("Loss")

    if self.print_loss:
      print("=============== Loss Array ===============")
      print(np.array(loss_list))
      
    return True

用法:

from sklearn.linear_model import SGDRegressor

model = SGDRegressor(verbose=1)

with DisplayLossCurve():
  model.fit(X, Y)

# OR

with DisplayLossCurve(print_loss=True):
  model.fit(X, Y)

【讨论】:

以上是关于Python sklearn 在训练期间显示损失值的主要内容,如果未能解决你的问题,请参考以下文章

如何在训练期间在每个时期修改损失函数内的变量?

莫烦sklearn学习自修第九天过拟合问题处理

为啥tf模型训练时的二元交叉熵损失与sklearn计算的不同?

在训练期间改变损失函数

sklearn之岭回归

图像分类。验证损失在初始训练期间卡住(v1)