Paddle 自定义python 算子,在调用时出现以下报错: (AlreadyExists) Op deps are not empty before preparing it for backward network execution. [Hint: Expected node_deps_.empty() == true, but received node_deps_.empty():0 != true:1.] (at /paddle/paddle/fluid/imperative/basic_engine.cc:239)

ha5z0ras  于 2021-11-30  发布在  Java
关注(0)|答案(7)|浏览(543)

自定义python 算子,在调用时出现以下报错:

(AlreadyExists) Op deps are not empty before preparing it for backward network execution.
[Hint: Expected node_deps_.empty() == true, but received node_deps_.empty():0 != true:1.] (at /paddle/paddle/fluid/imperative/basic_engine.cc:239)

就算把自定义算子改写成什么都不做,也是同样的报错:

class M(PyLayer):
@staticmethod
def forward(ctx, x):
return x
@staticmethod
def backward(ctx, dy):
return dy

 1)PaddlePaddle版本:PaddlePaddle 2.1.2
   2)CPU/GPU:GPU
   3)Python3.7
   

rjjhvcjd

rjjhvcjd1#

您好,我们已经收到了您的问题,会安排技术人员尽快解答您的问题,请耐心等待。请您再次检查是否提供了清晰的问题描述、复现代码、环境&版本、报错信息等。同时,您也可以通过查看官网API文档常见问题历史IssueAI社区来寻求解答。祝您生活愉快~

Hi! We've received your issue and please be patient to get responded. We will arrange technicians to answer your questions as soon as possible. Please make sure that you have posted enough message to demo your request. You may also check out the APIFAQGithub Issue and AI community to get the answer.Have a nice day!

k3bvogb1

k3bvogb12#

@youlingforever0328 �您好,请问能否提供自定义算子的源码,这段报错看起来是执行反向时,由于反向的逻辑是拓扑排序,创建入度统计时出错,所以想知道您这边源码的形式

llycmphe

llycmphe3#

class Myflatten(PyLayer):
	@staticmethod
	def forward(ctx, x):
		input_sort = paddle.sort(x, axis=2, descending=True) # x.shape:[ N C W*H ],对最后一维排序
		index = paddle.argsort(x, axis=2, descending=True) # 记录排序后的数据 在原来x中的index,以便反向时还原顺序
		ctx.save_for_backward(index,input_sort) # 保存,反向时用到
		result = paddle.flatten(input_sort,start_axis=1,stop_axis=-1) # [ N C W*H ] --> [ N CW*H ]
		return result
	@staticmethod
	def backward(ctx, dy):
		index,input_sort = ctx.saved_tensor()
		orgin_shape = input_sort.shape  # [N  C  W*H]
		grad_input = paddle.zeros(shape=orgin_shape,dtype=dy.dtype)
		temp = paddle.zeros(shape=orgin_shape,dtype=dy.dtype)
		grad_output = paddle.reshape(dy,shape=orgin_shape) # [N   C*W*H]   -->  [N   C   W*H]
		for i in range(orgin_shape[1]):
    		grad_input[0,i,:] = paddle.scatter(temp[0,i,:],index[0,i,:],grad_output[0,i,:]) # 根据前向保存的index还原梯度顺序
		return grad_input

然而我将前向反向的代码都删除了,什么都不做也是报同样的错误:

class M(PyLayer):
	@staticmethod
	def forward(ctx, x):
		return x
	@staticmethod
	def backward(ctx, dy):
		return dy

并且paddle文档里 自定义python算子部分的示例代码运行也是报同样的错误

vbopmzt1

vbopmzt14#

@youlingforever0328 您好,文档目前没法复现bug

mbyulnm0

mbyulnm05#

您好,目前没有复现出来,方便提供完整的单机可以运行的代码吗?@youlingforever0328

puruo6ea

puruo6ea6#

import paddle
import paddle.nn.functional as F
from paddle.vision.transforms import Compose, Normalize

import paddle
from paddle.autograd import PyLayer

# 通过创建`PyLayer`子类的方式实现动态图Python Op

class Myflatten(PyLayer):
    @staticmethod
    def forward(ctx, x):
        input_sort = paddle.sort(x, axis=2, descending=True)
        index = paddle.argsort(x, axis=2, descending=True)
        ctx.save_for_backward(index,input_sort)
        result = paddle.flatten(input_sort,start_axis=1,stop_axis=-1)
        return result

    @staticmethod
    # 因为forward只有一个输出,因此除了ctx外,backward只有一个输入。
    def backward(ctx, dy):
        index,input_sort = ctx.saved_tensor()
        orgin_shape = input_sort.shape # N C W*H
        grad_input = paddle.zeros(shape=orgin_shape,dtype=dy.dtype)
        temp = paddle.zeros(shape=orgin_shape,dtype=dy.dtype)
        grad_output = paddle.reshape(dy,shape=orgin_shape) # N C*W*H --> N C W*H
        for i in range(orgin_shape[1]):
            grad_input[0,i,:] = paddle.scatter(temp[0,i,:],index[0,i,:],grad_output[0,i,:])
        return grad_input

# 定义MyLeNet模型

class MyLeNet(paddle.nn.Layer): # 继承自paddle.nn.Layer
    def __init__(self):
        super(MyLeNet, self).__init__()
        self.conv1 = paddle.nn.Conv2D(in_channels=1,
                                      out_channels=6,
                                      kernel_size=5,
                                      stride=1)
        #池化层L2
        self.pool1 = paddle.nn.MaxPool2D(kernel_size=2,
                                         stride=2)
        #卷积层L3
        self.conv2 = paddle.nn.Conv2D(in_channels=6,
                                      out_channels=16,
                                      kernel_size=5,
                                      stride=1)
        #池化层L4
        self.pool2 = paddle.nn.MaxPool2D(kernel_size=2,
                                         stride=2)
        #线性层L5
        self.fc1=paddle.nn.Linear(256,120)
        #线性层L6
        self.fc2=paddle.nn.Linear(120,84)
        #线性层L7
        self.fc3=paddle.nn.Linear(84,10)

    # 定义前向传播
    def forward(self, x):
        x = self.conv1(x)
        x = F.relu(x)
        x = self.pool1(x)
        x = F.relu(x)
        x = self.conv2(x)
        x = self.pool2(x)
        x = paddle.reshape(x,(x.shape[0],x.shape[1],-1))
        x = Myflatten.apply(x) # 调用自定义的算子
        x = self.fc1(x)
        x = F.relu(x)
        x = self.fc2(x)
        x = F.relu(x)
        result = self.fc3(x)
        return result

data_transform = Compose([Normalize(mean=[127.5],
                               std=[127.5],
                               data_format='CHW')])
train_dataset=paddle.vision.datasets.MNIST(mode="train", transform=data_transform)
val_dataset=paddle.vision.datasets.MNIST(mode="test", transform=data_transform)

model=paddle.Model(MyLeNet())
model.prepare(paddle.optimizer.Adam(parameters=model.parameters()),
              paddle.nn.CrossEntropyLoss(),
              paddle.metric.Accuracy())
model.fit(train_dataset,
          epochs=5,
          batch_size=64,
          verbose=1)

# 模型评估

model.evaluate(val_dataset,verbose=1)

我把paddle自定义python算子文档上的例程代码贴上去也运行不了,报错. 这是教程文档的代码:

import paddle
from paddle.autograd import PyLayer

# 通过创建`PyLayer`子类的方式实现动态图Python Op

class cus_tanh(PyLayer):
    @staticmethod
    def forward(ctx, x):
        y = paddle.tanh(x)
        # ctx 为PyLayerContext对象,可以把y从forward传递到backward。
        ctx.save_for_backward(y)
        return y

    @staticmethod
    # 因为forward只有一个输出,因此除了ctx外,backward只有一个输入。
    def backward(ctx, dy):
        # ctx 为PyLayerContext对象,saved_tensor获取在forward时暂存的y。
        y, = ctx.saved_tensor()
        # 调用Paddle API自定义反向计算
        grad = dy * (1 - paddle.square(y))
        # forward只有一个Tensor输入,因此,backward只有一个输出。
        return grad

data = paddle.randn([2, 3], dtype="float32")
data.stop_gradient = False

# 通过 apply运行这个Python算子

z = cus_tanh.apply(data)
z.mean().backward()

print(data.grad)
daolsyd0

daolsyd07#

对于第一段代码报错,应该是使用inplace操作的问题,建议将backward返回值改成红框中代码。

《paddle自定义python算子文档上的例程代码》仍然没有复现,建议新建一个文件运行代码,以排除其他代码的影响。

相关问题