Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
P
pytensor
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
testgroup
pytensor
Commits
5fc50232
提交
5fc50232
authored
6月 21, 2009
作者:
Olivier Delalleau
浏览文件
操作
浏览文件
下载
差异文件
Merged
上级
9edf0705
00135e8f
隐藏空白字符变更
内嵌
并排
正在显示
3 个修改的文件
包含
116 行增加
和
15 行删除
+116
-15
function_module.py
theano/compile/function_module.py
+76
-11
io.py
theano/compile/io.py
+31
-3
module.py
theano/compile/module.py
+9
-1
没有找到文件。
theano/compile/function_module.py
浏览文件 @
5fc50232
...
...
@@ -234,10 +234,35 @@ class Function(object):
c
=
containers
[
0
]
#containers is being used as a stack. Here we pop off the next one.
if
input
.
strict
:
c
.
strict
=
True
# Whether the default value will be directly accessible within
# the function's container (c.copy_from_container = None), or
# if the function has its own container and thus needs to copy
# the default value at each call (c.copy_from_container =
# pointer towards it).
# Shared containers are only used for implicit inputs (so that
# there is no risk of overwriting their content with a user-
# provided value).
c
.
copy_from_container
=
None
if
value
is
not
None
:
# always initialize the storage
c
.
data
=
value
# Always initialize the storage.
if
isinstance
(
value
,
gof
.
Container
):
# There is no point in obtaining the current value
# stored in the container, since:
# - for an implicit input, the container is shared
# - for a non implicit input, the value may change
# the function is called.
if
not
input
.
implicit
:
c
.
copy_from_container
=
value
else
:
# Safety check: the container will be shared, so
# there should be no need to refeed the default
# value.
assert
not
refeed
else
:
c
.
value
=
value
c
.
required
=
required
c
.
implicit
=
input
.
implicit
c
.
provided
=
0
# this is a count of how many times the input has been provided (reinitialized to 0 on __call__)
finder
[
i
]
=
c
finder
[
input
.
variable
]
=
c
...
...
@@ -247,6 +272,9 @@ class Function(object):
#setters.append(partial(assign, c))
containers
[:
1
]
=
[]
else
:
# TODO The following code may need to do something to handle
# implicit inputs.
# The input is a SymbolicInputKit, so we take as many containers as the Kit provides inputs
cs
=
containers
[:
len
(
indices
)]
# distribute does the initialization of the containers
...
...
@@ -347,12 +375,33 @@ class Function(object):
# Set keyword arguments
for
k
,
arg
in
kwargs
.
iteritems
():
self
[
k
]
=
arg
# Check if inputs are missing or if inputs were set more than once
# Check if inputs are missing, or if inputs were set more than once, or
# if we tried to provide inputs that are supposed to be implicit.
# Also initialize default values that are obtained from an external
# container. This is required because this container's value may be
# modified between function calls.
# Other types of default values should not need to be re-initialized:
# - shared containers are updated automatically
# - default values defined directly by their value are re-fed into the
# input storage after a function call, and any modification possibly
# made to them (for mutable types) will be reflected there as well.
for
c
in
self
.
input_storage
:
if
c
.
required
and
not
c
.
provided
:
raise
TypeError
(
"Missing required input:
%
s"
%
getattr
(
self
.
inv_finder
[
c
],
'variable'
,
self
.
inv_finder
[
c
]))
if
c
.
provided
>
1
:
raise
TypeError
(
"Multiple values for input:
%
s"
%
getattr
(
self
.
inv_finder
[
c
],
'variable'
,
self
.
inv_finder
[
c
]))
if
c
.
implicit
and
c
.
provided
>
0
:
raise
TypeError
(
'Tried to provide value for implicit input:
%
s'
%
getattr
(
self
.
inv_finder
[
c
],
'variable'
,
self
.
inv_finder
[
c
]))
if
c
.
provided
==
0
and
c
.
copy_from_container
is
not
None
:
# Copy default value from another (non shared) container.
# Safety check, may be removed in the future.
assert
not
c
.
implicit
c
.
value
=
c
.
copy_from_container
.
value
# TODO Would it be better to use self[..] = value?
# Do the actual work
self
.
fn
()
...
...
@@ -377,12 +426,16 @@ class Function(object):
# Update the inputs that have an update function
for
input
,
storage
in
reversed
(
zip
(
self
.
maker
.
expanded_inputs
,
self
.
input_storage
)):
if
input
.
update
:
if
input
.
update
is
not
None
:
storage
.
data
=
outputs
.
pop
()
# Put default values back in the storage
for
i
,
(
required
,
refeed
,
value
)
in
enumerate
(
self
.
defaults
):
if
refeed
:
if
isinstance
(
value
,
gof
.
Container
):
value
=
value
.
storage
[
0
]
self
[
i
]
=
value
if
self
.
return_none
:
return
None
elif
self
.
unpack_single
and
len
(
outputs
)
==
1
:
...
...
@@ -643,12 +696,19 @@ class FunctionMaker(object):
# The following loop is to fill in the input_storage and _defaults lists.
for
(
input
,
indices
,
subinputs
),
default
in
zip
(
self
.
indices
,
defaults
):
# Replace any default value given as a variable by its container.
# Note that this makes sense only in the context of shared variables,
# but for now we avoid dealing directly with them to avoid dependency
# on the shared variables work-in-progress repository.
if
isinstance
(
default
,
gof
.
Variable
):
default
=
default
.
container
__default
=
default
if
isinstance
(
default
,
gof
.
Container
):
# If the default is a gof.Container
, this means we want to share
#
the same storage. This is done by appending default.storage
# to input_storage
if
isinstance
(
default
,
gof
.
Container
)
and
input
.
implicit
:
# If the default is a gof.Container
and it is an implicit
#
input, this means we want to share the same storage. This is
#
done by appending default.storage
to input_storage
if
indices
is
not
None
:
raise
TypeError
(
"Cannot take a Container instance as default for a SymbolicInputKit."
)
input_storage
.
append
(
default
.
storage
)
...
...
@@ -660,7 +720,8 @@ class FunctionMaker(object):
# of the kit's inputs are active in this graph, so we make as many
# storage units as needed
if
isinstance
(
default
,
(
list
,
tuple
))
\
and
all
(
isinstance
(
x
,
gof
.
Container
)
for
x
in
default
):
and
all
(
isinstance
(
x
,
gof
.
Container
)
for
x
in
default
)
\
and
input
.
implicit
:
if
len
(
default
)
==
len
(
indices
):
input_storage
+=
[
x
.
storage
for
x
in
default
]
elif
len
(
default
)
>
len
(
indices
):
...
...
@@ -695,7 +756,8 @@ class FunctionMaker(object):
# back into the storage as it would defeat the point of updating it. We
# always do this policy.
if
default
is
None
:
if
trustme
or
isinstance
(
__default
,
gof
.
Container
):
if
(
trustme
or
(
isinstance
(
__default
,
gof
.
Container
)
and
input
.
implicit
)):
_defaults
.
append
((
False
,
False
,
None
))
else
:
# This might catch some bugs early
...
...
@@ -704,7 +766,8 @@ class FunctionMaker(object):
_defaults
.
append
((
False
,
False
,
default
))
else
:
if
default
is
None
:
if
trustme
or
isinstance
(
__default
,
gof
.
Container
):
if
(
trustme
or
(
isinstance
(
__default
,
gof
.
Container
)
and
input
.
implicit
)):
_defaults
.
append
((
False
,
False
,
None
))
else
:
# No default, so this is a required input. Nothing to feed back, initial value is None.
...
...
@@ -809,6 +872,7 @@ def function(inputs, outputs, mode=None, accept_inplace = False):
"""
mode
=
mode
if
mode
is
not
None
else
mode_module
.
default_mode
inputs
=
map
(
convert_function_input
,
inputs
)
if
outputs
is
not
None
:
outputs
=
map
(
FunctionMaker
.
wrap_out
,
outputs
)
if
isinstance
(
outputs
,
(
list
,
tuple
))
else
FunctionMaker
.
wrap_out
(
outputs
)
...
...
@@ -824,6 +888,7 @@ def function(inputs, outputs, mode=None, accept_inplace = False):
else
:
#return a different kind of function
def
dup_defaults
():
# TODO This may need to be changed to use containers as defaults.
return
[
copy
.
copy
(
default
.
value
)
if
isinstance
(
default
,
gof
.
Container
)
else
copy
.
copy
(
default
)
for
default
in
defaults
]
...
...
theano/compile/io.py
浏览文件 @
5fc50232
"""Define `SymbolicInput`, `SymbolicOutput`, `In`, `Out` """
__docformat__
=
'restructuredtext en'
from
theano
import
gof
class
SymbolicInput
(
object
):
"""
Represents a symbolic input for use with function or FunctionMaker.
...
...
@@ -27,9 +29,15 @@ class SymbolicInput(object):
autoname: Bool (default: True)
See the name option.
implicit: Bool (default: False)
See help(In). Note that 'None' is not allowed here, since we are in the
symbolic case.
"""
def
__init__
(
self
,
variable
,
name
=
None
,
update
=
None
,
mutable
=
None
,
strict
=
False
,
autoname
=
True
):
def
__init__
(
self
,
variable
,
name
=
None
,
update
=
None
,
mutable
=
None
,
strict
=
False
,
autoname
=
True
,
implicit
=
False
):
assert
implicit
is
not
None
# Safety check.
self
.
variable
=
variable
self
.
name
=
variable
.
name
if
(
autoname
and
name
is
None
)
else
name
if
self
.
name
is
not
None
and
not
isinstance
(
self
.
name
,
str
):
...
...
@@ -37,6 +45,7 @@ class SymbolicInput(object):
self
.
update
=
update
self
.
mutable
=
mutable
if
(
mutable
is
not
None
)
else
(
update
is
not
None
)
self
.
strict
=
strict
self
.
implicit
=
implicit
def
__str__
(
self
):
if
self
.
update
:
...
...
@@ -136,10 +145,29 @@ class In(SymbolicInput):
autoname: Bool (default: True)
See the name option.
implicit: Bool or None (default: None)
True: This input is implicit in the sense that the user is not allowed
to provide a value for it. Requires 'value' to be set. Setting an
input as implicit allows Theano to directly share containers when
'value' is an existing container.
False: The user can provide a value for this input. In this case,
containers will not be shared (to avoid accidentally overwriting a
container's content with an input value provided by the user).
None: Automatically choose between True or False depending on the
situation. It will be set to False in all cases except if 'value'
is a container (so that it can be shared by default).
"""
def
__init__
(
self
,
variable
,
name
=
None
,
value
=
None
,
update
=
None
,
mutable
=
None
,
strict
=
False
,
autoname
=
True
):
super
(
In
,
self
)
.
__init__
(
variable
,
name
,
update
,
mutable
,
strict
,
autoname
)
def
__init__
(
self
,
variable
,
name
=
None
,
value
=
None
,
update
=
None
,
mutable
=
None
,
strict
=
False
,
autoname
=
True
,
implicit
=
None
):
if
implicit
is
None
:
implicit
=
isinstance
(
value
,
gof
.
Container
)
super
(
In
,
self
)
.
__init__
(
variable
,
name
,
update
,
mutable
,
strict
,
autoname
,
implicit
=
implicit
)
self
.
value
=
value
if
self
.
implicit
and
value
is
None
:
raise
TypeError
(
'An implicit input must be given a default value'
)
class
SymbolicOutput
(
object
):
...
...
theano/compile/module.py
浏览文件 @
5fc50232
...
...
@@ -405,7 +405,8 @@ class Method(Component):
variable
=
k
,
update
=
v
,
value
=
get_storage
(
k
,
not
allocate_all
)
.
value
,
mutable
=
True
)
mutable
=
True
,
implicit
=
True
)
inputs
.
append
(
input_k
)
else
:
raise
ValueError
((
'Variable listed in both inputs and updates.'
...
...
@@ -437,6 +438,13 @@ class Method(Component):
assert
storage
.
mutable
==
False
else
:
storage
=
get_storage
(
input
,
not
allocate_all
)
# Declare as an implicit input.
# TODO Note from OD: is this dangerous? (in case this storage
# is shared, and would sometimes need to be implicit, sometimes
# not).
storage
.
implicit
=
True
assert
type
(
storage
)
is
io
.
In
inputs
.
append
(
storage
)
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论