如下一段代码,在多次调用了K.ctc_decode时,会发现程序占用的内存会越来越高,执行速度越来越慢。
data = generator(...) model = init_model(...) for i in range(NUM): x, y = next(data) _y = model.predict(x) shape = _y.shape input_length = np.ones(shape[0]) * shape[1] ctc_decode = K.ctc_decode(_y, input_length)[0][0] out = K.get_value(ctc_decode)
原因
每次执行ctc_decode时都会向计算图中添加一个节点,这样会导致计算图逐渐变大,从而影响计算速度和内存。
PS:有资料说是由于get_value导致的,其中也给出了解决方案。
但是我将ctc_decode放在循环体之外就不再出现内存和速度问题,这是否说明get_value影响其实不大呢?
解决方案
通过K.function封装K.ctc_decode,只需初始化一次,只向计算图中添加一个计算节点,然后多次调用该节点(函数)
data = generator(...) model = init_model(...) x = model.output # [batch_sizes, series_length, classes] input_length = KL.Input(batch_shape=[None], dtype='int32') ctc_decode = K.ctc_decode(x, input_length=input_length * K.shape(x)[1]) decode = K.function([model.input, input_length], [ctc_decode[0][0]]) for i in range(NUM): _x, _y = next(data) out = decode([_x, np.ones(1)])
补充知识:CTC_loss和CTC_decode的模型封装代码避免节点不断增加
该问题可以参考上面的描述,无论是CTC_decode还是CTC_loss,每次运行都会创建节点,避免的方法是将其封装到model中,这样就固定了计算节点。
测试方法: 在初始化节点后(注意是在运行fit/predict至少一次后,因为这些方法也会更改计算图状态),运行K.get_session().graph.finalize()锁定节点,此时如果图节点变了会报错并提示出错代码。
from keras import backend as K from keras.layers import Lambda,Input from keras import Model from tensorflow.python.ops import ctc_ops as ctc import tensorflow as tf from keras.layers import Layer class CTC_Batch_Cost(): ''' 用于计算CTC loss ''' def ctc_lambda_func(self,args): """Runs CTC loss algorithm on each batch element. # Arguments y_true: tensor `(samples, max_string_length)` 真实标签 y_pred: tensor `(samples, time_steps, num_categories)` 预测前未经过softmax的向量 input_length: tensor `(samples, 1)` 每一个y_pred的长度 label_length: tensor `(samples, 1)` 每一个y_true的长度 # Returns Tensor with shape (samples,1) 包含了每一个样本的ctc loss """ y_true, y_pred, input_length, label_length = args # y_pred = y_pred[:, :, :] # y_pred = y_pred[:, 2:, :] return self.ctc_batch_cost(y_true, y_pred, input_length, label_length) def __call__(self, args): ''' ctc_decode 每次创建会生成一个节点,这里参考了上面的内容 将ctc封装成模型,是否会解决这个问题还没有测试过这种方法是否还会出现创建节点的问题 ''' y_true = Input(shape=(None,)) y_pred = Input(shape=(None,None)) input_length = Input(shape=(1,)) label_length = Input(shape=(1,)) lamd = Lambda(self.ctc_lambda_func, output_shape=(1,), name='ctc')([y_true,y_pred,input_length,label_length]) model = Model([y_true,y_pred,input_length,label_length],[lamd],name="ctc") # return Lambda(self.ctc_lambda_func, output_shape=(1,), name='ctc')(args) return model(args) def ctc_batch_cost(self,y_true, y_pred, input_length, label_length): """Runs CTC loss algorithm on each batch element. # Arguments y_true: tensor `(samples, max_string_length)` containing the truth labels. y_pred: tensor `(samples, time_steps, num_categories)` containing the prediction, or output of the softmax. input_length: tensor `(samples, 1)` containing the sequence length for each batch item in `y_pred`. label_length: tensor `(samples, 1)` containing the sequence length for each batch item in `y_true`. # Returns Tensor with shape (samples,1) containing the CTC loss of each element. """ label_length = tf.to_int32(tf.squeeze(label_length, axis=-1)) input_length = tf.to_int32(tf.squeeze(input_length, axis=-1)) sparse_labels = tf.to_int32(K.ctc_label_dense_to_sparse(y_true, label_length)) y_pred = tf.log(tf.transpose(y_pred, perm=[1, 0, 2]) + 1e-7) # 注意这里的True是为了忽略解码失败的情况,此时loss会变成nan直到下一个个batch return tf.expand_dims(ctc.ctc_loss(inputs=y_pred, labels=sparse_labels, sequence_length=input_length, ignore_longer_outputs_than_inputs=True), 1) # 使用方法:(注意shape) loss_out = CTC_Batch_Cost()([y_true, y_pred, audio_length, label_length])
from keras import backend as K from keras.layers import Lambda,Input from keras import Model from tensorflow.python.ops import ctc_ops as ctc import tensorflow as tf from keras.layers import Layer class CTCDecodeLayer(Layer): def __init__(self, **kwargs): super().__init__(**kwargs) def _ctc_decode(self,args): base_pred, in_len = args in_len = K.squeeze(in_len,axis=-1) r = K.ctc_decode(base_pred, in_len, greedy=True, beam_width=100, top_paths=1) r1 = r[0][0] prob = r[1][0] return [r1,prob] def call(self, inputs, **kwargs): return self._ctc_decode(inputs) def compute_output_shape(self, input_shape): return [(None,None),(1,)] class CTCDecode(): '''用与CTC 解码,得到真实语音序列 2019年7月18日所写,对ctc_decode使用模型进行了封装,从而在初始化完成后不会再有新节点的产生 ''' def __init__(self): base_pred = Input(shape=[None,None],name="pred") feature_len = Input(shape=[1,],name="feature_len") r1, prob = CTCDecodeLayer()([base_pred,feature_len]) self.model = Model([base_pred,feature_len],[r1,prob]) pass def ctc_decode(self,base_pred,in_len,return_prob = False): ''' :param base_pred:[sample,timestamp,vector] :param in_len: [sample,1] :return: ''' result,prob = self.model.predict([base_pred,in_len]) if return_prob: return result,prob return result def __call__(self,base_pred,in_len,return_prob = False): return self.ctc_decode(base_pred,in_len,return_prob) # 使用方法:(注意shape,是batch级的输入) ctc_decoder = CTCDecode() ctc_decoder.ctc_decode(result,feature_len)
以上这篇解决Keras中循环使用K.ctc_decode内存不释放的问题就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持。
免责声明:本站文章均来自网站采集或用户投稿,网站不提供任何软件下载或自行开发的软件! 如有用户或公司发现本站内容信息存在侵权行为,请邮件告知! 858582#qq.com
RTX 5090要首发 性能要翻倍!三星展示GDDR7显存
三星在GTC上展示了专为下一代游戏GPU设计的GDDR7内存。
首次推出的GDDR7内存模块密度为16GB,每个模块容量为2GB。其速度预设为32 Gbps(PAM3),但也可以降至28 Gbps,以提高产量和初始阶段的整体性能和成本效益。
据三星表示,GDDR7内存的能效将提高20%,同时工作电压仅为1.1V,低于标准的1.2V。通过采用更新的封装材料和优化的电路设计,使得在高速运行时的发热量降低,GDDR7的热阻比GDDR6降低了70%。
更新日志
- 《暗喻幻想》顺风耳作用介绍
- 崔健1985-梦中的倾诉[再版][WAV+CUE]
- 黄子馨《追星Xin的恋人们2》HQ头版限量编号[WAV+CUE]
- 孟庭苇《情人的眼泪》开盘母带[低速原抓WAV+CUE]
- 孙露《谁为我停留HQCD》[低速原抓WAV+CUE][1.1G]
- 孙悦《时光音乐会》纯银CD[低速原抓WAV+CUE][1.1G]
- 任然《渐晚》[FLAC/分轨][72.32MB]
- 英雄联盟新英雄安蓓萨上线了吗 新英雄安蓓萨技能介绍
- 魔兽世界奥杜尔竞速赛什么时候开启 奥杜尔竞速赛开启时间介绍
- 无畏契约CGRS准星代码多少 CGRS准星代码分享一览
- 张靓颖.2012-倾听【少城时代】【WAV+CUE】
- 游鸿明.1999-五月的雪【大宇国际】【WAV+CUE】
- 曹方.2005-遇见我【钛友文化】【WAV+CUE】
- Unity6引擎上线:稳定性提升、CPU性能最高提升4倍
- 人皇Sky今日举行婚礼!电竞传奇步入新篇章