老师,请帮忙看一下,用户代码用到了python 3.5的一个语法叫function annotation
代码是这一行:
def _bbox_overlaps(roi_boxes:np.ndarray, gt_boxes:np.ndarray):
咱们的PyFuncRegistry
处理这个函数的时候应该是没有兼容这个语法,要改成getfullargspec()
才行
麻烦您看一下哈
我换了一种写法,还是报错
import paddle.fluid as fluid
import numpy as np
def bbox_overlaps(roi_boxes, gt_boxes):
w1 = np.maximum(roi_boxes[:, 2] - roi_boxes[:, 0] + 1, 0)
h1 = np.maximum(roi_boxes[:, 3] - roi_boxes[:, 1] + 1, 0)
w2 = np.maximum(gt_boxes[:, 2] - gt_boxes[:, 0] + 1, 0)
h2 = np.maximum(gt_boxes[:, 3] - gt_boxes[:, 1] + 1, 0)
area1 = w1 * h1
area2 = w2 * h2
overlaps = np.zeros((roi_boxes.shape[0], gt_boxes.shape[0]))
for ind1 in range(roi_boxes.shape[0]):
for ind2 in range(gt_boxes.shape[0]):
inter_x1 = np.maximum(roi_boxes[ind1, 0], gt_boxes[ind2, 0])
inter_y1 = np.maximum(roi_boxes[ind1, 1], gt_boxes[ind2, 1])
inter_x2 = np.minimum(roi_boxes[ind1, 2], gt_boxes[ind2, 2])
inter_y2 = np.minimum(roi_boxes[ind1, 3], gt_boxes[ind2, 3])
inter_w = np.maximum(inter_x2 - inter_x1 + 1, 0)
inter_h = np.maximum(inter_y2 - inter_y1 + 1, 0)
inter_area = inter_w * inter_h
iou = inter_area / (area1[ind1] + area2[ind2] - inter_area)
overlaps[ind1, ind2] = iou
return overlaps
def create_tmp_var(name, dtype, shape):
return fluid.default_main_program().current_block().create_var(
name=name, dtype=dtype, shape=shape)
def py_func():
main=fluid.Program()
start=fluid.Program()
with fluid.program_guard(main,start):
roi=fluid.layers.data('roi',[3,4],append_batch_size=False)
gt=fluid.layers.data('gt',[2,4],append_batch_size=False)
overlap=create_tmp_var('overlap','float32',[3,2])
out=fluid.layers.py_func(bbox_overlaps,[roi,gt],overlap)
exe=fluid.Executor(fluid.CPUPlace())
exe.run(start)
out=exe.run(main,feed={'roi':np.ones([3,4]),'gt':np.ones([2,4])},fetch_list=[out])
print(out)
py_func()
报错信息
---------------------------------------------------------------------------TypeError Traceback (most recent call last)<ipython-input-11-d1585aa8c677> in <module>
51 out=exe.run(main,feed={'roi':np.ones([3,4]),'gt':np.ones([2,4])},fetch_list=[out])
52 print(out)
---> 53 py_func()
<ipython-input-11-d1585aa8c677> in py_func()
49 exe=fluid.Executor(fluid.CPUPlace())
50 exe.run(start)
---> 51 out=exe.run(main,feed={'roi':np.ones([3,4]),'gt':np.ones([2,4])},fetch_list=[out])
52 print(out)
53 py_func()
/opt/conda/envs/python35-paddle120-env/lib/python3.5/site-packages/paddle/fluid/executor.py in run(self, program, feed, fetch_list, feed_var_name, fetch_var_name, scope, return_numpy, use_program_cache)
563 scope=scope,
564 return_numpy=return_numpy,
--> 565 use_program_cache=use_program_cache)
566 else:
567 if fetch_list and program._is_data_parallel and program._program and (
/opt/conda/envs/python35-paddle120-env/lib/python3.5/site-packages/paddle/fluid/executor.py in _run(self, program, exe, feed, fetch_list, feed_var_name, fetch_var_name, scope, return_numpy, use_program_cache)
640
641 self._feed_data(program, feed, feed_var_name, scope)
--> 642 exe.run(program.desc, scope, 0, True, True, fetch_var_name)
643 outs = self._fetch_data(fetch_list, fetch_var_name, scope)
644 if return_numpy:
/opt/conda/envs/python35-paddle120-env/lib/python3.5/site-packages/paddle/fluid/layers/nn.py in __call__(self, *args)
10512 kwargs[arg] = args[idx]
10513 idx += 1
> 10514 func_ret = self._func(*args[idx:], **kwargs)
10515
10516 if not isinstance(func_ret, (list, tuple)):
<ipython-input-11-d1585aa8c677> in bbox_overlaps(roi_boxes, gt_boxes)
2 import numpy as np
3 def bbox_overlaps(roi_boxes, gt_boxes):
----> 4 w1 = np.maximum(roi_boxes[:, 2] - roi_boxes[:, 0] + 1, 0)
5 h1 = np.maximum(roi_boxes[:, 3] - roi_boxes[:, 1] + 1, 0)
6 w2 = np.maximum(gt_boxes[:, 2] - gt_boxes[:, 0] + 1, 0)
TypeError: unsupported operand type(s) for -: 'paddle.fluid.core.Tensor' and 'paddle.fluid.core.Tensor'
我换了一种写法,还是报错
这个错误比较明显,py_func的2个输入是Tensor,2个Tensor如果要做elementwise减法,可以用paddle提供的数学操作,比如layers.elementwise_sub
参考https://www.paddlepaddle.org.cn/documentation/docs/zh/api_guides/low_level/layers/math.html
py_func的主要思路是基于Paddle的LoDTensor和numpy array可以方便的互转来设计的,使用的主要思路是把传入的LoDTensor转换为numpy array,然后利用numpy的相关接口来进行计算。
既然支持numpy的接口,那我那个为什么会报错啊,麻烦您帮忙看一下
我换了一种写法,还是报错
import paddle.fluid as fluid import numpy as np def bbox_overlaps(roi_boxes, gt_boxes): w1 = np.maximum(roi_boxes[:, 2] - roi_boxes[:, 0] + 1, 0) h1 = np.maximum(roi_boxes[:, 3] - roi_boxes[:, 1] + 1, 0) w2 = np.maximum(gt_boxes[:, 2] - gt_boxes[:, 0] + 1, 0) h2 = np.maximum(gt_boxes[:, 3] - gt_boxes[:, 1] + 1, 0) area1 = w1 * h1 area2 = w2 * h2 overlaps = np.zeros((roi_boxes.shape[0], gt_boxes.shape[0])) for ind1 in range(roi_boxes.shape[0]): for ind2 in range(gt_boxes.shape[0]): inter_x1 = np.maximum(roi_boxes[ind1, 0], gt_boxes[ind2, 0]) inter_y1 = np.maximum(roi_boxes[ind1, 1], gt_boxes[ind2, 1]) inter_x2 = np.minimum(roi_boxes[ind1, 2], gt_boxes[ind2, 2]) inter_y2 = np.minimum(roi_boxes[ind1, 3], gt_boxes[ind2, 3]) inter_w = np.maximum(inter_x2 - inter_x1 + 1, 0) inter_h = np.maximum(inter_y2 - inter_y1 + 1, 0) inter_area = inter_w * inter_h iou = inter_area / (area1[ind1] + area2[ind2] - inter_area) overlaps[ind1, ind2] = iou return overlaps def create_tmp_var(name, dtype, shape): return fluid.default_main_program().current_block().create_var( name=name, dtype=dtype, shape=shape) def py_func(): main=fluid.Program() start=fluid.Program() with fluid.program_guard(main,start): roi=fluid.layers.data('roi',[3,4],append_batch_size=False) gt=fluid.layers.data('gt',[2,4],append_batch_size=False) overlap=create_tmp_var('overlap','float32',[3,2]) out=fluid.layers.py_func(bbox_overlaps,[roi,gt],overlap) exe=fluid.Executor(fluid.CPUPlace()) exe.run(start) out=exe.run(main,feed={'roi':np.ones([3,4]),'gt':np.ones([2,4])},fetch_list=[out]) print(out) py_func()报错信息
---------------------------------------------------------------------------TypeError Traceback (most recent call last)<ipython-input-11-d1585aa8c677> in <module> 51 out=exe.run(main,feed={'roi':np.ones([3,4]),'gt':np.ones([2,4])},fetch_list=[out]) 52 print(out) ---> 53 py_func() <ipython-input-11-d1585aa8c677> in py_func() 49 exe=fluid.Executor(fluid.CPUPlace()) 50 exe.run(start) ---> 51 out=exe.run(main,feed={'roi':np.ones([3,4]),'gt':np.ones([2,4])},fetch_list=[out]) 52 print(out) 53 py_func() /opt/conda/envs/python35-paddle120-env/lib/python3.5/site-packages/paddle/fluid/executor.py in run(self, program, feed, fetch_list, feed_var_name, fetch_var_name, scope, return_numpy, use_program_cache) 563 scope=scope, 564 return_numpy=return_numpy, --> 565 use_program_cache=use_program_cache) 566 else: 567 if fetch_list and program._is_data_parallel and program._program and ( /opt/conda/envs/python35-paddle120-env/lib/python3.5/site-packages/paddle/fluid/executor.py in _run(self, program, exe, feed, fetch_list, feed_var_name, fetch_var_name, scope, return_numpy, use_program_cache) 640 641 self._feed_data(program, feed, feed_var_name, scope) --> 642 exe.run(program.desc, scope, 0, True, True, fetch_var_name) 643 outs = self._fetch_data(fetch_list, fetch_var_name, scope) 644 if return_numpy: /opt/conda/envs/python35-paddle120-env/lib/python3.5/site-packages/paddle/fluid/layers/nn.py in __call__(self, *args) 10512 kwargs[arg] = args[idx] 10513 idx += 1 > 10514 func_ret = self._func(*args[idx:], **kwargs) 10515 10516 if not isinstance(func_ret, (list, tuple)): <ipython-input-11-d1585aa8c677> in bbox_overlaps(roi_boxes, gt_boxes) 2 import numpy as np 3 def bbox_overlaps(roi_boxes, gt_boxes): ----> 4 w1 = np.maximum(roi_boxes[:, 2] - roi_boxes[:, 0] + 1, 0) 5 h1 = np.maximum(roi_boxes[:, 3] - roi_boxes[:, 1] + 1, 0) 6 w2 = np.maximum(gt_boxes[:, 2] - gt_boxes[:, 0] + 1, 0) TypeError: unsupported operand type(s) for -: 'paddle.fluid.core.Tensor' and 'paddle.fluid.core.Tensor'
import paddle.fluid as fluid
import numpy as np
def bbox_overlaps(roi_boxes, gt_boxes):
roi_boxes=np.array(roi_boxes)#手动转换成numpy
gt_boxes=np.array(gt_boxes)
w1 = np.maximum(roi_boxes[:, 2] - roi_boxes[:, 0] + 1, 0)
h1 = np.maximum(roi_boxes[:, 3] - roi_boxes[:, 1] + 1, 0)
w2 = np.maximum(gt_boxes[:, 2] - gt_boxes[:, 0] + 1, 0)
h2 = np.maximum(gt_boxes[:, 3] - gt_boxes[:, 1] + 1, 0)
area1 = w1 * h1
area2 = w2 * h2
overlaps = np.zeros((roi_boxes.shape[0], gt_boxes.shape[0]))
for ind1 in range(roi_boxes.shape[0]):
for ind2 in range(gt_boxes.shape[0]):
inter_x1 = np.maximum(roi_boxes[ind1, 0], gt_boxes[ind2, 0])
inter_y1 = np.maximum(roi_boxes[ind1, 1], gt_boxes[ind2, 1])
inter_x2 = np.minimum(roi_boxes[ind1, 2], gt_boxes[ind2, 2])
inter_y2 = np.minimum(roi_boxes[ind1, 3], gt_boxes[ind2, 3])
inter_w = np.maximum(inter_x2 - inter_x1 + 1, 0)
inter_h = np.maximum(inter_y2 - inter_y1 + 1, 0)
inter_area = inter_w * inter_h
iou = inter_area / (area1[ind1] + area2[ind2] - inter_area)
overlaps[ind1, ind2] = iou
return overlaps
def create_tmp_var(name, dtype, shape):
return fluid.default_main_program().current_block().create_var(
name=name, dtype=dtype, shape=shape)
def py_func():
main=fluid.Program()
start=fluid.Program()
with fluid.program_guard(main,start):
roi=fluid.layers.data('roi',[3,4],append_batch_size=False)
gt=fluid.layers.data('gt',[2,4],append_batch_size=False)
overlap=create_tmp_var('overlap','float32',[3,2])
out=fluid.layers.py_func(bbox_overlaps,[roi,gt],overlap)
exe=fluid.Executor(fluid.CPUPlace())
exe.run(start)
out=exe.run(main,feed={'roi':np.ones([3,4]),'gt':np.ones([2,4])},fetch_list=[out])
print(out)
py_func()
py_func好像是会把输入直接传进去,不会自动把输入变量变成numpy,需要手动转换一下,转换之后就不报错了
是的,传入的LoDTensor需要主动转换为numpy array,具体的解释可以参考一下这个链接https://www.paddlepaddle.org.cn/documentation/docs/zh/advanced_usage/development/new_op/new_python_op.html#py-func
我们的API示例写的的确有些简单,我会找相关同事优化一下
1)PaddlePaddle版本:1.4.1
2)CPU/GPU:如果您使用GPU训练,请提供GPU驱动版本、CUDA和cuDNN版本号
3)系统环境:请您描述系统类型、版本,例如Mac OS 10.14
4)Python 3.6
5)显存信息
运行下面代码
报错信息如下