我有一个多标签分类问题。我写了这个自定义生成器。它从磁盘读取图像和输出标签,并以32的大小批量返回它们。
def get_input(img_name):
path = os.path.join("images", img_name)
img = image.load_img(path, target_size=(224, 224))
return img
def get_output(img_name, file_path):
data = pd.read_csv(file_path, delim_whitespace=True, header=None)
img_id = img_name.split(".")[0]
img_id = img_id.lstrip("0")
img_id = int(img_id)
labels = data.loc[img_id - 1].values
labels = labels[1:]
labels = list(labels)
label_arrays = []
for i in range(20):
val = np.zeros((1))
val[0] = labels[i]
label_arrays.append(val)
return label_arrays
def preprocess_input(img_name):
img = get_input(img_name)
x = image.img_to_array(img)
x = np.expand_dims(x, axis=0)
return x
def train_generator(batch_size):
file_path = "train.txt"
data = pd.read_csv(file_path, delim_whitespace=True, header=None)
while True:
for i in range(math.floor(8000/batch_size)):
x_batch = np.zeros(shape=(32, 224, 224, 3))
y_batch = np.zeros(shape=(32, 20))
for j in range(batch_size):
img_name = data.loc[i * batch_size + j].values
img_name = img_name[0]
x = preprocess_input(img_name)
y = get_output(img_name, file_path)
x_batch[j, :, :, :] = x
y_batch[j] = y
ys = []
for i in range(20):
ys.append(y_batch[:,i])
yield(x_batch, ys)
标签返回模型时出现了一个小问题,并在以下问题中得到解决: training a multi-output keras model
我在单个输出问题上测试了此生成器。此自定义生成器非常慢。使用此自定义生成器的单个时间段的预计到达时间约为27小时,而内置生成器(使用flow_from_directory)单个时间段则需要25分钟。我究竟做错了什么?
除了所使用的生成器外,两个测试的训练过程都相同。验证生成器类似于训练生成器。我知道我无法达到Keras内置发电机的效率,但是这种速度差异太大。
编辑
我阅读了一些有关创建自定义生成器的指南。
Writing Custom Keras Generators
custom generator for fit_generator() that yields multiple inputs with different shapes
答案 0 :(得分:0)
也许当您的自定义生成器在cpu上运行时,内置的生成器会在gpu上处理数据,这会大大降低速度。
另一个猜测是因为Keras在后台使用Dataset。您的实现可能使用feed-dict
,这是将信息传递给TensorFlow的最慢的方法。将数据输入模型的最好方法是使用输入管道,以确保GPU永远不必等待新的东西进入。