python - 避免 tensorflow 会话扩展
问题描述
我有一个使用 keras 的 tensorflow 后端的函数。在一个循环中,我将操作添加到会话图中,然后运行会话。问题在于,在多次调用该函数后,图表似乎大幅增长。这导致在对函数进行 4/5 次调用后,函数评估的时间要长 2 倍。
这是功能:
def attack_fgsm(self, x, y, epsilon=1e-2):
sess = K.get_session()
nabla_x = np.zeros(x.shape)
for (weak_classi, alpha) in zip(self.models, self.alphas):
grads = K.gradients(K.categorical_crossentropy(y, weak_classi.model.output), weak_classi.model.input)[0]
grads = sess.run(grads, feed_dict={weak_classi.model.input: x})
nabla_x += alpha*grads
x_adv = x + epsilon*np.sign(nabla_x)
return x_adv
所以问题是如何优化这个函数,使图形不会增长太多?
经过一些研究,我似乎需要使用占位符来克服这个问题。所以我想出了这个:
def attack_fgsm(self, x, y, epsilon=1e-2):
sess = K.get_session()
nabla_x = np.zeros(x.shape)
y_ph = K.placeholder(y.shape)
model_in = K.placeholder(x.shape, dtype="float")
for (weak_classi, alpha) in zip(self.models, self.alphas):
grads = K.gradients(K.categorical_crossentropy(y_ph, weak_classi.model.output), weak_classi.model.input)[0]
grads = sess.run(grads, feed_dict={y_ph:y, model_in:x})
nabla_x += alpha*grads
x_adv = x + epsilon*np.sign(nabla_x)
#K.clear_session()
return x_adv
这导致 :
Traceback (most recent call last):
File "/home/simond/adversarialboosting/src/scripts/robustness_study.py", line 93, in <module>
x_att_ada = adaboost.attack_fgsm(x_test, y_test, epsilon=eps)
File "/home/simond/adversarialboosting/src/classes/AdvBoostM1.py", line 308, in attack_fgsm
grads = sess.run(grads, feed_dict={y_ph:y, model_in:x})
File "/home/simond/miniconda3/envs/keras/lib/python3.6/site-packages/tensorflow/python/client/session.py", line 950, in run
run_metadata_ptr)
File "/home/simond/miniconda3/envs/keras/lib/python3.6/site-packages/tensorflow/python/client/session.py", line 1158, in _run
self._graph, fetches, feed_dict_tensor, feed_handles=feed_handles)
File "/home/simond/miniconda3/envs/keras/lib/python3.6/site-packages/tensorflow/python/client/session.py", line 474, in __init__
self._fetch_mapper = _FetchMapper.for_fetch(fetches)
File "/home/simond/miniconda3/envs/keras/lib/python3.6/site-packages/tensorflow/python/client/session.py", line 261, in for_fetch
type(fetch)))
TypeError: Fetch argument None has invalid type <class 'NoneType'>
解决方案
问题是每次调用此函数时都运行这行代码:
grads = K.gradients(K.categorical_crossentropy(y, weak_classi.model.output), weak_classi.model.input)[0]
这会将梯度的符号计算添加到您的图形中,并且不需要为每个实例运行多次weak_classi
,因此您可以将其分成两部分。这部分应该只运行一次,比如在初始化时:
self.weak_classi_grads = []
for (weak_classi, alpha) in zip(self.models, self.alphas):
grads = K.gradients(K.categorical_crossentropy(y_ph, weak_classi.model.output), weak_classi.model.input)[0]
self.weak_classi_grads.append(grads)
然后您可以将评估函数重写为:
def attack_fgsm(self, x, y, epsilon=1e-2):
sess = K.get_session()
nabla_x = np.zeros(x.shape)
for (weak_classi, alpha, grads) in zip(self.models, self.alphas, self.weak_classi_grads):
grads = sess.run(grads, feed_dict={weak_classi.model.input: x})
nabla_x += alpha*grads
x_adv = x + epsilon*np.sign(nabla_x)
return x_adv
这样,该图对于每个模型只有一个梯度计算实例,然后您只需要运行会话来评估具有不同输入的梯度。
推荐阅读
- python - hubspot3 客户端和“重试次数过多”错误
- sql - 过去 6 个月的 SQL Server 查询
- lua - 我将如何使这个“仅限团队项目”脚本工作?
- html - .css 中的样式不起作用。怎么了?
- security - 存储由 Bitbucket Server 管理的本地存储库的最佳实践是什么?
- c# - 在 Unity 中,如何使用 X、Y 屏幕坐标来查找那里是否有 Canvas 对象的子对象?
- javascript - 无法访问数组索引,数组长度返回 0,尽管控制台显示完整数组
- laravel - 一对多 + 多对多
- powershell - Thycotic Secret Server 将凭据传递给 Powershell
- android - 找不到属性 app:visibleGone 的设置器