在对此进行研究期间,我遇到了一些信息,回答了我的问题。
注意 :由于在较新的问题更新
tensorflow/
keras-versions(
tf>
2)
fit_generator()已被弃用。相反,建议
fit()与发电机一起使用。但是,答案仍然适用于
fit()使用生成器。
1. Keras是否仅由于生成器未继承序列而发出此警告,或者Keras是否还检查生成器是否总体上是线程安全的?
取自Keras的gitRepo(training_generators.py),我在
46-52以下几行中找到:
use_sequence_api = is_sequence(generator)if not use_sequence_api and use_multiprocessing and workers > 1: warnings.warn( UserWarning('Using a generator with `use_multiprocessing=True`' ' and multiple workers may duplicate your data.' ' Please consider using the `keras.utils.Sequence' ' class.'))的定义
is_sequence()取自training_utils.py在线路
624-635是:
def is_sequence(seq): """Determine if an object follows the Sequence API. # Arguments seq: a possible Sequence object # Returns boolean, whether the object follows the Sequence API. """ # TODO Dref360: Decide which pattern to follow. First needs a new TF Version. return (getattr(seq, 'use_sequence_api', False) or set(dir(Sequence())).issubset(set(dir(seq) + ['use_sequence_api'])))
乱码这段代码Keras仅检查传递的生成器是否为Keras序列(或者使用Keras的序列API),并且通常不检查生成器是否是线程安全的。
2. 是否正在使用我选择的线程安全方法,而不是使用Keras-
docs中的generatorClass(Sequence)-version ?
正如Omer
Zohar在gitHub上显示的那样,他的装饰器是线程安全的-
我看不出有什么理由不应该将其视为Keras的线程安全(即使Keras会发出警告,如图1所示)。
thread.Lock()可以根据docs将其实现视为线程安全的:
返回新的原始锁定对象的工厂函数。 一旦线程获取了它,随后尝试获取它就会阻塞,直到被释放 ;任何线程都可以释放它。
生成器也是可腌制的,可以像这样进行测试(有关更多信息,请参见此处的SO-Q&A ):
#Dump yielded data in order to check if picklablewith open("test.pickle", "wb") as outfile: for yielded_data in generator(data): pickle.dump(yielded_data, outfile, protocol=pickle.HIGHEST_PROTOCOL)继续这一点,我什至建议
thread.Lock()您在扩展Keras的时候实现
Sequence():
import threadingclass generatorClass(Sequence): def __init__(self, x_set, y_set, batch_size): self.x, self.y = x_set, y_set self.batch_size = batch_size self.lock = threading.Lock() #Set self.lock def __len__(self): return int(np.ceil(len(self.x) / float(self.batch_size))) def __getitem__(self, idx): with self.lock: #Use self.lock batch_x = self.x[idx * self.batch_size:(idx + 1) * self.batch_size] batch_y = self.y[idx * self.batch_size:(idx + 1) * self.batch_size] return ...
编辑24/04/2020:
通过使用
self.lock = threading.Lock()您可能会遇到以下错误:
TypeError:无法腌制_thread.lock对象
如果发生这种情况尝试更换
with self.lock:内部
__getitem__与
withthreading.Lock():和注释掉/删除
self.lock = threading.Lock()里面的
__init__。
将
lock-object存储在类中时,似乎存在一些问题(例如,参见本问答)。
3. 是否有其他方法可以导致Keras处理线程安全生成器,这与这两个示例不同?
在研究期间,我没有遇到任何其他方法。当然,我不能100%肯定地说出来。



