我有一个字符串表达式:self.w0torch.sin(x)+self.w1torch.exp(x)。如何使用此表达式作为 PyTorch 中模型的前向传递?实例化模型的类如下:
class MyModule(nn.Module):
def __init__(self,vector):
super().__init__()
self.s='self.w0*torch.sin(x)+self.w1*torch.exp(x)'
w0=0.01*torch.rand(1,dtype=torch.float,requires_grad=True)
self.w0 = nn.Parameter(w0)
w1=0.01*torch.rand(1,dtype=torch.float,requires_grad=True)
self.w1 = nn.Parameter(w1)
def forward(self,x):
return ????
对于这个 self.w0torch.sin(x)+self.w1torch.exp(x) 字符串表达式,模型的架构如下:
我尝试了以下方法作为前向传播:
def forward(self,x):
return eval(self.s)
这是向前传球的最佳方式吗?请注意,字符串表达式可能会有所不同,我不想定义一个恒定的前向传递,例如:
def forward(self,x):
return self.w0*torch.sin(x)+self.w1*torch.exp(x)
我不建议直接使用
eval
,原因如下:
eval
可以执行任何任意代码,这是潜在的安全风险,尤其是在输入不受信任的情况下。eval
可能会更慢,因为每次调用时都需要解析和解释字符串。eval
的代码通常更难理解、调试和维护。但是,如果要求前向传递有一个动态表达式,其中表达式可以更改,则可以使用 eval 的更安全的替代方案。其中一种替代方案是使用 torch 的内置操作并动态构建计算图。这可以使用 Python 的内置函数(如 getattr 和 setattr)来完成。以下是如何实现这一点的示例:
import torch
import torch.nn as nn
class MyModule(nn.Module):
def __init__(self, vector):
super().__init__()
self.s = 'self.w0*torch.sin(x)+self.w1*torch.exp(x)'
w0 = 0.01 * torch.rand(1, dtype=torch.float, requires_grad=True)
self.w0 = nn.Parameter(w0)
w1 = 0.01 * torch.rand(1, dtype=torch.float, requires_grad=True)
self.w1 = nn.Parameter(w1)
def parse_expression(self, x, expression):
terms = expression.split('+')
result = 0.0
for term in terms:
parts = term.split('*')
weight = getattr(self, parts[0].strip())
operation = parts[1].split('(')[0].strip()
operand = x
operation_func = getattr(torch, operation)
result += weight * operation_func(operand)
return result
def forward(self, x):
return self.parse_expression(x, self.s)