gpt4 book ai didi

python - 在分配期间使用后删除变量

转载 作者:太空宇宙 更新时间:2023-11-04 02:04:52 25 4
gpt4 key购买 nike

我倾向于在查看单行时看不清楚您在计算中的位置的代码。例如:

def forward(self, X):
X = layer(X)
X = activation(X)
X = layer(X)
X = activation(X)
return X

显然,第 2 行和第 4 行以及第 3 行和第 5 行彼此没有区别。

我宁愿编写更具可读性的代码,在查看特定代码行时可以清楚地知道您在计算中的位置。例如(使用 Andrew Ng 的符号):

def forward(self, X):
A0 = X
Z1 = layer(A0)
A1 = activation(Z1)
Z2 = layer(A1)
A2 = activation(Z2)
return A2

但这可能会导致给定大变量的内存错误,因此可能需要执行以下操作......

def forward(self, X):
A0 = X
Z1 = layer(A0); del A0
A1 = activation(Z1); del Z1
Z2 = layer(A1); del A1
A2 = activation(Z2); del Z2
return A2

但是,这损害了可读性,并没有利用垃圾收集器的特性。我不确定这个替代方案是否有所作为。

如果 A0、Z1、A1、Z2、A2 的大小都相同,那么理想情况下会有一个解决方案最多只占用内存中两个变量的大小。

有没有一种pythonic方法可以在计算完左侧后删除右侧使用的所有变量,或者有类似的效果?或者,您能否创建一个执行删除和赋值的函数(给定范围限制),那里的效率权衡是什么?

最佳答案

there would ideally be a solution that only took up the size of at most two of the variables in memory.

del 在 Python 中并不经常需要。重复是一种代码味道。不要重复自己(DRY 原则)。您可以使用循环删除重复项。

def forward(self, A):
for _ in range(2):
Z = layer(A)
A = activation(Z)
return A

您将重复使用两个变量 AZ

您可以通过嵌套调用进一步压缩它,这将完全删除 Z

def forward(self, A):
for _ in range(2):
A = activation(layer(A))
return A

如果您倾向于功能性,则此模式称为“减少”(有时也称为“折叠”)。这可能不太“Pythonic”,但函数式风格在 Python 代码中仍然很常用。

from functools import reduce

def forward(self, X):
return reduce(lambda A, _: activation(layer(A)), range(2), X)

甚至,

def forward(self, X):
return reduce(lambda x, f: f(x), [layer, activation]*2, X)

流行的 toolz 库也实现了这种模式

from toolz.functoolz import thread_first

def forward(self, X):
return thread_first(X, layer, activation, layer, activation)

不需要中间变量,但如果感觉更好,您可以添加评论。

def forward(self, X):
return thread_first(
X, # A0
layer, # Z1
activation, # A1
layer, # Z2
activation, # A2
)

这些不是强制执行的。


实际上,除了参数之外,根本不需要变量。

def forward(self, X):
return activate(layer(activate(layer(X))))

函数真的就是这么简单,变量名的大惊小怪似乎过于复杂了。

对于只有两层的情况,这可能没问题,但是循环/缩减版本通过更新 range() 参数可以更轻松地在以后添加更多层,该参数甚至可以是.forward() 方法。


could you create a function that does the deletion and assignment (given scoping limitations) and what's the efficiency tradeoff there?

除非使用 del(或者当它们超出范围时),否则您无法真正删除局部变量。但是您可以创建自己的命名空间而不是本地人。这是由一个 dict 支持的,它的效率只比本地人低一点,在这里不够重要。

from types import SimpleNamespace

class MonoNamespace(SimpleNamespace):
"""A namespace that holds only one attribute at a time."""
def __setattr__(self, name, value):
vars(self).clear()
vars(self)[name] = value

def forward(self, X):
ns = MonoNamespace(A0=X)
ns.Z1 = layer(ns.A0)
ns.A1 = activation(ns.Z1)
ns.Z2 = layer(ns.A1)
ns.A2 = activation(ns.Z2)
return ns.A2

关于python - 在分配期间使用后删除变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54919993/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com