Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
PaddlePaddle
Paddle
提交
fa72e544
P
Paddle
项目概览
PaddlePaddle
/
Paddle
大约 1 年 前同步成功
通知
2299
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看板
提交
fa72e544
编写于
10月 23, 2017
作者:
Y
Yu Yang
提交者:
Yang Yang(Tony)
10月 23, 2017
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Python API for StaticRNN (#4991)
上级
23bf6b2c
变更
4
显示空白变更内容
内联
并排
Showing
4 changed file
with
226 addition
and
10 deletion
+226
-10
python/paddle/v2/framework/framework.py
python/paddle/v2/framework/framework.py
+4
-0
python/paddle/v2/framework/layer_helper.py
python/paddle/v2/framework/layer_helper.py
+8
-2
python/paddle/v2/framework/layers.py
python/paddle/v2/framework/layers.py
+176
-8
python/paddle/v2/framework/tests/test_rnn_helpers.py
python/paddle/v2/framework/tests/test_rnn_helpers.py
+38
-0
未找到文件。
python/paddle/v2/framework/framework.py
浏览文件 @
fa72e544
...
...
@@ -113,6 +113,10 @@ class Variable(object):
def
lod_level
(
self
):
return
self
.
desc
.
lod_level
()
@
property
def
type
(
self
):
return
self
.
desc
.
type
()
@
staticmethod
def
_unique_var_name_
():
uid
=
core
.
unique_integer
()
# unique during whole process.
...
...
python/paddle/v2/framework/layer_helper.py
浏览文件 @
fa72e544
from
paddle.v2.framework.framework
import
Variable
,
OpProtoHolder
,
g_program
,
g_init_program
import
paddle.v2.framework.core
as
core
import
copy
import
itertools
import
paddle.v2.framework.core
as
core
from
paddle.v2.framework.framework
import
Variable
,
g_program
,
\
g_init_program
def
unique_name
(
prefix
):
uid
=
core
.
unique_integer
()
# unique during whole process.
...
...
@@ -130,6 +133,9 @@ class LayerHelper(object):
dtype
=
dtype
,
persistable
=
False
)
def
create_variable
(
self
,
*
args
,
**
kwargs
):
return
self
.
program
.
current_block
().
create_var
(
*
args
,
**
kwargs
)
def
create_global_variable
(
self
,
*
args
,
**
kwargs
):
return
self
.
program
.
global_block
().
create_var
(
*
args
,
persistable
=
False
,
**
kwargs
)
...
...
python/paddle/v2/framework/layers.py
浏览文件 @
fa72e544
from
paddle.v2.framework.layer_helper
import
LayerHelper
from
paddle.v2.framework.layer_helper
import
LayerHelper
,
unique_name
import
paddle.v2.framework.core
as
core
from
paddle.v2.framework.framework
import
OpProtoHolder
,
Variable
from
paddle.v2.framework.framework
import
OpProtoHolder
,
Variable
,
Program
import
re
__all__
=
[
'fc'
,
'data'
,
'cross_entropy'
,
'conv2d'
,
'pool2d'
,
'embedding'
,
'concat'
'fc'
,
'data'
,
'cross_entropy'
,
'conv2d'
,
'pool2d'
,
'embedding'
,
'concat'
,
'StaticRNN'
]
...
...
@@ -26,7 +27,9 @@ def fc(input,
mul_results
=
[]
for
input_var
,
param_attr
in
helper
.
iter_inputs_and_params
():
input_shape
=
input_var
.
shape
param_shape
=
list
(
input_shape
[
num_flatten_dims
:])
+
[
size
]
param_shape
=
[
reduce
(
lambda
a
,
b
:
a
*
b
,
input_shape
[
num_flatten_dims
:],
1
)
]
+
[
size
]
w
=
helper
.
create_parameter
(
attr
=
param_attr
,
shape
=
param_shape
,
dtype
=
dtype
)
...
...
@@ -38,10 +41,8 @@ def fc(input,
"Y"
:
w
,
},
outputs
=
{
"Out"
:
tmp
},
attrs
=
{
'x_num_col_dims'
:
num_flatten_dims
,
'y_num_col_dims'
:
len
(
input_shape
)
-
num_flatten_dims
})
attrs
=
{
'x_num_col_dims'
:
num_flatten_dims
,
'y_num_col_dims'
:
1
})
mul_results
.
append
(
tmp
)
# sum
...
...
@@ -273,3 +274,170 @@ def pool2d(input,
})
return
pool_out
class
BlockGuard
(
object
):
"""
BlockGuard used to create sub-block in program by using Python `with`
keyword.
"""
def
__init__
(
self
,
program
):
if
not
isinstance
(
program
,
Program
):
raise
TypeError
(
"BlockGuard takes a program"
)
self
.
program
=
program
def
__enter__
(
self
):
self
.
program
.
create_block
()
def
__exit__
(
self
,
exc_type
,
exc_val
,
exc_tb
):
self
.
program
.
rollback
()
if
exc_type
is
not
None
:
return
False
# re-raise exception
return
True
class
StaticRNNGuard
(
BlockGuard
):
def
__init__
(
self
,
rnn
):
if
not
isinstance
(
rnn
,
StaticRNN
):
raise
TypeError
(
"StaticRNNGuard takes an StaticRNN"
)
super
(
StaticRNNGuard
,
self
).
__init__
(
rnn
.
helper
.
program
)
self
.
rnn
=
rnn
def
__enter__
(
self
):
self
.
rnn
.
status
=
StaticRNN
.
IN_RNN_BLOCK
return
super
(
StaticRNNGuard
,
self
).
__enter__
()
def
__exit__
(
self
,
exc_type
,
exc_val
,
exc_tb
):
self
.
rnn
.
status
=
StaticRNN
.
AFTER_RNN_BLOCK
self
.
rnn
.
complete_rnn_op
()
return
super
(
StaticRNNGuard
,
self
).
__exit__
(
exc_type
,
exc_val
,
exc_tb
)
class
StaticRNNMemoryLink
(
object
):
"""
:param init: the initial variable for Memory
:type init: Variable
:param pre_mem: the memory variable in previous time step
:type pre_mem: Variable
:param mem: the memory variable in current time step
:type mem: Variable
"""
def
__init__
(
self
,
init
,
pre_mem
,
mem
=
None
):
self
.
init
=
init
self
.
pre_mem
=
pre_mem
self
.
mem
=
mem
class
StaticRNN
(
object
):
BEFORE_RNN_BLOCK
=
0
IN_RNN_BLOCK
=
1
AFTER_RNN_BLOCK
=
2
def
__init__
(
self
,
name
=
None
,
program
=
None
):
self
.
helper
=
LayerHelper
(
"static_rnn"
,
name
=
name
,
program
=
program
)
self
.
memories
=
{}
# memory map, from pre_mem.name --> MemoryLink
self
.
inputs
=
[]
# input variable list in current block
self
.
outputs
=
[]
# output variable list in parent block
self
.
status
=
StaticRNN
.
BEFORE_RNN_BLOCK
# status flag.
# sequence length, since it is a static RNN, sequence length are fixed.
self
.
seq_len
=
None
def
step
(
self
):
return
StaticRNNGuard
(
self
)
def
_assert_in_rnn_block_
(
self
,
method
):
if
self
.
status
!=
StaticRNN
.
IN_RNN_BLOCK
:
raise
ValueError
(
"You must invoke {0} in rnn block"
.
format
(
method
))
def
memory
(
self
,
init
=
None
,
shape
=
None
,
dtype
=
None
,
init_value
=
0
):
self
.
_assert_in_rnn_block_
(
'memory'
)
if
init
is
None
:
if
shape
is
None
or
dtype
is
None
:
raise
ValueError
(
"if init is None, memory at least need shape and dtype"
)
parent_block
=
self
.
parent_block
()
var_name
=
unique_name
(
"@"
.
join
([
self
.
helper
.
name
,
"memory_boot"
]))
boot_var
=
parent_block
.
create_var
(
name
=
var_name
,
shape
=
shape
,
dtype
=
dtype
,
persistable
=
False
)
parent_block
.
append_op
(
type
=
"fill_constant"
,
inputs
=
{},
outputs
=
{
'Out'
:
[
boot_var
]},
attrs
=
{
'value'
:
init_value
,
'shape'
:
boot_var
.
shape
,
'data_type'
:
boot_var
.
data_type
})
return
self
.
memory
(
init
=
boot_var
)
else
:
pre_mem
=
self
.
helper
.
create_variable
(
name
=
unique_name
(
"@"
.
join
([
self
.
helper
.
name
,
"mem"
])),
dtype
=
init
.
data_type
,
shape
=
init
.
shape
)
self
.
memories
[
pre_mem
.
name
]
=
StaticRNNMemoryLink
(
init
=
init
,
pre_mem
=
pre_mem
)
return
pre_mem
def
step_input
(
self
,
x
):
self
.
_assert_in_rnn_block_
(
'step_input'
)
if
not
isinstance
(
x
,
Variable
):
raise
TypeError
(
"step input takes a Variable"
)
if
self
.
seq_len
is
None
:
self
.
seq_len
=
x
.
shape
[
1
]
elif
self
.
seq_len
!=
x
.
shape
[
1
]:
raise
ValueError
(
"Static RNN only take fix seq_len input"
)
ipt
=
self
.
helper
.
create_variable
(
name
=
x
.
name
,
dtype
=
x
.
data_type
,
shape
=
[
-
1
]
+
list
(
x
.
shape
[
2
:]),
type
=
x
.
type
)
self
.
inputs
.
append
(
ipt
)
return
ipt
def
step_output
(
self
,
o
):
self
.
_assert_in_rnn_block_
(
'step_output'
)
if
not
isinstance
(
o
,
Variable
):
raise
TypeError
(
"step output takes a Variable"
)
out_var
=
self
.
parent_block
().
create_var
(
name
=
o
.
name
,
shape
=
[
-
1
,
self
.
seq_len
]
+
list
(
o
.
shape
[
1
:]),
dtype
=
o
.
data_type
)
self
.
outputs
.
append
(
out_var
)
def
output
(
self
,
*
outputs
):
for
each
in
outputs
:
self
.
step_output
(
each
)
def
update_memory
(
self
,
mem
,
var
):
if
not
isinstance
(
mem
,
Variable
)
or
not
isinstance
(
var
,
Variable
):
raise
TypeError
(
"update memory should take variables"
)
self
.
memories
[
mem
.
name
].
mem
=
var
def
parent_block
(
self
):
prog
=
self
.
helper
.
program
parent_idx
=
prog
.
current_block
().
parent_idx
assert
parent_idx
>=
0
parent_block
=
prog
.
block
(
parent_idx
)
return
parent_block
def
__call__
(
self
,
*
args
,
**
kwargs
):
if
self
.
status
!=
StaticRNN
.
AFTER_RNN_BLOCK
:
raise
ValueError
(
"RNN output can only be retrieved after rnn block"
)
if
len
(
self
.
outputs
)
==
0
:
raise
ValueError
(
"RNN has no output"
)
elif
len
(
self
.
outputs
)
==
1
:
return
self
.
outputs
[
0
]
else
:
return
self
.
outputs
def
complete_rnn_op
(
self
):
# TODO(yuyang18): Create RNN Op here.
# Implement this method after RNN op complete.
pass
python/paddle/v2/framework/tests/test_rnn_helpers.py
0 → 100644
浏览文件 @
fa72e544
import
unittest
from
paddle.v2.framework.layers
import
*
from
paddle.v2.framework.framework
import
g_program
class
TestRNN
(
unittest
.
TestCase
):
def
test_rnn
(
self
):
img
=
data
(
shape
=
[
80
,
# sequence length
22
,
# image height
22
],
# image width
data_type
=
'float32'
,
name
=
'image'
)
hidden
=
fc
(
input
=
img
,
size
=
100
,
act
=
'sigmoid'
,
num_flatten_dims
=
2
)
self
.
assertEqual
((
-
1
,
80
,
100
),
hidden
.
shape
)
hidden
=
fc
(
input
=
hidden
,
size
=
100
,
act
=
'sigmoid'
,
num_flatten_dims
=
2
)
self
.
assertEqual
((
-
1
,
80
,
100
),
hidden
.
shape
)
rnn
=
StaticRNN
()
with
rnn
.
step
():
hidden
=
rnn
.
step_input
(
hidden
)
self
.
assertEqual
((
-
1
,
100
),
hidden
.
shape
)
memory
=
rnn
.
memory
(
shape
=
(
-
1
,
32
),
dtype
=
'float32'
,
init_value
=
0.0
)
rnn_out
=
fc
(
input
=
[
hidden
,
memory
],
size
=
32
,
act
=
'sigmoid'
)
self
.
assertEqual
((
-
1
,
32
),
rnn_out
.
shape
)
rnn
.
update_memory
(
memory
,
rnn_out
)
rnn
.
output
(
rnn_out
)
out
=
rnn
()
self
.
assertEqual
((
-
1
,
80
,
32
),
out
.
shape
)
print
g_program
if
__name__
==
'__main__'
:
unittest
.
main
()
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录