Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
PaddlePaddle
Paddle
提交
b7c179a8
P
Paddle
项目概览
PaddlePaddle
/
Paddle
1 年多 前同步成功
通知
2302
Star
20931
Fork
5422
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
1423
列表
看板
标记
里程碑
合并请求
543
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
P
Paddle
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
1,423
Issue
1,423
列表
看板
标记
里程碑
合并请求
543
合并请求
543
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
b7c179a8
编写于
6月 26, 2018
作者:
K
Kexin Zhao
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
fix lodtensor.py
上级
6b95a8a8
变更
2
显示空白变更内容
内联
并排
Showing
2 changed file
with
73 addition
and
57 deletion
+73
-57
python/paddle/fluid/lod_tensor.py
python/paddle/fluid/lod_tensor.py
+31
-26
python/paddle/fluid/tests/test_lod_tensor.py
python/paddle/fluid/tests/test_lod_tensor.py
+42
-31
未找到文件。
python/paddle/fluid/lod_tensor.py
浏览文件 @
b7c179a8
...
...
@@ -18,15 +18,16 @@ import numpy as np
__all__
=
[
'create_lod_tensor'
,
'create_random_int_lodtensor'
]
def
create_lod_tensor
(
data
,
lod
,
place
):
def
create_lod_tensor
(
data
,
recursive_seq_lens
,
place
):
"""
Create a lod tensor from a numpy array, a list, or an existing lod tensor.
Create a lod tensor by doing the following:
1. Check that the length-based input lod is valid.
1. Check that the length-based level of detail (LoD) also known as
recursive_sequence_lengths of the input is valid.
2. Convert
the length-based lod
to a offset-based LoD.
2. Convert
recursive_sequence_lengths
to a offset-based LoD.
3. Copy the data from a numpy array, a list or a existing lod tensor to
CPU or GPU device (based on input place).
...
...
@@ -40,9 +41,9 @@ def create_lod_tensor(data, lod, place):
represent two sentences, one of 2 words, and one of 3 words.
Then :code:`data` can be a numpy array of integers with shape (5, 1).
:code:`
lod
` will be [[2, 3]], indicating the length(# of words) in each
sentence. This length-based
input lod
[[2, 3]] will be converted to
offset-based
lod
[[0, 2, 5]] inside the function call.
:code:`
recursive_seq_lens
` will be [[2, 3]], indicating the length(# of words) in each
sentence. This length-based
:code:`recursive_seq_lens`
[[2, 3]] will be converted to
offset-based
LoD
[[0, 2, 5]] inside the function call.
Please reference :ref:`api_guide_low_level_lod_tensor` for more details
regarding LoD.
...
...
@@ -50,32 +51,34 @@ def create_lod_tensor(data, lod, place):
Args:
data(numpy.ndarray|list|LoDTensor): a numpy array or a LoDTensor or a
list holding the data to be copied.
lod(list): a list of lists indicating the length-based LoD info
specified by the user.
recursive_seq_lens(list): a list of lists indicating the length-based level of detail
info
specified by the user.
place(Place): CPU or GPU place indicating where the data in the new
LoDTensor will be stored.
Returns:
A fluid LoDTensor object with tensor data and
lod
info.
A fluid LoDTensor object with tensor data and
recursive_seq_lens
info.
"""
if
isinstance
(
data
,
core
.
LoDTensor
):
return
create_lod_tensor
(
np
.
array
(
data
),
lod
,
place
)
return
create_lod_tensor
(
np
.
array
(
data
),
recursive_seq_lens
,
place
)
elif
isinstance
(
data
,
list
):
# When input data is a list, it only deal with the case where the base element
# is an index of shape [1] and dtype int64 (e.g., word id). Hence, the generated
# LoDTensor will be of shape [n, 1] and dtype int64, where `n` is the total number
# of words or other indexes in the sequence.
new_
lod
=
[]
new_
recursive_seq_lens
=
[]
for
seq
in
data
:
new_lod
.
append
(
len
(
seq
))
assert
[
new_lod
]
==
lod
,
"data and lod do not match"
new_recursive_seq_lens
.
append
(
len
(
seq
))
assert
[
new_recursive_seq_lens
]
==
recursive_seq_lens
,
"data and recursive_seq_lens do not match"
flattened_data
=
np
.
concatenate
(
data
,
axis
=
0
).
astype
(
"int64"
)
flattened_data
=
flattened_data
.
reshape
([
len
(
flattened_data
),
1
])
return
create_lod_tensor
(
flattened_data
,
lod
,
place
)
return
create_lod_tensor
(
flattened_data
,
recursive_seq_lens
,
place
)
elif
isinstance
(
data
,
np
.
ndarray
):
tensor
=
core
.
LoDTensor
()
tensor
.
set
(
data
,
place
)
tensor
.
set_recursive_sequence_lengths
(
lod
)
tensor
.
set_recursive_sequence_lengths
(
recursive_seq_lens
)
assert
tensor
.
has_valid_recursive_sequence_lengths
(
),
"the provided lod info is invalid"
return
tensor
...
...
@@ -84,7 +87,8 @@ def create_lod_tensor(data, lod, place):
"data should be either a LoDTensor, a Numpy array or a list"
)
def
create_random_int_lodtensor
(
lod
,
base_shape
,
place
,
low
,
high
):
def
create_random_int_lodtensor
(
recursive_seq_lens
,
base_shape
,
place
,
low
,
high
):
"""
Create a LoDTensor containing random integers.
...
...
@@ -95,7 +99,7 @@ def create_random_int_lodtensor(lod, base_shape, place, low, high):
The function does the following:
1. Calculate the overall shape of the LoDTensor based on the length-based
:code:`
lod
` input and the shape of the basic element in
:code:`
recursive_seq_lens
` input and the shape of the basic element in
:code:`base_shape`.
2. Create a numpy array of this shape.
...
...
@@ -105,12 +109,13 @@ def create_random_int_lodtensor(lod, base_shape, place, low, high):
Suppose we want LoDTensor to hold data for sequences of word, where each
word is represented by an integer. If we want to create a LoDTensor to
represent two sentences, one of 2 words, and one of 3 words. Then
'base_shape' is [1], input length-based 'lod' is [[2, 3]]. Then the overall
shape of the LoDTensor would be [5, 1], holding 5 words for two sentences.
'base_shape' is [1], input length-based 'recursive_seq_lens' is [[2, 3]].
Then the overall shape of the LoDTensor would be [5, 1], holding 5 words
for two sentences.
Args:
lod(list): a list of lists indicating the length-based LoD info
specified by the user.
recursive_seq_lens(list): a list of lists indicating the length-based
level of detail info
specified by the user.
base_shape(list): the shape of the basic element to be held by the
LoDTensor.
place(Place): CPU or GPU place indicating where the data in the new
...
...
@@ -119,11 +124,11 @@ def create_random_int_lodtensor(lod, base_shape, place, low, high):
high(int): the upper bound of the random integers.
Returns:
A fluid LoDTensor object with tensor data and
lod
info.
A fluid LoDTensor object with tensor data and
recursive_seq_lens
info.
"""
assert
isinstance
(
base_shape
,
list
),
"base_shape should be a list"
# append the total number of basic elements to the front of its shape
overall_shape
=
[
sum
(
lod
[
-
1
])]
+
base_shape
overall_shape
=
[
sum
(
recursive_seq_lens
[
-
1
])]
+
base_shape
# the range of integer data elements is [low, high]
data
=
np
.
random
.
random_integers
(
low
,
high
,
overall_shape
).
astype
(
"int64"
)
return
create_lod_tensor
(
data
,
lod
,
place
)
return
create_lod_tensor
(
data
,
recursive_seq_lens
,
place
)
python/paddle/fluid/tests/test_lod_tensor.py
浏览文件 @
b7c179a8
...
...
@@ -19,18 +19,21 @@ import unittest
class
TestLoDTensor
(
unittest
.
TestCase
):
def
test_pybind_
lod
(
self
):
def
test_pybind_
recursive_seq_lens
(
self
):
tensor
=
fluid
.
LoDTensor
()
lod
=
[]
tensor
.
set_recursive_sequence_lengths
(
lod
)
lod
=
[[],
[
1
],
[
3
]]
self
.
assertRaises
(
Exception
,
tensor
.
set_recursive_sequence_lengths
,
lod
)
lod
=
[[
0
],
[
2
],
[
3
]]
self
.
assertRaises
(
Exception
,
tensor
.
set_recursive_sequence_lengths
,
lod
)
recursive_seq_lens
=
[]
tensor
.
set_recursive_sequence_lengths
(
recursive_seq_lens
)
recursive_seq_lens
=
[[],
[
1
],
[
3
]]
self
.
assertRaises
(
Exception
,
tensor
.
set_recursive_sequence_lengths
,
recursive_seq_lens
)
recursive_seq_lens
=
[[
0
],
[
2
],
[
3
]]
self
.
assertRaises
(
Exception
,
tensor
.
set_recursive_sequence_lengths
,
recursive_seq_lens
)
lod
=
[[
1
,
2
,
3
]]
tensor
.
set_recursive_sequence_lengths
(
lod
)
self
.
assertEqual
(
tensor
.
recursive_sequence_lengths
(),
lod
)
recursive_seq_lens
=
[[
1
,
2
,
3
]]
tensor
.
set_recursive_sequence_lengths
(
recursive_seq_lens
)
self
.
assertEqual
(
tensor
.
recursive_sequence_lengths
(),
recursive_seq_lens
)
tensor
.
set
(
np
.
random
.
random
([
6
,
1
]),
fluid
.
CPUPlace
())
self
.
assertTrue
(
tensor
.
has_valid_recursive_sequence_lengths
())
tensor
.
set
(
np
.
random
.
random
([
9
,
1
]),
fluid
.
CPUPlace
())
...
...
@@ -38,13 +41,14 @@ class TestLoDTensor(unittest.TestCase):
# Each level's sum should be equal to the number of items in the next level
# Moreover, last level's sum should be equal to the tensor height
lod
=
[[
2
,
3
],
[
1
,
3
,
1
,
2
,
2
]]
tensor
.
set_recursive_sequence_lengths
(
lod
)
self
.
assertEqual
(
tensor
.
recursive_sequence_lengths
(),
lod
)
recursive_seq_lens
=
[[
2
,
3
],
[
1
,
3
,
1
,
2
,
2
]]
tensor
.
set_recursive_sequence_lengths
(
recursive_seq_lens
)
self
.
assertEqual
(
tensor
.
recursive_sequence_lengths
(),
recursive_seq_lens
)
tensor
.
set
(
np
.
random
.
random
([
8
,
1
]),
fluid
.
CPUPlace
())
self
.
assertFalse
(
tensor
.
has_valid_recursive_sequence_lengths
())
lod
=
[[
2
,
3
],
[
1
,
3
,
1
,
2
,
1
]]
tensor
.
set_recursive_sequence_lengths
(
lod
)
recursive_seq_lens
=
[[
2
,
3
],
[
1
,
3
,
1
,
2
,
1
]]
tensor
.
set_recursive_sequence_lengths
(
recursive_seq_lens
)
self
.
assertTrue
(
tensor
.
has_valid_recursive_sequence_lengths
())
tensor
.
set
(
np
.
random
.
random
([
9
,
1
]),
fluid
.
CPUPlace
())
self
.
assertFalse
(
tensor
.
has_valid_recursive_sequence_lengths
())
...
...
@@ -52,35 +56,42 @@ class TestLoDTensor(unittest.TestCase):
def
test_create_lod_tensor
(
self
):
# Create LoDTensor from a list
data
=
[[
1
,
2
,
3
],
[
3
,
4
]]
wrong_lod
=
[[
2
,
2
]]
correct_lod
=
[[
3
,
2
]]
self
.
assertRaises
(
AssertionError
,
create_lod_tensor
,
data
,
wrong_lod
,
wrong_recursive_seq_lens
=
[[
2
,
2
]]
correct_recursive_seq_lens
=
[[
3
,
2
]]
self
.
assertRaises
(
AssertionError
,
create_lod_tensor
,
data
,
wrong_recursive_seq_lens
,
fluid
.
CPUPlace
())
tensor
=
create_lod_tensor
(
data
,
correct_recursive_seq_lens
,
fluid
.
CPUPlace
())
tensor
=
create_lod_tensor
(
data
,
correct_lod
,
fluid
.
CPUPlace
())
self
.
assertEqual
(
tensor
.
recursive_sequence_lengths
(),
correct_lod
)
self
.
assertEqual
(
tensor
.
recursive_sequence_lengths
(),
correct_recursive_seq_lens
)
# Create LoDTensor from numpy array
data
=
np
.
random
.
random
([
10
,
1
])
lod
=
[[
2
,
1
],
[
3
,
3
,
4
]]
tensor
=
create_lod_tensor
(
data
,
lod
,
fluid
.
CPUPlace
())
self
.
assertEqual
(
tensor
.
recursive_sequence_lengths
(),
lod
)
recursive_seq_lens
=
[[
2
,
1
],
[
3
,
3
,
4
]]
tensor
=
create_lod_tensor
(
data
,
recursive_seq_lens
,
fluid
.
CPUPlace
())
self
.
assertEqual
(
tensor
.
recursive_sequence_lengths
(),
recursive_seq_lens
)
# Create LoDTensor from another LoDTensor, they are differnt instances
new_lod
=
[[
2
,
2
,
1
],
[
1
,
2
,
2
,
3
,
2
]]
new_tensor
=
create_lod_tensor
(
tensor
,
new_lod
,
fluid
.
CPUPlace
())
self
.
assertEqual
(
tensor
.
recursive_sequence_lengths
(),
lod
)
self
.
assertEqual
(
new_tensor
.
recursive_sequence_lengths
(),
new_lod
)
new_recursive_seq_lens
=
[[
2
,
2
,
1
],
[
1
,
2
,
2
,
3
,
2
]]
new_tensor
=
create_lod_tensor
(
tensor
,
new_recursive_seq_lens
,
fluid
.
CPUPlace
())
self
.
assertEqual
(
tensor
.
recursive_sequence_lengths
(),
recursive_seq_lens
)
self
.
assertEqual
(
new_tensor
.
recursive_sequence_lengths
(),
new_recursive_seq_lens
)
def
test_create_random_int_lodtensor
(
self
):
# The shape of a word, commonly used in speech and NLP problem, is [1]
shape
=
[
1
]
lod
=
[[
2
,
3
,
5
]]
recursive_seq_lens
=
[[
2
,
3
,
5
]]
dict_size
=
10000
low
=
0
high
=
dict_size
-
1
tensor
=
create_random_int_lodtensor
(
lod
,
shape
,
tensor
=
create_random_int_lodtensor
(
recursive_seq_lens
,
shape
,
fluid
.
CPUPlace
(),
low
,
high
)
self
.
assertEqual
(
tensor
.
recursive_sequence_lengths
(),
lod
)
self
.
assertEqual
(
tensor
.
recursive_sequence_lengths
(),
recursive_seq_lens
)
self
.
assertEqual
(
tensor
.
shape
(),
[
10
,
1
])
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录