简体   繁体   English

获取每个训练实例的损失值 - Keras

[英]Get loss values for each training instance - Keras

I want to get loss values as model train with each instance.我想获得每个实例的损失值作为模型训练。

history = model.fit(..)

for example above code returns the loss values for each epoch not mini batch or instance.例如上面的代码返回每个时期的损失值,而不是小批量或实例。

what is the best way to do this?这样做的最佳方法是什么? Any suggestions?有什么建议吗?

There is exactly what you are looking for at the end of this official keras documentation page https://keras.io/callbacks/#callback在此官方 keras 文档页面https://keras.io/callbacks/#callback的末尾,正是您要寻找的内容

Here is the code to create a custom callback这是创建自定义回调的代码

class LossHistory(keras.callbacks.Callback):
    def on_train_begin(self, logs={}):
        self.losses = []

    def on_batch_end(self, batch, logs={}):
        self.losses.append(logs.get('loss'))

model = Sequential()
model.add(Dense(10, input_dim=784, kernel_initializer='uniform'))
model.add(Activation('softmax'))
model.compile(loss='categorical_crossentropy', optimizer='rmsprop')

history = LossHistory()
model.fit(x_train, y_train, batch_size=128, epochs=20, verbose=0, callbacks=[history])

print(history.losses)
# outputs
'''
[0.66047596406559383, 0.3547245744908703, ..., 0.25953155204159617, 0.25901699725311789]
'''

If you want to get loss values for each batch, you might want to use call model.train_on_batch inside a generator.如果您想获得每个批次的损失值,您可能需要在生成器中使用 call model.train_on_batch It's hard to provide a complete example without knowing your dataset, but you will have to break your dataset into batches and feed them one by one在不知道您的数据集的情况下很难提供完整的示例,但是您必须将数据集分成多个批次并一个一个地提供给它们

def make_batches(...):
    ...

batches = make_batches(...)
batch_losses = [model.train_on_batch(x, y) for x, y in batches]

It's a bit more complicated with single instances.单个实例稍微复杂一些。 You can, of course, train on 1-sized batches, though it will most likely thrash your optimiser (by maximising gradient variance) and significantly degrade performance.当然,您可以对 1 大小的批次进行训练,但它很可能会影响您的优化器(通过最大化梯度方差)并显着降低性能。 Besides, since loss functions are evaluated outside of Python's domain, there is no direct way to hijack the computation without tinkering with C/C++ and CUDA sources.此外,由于损失函数是在 Python 域之外进行评估的,因此如果不修改 C/C++ 和 CUDA 源,就没有直接的方法来劫持计算。 Even then, the backend itself evaluates the loss batch-wise (benefitting from highly vectorised matrix-operations), therefore you will severely degrade performance by forcing it to evaluate loss on each instance.即便如此,后端本身也会批量评估损失(受益于高度矢量化的矩阵操作),因此您将通过强制它评估每个实例的损失来严重降低性能。 Simply put, hacking the backend will only (probably) help you reduce GPU memory transfers (as compared to training on 1-sized batches from the Python interface).简而言之,攻击后端只会(可能)帮助您减少 GPU 内存传输(与从 Python 接口对 1 大小的批次进行训练相比)。 If you really want to get per-instance scores, I would recommend you to train on batches and evaluate on instances (this way you will avoid issues with high variance and reduce expensive gradient computations, since gradients are only estimated during training):如果您真的想获得每个实例的分数,我建议您进行批量训练并评估实例(这样您将避免高方差问题并减少昂贵的梯度计算,因为梯度仅在训练期间估计):

def make_batches(batchsize, x, y):
    ...


batchsize = n
batches = make_batches(n, ...)
batch_instances = [make_batches(1, x, y) for x, y in batches]
losses = [
    (model.train_on_batch(x, y), [model.test_on_batch(*inst) for inst in instances]) 
    for batch, instances in zip(batches, batch_instances)
]

After combining resources from here and here I came up with the following code.在结合了herehere的资源后,我想出了以下代码。 Maybe it will help you.也许它会帮助你。 The idea is that you can override the Callbacks class from keras and then use the on_batch_end method to check the loss value from the logs that keras will supply automatically to that method.这个想法是,您可以从 keras 覆盖Callbacks类,然后使用on_batch_end方法从 keras 将自动提供给该方法的logs中检查损失值。

Here is a working code of an NN with that particular function built in. Maybe you can start from here -这是内置特定功能的 NN 的工作代码。也许您可以从这里开始 -

import numpy as np
import pandas as pd
import seaborn as sns
import os
import matplotlib.pyplot as plt
import time
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import train_test_split

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

# fix random seed for reproducibility
seed = 155
np.random.seed(seed)

# load pima indians dataset

# download directly from website
dataset = pd.read_csv("https://archive.ics.uci.edu/ml/machine-learning-databases/pima-indians-diabetes/pima-indians-diabetes.data", 
                      header=None).values
X_train, X_test, Y_train, Y_test = train_test_split(dataset[:,0:8], dataset[:,8], test_size=0.25, random_state=87)
class NBatchLogger(Callback):
    def __init__(self,display=100):
        '''
        display: Number of batches to wait before outputting loss
        '''
        self.seen = 0
        self.display = display

    def on_batch_end(self,batch,logs={}):
        self.seen += logs.get('size', 0)
        if self.seen % self.display == 0:
            print('\n{0}/{1} - Batch Loss: {2}'.format(self.seen,self.params['samples'],
                                                logs.get('loss')))


out_batch = NBatchLogger(display=1000)
np.random.seed(seed)
my_first_nn = Sequential() # create model
my_first_nn.add(Dense(5, input_dim=8, activation='relu')) # hidden layer
my_first_nn.add(Dense(1, activation='sigmoid')) # output layer
my_first_nn.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])

my_first_nn_fitted = my_first_nn.fit(X_train, Y_train, epochs=1000, verbose=0, batch_size=128,
                                     callbacks=[out_batch], initial_epoch=0)

Please let me know if you wanted to have something like this.如果你想要这样的东西,请告诉我。

One solution is to calculate the loss function between train expectations and predictions from train input.一种解决方案是计算训练期望值和训练输入预测值之间的损失函数。 In the case of loss = mean_squared_error and three dimensional outputs (ie image width x height x channels):在 loss = mean_squared_error 和三维输出(即图像宽度 x 高度 x 通道)的情况下:

model.fit(train_in,train_out,...)

pred = model.predict(train_in)
loss = np.add.reduce(np.square(test_out-pred),axis=(1,2,3)) # this computes the total squared error for each sample
loss = loss / ( pred.shape[1]*pred.shape[2]*pred.shape[3]) # this computes the mean over the sample entry 

np.savetxt("loss.txt",loss) # This line saves the data to file

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM