Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
BaiXuePrincess
Paddle
提交
035c7425
P
Paddle
项目概览
BaiXuePrincess
/
Paddle
与 Fork 源项目一致
Fork自
PaddlePaddle / Paddle
通知
1
Star
1
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
P
Paddle
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
未验证
提交
035c7425
编写于
5月 06, 2021
作者:
Z
Zhou Wei
提交者:
GitHub
5月 06, 2021
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
add API Tensor.item() to convert Tensor element to a Python scalar (#32634)
cherry-pick #32561
上级
cdfc34d2
变更
3
显示空白变更内容
内联
并排
Showing
3 changed file
with
200 addition
and
2 deletion
+200
-2
paddle/fluid/pybind/imperative.cc
paddle/fluid/pybind/imperative.cc
+64
-0
python/paddle/fluid/dygraph/varbase_patch_methods.py
python/paddle/fluid/dygraph/varbase_patch_methods.py
+68
-2
python/paddle/fluid/tests/unittests/test_var_base.py
python/paddle/fluid/tests/unittests/test_var_base.py
+68
-0
未找到文件。
paddle/fluid/pybind/imperative.cc
浏览文件 @
035c7425
...
@@ -784,6 +784,70 @@ void BindImperative(py::module *m_ptr) {
...
@@ -784,6 +784,70 @@ void BindImperative(py::module *m_ptr) {
return
out
;
return
out
;
}
}
})
})
.
def
(
"_getitem_from_offset"
,
[](
std
::
shared_ptr
<
imperative
::
VarBase
>
&
self
,
const
py
::
args
&
args
)
{
const
auto
&
tensor
=
self
->
Var
().
Get
<
framework
::
LoDTensor
>
();
PADDLE_ENFORCE_EQ
(
tensor
.
IsInitialized
(),
true
,
platform
::
errors
::
InvalidArgument
(
"Tensor of %s is Empty, please check if it has no data."
,
self
->
Name
()));
const
auto
&
tensor_dims
=
tensor
.
dims
();
std
::
vector
<
size_t
>
dims
(
tensor_dims
.
size
());
std
::
vector
<
size_t
>
strides
(
tensor_dims
.
size
());
size_t
numel
=
1
;
for
(
int
i
=
tensor_dims
.
size
()
-
1
;
i
>=
0
;
--
i
)
{
strides
[
i
]
=
numel
;
dims
[
i
]
=
static_cast
<
size_t
>
(
tensor_dims
[
i
]);
numel
*=
dims
[
i
];
}
size_t
offset
=
0
;
if
(
args
.
empty
())
{
PADDLE_ENFORCE_EQ
(
numel
,
1
,
platform
::
errors
::
InvalidArgument
(
"only one element tensors can be converted to Python "
"scalars when no input coordinates"
));
}
else
if
(
args
.
size
()
==
1
)
{
offset
=
args
[
0
].
cast
<
size_t
>
();
PADDLE_ENFORCE_LT
(
offset
,
numel
,
platform
::
errors
::
InvalidArgument
(
"index %d is out of bounds for size %d"
,
offset
,
numel
));
}
else
{
PADDLE_ENFORCE_EQ
(
args
.
size
(),
dims
.
size
(),
platform
::
errors
::
InvalidArgument
(
"incorrect number of indices for Tensor"
));
for
(
size_t
i
=
0
;
i
<
args
.
size
();
++
i
)
{
size_t
index
=
args
[
i
].
cast
<
size_t
>
();
PADDLE_ENFORCE_LT
(
index
,
dims
[
i
],
platform
::
errors
::
InvalidArgument
(
"index %d is out fo bounds for axis %d with size %d"
,
index
,
i
,
dims
[
i
]));
offset
+=
index
*
strides
[
i
];
}
}
#define TENSOR_TO_PY_SCALAR(T, proto_type) \
if (tensor.type() == proto_type) { \
std::string py_dtype_str = details::TensorDTypeToPyDTypeStr(proto_type); \
T b = TensorGetElement<T>(tensor, offset); \
return py::array(py::dtype(py_dtype_str.c_str()), {}, {}, \
static_cast<void *>(&b)); \
}
_ForEachDataType_
(
TENSOR_TO_PY_SCALAR
);
#undef TENSOR_TO_PY_SCALAR
PADDLE_THROW
(
platform
::
errors
::
Unimplemented
(
"Unsupported tensor data type: %s"
,
framework
::
DataTypeToString
(
tensor
.
type
())));
},
py
::
return_value_policy
::
copy
)
.
def
(
"_inplace_version"
,
.
def
(
"_inplace_version"
,
[](
imperative
::
VarBase
&
self
)
->
uint32_t
{
[](
imperative
::
VarBase
&
self
)
->
uint32_t
{
const
auto
&
var
=
self
.
MutableVar
();
const
auto
&
var
=
self
.
MutableVar
();
...
...
python/paddle/fluid/dygraph/varbase_patch_methods.py
浏览文件 @
035c7425
...
@@ -375,6 +375,49 @@ def monkey_patch_varbase():
...
@@ -375,6 +375,49 @@ def monkey_patch_varbase():
"""
"""
self
.
clear_gradient
()
self
.
clear_gradient
()
def
item
(
self
,
*
args
):
"""
Convert one element Tensor to a Python scalar.
Args:
*args(int): The input coordinates. If it's single int, the data in the corresponding order of flattened Tensor will be returned.
Default: None, and it must be in the case where Tensor has only one element.
Returns(Python scalar): A Python scalar, whose dtype is corresponds to the dtype of Tensor.
Raises:
ValueError: If the Tensor has more than one element, there must be coordinates.
Examples:
.. code-block:: python
import paddle
x = paddle.to_tensor(1)
print(x.item()) #1
print(type(x.item())) #<class 'int'>
x = paddle.to_tensor(1.0)
print(x.item()) #1.0
print(type(x.item())) #<class 'float'>
x = paddle.to_tensor(True)
print(x.item()) #True
print(type(x.item())) #<class 'bool'>
x = paddle.to_tensor(1+1j)
print(x.item()) #(1+1j)
print(type(x.item())) #<class 'complex'>
x = paddle.to_tensor([[1.1, 2.2, 3.3]])
print(x.item(2)) #3.3
print(x.item(0, 2)) #3.3
x = paddle.to_tensor([1, 2])
x.item() #ValueError: only one element tensor can be converted to Python scalar when no input coordinates.
"""
return
self
.
_getitem_from_offset
(
*
args
).
item
()
@
property
@
property
def
inplace_version
(
self
):
def
inplace_version
(
self
):
"""
"""
...
@@ -462,7 +505,30 @@ def monkey_patch_varbase():
...
@@ -462,7 +505,30 @@ def monkey_patch_varbase():
return
self
.
__nonzero__
()
return
self
.
__nonzero__
()
def
__array__
(
self
,
dtype
=
None
):
def
__array__
(
self
,
dtype
=
None
):
return
self
.
numpy
().
astype
(
dtype
)
"""
Returns a numpy array shows the value of current Tensor.
Returns:
ndarray: The numpy value of current Tensor.
Returns type:
ndarray: dtype is same as current Tensor
Examples:
.. code-block:: python
import paddle
import numpy as np
x = paddle.randn([2, 2])
x_array = np.array(x)
print(type(x_array)) #<class 'numpy.ndarray'>
print(x_array.shape) #(2, 2)
"""
array
=
self
.
numpy
()
if
dtype
:
array
=
array
.
astype
(
dtype
)
return
array
def
__getitem__
(
self
,
item
):
def
__getitem__
(
self
,
item
):
def
contain_tensor
(
item
):
def
contain_tensor
(
item
):
...
@@ -498,7 +564,7 @@ def monkey_patch_varbase():
...
@@ -498,7 +564,7 @@ def monkey_patch_varbase():
(
"__str__"
,
__str__
),
(
"__repr__"
,
__str__
),
(
"__str__"
,
__str__
),
(
"__repr__"
,
__str__
),
(
"__deepcopy__"
,
__deepcopy__
),
(
"__module__"
,
"paddle"
),
(
"__deepcopy__"
,
__deepcopy__
),
(
"__module__"
,
"paddle"
),
(
"__name__"
,
"Tensor"
),
(
"__array__"
,
__array__
),
(
"__name__"
,
"Tensor"
),
(
"__array__"
,
__array__
),
(
"__getitem__"
,
__getitem__
)):
(
"__getitem__"
,
__getitem__
)
,
(
"item"
,
item
)
):
setattr
(
core
.
VarBase
,
method_name
,
method
)
setattr
(
core
.
VarBase
,
method_name
,
method
)
# NOTE(zhiqiu): pybind11 will set a default __str__ method of enum class.
# NOTE(zhiqiu): pybind11 will set a default __str__ method of enum class.
...
...
python/paddle/fluid/tests/unittests/test_var_base.py
浏览文件 @
035c7425
...
@@ -143,6 +143,74 @@ class TestVarBase(unittest.TestCase):
...
@@ -143,6 +143,74 @@ class TestVarBase(unittest.TestCase):
self
.
assertEqual
(
y
.
dtype
,
core
.
VarDesc
.
VarType
.
COMPLEX64
)
self
.
assertEqual
(
y
.
dtype
,
core
.
VarDesc
.
VarType
.
COMPLEX64
)
self
.
assertEqual
(
y
.
shape
,
[
2
])
self
.
assertEqual
(
y
.
shape
,
[
2
])
paddle
.
set_default_dtype
(
'float32'
)
x
=
paddle
.
randn
([
3
,
4
])
x_array
=
np
.
array
(
x
)
self
.
assertEqual
(
x_array
.
shape
,
x
.
numpy
().
shape
)
self
.
assertEqual
(
x_array
.
dtype
,
x
.
numpy
().
dtype
)
self
.
assertTrue
(
np
.
array_equal
(
x_array
,
x
.
numpy
()))
x
=
paddle
.
to_tensor
(
1.0
)
self
.
assertEqual
(
x
.
item
(),
1.0
)
self
.
assertTrue
(
isinstance
(
x
.
item
(),
float
))
x
=
paddle
.
randn
([
3
,
2
,
2
])
self
.
assertTrue
(
isinstance
(
x
.
item
(
5
),
float
))
self
.
assertTrue
(
isinstance
(
x
.
item
(
1
,
0
,
1
),
float
))
self
.
assertEqual
(
x
.
item
(
5
),
x
.
item
(
1
,
0
,
1
))
self
.
assertTrue
(
np
.
array_equal
(
x
.
item
(
1
,
0
,
1
),
x
.
numpy
().
item
(
1
,
0
,
1
)))
x
=
paddle
.
to_tensor
([[
1.111111
,
2.222222
,
3.333333
]])
self
.
assertEqual
(
x
.
item
(
0
,
2
),
x
.
item
(
2
))
self
.
assertAlmostEqual
(
x
.
item
(
2
),
3.333333
)
self
.
assertTrue
(
isinstance
(
x
.
item
(
0
,
2
),
float
))
x
=
paddle
.
to_tensor
(
1.0
,
dtype
=
'float64'
)
self
.
assertEqual
(
x
.
item
(),
1.0
)
self
.
assertTrue
(
isinstance
(
x
.
item
(),
float
))
x
=
paddle
.
to_tensor
(
1.0
,
dtype
=
'float16'
)
self
.
assertEqual
(
x
.
item
(),
1.0
)
self
.
assertTrue
(
isinstance
(
x
.
item
(),
float
))
x
=
paddle
.
to_tensor
(
1
,
dtype
=
'uint8'
)
self
.
assertEqual
(
x
.
item
(),
1
)
print
(
type
(
x
.
item
()))
self
.
assertTrue
(
isinstance
(
x
.
item
(),
int
))
x
=
paddle
.
to_tensor
(
1
,
dtype
=
'int8'
)
self
.
assertEqual
(
x
.
item
(),
1
)
self
.
assertTrue
(
isinstance
(
x
.
item
(),
int
))
x
=
paddle
.
to_tensor
(
1
,
dtype
=
'int16'
)
self
.
assertEqual
(
x
.
item
(),
1
)
self
.
assertTrue
(
isinstance
(
x
.
item
(),
int
))
x
=
paddle
.
to_tensor
(
1
,
dtype
=
'int32'
)
self
.
assertEqual
(
x
.
item
(),
1
)
self
.
assertTrue
(
isinstance
(
x
.
item
(),
int
))
x
=
paddle
.
to_tensor
(
1
,
dtype
=
'int64'
)
self
.
assertEqual
(
x
.
item
(),
1
)
self
.
assertTrue
(
isinstance
(
x
.
item
(),
long
if
six
.
PY2
else
int
))
x
=
paddle
.
to_tensor
(
True
)
self
.
assertEqual
(
x
.
item
(),
True
)
self
.
assertTrue
(
isinstance
(
x
.
item
(),
bool
))
x
=
paddle
.
to_tensor
(
1
+
1j
)
self
.
assertEqual
(
x
.
item
(),
1
+
1j
)
self
.
assertTrue
(
isinstance
(
x
.
item
(),
complex
))
with
self
.
assertRaises
(
ValueError
):
paddle
.
randn
([
3
,
2
,
2
]).
item
()
with
self
.
assertRaises
(
ValueError
):
paddle
.
randn
([
3
,
2
,
2
]).
item
(
18
)
with
self
.
assertRaises
(
ValueError
):
paddle
.
randn
([
3
,
2
,
2
]).
item
(
1
,
2
)
with
self
.
assertRaises
(
ValueError
):
paddle
.
randn
([
3
,
2
,
2
]).
item
(
2
,
1
,
2
)
with
self
.
assertRaises
(
TypeError
):
with
self
.
assertRaises
(
TypeError
):
paddle
.
to_tensor
(
'test'
)
paddle
.
to_tensor
(
'test'
)
with
self
.
assertRaises
(
TypeError
):
with
self
.
assertRaises
(
TypeError
):
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录