未验证 提交 6877b134 编写于 作者: L Leo Chen 提交者: GitHub

make paddle.to_tensor() copy if data is varbase (#33335)

* fix stop_gradient in paddle.to_tensor

* make to_tensor copy if data is varbase

* add ut

* refine sample code
上级 57bdf32a
...@@ -230,6 +230,14 @@ class TestVarBase(unittest.TestCase): ...@@ -230,6 +230,14 @@ class TestVarBase(unittest.TestCase):
_test_place(core.CUDAPlace(0)) _test_place(core.CUDAPlace(0))
_test_place("gpu:0") _test_place("gpu:0")
def test_to_tensor_not_change_input_stop_gradient(self):
with paddle.fluid.dygraph.guard(core.CPUPlace()):
a = paddle.zeros([1024])
a.stop_gradient = False
b = paddle.to_tensor(a)
self.assertEqual(a.stop_gradient, False)
self.assertEqual(b.stop_gradient, True)
def test_to_tensor_change_place(self): def test_to_tensor_change_place(self):
if core.is_compiled_with_cuda(): if core.is_compiled_with_cuda():
a_np = np.random.rand(1024, 1024) a_np = np.random.rand(1024, 1024)
...@@ -260,8 +268,9 @@ class TestVarBase(unittest.TestCase): ...@@ -260,8 +268,9 @@ class TestVarBase(unittest.TestCase):
with paddle.fluid.dygraph.guard(core.CUDAPlace(0)): with paddle.fluid.dygraph.guard(core.CUDAPlace(0)):
lod_tensor = core.LoDTensor() lod_tensor = core.LoDTensor()
lod_tensor.set(a_np, core.CUDAPlace(0)) lod_tensor.set(a_np, core.CUDAPlace(0))
a = paddle.to_tensor(lod_tensor) a = paddle.to_tensor(lod_tensor, place=core.CPUPlace())
self.assertTrue(np.array_equal(a_np, a.numpy())) self.assertTrue(np.array_equal(a_np, a.numpy()))
self.assertTrue(a.place.__repr__(), "CPUPlace")
def test_to_variable(self): def test_to_variable(self):
with fluid.dygraph.guard(): with fluid.dygraph.guard():
......
...@@ -40,9 +40,8 @@ def to_tensor(data, dtype=None, place=None, stop_gradient=True): ...@@ -40,9 +40,8 @@ def to_tensor(data, dtype=None, place=None, stop_gradient=True):
Constructs a ``paddle.Tensor`` from ``data`` , Constructs a ``paddle.Tensor`` from ``data`` ,
which can be scalar, tuple, list, numpy\.ndarray, paddle\.Tensor. which can be scalar, tuple, list, numpy\.ndarray, paddle\.Tensor.
If the ``data`` is already a tensor, and ``dtype`` or ``place`` does't change, no copy If the ``data`` is already a Tensor, copy will be performed and return a new tensor.
will be performed and return origin tensor, otherwise a new tensor will be constructed If you only want to change stop_gradient property, please call ``Tensor.stop_gradient = stop_gradient`` directly.
and returned.
Args: Args:
data(scalar|tuple|list|ndarray|Tensor): Initial data for the tensor. data(scalar|tuple|list|ndarray|Tensor): Initial data for the tensor.
...@@ -75,32 +74,31 @@ def to_tensor(data, dtype=None, place=None, stop_gradient=True): ...@@ -75,32 +74,31 @@ def to_tensor(data, dtype=None, place=None, stop_gradient=True):
# <class 'paddle.Tensor'> # <class 'paddle.Tensor'>
paddle.to_tensor(1) paddle.to_tensor(1)
# Tensor(shape=[1], dtype=int64, place=CUDAPlace(0), stop_gradient=True, # Tensor(shape=[1], dtype=int64, place=CPUPlace, stop_gradient=True,
# [1]) # [1])
x = paddle.to_tensor(1) x = paddle.to_tensor(1, stop_gradient=False)
paddle.to_tensor(x, dtype='int32', place=paddle.CPUPlace()) # A new tensor will be constructed due to different dtype or place print(x)
# Tensor(shape=[1], dtype=int32, place=CPUPlace, stop_gradient=True, # Tensor(shape=[1], dtype=int64, place=CPUPlace, stop_gradient=False,
# [1]) # [1])
paddle.to_tensor((1.1, 2.2), place=paddle.CUDAPinnedPlace()) paddle.to_tensor(x) # A new tensor will be created with default stop_gradient=True
# Tensor(shape=[1], dtype=float32, place=CUDAPinnedPlace, stop_gradient=True, # Tensor(shape=[1], dtype=int64, place=CPUPlace, stop_gradient=True,
# [1]) # [1])
paddle.to_tensor([[0.1, 0.2], [0.3, 0.4]], place=paddle.CUDAPlace(0), stop_gradient=False) paddle.to_tensor([[0.1, 0.2], [0.3, 0.4]], place=paddle.CPUPlace(), stop_gradient=False)
# Tensor(shape=[2, 2], dtype=float32, place=CUDAPlace(0), stop_gradient=False, # Tensor(shape=[2, 2], dtype=float32, place=CPUPlace, stop_gradient=False,
# [[0.10000000, 0.20000000], # [[0.10000000, 0.20000000],
# [0.30000001, 0.40000001]]) # [0.30000001, 0.40000001]])
type(paddle.to_tensor([[1+1j, 2], [3+2j, 4]], dtype='complex64')) type(paddle.to_tensor([[1+1j, 2], [3+2j, 4]], dtype='complex64'))
# <class 'paddle.VarBase'> # <class 'paddle.Tensor'>
paddle.to_tensor([[1+1j, 2], [3+2j, 4]], dtype='complex64') paddle.to_tensor([[1+1j, 2], [3+2j, 4]], dtype='complex64')
# Tensor(shape=[2, 2], dtype=complex64, place=CUDAPlace(0), stop_gradient=True, # Tensor(shape=[2, 2], dtype=complex64, place=CPUPlace, stop_gradient=True,
# [[(1+1j), (2+0j)], # [[(1+1j), (2+0j)],
# [(3+2j), (4+0j)]]) # [(3+2j), (4+0j)]])
""" """
place = _get_paddle_place(place) place = _get_paddle_place(place)
if place is None: if place is None:
place = _current_expected_place() place = _current_expected_place()
...@@ -119,10 +117,7 @@ def to_tensor(data, dtype=None, place=None, stop_gradient=True): ...@@ -119,10 +117,7 @@ def to_tensor(data, dtype=None, place=None, stop_gradient=True):
if not isinstance(data, np.ndarray): if not isinstance(data, np.ndarray):
def _handle_diff_place_dtype(data, dtype, place, stop_gradient): def _handle_dtype(data, dtype):
data.stop_gradient = stop_gradient
if not data.place._equals(place):
data = data._copy_to(place, False)
if dtype: if dtype:
if convert_dtype(dtype) != convert_dtype(data.dtype): if convert_dtype(dtype) != convert_dtype(data.dtype):
return data.astype(convert_dtype(dtype)) return data.astype(convert_dtype(dtype))
...@@ -138,11 +133,17 @@ def to_tensor(data, dtype=None, place=None, stop_gradient=True): ...@@ -138,11 +133,17 @@ def to_tensor(data, dtype=None, place=None, stop_gradient=True):
"this means the input data contains nested lists with different lengths. " "this means the input data contains nested lists with different lengths. "
) )
elif isinstance(data, paddle.Tensor): elif isinstance(data, paddle.Tensor):
return _handle_diff_place_dtype(data, dtype, place, stop_gradient) data = data._copy_to(place, False)
elif isinstance(data, (core.Tensor, core.LoDTensor)): ata = _handle_dtype(data, dtype)
# convert LoDTensor to VarBase first, and then process it as input VarBase data.stop_gradient = stop_gradient
elif isinstance(data, core.LoDTensor):
# convert LoDTensor to VarBase first
# Currenly, LoDTensor does no copy when places are same
data = paddle.Tensor(data) data = paddle.Tensor(data)
return _handle_diff_place_dtype(data, dtype, place, stop_gradient) if not data.place._equals(place):
data = data._copy_to(place, False)
data = _handle_dtype(data, dtype)
data.stop_gradient = stop_gradient
else: else:
raise TypeError( raise TypeError(
"Can't constructs a 'paddle.Tensor' with data type {}, data type must be scalar|list|tuple|numpy.ndarray|paddle.Tensor". "Can't constructs a 'paddle.Tensor' with data type {}, data type must be scalar|list|tuple|numpy.ndarray|paddle.Tensor".
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册