在 tensorflow 中使用 tf.contrib.data.Datasets API 时无法处理纪元末尾的错误
Unable to handle Errors at end of epoch when using tf.contrib.data.Datasets API in tensorflow
我已经创建了 tfrecords 作为我的数据库。该数据库由 9 个不同的 tfrecord 文件组成。目的是将来自 9 个数据库的一批样本输入到模型中。因此,我使用了 TFRecordDataset 的 zip 函数。每个样本都包含一个框架及其特征集。因此,我需要从每个 tfrecord 文件中提取 8 个样本,这在一个批次中总共提供了 72 (features, image)
个样本。因此,我单独使用图像提取特征,如下面的代码所示。
问题:当我到达第一个 epoch 的末尾时,剩余数据少于 72 个。结果,第二个 epoch 的数据被添加以组成一批 72 个样本。所以,这在我的情况下是不可取的,因为我正在训练循环神经网络,所以我有一个应该一致的状态(现在没有必要讨论)。
因此,我没有使用 repeat 函数,而是尝试实现 https://www.tensorflow.org/programmers_guide/datasets 在 Processing multiple epochs 下提到的,即使用 for 循环和 try 和 except。
# Compute for 100 epochs.
for _ in range(100):
sess.run(iterator.initializer)
while True:
try:
sess.run(next_element)
except tf.errors.OutOfRangeError:
break
# [Perform end-of-epoch calculations here.]
一旦我这样做了,我就遇到了另一个问题。首先是我的完整代码:
import tensorflow as tf
import numpy as np
import time
import cv2
num_epoch = 1
batch_size = 8 # This is set to 8 since
num_threads = 9
common = "C:/Users/user/PycharmProjects/AffectiveComputingNew/database/"
filenames = [(common + "train_1_db.tfrecords"), (common + "train_2_db.tfrecords"), (common + "train_3_db.tfrecords"),
(common + "train_4_db.tfrecords"), (common + "train_5_db.tfrecords"), (common + "train_6_db.tfrecords"),
(common + "train_7_db.tfrecords"), (common + "train_8_db.tfrecords"), (common + "train_9_db.tfrecords")]
# Transforms a scalar string `example_proto` into a pair of a scalar string and
# a scalar integer, representing an image and its label, respectively.
def _parse_function(example_proto):
features = {
'height': tf.FixedLenFeature([], tf.int64),
'width': tf.FixedLenFeature([], tf.int64),
'image_raw': tf.FixedLenFeature([], tf.string),
'features': tf.FixedLenFeature([432], tf.float32)
}
parsed_features = tf.parse_single_example(example_proto, features)
# This is how we create one example, that is, extract one example from the database.
image = tf.decode_raw(parsed_features['image_raw'], tf.uint8)
# The height and the weights are used to
height = tf.cast(parsed_features['height'], tf.int32)
width = tf.cast(parsed_features['width'], tf.int32)
# The image is reshaped since when stored as a binary format, it is flattened. Therefore, we need the
# height and the weight to restore the original image back.
image = tf.reshape(image, [height, width, 3])
features = parsed_features['features']
return features, image
random_features = tf.Variable(tf.zeros([72, 432], tf.float32))
random_images = tf.Variable(tf.zeros([72, 112, 112, 3]))
datasets = []
for _ in filenames:
datasets.append(tf.contrib.data.TFRecordDataset(_).map(_parse_function))
dataset_ziped = tf.contrib.data.TFRecordDataset.zip((datasets[0], datasets[1], datasets[2], datasets[3],
datasets[4], datasets[5], datasets[6], datasets[7], datasets[8]))
#dataset = dataset_ziped.repeat(num_epoch)
dataset = dataset_ziped.batch(batch_size)
iterator = dataset.make_initializable_iterator()
next_batch = iterator.get_next() # This has shape: [9, 2]
features = tf.concat((next_batch[0][0], next_batch[1][0], next_batch[2][0], next_batch[3][0],
next_batch[4][0], next_batch[5][0], next_batch[6][0], next_batch[7][0],
next_batch[8][0]), axis=0)
features = tf.reshape(features, shape=[9, 8, 432]) # where 8 * 9 = 72
features = tf.transpose(features, perm=[1, 0, 2]) # shape becomes: [8, 9, 432]
features = tf.reshape(features, shape=[72, 432]) # Now frames will be: 1st frame from 1st video, second from second video...
images = tf.concat((next_batch[0][1], next_batch[1][1], next_batch[2][1], next_batch[3][1],
next_batch[4][1], next_batch[5][1], next_batch[6][1], next_batch[7][1],
next_batch[8][1]), axis=0)
images = tf.reshape(images, shape=[9, 8, 112, 112, 3])
images = tf.transpose(images, perm=[1, 0, 2, 3, 4])
images = tf.reshape(images, shape=[72, 112, 112, 3])
init_op = tf.global_variables_initializer()
with tf.Session() as sess:
# Initialize `iterator` with training data.
sess.run(init_op)
for _ in range(num_epoch):
sess.run(iterator.initializer)
# This while loop will run indefinitly until the end of the first epoch
while True:
try:
lst = []
features_np = sess.run([features])[0] # since the output is always: (1, 72, 432)
for f in features_np:
lst.append(f[0])
except tf.errors.OutOfRangeError:
print('errorrrrr')
因此,由于样本数不再是 72,我 运行 在第
行出错
features = tf.reshape(features, shape=[9, 8, 432]) # where 8 * 9 = 72
所以,我需要一种方法来处理这个错误。我尝试断言如下:
assert_op = tf.Assert(tf.equal(tf.shape(features[0]), batch_size * 9), [features])
with tf.control_dependencies([assert_op])... after features = tf.concat...
它没有用。我尝试了 tf.cond 如下(但效果不佳):
tf.cond(tf.equal(tf.shape(features)[0], batch_size * 9),
lambda: tf.assign(random_features, features),
lambda: tf.assign(random_features, random_features))
features = tf.reshape(random_features, shape=[9, 8, 432]) # where 8 * 9 = 72
....
总而言之,我需要在不交织来自不同迭代的样本的情况下迭代历元,同时在使用 reshape
函数时解决特征问题(批量大小较小在我的情况下比 72)。
非常感谢任何帮助!!
因此,由于最后一批被截断,我创建了一个临时 variable
,每当批大小等于我在代码中指定的 batch_size
时,它将被分配初始批的值.因此,一旦当前批次的大小不再等于 batch_size
,我就使用了我创建的临时批次。这是以下解决方案:
import tensorflow as tf
import numpy as np
import time
import cv2
num_epoch = 2
batch_size = 8 # This is set to 8 since
num_threads = 9
common = "C:/Users/user/PycharmProjects/AffectiveComputingNew/database/"
filenames = [(common + "train_1_db.tfrecords"), (common + "train_2_db.tfrecords"), (common + "train_3_db.tfrecords"),
(common + "train_4_db.tfrecords"), (common + "train_5_db.tfrecords"), (common + "train_6_db.tfrecords"),
(common + "train_7_db.tfrecords"), (common + "train_8_db.tfrecords"), (common + "train_9_db.tfrecords")]
# Transforms a scalar string `example_proto` into a pair of a scalar string and
# a scalar integer, representing an image and its label, respectively.
def _parse_function(example_proto):
features = {
'height': tf.FixedLenFeature([], tf.int64),
'width': tf.FixedLenFeature([], tf.int64),
'image_raw': tf.FixedLenFeature([], tf.string),
'features': tf.FixedLenFeature([432], tf.float32)
}
parsed_features = tf.parse_single_example(example_proto, features)
# This is how we create one example, that is, extract one example from the database.
image = tf.decode_raw(parsed_features['image_raw'], tf.uint8)
# The height and the weights are used to
height = tf.cast(parsed_features['height'], tf.int32)
width = tf.cast(parsed_features['width'], tf.int32)
# The image is reshaped since when stored as a binary format, it is flattened. Therefore, we need the
# height and the weight to restore the original image back.
image = tf.reshape(image, [height, width, 3])
features = parsed_features['features']
return features, image
# Here is the temp var that I will use whenever the return batch from the dataset doesn't have a size of batch_size * 9 mentioned above.
random_features = tf.Variable(tf.zeros([72, 432], tf.float32))
random_images = tf.Variable(tf.zeros([72, 112, 112, 3], tf.uint8))
datasets = []
for _ in filenames:
datasets.append(tf.contrib.data.TFRecordDataset(_).map(_parse_function))
dataset_ziped = tf.contrib.data.TFRecordDataset.zip((datasets[0], datasets[1], datasets[2], datasets[3],
datasets[4], datasets[5], datasets[6], datasets[7], datasets[8]))
dataset = dataset_ziped.batch(batch_size)
iterator = dataset.make_initializable_iterator()
next_batch = iterator.get_next() # This has shape: [9, 2]
features = tf.concat((next_batch[0][0], next_batch[1][0], next_batch[2][0], next_batch[3][0],
next_batch[4][0], next_batch[5][0], next_batch[6][0], next_batch[7][0],
next_batch[8][0]), axis=0)
images = tf.concat((next_batch[0][1], next_batch[1][1], next_batch[2][1], next_batch[3][1],
next_batch[4][1], next_batch[5][1], next_batch[6][1], next_batch[7][1],
next_batch[8][1]), axis=0)
def get_features(features, images):
with tf.control_dependencies([tf.assign(random_features, features), tf.assign(random_images, images)]):
features = tf.reshape(features, shape=[9, 8, 432]) # where 8 * 9 = 72
features = tf.transpose(features, perm=[1, 0, 2]) # shape becomes: [8, 9, 432]
features = tf.reshape(features, shape=[72, 432]) # Now frames will be: 1st frame from 1st video, second from second video...
images = tf.reshape(images, shape=[9, 8, 112, 112, 3])
images = tf.transpose(images, perm=[1, 0, 2, 3, 4])
images = tf.reshape(images, shape=[72, 112, 112, 3])
return features, images
condition1 = tf.equal(tf.shape(features)[0], batch_size * 9)
condition2 = tf.equal(tf.shape(images)[0], batch_size * 9)
condition = tf.logical_and(condition1, condition2)
features, images = tf.cond(condition,
lambda: get_features(features, images),
lambda: get_features(random_features, random_images))
init_op = tf.global_variables_initializer()
with tf.Session() as sess:
# Initialize `iterator` with training data.
sess.run(init_op)
for _ in range(num_epoch):
sess.run(iterator.initializer)
# This while loop will run indefinitly until the end of the first epoch
while True:
try:
lst = []
features_np, images_np = sess.run([features, images])
for f in features_np:
lst.append(f[0])
print(lst)
except tf.errors.OutOfRangeError:
print('errorrrrr')
break
请注意,我总是提到 batch_size * 9
,因为在压缩数据集时,这会创建一个样本数据,其元素是从 9 个不同的数据集中获取的。因此,由于我将 batch_size 指定为 8,有 72 个样本,所以我取了 8 * 9.
我已经创建了 tfrecords 作为我的数据库。该数据库由 9 个不同的 tfrecord 文件组成。目的是将来自 9 个数据库的一批样本输入到模型中。因此,我使用了 TFRecordDataset 的 zip 函数。每个样本都包含一个框架及其特征集。因此,我需要从每个 tfrecord 文件中提取 8 个样本,这在一个批次中总共提供了 72 (features, image)
个样本。因此,我单独使用图像提取特征,如下面的代码所示。
问题:当我到达第一个 epoch 的末尾时,剩余数据少于 72 个。结果,第二个 epoch 的数据被添加以组成一批 72 个样本。所以,这在我的情况下是不可取的,因为我正在训练循环神经网络,所以我有一个应该一致的状态(现在没有必要讨论)。
因此,我没有使用 repeat 函数,而是尝试实现 https://www.tensorflow.org/programmers_guide/datasets 在 Processing multiple epochs 下提到的,即使用 for 循环和 try 和 except。
# Compute for 100 epochs.
for _ in range(100):
sess.run(iterator.initializer)
while True:
try:
sess.run(next_element)
except tf.errors.OutOfRangeError:
break
# [Perform end-of-epoch calculations here.]
一旦我这样做了,我就遇到了另一个问题。首先是我的完整代码:
import tensorflow as tf
import numpy as np
import time
import cv2
num_epoch = 1
batch_size = 8 # This is set to 8 since
num_threads = 9
common = "C:/Users/user/PycharmProjects/AffectiveComputingNew/database/"
filenames = [(common + "train_1_db.tfrecords"), (common + "train_2_db.tfrecords"), (common + "train_3_db.tfrecords"),
(common + "train_4_db.tfrecords"), (common + "train_5_db.tfrecords"), (common + "train_6_db.tfrecords"),
(common + "train_7_db.tfrecords"), (common + "train_8_db.tfrecords"), (common + "train_9_db.tfrecords")]
# Transforms a scalar string `example_proto` into a pair of a scalar string and
# a scalar integer, representing an image and its label, respectively.
def _parse_function(example_proto):
features = {
'height': tf.FixedLenFeature([], tf.int64),
'width': tf.FixedLenFeature([], tf.int64),
'image_raw': tf.FixedLenFeature([], tf.string),
'features': tf.FixedLenFeature([432], tf.float32)
}
parsed_features = tf.parse_single_example(example_proto, features)
# This is how we create one example, that is, extract one example from the database.
image = tf.decode_raw(parsed_features['image_raw'], tf.uint8)
# The height and the weights are used to
height = tf.cast(parsed_features['height'], tf.int32)
width = tf.cast(parsed_features['width'], tf.int32)
# The image is reshaped since when stored as a binary format, it is flattened. Therefore, we need the
# height and the weight to restore the original image back.
image = tf.reshape(image, [height, width, 3])
features = parsed_features['features']
return features, image
random_features = tf.Variable(tf.zeros([72, 432], tf.float32))
random_images = tf.Variable(tf.zeros([72, 112, 112, 3]))
datasets = []
for _ in filenames:
datasets.append(tf.contrib.data.TFRecordDataset(_).map(_parse_function))
dataset_ziped = tf.contrib.data.TFRecordDataset.zip((datasets[0], datasets[1], datasets[2], datasets[3],
datasets[4], datasets[5], datasets[6], datasets[7], datasets[8]))
#dataset = dataset_ziped.repeat(num_epoch)
dataset = dataset_ziped.batch(batch_size)
iterator = dataset.make_initializable_iterator()
next_batch = iterator.get_next() # This has shape: [9, 2]
features = tf.concat((next_batch[0][0], next_batch[1][0], next_batch[2][0], next_batch[3][0],
next_batch[4][0], next_batch[5][0], next_batch[6][0], next_batch[7][0],
next_batch[8][0]), axis=0)
features = tf.reshape(features, shape=[9, 8, 432]) # where 8 * 9 = 72
features = tf.transpose(features, perm=[1, 0, 2]) # shape becomes: [8, 9, 432]
features = tf.reshape(features, shape=[72, 432]) # Now frames will be: 1st frame from 1st video, second from second video...
images = tf.concat((next_batch[0][1], next_batch[1][1], next_batch[2][1], next_batch[3][1],
next_batch[4][1], next_batch[5][1], next_batch[6][1], next_batch[7][1],
next_batch[8][1]), axis=0)
images = tf.reshape(images, shape=[9, 8, 112, 112, 3])
images = tf.transpose(images, perm=[1, 0, 2, 3, 4])
images = tf.reshape(images, shape=[72, 112, 112, 3])
init_op = tf.global_variables_initializer()
with tf.Session() as sess:
# Initialize `iterator` with training data.
sess.run(init_op)
for _ in range(num_epoch):
sess.run(iterator.initializer)
# This while loop will run indefinitly until the end of the first epoch
while True:
try:
lst = []
features_np = sess.run([features])[0] # since the output is always: (1, 72, 432)
for f in features_np:
lst.append(f[0])
except tf.errors.OutOfRangeError:
print('errorrrrr')
因此,由于样本数不再是 72,我 运行 在第
行出错features = tf.reshape(features, shape=[9, 8, 432]) # where 8 * 9 = 72
所以,我需要一种方法来处理这个错误。我尝试断言如下:
assert_op = tf.Assert(tf.equal(tf.shape(features[0]), batch_size * 9), [features])
with tf.control_dependencies([assert_op])... after features = tf.concat...
它没有用。我尝试了 tf.cond 如下(但效果不佳):
tf.cond(tf.equal(tf.shape(features)[0], batch_size * 9),
lambda: tf.assign(random_features, features),
lambda: tf.assign(random_features, random_features))
features = tf.reshape(random_features, shape=[9, 8, 432]) # where 8 * 9 = 72
....
总而言之,我需要在不交织来自不同迭代的样本的情况下迭代历元,同时在使用 reshape
函数时解决特征问题(批量大小较小在我的情况下比 72)。
非常感谢任何帮助!!
因此,由于最后一批被截断,我创建了一个临时 variable
,每当批大小等于我在代码中指定的 batch_size
时,它将被分配初始批的值.因此,一旦当前批次的大小不再等于 batch_size
,我就使用了我创建的临时批次。这是以下解决方案:
import tensorflow as tf
import numpy as np
import time
import cv2
num_epoch = 2
batch_size = 8 # This is set to 8 since
num_threads = 9
common = "C:/Users/user/PycharmProjects/AffectiveComputingNew/database/"
filenames = [(common + "train_1_db.tfrecords"), (common + "train_2_db.tfrecords"), (common + "train_3_db.tfrecords"),
(common + "train_4_db.tfrecords"), (common + "train_5_db.tfrecords"), (common + "train_6_db.tfrecords"),
(common + "train_7_db.tfrecords"), (common + "train_8_db.tfrecords"), (common + "train_9_db.tfrecords")]
# Transforms a scalar string `example_proto` into a pair of a scalar string and
# a scalar integer, representing an image and its label, respectively.
def _parse_function(example_proto):
features = {
'height': tf.FixedLenFeature([], tf.int64),
'width': tf.FixedLenFeature([], tf.int64),
'image_raw': tf.FixedLenFeature([], tf.string),
'features': tf.FixedLenFeature([432], tf.float32)
}
parsed_features = tf.parse_single_example(example_proto, features)
# This is how we create one example, that is, extract one example from the database.
image = tf.decode_raw(parsed_features['image_raw'], tf.uint8)
# The height and the weights are used to
height = tf.cast(parsed_features['height'], tf.int32)
width = tf.cast(parsed_features['width'], tf.int32)
# The image is reshaped since when stored as a binary format, it is flattened. Therefore, we need the
# height and the weight to restore the original image back.
image = tf.reshape(image, [height, width, 3])
features = parsed_features['features']
return features, image
# Here is the temp var that I will use whenever the return batch from the dataset doesn't have a size of batch_size * 9 mentioned above.
random_features = tf.Variable(tf.zeros([72, 432], tf.float32))
random_images = tf.Variable(tf.zeros([72, 112, 112, 3], tf.uint8))
datasets = []
for _ in filenames:
datasets.append(tf.contrib.data.TFRecordDataset(_).map(_parse_function))
dataset_ziped = tf.contrib.data.TFRecordDataset.zip((datasets[0], datasets[1], datasets[2], datasets[3],
datasets[4], datasets[5], datasets[6], datasets[7], datasets[8]))
dataset = dataset_ziped.batch(batch_size)
iterator = dataset.make_initializable_iterator()
next_batch = iterator.get_next() # This has shape: [9, 2]
features = tf.concat((next_batch[0][0], next_batch[1][0], next_batch[2][0], next_batch[3][0],
next_batch[4][0], next_batch[5][0], next_batch[6][0], next_batch[7][0],
next_batch[8][0]), axis=0)
images = tf.concat((next_batch[0][1], next_batch[1][1], next_batch[2][1], next_batch[3][1],
next_batch[4][1], next_batch[5][1], next_batch[6][1], next_batch[7][1],
next_batch[8][1]), axis=0)
def get_features(features, images):
with tf.control_dependencies([tf.assign(random_features, features), tf.assign(random_images, images)]):
features = tf.reshape(features, shape=[9, 8, 432]) # where 8 * 9 = 72
features = tf.transpose(features, perm=[1, 0, 2]) # shape becomes: [8, 9, 432]
features = tf.reshape(features, shape=[72, 432]) # Now frames will be: 1st frame from 1st video, second from second video...
images = tf.reshape(images, shape=[9, 8, 112, 112, 3])
images = tf.transpose(images, perm=[1, 0, 2, 3, 4])
images = tf.reshape(images, shape=[72, 112, 112, 3])
return features, images
condition1 = tf.equal(tf.shape(features)[0], batch_size * 9)
condition2 = tf.equal(tf.shape(images)[0], batch_size * 9)
condition = tf.logical_and(condition1, condition2)
features, images = tf.cond(condition,
lambda: get_features(features, images),
lambda: get_features(random_features, random_images))
init_op = tf.global_variables_initializer()
with tf.Session() as sess:
# Initialize `iterator` with training data.
sess.run(init_op)
for _ in range(num_epoch):
sess.run(iterator.initializer)
# This while loop will run indefinitly until the end of the first epoch
while True:
try:
lst = []
features_np, images_np = sess.run([features, images])
for f in features_np:
lst.append(f[0])
print(lst)
except tf.errors.OutOfRangeError:
print('errorrrrr')
break
请注意,我总是提到 batch_size * 9
,因为在压缩数据集时,这会创建一个样本数据,其元素是从 9 个不同的数据集中获取的。因此,由于我将 batch_size 指定为 8,有 72 个样本,所以我取了 8 * 9.