gpt4 book ai didi

python - 使用输入管道时如何将数据注入(inject)图形?

转载 作者:行者123 更新时间:2023-11-28 17:03:52 26 4
gpt4 key购买 nike

我在我的代码中使用了一个可初始化的迭代器。迭代器从具有 20.000 个条目的 csv 数据集中返回大小为 100 的批处理。然而,在训练过程中,我遇到了一个问题。考虑这段代码:

def get_dataset_iterator(batch_size): 

# parametrized with batch_size
dataset = ...
return dataset.make_initializable_iterator()


## build a model and train it (x is the input of my model)
iterator = get_dataset_iterator(100)
x = iterator.get_next()
y = model(x)

## L1 norm as loss, this works because the model is an autoencoder
loss = tf.abs(x - y)

## training operator
train_op = tf.train.AdamOptimizer(0.01).minimize(loss)

with tf.Session() as sess:

for epoch in range(100):

sess.run(iterator.initializer)

# iterate through the whole dataset once during the epoch and
# do 200 mini batch updates

for _ in range(number_of_samples // batch_size):
sess.run(train_op)

print(f'Epoch {epoch} training done!')

# TODO: print loss after epoch here

我对完成 epoch 后的训练损失很感兴趣。对我来说最有意义的是我计算整个训练集的平均损失(例如,通过网络提供所有 20.000 个样本并平均它们的损失)。我可以在这里重用批​​量大小为 20.000 的数据集迭代器,但我已将 x 声明为输入。

所以问题是:

1.) 对所有 20.000 个示例的损失计算是否有意义?我看到有些人只用一个小批量(最后一批 epoch)进行计算。

2.) 如何使用输入管道计算整个训练集的损失?我必须以某种方式注入(inject)所有训练数据,这样我就可以运行 sess.run(loss) 而无需仅对 100 个样本进行计算(因为 x 被声明为输入)。

编辑澄清:

如果我按以下方式编写我的训练循环,会有一些事情困扰我:

with tf.Session() as sess:

for epoch in range(100):

sess.run(iterator.initializer)

# iterate through the whole dataset once during the epoch and
# do 200 mini batch updates

for _ in range(number_of_samples // batch_size):
_, current_loss = sess.run([train_op, loss])

print(f'Epoch {epoch} training done!')
print(current_loss)

首先,在进行最后一次权重更新之前,仍然会评估损失。这意味着无论出现什么都不是最新的值(value)。其次,退出 for 循环后我将无法访问 current_loss,因此无法打印它。

最佳答案

1) 整个训练集的损失计算(在更新权重之前)确实有意义,称为批量梯度下降(尽管使用整个训练集而不是小批量)。

但是,在更新权重之前计算整个数据集的损失很慢(尤其是对于大型数据集)并且训练需要很长时间才能收敛。因此,通常使用的是使用一小批数据来计算损失和更新权重。尽管使用小批量会产生有噪声的损失估计,但它实际上是足够好的估计来训练具有足够训练迭代的网络。

编辑:

我同意您打印的损失值不会是最新更新权重的最新损失。可能在大多数情况下,它实际上并没有太大的不同或改变结果,所以人们只是按照你写上面代码的方式去做。但是,如果您真的想在完成训练(打印出来)后获得真实的最新损失值,那么您只需在完成训练操作后再次运行损失操作,例如:

for _ in range(number_of_samples // batch_size):
sess.run([train_op])
current_loss = sess.run([loss])

这将获得您真正的最新值(value)。当然,这不会出现在整个数据集上,只会针对 100 个的小批量。同样,该值可能是一个足够好的估计值,但如果您希望计算整个数据集的确切损失,则必须运行整个数据集,例如另一个循环然后平均损失:

    ...
# Train loop
for _ in range(number_of_samples // batch_size):
_, current_loss = sess.run([train_op, loss])

print(f'Epoch {epoch} training done!')

# Calculate loss of whole train set after training an epoch.
sess.run(iterator.initializer)
current_loss_list = []
for _ in range(number_of_samples // batch_size):
_, current_loss = sess.run([loss])
current_loss_list.append(current_loss)
train_loss_whole_dataset = np.mean(current_loss_list)
print(train_loss_whole_dataset)

编辑 2:正如所指出的那样,对 train_op 进行串行调用,然后 loss 将调用迭代器两次,因此事情可能不会很好地进行(例如,数据用完)。因此,我的第二段代码会更好用。

关于python - 使用输入管道时如何将数据注入(inject)图形?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52552978/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com