Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
P
pytensor
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
testgroup
pytensor
Commits
04c38218
提交
04c38218
authored
1月 23, 2013
作者:
Vivek Kulkarni
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Merging from LatestTheano
上级
0ae2dc70
隐藏空白字符变更
内嵌
并排
正在显示
2 个修改的文件
包含
212 行增加
和
203 行删除
+212
-203
basic.py
theano/sparse/basic.py
+20
-63
basic.py
theano/tensor/basic.py
+192
-140
没有找到文件。
theano/sparse/basic.py
浏览文件 @
04c38218
...
@@ -8,11 +8,9 @@ http://www-users.cs.umn.edu/~saad/software/SPARSKIT/paper.ps
...
@@ -8,11 +8,9 @@ http://www-users.cs.umn.edu/~saad/software/SPARSKIT/paper.ps
# Automatic methods for determining best sparse format?
# Automatic methods for determining best sparse format?
import
sys
import
sys
from
itertools
import
izip
import
numpy
import
numpy
import
theano
import
theano
import
scipy.sparse
import
scipy.sparse
from
theano
import
gof
,
tensor
,
compile
,
scalar
,
config
from
theano
import
gof
,
tensor
,
compile
,
scalar
,
config
from
theano.gof.python25
import
all
from
theano.gof.python25
import
all
from
theano.gradient
import
DisconnectedType
from
theano.gradient
import
DisconnectedType
...
@@ -21,13 +19,9 @@ import theano.tests.unittest_tools as utt
...
@@ -21,13 +19,9 @@ import theano.tests.unittest_tools as utt
from
theano.gradient
import
grad_not_implemented
from
theano.gradient
import
grad_not_implemented
from
theano.sparse.type
import
SparseType
,
_is_sparse
from
theano.sparse.type
import
SparseType
,
_is_sparse
#Column compressed (CSC)
#Row compressed (CSR)
sparse_formats
=
[
'csc'
,
'csr'
]
sparse_formats
=
[
'csc'
,
'csr'
]
#Register an optimization that does a specialization
#Does the same thing but better
# TODO: move this decorator to the compile submodule
# TODO: move this decorator to the compile submodule
def
register_specialize
(
lopt
,
*
tags
,
**
kwargs
):
def
register_specialize
(
lopt
,
*
tags
,
**
kwargs
):
compile
.
optdb
[
'specialize'
]
.
register
((
kwargs
and
kwargs
.
pop
(
'name'
))
or
compile
.
optdb
[
'specialize'
]
.
register
((
kwargs
and
kwargs
.
pop
(
'name'
))
or
...
@@ -1714,49 +1708,30 @@ class AddSD(gof.op.Op):
...
@@ -1714,49 +1708,30 @@ class AddSD(gof.op.Op):
:note: The grad implemented is structured on `x`.
:note: The grad implemented is structured on `x`.
"""
"""
#Constructor of the object
def
__init__
(
self
,
inplace
=
False
,
*
args
,
**
kwargs
):
def
__init__
(
self
,
inplace
=
False
,
*
args
,
**
kwargs
):
gof
.
Op
.
__init__
(
self
,
*
args
,
**
kwargs
)
gof
.
Op
.
__init__
(
self
,
*
args
,
**
kwargs
)
#Should we do inplace addition or not ?
#Should we do inplace addition or not ?
self
.
inplace
=
inplace
self
.
inplace
=
inplace
if
self
.
inplace
:
if
self
.
inplace
:
#This is a hint to the local optimizer that says that the first
self
.
destroy_map
=
{
0
:
[
3
]}
#output is the same as the 3rd input and no intermdiate storage
#needs to be allocated
self
.
destroy_map
=
{
0
:
[
3
]}
def
__eq__
(
self
,
other
):
def
__eq__
(
self
,
other
):
#Compare the inplace flag as well
return
(
type
(
self
)
==
type
(
other
))
and
self
.
inplace
==
other
.
inplace
return
(
type
(
self
)
==
type
(
other
))
and
self
.
inplace
==
other
.
inplace
def
__hash__
(
self
):
def
__hash__
(
self
):
#Now use the hash of inplace as well
return
hash
(
type
(
self
))
^
hash
(
self
.
inplace
)
return
hash
(
type
(
self
))
^
hash
(
self
.
inplace
)
def
__str__
(
self
):
def
__str__
(
self
):
#If we are running the inplace version, display that
# so that it is useful for debugging
if
self
.
inplace
:
if
self
.
inplace
:
return
self
.
__class__
.
__name__
+
'{inplace}'
return
self
.
__class__
.
__name__
+
'{inplace}'
return
self
.
__class__
.
__name__
return
self
.
__class__
.
__name__
# Op Contract implementation: make_node:
# Should return a Apply object that specifies what:
# 1. Input variables type are etc for the operation
# 2. What are the types of the output variables
# These should be Theano variables
def
make_node
(
self
,
x
,
y
):
def
make_node
(
self
,
x
,
y
):
# x is a sparse matrix, y is a dense one
# Wrap them around theano variables as this must be symbolic
x
,
y
=
as_sparse_variable
(
x
),
tensor
.
as_tensor_variable
(
y
)
x
,
y
=
as_sparse_variable
(
x
),
tensor
.
as_tensor_variable
(
y
)
# If the types of both variables are of different types
# this is bad as theres a type mismatch
if
x
.
type
.
dtype
!=
y
.
type
.
dtype
:
if
x
.
type
.
dtype
!=
y
.
type
.
dtype
:
raise
NotImplementedError
()
raise
NotImplementedError
()
#Obtains the indices, indpt, data of NNZ sparse matrix x
indices
,
indptr
,
data
=
csm_indices
(
x
),
csm_indptr
(
x
),
csm_data
(
x
)
indices
,
indptr
,
data
=
csm_indices
(
x
),
csm_indptr
(
x
),
csm_data
(
x
)
# We either use CSC or CSR depending on the format of input
# We either use CSC or CSR depending on the format of input
...
@@ -1771,10 +1746,10 @@ class AddSD(gof.op.Op):
...
@@ -1771,10 +1746,10 @@ class AddSD(gof.op.Op):
)
.
make_variable
()])
)
.
make_variable
()])
def
c_code
(
self
,
node
,
name
,
(
_data
,
_indices
,
_indptr
,
y
),
(
z
,
),
sub
):
def
c_code
(
self
,
node
,
name
,
(
_data
,
_indices
,
_indptr
,
y
),
(
z
,
),
sub
):
inplace
=
int
(
self
.
inplace
)
inplace
=
int
(
self
.
inplace
)
format
=
{
'csc'
:
0
,
'csr'
:
1
}[
self
.
format
]
format
=
{
'csc'
:
0
,
'csr'
:
1
}[
self
.
format
]
code
=
"""
code
=
"""
if(
%(z)
s) {Py_XDECREF(
%(z)
s);}
Py_XDECREF(
%(z)
s);
if (!
%(inplace)
s){
if (!
%(inplace)
s){
%(z)
s = (PyArrayObject *) PyArray_NewCopy(
%(y)
s, NPY_CORDER);
%(z)
s = (PyArrayObject *) PyArray_NewCopy(
%(y)
s, NPY_CORDER);
}else{
}else{
...
@@ -1811,44 +1786,26 @@ class AddSD(gof.op.Op):
...
@@ -1811,44 +1786,26 @@ class AddSD(gof.op.Op):
}
}
}
}
"""
%
dict
(
locals
(),
**
sub
)
"""
%
dict
(
locals
(),
**
sub
)
return
code
return
code
def
perform
(
self
,
node
,
(
data
,
indices
,
indptr
,
y
),
(
out
,
)):
def
perform
(
self
,
node
,
(
data
,
indices
,
indptr
,
y
),
(
out
,
)):
assert
_is_dense
(
y
)
assert
_is_dense
(
y
)
if
self
.
inplace
:
#inplace enabled
if
self
.
format
==
'csc'
:
#column compressed
if
self
.
format
==
'csr'
:
for
c
in
xrange
(
y
.
shape
[
1
]):
#Loop through each column
x
=
scipy
.
sparse
.
csr_matrix
((
data
,
indices
,
indptr
),
shape
=
y
.
shape
)
low
=
indptr
[
c
]
#indptr will pint to slice of indices array for column
elif
self
.
format
==
'csc'
:
high
=
indptr
[
c
+
1
]
x
=
scipy
.
sparse
.
csc_matrix
((
data
,
indices
,
indptr
),
shape
=
y
.
shape
)
for
ind
in
xrange
(
low
,
high
):
y
[(
indices
[
ind
],
c
)]
+=
data
[
ind
]
#Add that data element
# The asarray is needed as in some case, this return a
elif
self
.
format
==
'csr'
:
# numpy.matrixlib.defmatrix.matrix object and not an ndarray.
#Case for row's. Symmetric to what was done for columns
out
[
0
]
=
theano
.
_asarray
(
x
+
y
,
dtype
=
node
.
outputs
[
0
]
.
type
.
dtype
)
for
r
in
xrange
(
y
.
shape
[
0
]):
low
=
indptr
[
r
]
high
=
indptr
[
r
+
1
]
for
ind
in
xrange
(
low
,
high
):
y
[(
r
,
indices
[
ind
])]
+=
data
[
ind
]
out
[
0
]
=
y
#Output storage cell is y
else
:
#If in place is not enabled, create back the sparse matrix and
# and just add them normally.
if
self
.
format
==
'csr'
:
x
=
scipy
.
sparse
.
csr_matrix
(
(
data
,
indices
,
indptr
),
shape
=
y
.
shape
)
elif
self
.
format
==
'csc'
:
x
=
scipy
.
sparse
.
csc_matrix
(
(
data
,
indices
,
indptr
),
shape
=
y
.
shape
)
# The asarray is needed as in some case, this return a
# numpy.matrixlib.defmatrix.matrix object and not an ndarray.
out
[
0
]
=
theano
.
_asarray
(
x
+
y
,
dtype
=
node
.
outputs
[
0
]
.
type
.
dtype
)
def
grad
(
self
,
(
x
,
y
),
(
gz
,)):
def
grad
(
self
,
(
x
,
y
),
(
gz
,)):
assert
_is_sparse_variable
(
x
)
and
_is_dense_variable
(
y
)
assert
_is_sparse_variable
(
x
)
and
_is_dense_variable
(
y
)
assert
_is_dense_variable
(
gz
)
assert
_is_dense_variable
(
gz
)
return
sp_ones_like
(
x
)
*
gz
,
gz
return
sp_ones_like
(
x
)
*
gz
,
gz
def
infer_shape
(
self
,
node
,
shapes
):
def
infer_shape
(
self
,
node
,
shapes
):
#Shape of output is the shape of y
return
[
shapes
[
3
]]
return
[
shapes
[
3
]]
add_s_d
=
AddSD
()
add_s_d
=
AddSD
()
...
...
theano/tensor/basic.py
浏览文件 @
04c38218
...
@@ -7,8 +7,6 @@ import warnings
...
@@ -7,8 +7,6 @@ import warnings
from
itertools
import
izip
from
itertools
import
izip
import
numpy
import
numpy
from
numpy.lib.stride_tricks
import
as_strided
import
scipy.sparse
as
ssparse
#from copy import copy as python_copy
#from copy import copy as python_copy
import
theano
import
theano
...
@@ -465,70 +463,88 @@ def _allclose(a, b, rtol=None, atol=None):
...
@@ -465,70 +463,88 @@ def _allclose(a, b, rtol=None, atol=None):
return
numpy
.
allclose
(
a
,
b
,
atol
=
atol_
,
rtol
=
rtol_
)
return
numpy
.
allclose
(
a
,
b
,
atol
=
atol_
,
rtol
=
rtol_
)
class
Not
ConstantError
(
TypeError
):
class
Not
ScalarConstantError
(
Exception
):
"""
"""
Raised by get_constant_value if called on something that is
Raised by get_scalar_constant_value if called on something that is
not constant.
not a scalar constant.
For now it is a TypeError, to maintain the old interface
that get_constant_value should raise a TypeError in this
situation. However, this is unsafe because get_constant_value
could inadvertently raise a TypeError if it has a bug.
So we should eventually make NotConstantError derive
from Exception directly, and modify all code that uses
get_constant_value to catch this more specific exception.
"""
"""
pass
def
get_constant_value
(
v
):
class
EmptyConstantError
(
NotScalarConstantError
):
"""
Raised by get_scalar_const_value if called on something that is a
zero dimensional constant.
"""
def
get_scalar_constant_value
(
v
):
"""return the constant scalar(0-D) value underlying variable `v`
"""return the constant scalar(0-D) value underlying variable `v`
If v is the output of dimshuffles, fills, allocs, rebroadcasts, cast
If v is the output of dimshuffles, fills, allocs, rebroadcasts, cast
this function digs through them.
this function digs through them.
If `v` is not some view of constant
data, then raise a Not
ConstantError.
If `v` is not some view of constant
scalar data, then raise a NotScalar
ConstantError.
:note: There may be another function similar to this one in the
:note: There may be another function similar to this one in the
code, but I'm not sure where it is.
code, but I'm not sure where it is.
"""
"""
if
isinstance
(
v
,
Constant
):
if
v
is
None
:
if
getattr
(
v
.
tag
,
'unique_value'
,
None
)
is
not
None
:
# None is not a scalar (and many uses of this function seem to depend
data
=
v
.
tag
.
unique_value
# on passing it None)
else
:
raise
NotScalarConstantError
()
data
=
v
.
data
if
isinstance
(
v
,
(
int
,
float
)):
return
numpy
.
asarray
(
v
)
def
numpy_scalar
(
n
):
""" Return a scalar stored in a numpy ndarray, or raise
NotScalarConstantError if the numpy ndarray is not a scalar
"""
# handle case where data is numpy.array([])
# handle case where data is numpy.array([])
if
hasattr
(
data
,
'shape'
)
and
len
(
data
.
shape
)
==
0
or
\
if
data
.
ndim
>
0
and
(
len
(
data
.
shape
)
==
0
or
__builtins__
[
'max'
](
data
.
shape
)
==
0
:
__builtins__
[
'max'
](
data
.
shape
)
==
0
)
:
assert
numpy
.
all
(
numpy
.
array
([])
==
data
)
assert
numpy
.
all
(
numpy
.
array
([])
==
data
)
r
eturn
data
r
aise
EmptyConstantError
()
try
:
try
:
numpy
.
complex
(
data
)
# works for all numeric scalars
numpy
.
complex
(
data
)
# works for all numeric scalars
return
data
return
data
except
Exception
:
except
Exception
:
raise
NotConstantError
(
raise
Not
Scalar
ConstantError
(
'v.data is non-numeric, non-scalar, or has more than one'
'v.data is non-numeric, non-scalar, or has more than one'
' unique value'
,
v
)
' unique value'
,
n
)
if
isinstance
(
v
,
numpy
.
ndarray
):
return
numpy_scalar
(
v
)
if
isinstance
(
v
,
Constant
):
if
getattr
(
v
.
tag
,
'unique_value'
,
None
)
is
not
None
:
data
=
v
.
tag
.
unique_value
else
:
data
=
v
.
data
return
numpy_scalar
(
data
)
if
v
.
owner
:
if
v
.
owner
:
if
isinstance
(
v
.
owner
.
op
,
Alloc
):
if
isinstance
(
v
.
owner
.
op
,
Alloc
):
return
get_constant_value
(
v
.
owner
.
inputs
[
0
])
return
get_
scalar_
constant_value
(
v
.
owner
.
inputs
[
0
])
if
isinstance
(
v
.
owner
.
op
,
DimShuffle
):
if
isinstance
(
v
.
owner
.
op
,
DimShuffle
):
return
get_constant_value
(
v
.
owner
.
inputs
[
0
])
return
get_
scalar_
constant_value
(
v
.
owner
.
inputs
[
0
])
if
isinstance
(
v
.
owner
.
op
,
Rebroadcast
):
if
isinstance
(
v
.
owner
.
op
,
Rebroadcast
):
return
get_constant_value
(
v
.
owner
.
inputs
[
0
])
return
get_
scalar_
constant_value
(
v
.
owner
.
inputs
[
0
])
if
isinstance
(
v
.
owner
.
op
,
Elemwise
)
and
\
if
isinstance
(
v
.
owner
.
op
,
Elemwise
)
and
\
isinstance
(
v
.
owner
.
op
.
scalar_op
,
scal
.
Second
):
isinstance
(
v
.
owner
.
op
.
scalar_op
,
scal
.
Second
):
shape
,
val
=
v
.
owner
.
inputs
shape
,
val
=
v
.
owner
.
inputs
return
get_constant_value
(
val
)
return
get_
scalar_
constant_value
(
val
)
if
isinstance
(
v
.
owner
.
op
,
scal
.
Second
):
if
isinstance
(
v
.
owner
.
op
,
scal
.
Second
):
x
,
y
=
v
.
owner
.
inputs
x
,
y
=
v
.
owner
.
inputs
return
get_constant_value
(
y
)
return
get_
scalar_
constant_value
(
y
)
# Don't act as the constant_folding optimization here as this
# Don't act as the constant_folding optimization here as this
# fct is used too early in the optimization phase. This would
# fct is used too early in the optimization phase. This would
# mess with the stabilization optimization.
# mess with the stabilization optimization.
if
(
isinstance
(
v
.
owner
.
op
,
Elemwise
)
and
isinstance
(
if
(
isinstance
(
v
.
owner
.
op
,
Elemwise
)
and
isinstance
(
v
.
owner
.
op
.
scalar_op
,
scal
.
Cast
))
or
\
v
.
owner
.
op
.
scalar_op
,
scal
.
Cast
))
or
\
isinstance
(
v
.
owner
.
op
,
scal
.
Cast
):
isinstance
(
v
.
owner
.
op
,
scal
.
Cast
):
const
=
get_constant_value
(
v
.
owner
.
inputs
[
0
])
const
=
get_
scalar_
constant_value
(
v
.
owner
.
inputs
[
0
])
ret
=
[[
None
]]
ret
=
[[
None
]]
v
.
owner
.
op
.
perform
(
v
.
owner
,
[
const
],
ret
)
v
.
owner
.
op
.
perform
(
v
.
owner
,
[
const
],
ret
)
return
ret
[
0
][
0
]
return
ret
[
0
][
0
]
...
@@ -565,7 +581,7 @@ def get_constant_value(v):
...
@@ -565,7 +581,7 @@ def get_constant_value(v):
# axis.
# axis.
ret
=
v
.
owner
.
inputs
[
0
]
.
owner
.
inputs
[
ret
=
v
.
owner
.
inputs
[
0
]
.
owner
.
inputs
[
v
.
owner
.
op
.
idx_list
[
0
]
+
1
]
v
.
owner
.
op
.
idx_list
[
0
]
+
1
]
ret
=
get_constant_value
(
ret
)
ret
=
get_
scalar_
constant_value
(
ret
)
# join can cast implicitly its input in some case.
# join can cast implicitly its input in some case.
return
theano
.
_asarray
(
ret
,
dtype
=
v
.
type
.
dtype
)
return
theano
.
_asarray
(
ret
,
dtype
=
v
.
type
.
dtype
)
if
(
v
.
owner
.
inputs
[
0
]
.
owner
and
if
(
v
.
owner
.
inputs
[
0
]
.
owner
and
...
@@ -578,7 +594,7 @@ def get_constant_value(v):
...
@@ -578,7 +594,7 @@ def get_constant_value(v):
len
(
v
.
owner
.
op
.
idx_list
)
==
1
):
len
(
v
.
owner
.
op
.
idx_list
)
==
1
):
ret
=
v
.
owner
.
inputs
[
0
]
.
owner
.
inputs
[
v
.
owner
.
op
.
idx_list
[
0
]]
ret
=
v
.
owner
.
inputs
[
0
]
.
owner
.
inputs
[
v
.
owner
.
op
.
idx_list
[
0
]]
ret
=
get_constant_value
(
ret
)
ret
=
get_
scalar_
constant_value
(
ret
)
# MakeVector can cast implicitly its input in some case.
# MakeVector can cast implicitly its input in some case.
return
theano
.
_asarray
(
ret
,
dtype
=
v
.
type
.
dtype
)
return
theano
.
_asarray
(
ret
,
dtype
=
v
.
type
.
dtype
)
...
@@ -591,7 +607,7 @@ def get_constant_value(v):
...
@@ -591,7 +607,7 @@ def get_constant_value(v):
v
.
owner
.
op
.
idx_list
[
0
]]:
v
.
owner
.
op
.
idx_list
[
0
]]:
return
numpy
.
asarray
(
1
)
return
numpy
.
asarray
(
1
)
raise
Type
Error
(
v
)
raise
NotScalarConstant
Error
(
v
)
class
TensorType
(
Type
):
class
TensorType
(
Type
):
...
@@ -738,7 +754,7 @@ class TensorType(Type):
...
@@ -738,7 +754,7 @@ class TensorType(Type):
except
AttributeError
:
except
AttributeError
:
msg
=
""
msg
=
""
raise
TypeError
(
"The numpy.ndarray object is not aligned."
raise
TypeError
(
"The numpy.ndarray object is not aligned."
" Theano
c code do
not support that."
,
" Theano
C code does
not support that."
,
msg
,
msg
,
"object shape"
,
data
.
shape
,
"object shape"
,
data
.
shape
,
"object strides"
,
data
.
strides
)
"object strides"
,
data
.
strides
)
...
@@ -1445,7 +1461,7 @@ class _tensor_py_operators:
...
@@ -1445,7 +1461,7 @@ class _tensor_py_operators:
def
__sub__
(
self
,
other
):
def
__sub__
(
self
,
other
):
# See explanation in __add__ for the error catched
# See explanation in __add__ for the error catched
# a
dn
the return value in that case
# a
nd
the return value in that case
try
:
try
:
return
sub
(
self
,
other
)
return
sub
(
self
,
other
)
except
(
NotImplementedError
,
TypeError
):
except
(
NotImplementedError
,
TypeError
):
...
@@ -1453,7 +1469,7 @@ class _tensor_py_operators:
...
@@ -1453,7 +1469,7 @@ class _tensor_py_operators:
def
__mul__
(
self
,
other
):
def
__mul__
(
self
,
other
):
# See explanation in __add__ for the error catched
# See explanation in __add__ for the error catched
# a
dn
the return value in that case
# a
nd
the return value in that case
try
:
try
:
return
mul
(
self
,
other
)
return
mul
(
self
,
other
)
except
(
NotImplementedError
,
TypeError
):
except
(
NotImplementedError
,
TypeError
):
...
@@ -1461,7 +1477,7 @@ class _tensor_py_operators:
...
@@ -1461,7 +1477,7 @@ class _tensor_py_operators:
def
__div__
(
self
,
other
):
def
__div__
(
self
,
other
):
# See explanation in __add__ for the error catched
# See explanation in __add__ for the error catched
# a
dn
the return value in that case
# a
nd
the return value in that case
try
:
try
:
return
div_proxy
(
self
,
other
)
return
div_proxy
(
self
,
other
)
except
IntegerDivisionError
:
except
IntegerDivisionError
:
...
@@ -1664,21 +1680,29 @@ class _tensor_py_operators:
...
@@ -1664,21 +1680,29 @@ class _tensor_py_operators:
# standard indexing is used; if it fails with
# standard indexing is used; if it fails with
# AdvancedIndexingError, advanced indexing
# AdvancedIndexingError, advanced indexing
advanced
=
False
advanced
=
False
for
arg
in
args
:
axis
=
None
for
i
,
arg
in
enumerate
(
args
):
try
:
try
:
arg
==
numpy
.
newaxis
or
Subtensor
.
convert
(
arg
)
arg
==
numpy
.
newaxis
or
Subtensor
.
convert
(
arg
)
except
AdvancedIndexingError
:
except
AdvancedIndexingError
:
advanced
=
True
if
advanced
:
break
axis
=
None
break
else
:
advanced
=
True
axis
=
i
if
advanced
:
if
advanced
:
if
(
len
(
args
)
==
1
if
(
axis
is
not
None
and
isinstance
(
args
[
0
],
(
and
numpy
.
all
(
a
==
slice
(
None
)
for
a
in
args
[:
axis
])
and
numpy
.
all
(
a
==
slice
(
None
)
for
a
in
args
[
axis
+
1
:])
and
isinstance
(
args
[
axis
],
(
numpy
.
ndarray
,
list
,
list
,
TensorVariable
,
TensorVariable
,
TensorConstant
,
TensorConstant
,
theano
.
tensor
.
sharedvar
.
TensorSharedVariable
))):
theano
.
tensor
.
sharedvar
.
TensorSharedVariable
))):
return
advanced_subtensor1
(
self
,
*
arg
s
)
return
self
.
take
(
arg
,
axi
s
)
else
:
else
:
return
AdvancedSubtensor
()(
self
,
*
args
)
return
AdvancedSubtensor
()(
self
,
*
args
)
else
:
else
:
...
@@ -1707,6 +1731,9 @@ class _tensor_py_operators:
...
@@ -1707,6 +1731,9 @@ class _tensor_py_operators:
return
Subtensor
(
args
)(
self
,
*
Subtensor
.
collapse
(
args
,
return
Subtensor
(
args
)(
self
,
*
Subtensor
.
collapse
(
args
,
lambda
entry
:
isinstance
(
entry
,
Variable
)))
lambda
entry
:
isinstance
(
entry
,
Variable
)))
def
take
(
self
,
indices
,
axis
=
None
,
mode
=
'raise'
):
return
take
(
self
,
indices
,
axis
,
mode
)
# COPYING
# COPYING
def
copy
(
self
):
def
copy
(
self
):
return
tensor_copy
(
self
)
return
tensor_copy
(
self
)
...
@@ -1742,7 +1769,7 @@ class _tensor_py_operators:
...
@@ -1742,7 +1769,7 @@ class _tensor_py_operators:
return
dot
(
left
,
right
)
return
dot
(
left
,
right
)
dot
=
__dot__
dot
=
__dot__
def
sum
(
self
,
axis
=
None
,
dtype
=
None
,
keepdims
=
False
):
def
sum
(
self
,
axis
=
None
,
dtype
=
None
,
keepdims
=
False
):
"""See `theano.tensor.sum`"""
"""See `theano.tensor.sum`"""
return
sum
(
self
,
axis
=
axis
,
dtype
=
dtype
,
keepdims
=
keepdims
)
return
sum
(
self
,
axis
=
axis
,
dtype
=
dtype
,
keepdims
=
keepdims
)
...
@@ -1787,11 +1814,16 @@ class _tensor_py_operators:
...
@@ -1787,11 +1814,16 @@ class _tensor_py_operators:
"""See `theano.tensor.argmax`"""
"""See `theano.tensor.argmax`"""
return
argmax
(
self
,
axis
,
keepdims
=
keepdims
)
return
argmax
(
self
,
axis
,
keepdims
=
keepdims
)
def
sort
(
self
,
axis
=-
1
,
kind
=
'quicksort'
,
order
=
None
):
"""See `theano.tensor.sort`"""
from
theano.tensor.sort
import
sort
return
sort
(
self
,
axis
,
kind
,
order
)
def
argsort
(
self
,
axis
=-
1
,
kind
=
'quicksort'
,
order
=
None
):
def
argsort
(
self
,
axis
=-
1
,
kind
=
'quicksort'
,
order
=
None
):
"""See `theano.tensor.
sort.
argsort`"""
"""See `theano.tensor.argsort`"""
from
theano.tensor.sort
import
argsort
from
theano.tensor.sort
import
argsort
return
argsort
(
self
,
axis
,
kind
,
order
)
return
argsort
(
self
,
axis
,
kind
,
order
)
def
clip
(
self
,
a_min
,
a_max
):
def
clip
(
self
,
a_min
,
a_max
):
"Clip (limit) the values in an array."
"Clip (limit) the values in an array."
return
clip
(
self
,
a_min
,
a_max
)
return
clip
(
self
,
a_min
,
a_max
)
...
@@ -1801,7 +1833,7 @@ class _tensor_py_operators:
...
@@ -1801,7 +1833,7 @@ class _tensor_py_operators:
return
conj
(
self
)
return
conj
(
self
)
conjugate
=
conj
conjugate
=
conj
def
repeat
(
self
,
repeats
,
axis
=
None
):
def
repeat
(
self
,
repeats
,
axis
=
None
):
"""See `theano.tensor.repeat`"""
"""See `theano.tensor.repeat`"""
from
theano.tensor.extra_ops
import
repeat
from
theano.tensor.extra_ops
import
repeat
...
@@ -1818,8 +1850,8 @@ class _tensor_py_operators:
...
@@ -1818,8 +1850,8 @@ class _tensor_py_operators:
# TO TRUMP NUMPY OPERATORS
# TO TRUMP NUMPY OPERATORS
__array_priority__
=
1000
__array_priority__
=
1000
def
get_constant_value
(
self
):
def
get_
scalar_
constant_value
(
self
):
return
get_constant_value
(
self
)
return
get_
scalar_
constant_value
(
self
)
def
zeros_like
(
model
):
def
zeros_like
(
model
):
return
zeros_like
(
model
)
return
zeros_like
(
model
)
...
@@ -2347,10 +2379,10 @@ class SpecifyShape(Op):
...
@@ -2347,10 +2379,10 @@ class SpecifyShape(Op):
new_shape
=
[]
new_shape
=
[]
for
dim
in
xrange
(
node
.
inputs
[
0
]
.
ndim
):
for
dim
in
xrange
(
node
.
inputs
[
0
]
.
ndim
):
try
:
try
:
s
=
get_constant_value
(
node
.
inputs
[
1
][
dim
])
s
=
get_
scalar_
constant_value
(
node
.
inputs
[
1
][
dim
])
s
=
as_tensor_variable
(
s
)
s
=
as_tensor_variable
(
s
)
new_shape
.
append
(
s
)
new_shape
.
append
(
s
)
except
Type
Error
:
except
NotScalarConstant
Error
:
new_shape
.
append
(
node
.
inputs
[
1
][
dim
])
new_shape
.
append
(
node
.
inputs
[
1
][
dim
])
assert
len
(
new_shape
)
==
len
(
xshape
)
assert
len
(
new_shape
)
==
len
(
xshape
)
...
@@ -2379,8 +2411,8 @@ class SpecifyShape(Op):
...
@@ -2379,8 +2411,8 @@ class SpecifyShape(Op):
def
c_code
(
self
,
node
,
nodename
,
inp
,
out
,
sub
):
def
c_code
(
self
,
node
,
nodename
,
inp
,
out
,
sub
):
if
not
isinstance
(
node
.
inputs
[
0
],
TensorVariable
):
if
not
isinstance
(
node
.
inputs
[
0
],
TensorVariable
):
# The
c code bellow support
only Tensor. super.c_code
# The
C code below supports
only Tensor. super.c_code
# will raise an exception to tell that there is
n't c
code
# will raise an exception to tell that there is
no C
code
# for the other cases.
# for the other cases.
return
super
(
SpecifyShape
,
self
)
.
c_code
(
node
,
nodename
,
return
super
(
SpecifyShape
,
self
)
.
c_code
(
node
,
nodename
,
inp
,
out
,
sub
)
inp
,
out
,
sub
)
...
@@ -2391,8 +2423,8 @@ class SpecifyShape(Op):
...
@@ -2391,8 +2423,8 @@ class SpecifyShape(Op):
return
"""
return
"""
if (PyArray_NDIM(
%(iname)
s) != PyArray_DIMS(
%(shape)
s)[0]) {
if (PyArray_NDIM(
%(iname)
s) != PyArray_DIMS(
%(shape)
s)[0]) {
PyErr_Format(PyExc_AssertionError,
PyErr_Format(PyExc_AssertionError,
"SpecifyShape: vector of shape ha
ve
%%
d element
,"
"SpecifyShape: vector of shape ha
s
%%
d elements
,"
" but the input ha
ve
%%
d dimensions.",
" but the input ha
s
%%
d dimensions.",
PyArray_NDIM(
%(iname)
s),
PyArray_NDIM(
%(iname)
s),
PyArray_DIMS(
%(shape)
s)[0]);
PyArray_DIMS(
%(shape)
s)[0]);
%(fail)
s;
%(fail)
s;
...
@@ -2402,7 +2434,7 @@ class SpecifyShape(Op):
...
@@ -2402,7 +2434,7 @@ class SpecifyShape(Op):
i))[0];
i))[0];
if (PyArray_DIMS(
%(iname)
s)[i] != shp) {
if (PyArray_DIMS(
%(iname)
s)[i] != shp) {
PyErr_Format(PyExc_AssertionError,
PyErr_Format(PyExc_AssertionError,
"SpecifyShape: dim
%%
d of input ha
ve
shape
%%
d,"
"SpecifyShape: dim
%%
d of input ha
s
shape
%%
d,"
" expected
%%
d.",
" expected
%%
d.",
i, PyArray_DIMS(
%(iname)
s)[i],
i, PyArray_DIMS(
%(iname)
s)[i],
shp);
shp);
...
@@ -2642,14 +2674,22 @@ def max(x, axis=None, keepdims=False):
...
@@ -2642,14 +2674,22 @@ def max(x, axis=None, keepdims=False):
:note: we return an error as numpy when we reduce a dim with a shape of 0
:note: we return an error as numpy when we reduce a dim with a shape of 0
"""
"""
if
isinstance
(
axis
,
(
list
,
tuple
))
and
len
(
axis
)
>
1
:
# We have a choice of implementing this call with the
# CAReduce op or the MaxAndArgmax op.
# MaxAndArgmax supports grad and Rop, so we prefer to use that.
# CAReduce is faster, but optimizations will replace MaxAndArgmax[0]
# with CAReduce at compile time, so at this stage the important
# thing is supporting all user interface features, not speed.
# Some cases can be implemented only with CAReduce.
# We thus prefer to use MaxAndArgmax, if possible. It does not
# support all axis arguments, so we may need to fall back to CAReduce.
try
:
out
=
max_and_argmax
(
x
,
axis
)[
0
]
except
Exception
:
out
=
CAReduce
(
scal
.
maximum
,
axis
)(
x
)
out
=
CAReduce
(
scal
.
maximum
,
axis
)(
x
)
else
:
try
:
const
=
get_constant_value
(
axis
)
out
=
CAReduce
(
scal
.
maximum
,
list
(
const
))(
x
)
except
Exception
:
out
=
max_and_argmax
(
x
,
axis
)[
0
]
if
keepdims
:
if
keepdims
:
out
=
makeKeepDims
(
x
,
out
,
axis
)
out
=
makeKeepDims
(
x
,
out
,
axis
)
...
@@ -3257,8 +3297,8 @@ class Alloc(gof.Op):
...
@@ -3257,8 +3297,8 @@ class Alloc(gof.Op):
(
i
,
s_as_str
))
(
i
,
s_as_str
))
# if s is constant 1, then we're broadcastable in that dim
# if s is constant 1, then we're broadcastable in that dim
try
:
try
:
const_shp
=
get_constant_value
(
s
)
const_shp
=
get_
scalar_
constant_value
(
s
)
except
Type
Error
:
except
NotScalarConstant
Error
:
const_shp
=
None
const_shp
=
None
bcast
.
append
(
numpy
.
all
(
1
==
const_shp
))
bcast
.
append
(
numpy
.
all
(
1
==
const_shp
))
otype
=
TensorType
(
dtype
=
v
.
dtype
,
broadcastable
=
bcast
)
otype
=
TensorType
(
dtype
=
v
.
dtype
,
broadcastable
=
bcast
)
...
@@ -3372,6 +3412,10 @@ class Alloc(gof.Op):
...
@@ -3372,6 +3412,10 @@ class Alloc(gof.Op):
return
self
.
make_node
(
eval_points
[
0
],
*
inputs
[
1
:])
.
outputs
return
self
.
make_node
(
eval_points
[
0
],
*
inputs
[
1
:])
.
outputs
def
do_constant_folding
(
self
,
node
):
def
do_constant_folding
(
self
,
node
):
if
not
getattr
(
node
.
outputs
[
0
],
'clients'
,
[]):
# If there are no clients then there is no point doing constant
# folding.
return
False
for
client
in
node
.
outputs
[
0
]
.
clients
:
for
client
in
node
.
outputs
[
0
]
.
clients
:
if
client
[
0
]
==
'output'
:
if
client
[
0
]
==
'output'
:
# If the output is a constant, it will have to be deepcopied
# If the output is a constant, it will have to be deepcopied
...
@@ -3793,16 +3837,16 @@ def get_idx_list(inputs, idx_list):
...
@@ -3793,16 +3837,16 @@ def get_idx_list(inputs, idx_list):
def
extract_constant
(
x
):
def
extract_constant
(
x
):
'''
'''
This function is basically a call to tensor.get_constant_value. The
This function is basically a call to tensor.get_
scalar_
constant_value. The
main difference is the behaviour in case of failure. While
main difference is the behaviour in case of failure. While
get_constant_value raises an TypeError, this function returns x,
get_
scalar_
constant_value raises an TypeError, this function returns x,
as a tensor if possible. If x is a ScalarVariable from a
as a tensor if possible. If x is a ScalarVariable from a
scalar_from_tensor, we remove the conversion. If x is just a
scalar_from_tensor, we remove the conversion. If x is just a
ScalarVariable, we convert it to a tensor with tensor_from_scalar.
ScalarVariable, we convert it to a tensor with tensor_from_scalar.
'''
'''
try
:
try
:
x
=
get_constant_value
(
x
)
x
=
get_
scalar_
constant_value
(
x
)
except
Exception
:
except
NotScalarConstantError
:
pass
pass
if
(
isinstance
(
x
,
scal
.
ScalarVariable
)
or
if
(
isinstance
(
x
,
scal
.
ScalarVariable
)
or
isinstance
(
x
,
scal
.
sharedvar
.
ScalarSharedVariable
)):
isinstance
(
x
,
scal
.
sharedvar
.
ScalarSharedVariable
)):
...
@@ -4953,9 +4997,10 @@ class IncSubtensor(Op):
...
@@ -4953,9 +4997,10 @@ class IncSubtensor(Op):
def
copy_of_x
(
self
,
x
):
def
copy_of_x
(
self
,
x
):
"""
"""
x: a string giving the name of a C variable pointing to an array
:param x: a string giving the name of a C variable
pointing to an array
Returns C code expression to make a copy of x.
:return: C code expression to make a copy of x
Base class uses PyArrayObject *, subclasses may override for
Base class uses PyArrayObject *, subclasses may override for
different types of arrays.
different types of arrays.
...
@@ -4973,9 +5018,9 @@ class IncSubtensor(Op):
...
@@ -4973,9 +5018,9 @@ class IncSubtensor(Op):
def
make_view_array
(
self
,
x
,
view_ndim
):
def
make_view_array
(
self
,
x
,
view_ndim
):
"""
"""
x: a string identifying an array to be viewed
:param
x: a string identifying an array to be viewed
view_ndim: a string specifying the number of dimensions
:param
view_ndim: a string specifying the number of dimensions
to have in the view
to have in the view
This doesn't need to actually set up the view with the
This doesn't need to actually set up the view with the
right indexing; we'll do that manually later.
right indexing; we'll do that manually later.
...
@@ -5400,11 +5445,11 @@ class Join(Op):
...
@@ -5400,11 +5445,11 @@ class Join(Op):
# Axis can also be a constant
# Axis can also be a constant
if
not
isinstance
(
axis
,
int
):
if
not
isinstance
(
axis
,
int
):
try
:
try
:
# Note : `get_constant_value` returns a ndarray not a
# Note : `get_
scalar_
constant_value` returns a ndarray not a
# int
# int
axis
=
int
(
get_constant_value
(
axis
))
axis
=
int
(
get_
scalar_
constant_value
(
axis
))
except
Type
Error
:
except
NotScalarConstant
Error
:
pass
pass
if
isinstance
(
axis
,
int
):
if
isinstance
(
axis
,
int
):
# Basically, broadcastable -> length 1, but the
# Basically, broadcastable -> length 1, but the
...
@@ -5771,9 +5816,9 @@ class Reshape(Op):
...
@@ -5771,9 +5816,9 @@ class Reshape(Op):
# Try to see if we can infer that y has a constant value of 1.
# Try to see if we can infer that y has a constant value of 1.
# If so, that dimension should be broadcastable.
# If so, that dimension should be broadcastable.
try
:
try
:
bcasts
[
index
]
=
(
hasattr
(
y
,
'get_constant_value'
)
and
bcasts
[
index
]
=
(
hasattr
(
y
,
'get_
scalar_
constant_value'
)
and
y
.
get_constant_value
()
==
1
)
y
.
get_
scalar_
constant_value
()
==
1
)
except
Type
Error
:
except
NotScalarConstant
Error
:
pass
pass
return
gof
.
Apply
(
self
,
[
x
,
shp
],
[
tensor
(
x
.
type
.
dtype
,
bcasts
)])
return
gof
.
Apply
(
self
,
[
x
,
shp
],
[
tensor
(
x
.
type
.
dtype
,
bcasts
)])
...
@@ -5846,10 +5891,10 @@ class Reshape(Op):
...
@@ -5846,10 +5891,10 @@ class Reshape(Op):
for
i
in
xrange
(
self
.
ndim
):
for
i
in
xrange
(
self
.
ndim
):
default_os_i
=
theano
.
tensor
.
opt
.
Shape_i
(
i
)(
node
.
outputs
[
0
])
default_os_i
=
theano
.
tensor
.
opt
.
Shape_i
(
i
)(
node
.
outputs
[
0
])
try
:
try
:
os_i
=
get_constant_value
(
node
.
inputs
[
1
][
i
])
.
item
()
os_i
=
get_
scalar_
constant_value
(
node
.
inputs
[
1
][
i
])
.
item
()
if
os_i
==
-
1
:
if
os_i
==
-
1
:
os_i
=
default_os_i
os_i
=
default_os_i
except
Type
Error
:
except
NotScalarConstant
Error
:
os_i
=
default_os_i
os_i
=
default_os_i
oshape
.
append
(
os_i
)
oshape
.
append
(
os_i
)
return
[
tuple
(
oshape
)]
return
[
tuple
(
oshape
)]
...
@@ -6129,9 +6174,9 @@ class ARange(Op):
...
@@ -6129,9 +6174,9 @@ class ARange(Op):
def
is_constant_value
(
var
,
value
):
def
is_constant_value
(
var
,
value
):
try
:
try
:
v
=
get_constant_value
(
var
)
v
=
get_
scalar_
constant_value
(
var
)
return
numpy
.
all
(
v
==
value
)
return
numpy
.
all
(
v
==
value
)
except
Exception
:
except
NotScalarConstantError
:
pass
pass
return
False
return
False
...
@@ -6475,13 +6520,10 @@ class AdvancedSubtensor1(Op):
...
@@ -6475,13 +6520,10 @@ class AdvancedSubtensor1(Op):
return
rval
return
rval
def
grad
(
self
,
inputs
,
grads
):
def
grad
(
self
,
inputs
,
grads
):
gz
,
=
grads
gz
,
=
grads
assert
len
(
inputs
)
==
2
assert
len
(
inputs
)
==
2
# rval1 = [advanced_inc_subtensor1(zeros_like(inputs[0]), gz, inputs[1])]
#Construct a sparse matrix to boost performance of gradient
rval1
=
[
ConstructSparse
()(
inputs
[
0
],
gz
,
inputs
[
1
])]
rval1
=
[
ConstructSparse
()(
inputs
[
0
],
gz
,
inputs
[
1
])]
return
rval1
+
[
DisconnectedType
()()]
*
(
len
(
inputs
)
-
1
)
return
rval1
+
[
DisconnectedType
()()]
*
(
len
(
inputs
)
-
1
)
def
R_op
(
self
,
inputs
,
eval_points
):
def
R_op
(
self
,
inputs
,
eval_points
):
...
@@ -6493,8 +6535,9 @@ class AdvancedSubtensor1(Op):
...
@@ -6493,8 +6535,9 @@ class AdvancedSubtensor1(Op):
x
,
ilist
=
ishapes
x
,
ilist
=
ishapes
return
[
ilist
+
x
[
1
:]]
return
[
ilist
+
x
[
1
:]]
class
ConstructSparse
(
Op
):
class
ConstructSparse
(
Op
):
"""Construct
a sparse CSC
matrix out of a list of 2-D matrix rows"""
"""Construct
s a sparse
matrix out of a list of 2-D matrix rows"""
def
__hash__
(
self
):
def
__hash__
(
self
):
return
hash
((
type
(
self
)))
return
hash
((
type
(
self
)))
...
@@ -6505,18 +6548,7 @@ class ConstructSparse(Op):
...
@@ -6505,18 +6548,7 @@ class ConstructSparse(Op):
def
__str__
(
self
):
def
__str__
(
self
):
return
self
.
__class__
.
__name__
return
self
.
__class__
.
__name__
# self: this object
# x: x is a dense matrix
# y: y is a dense matrix (small) which has data
# ilist is the list of rows to which we want to copy rows of y into x
# Output must be a sparse representation of x
def
make_node
(
self
,
x
,
y
,
ilist
):
def
make_node
(
self
,
x
,
y
,
ilist
):
#Convert to a sparse matrix, the shape is what is needed
x_sparse
=
ssparse
.
csc_matrix
(
tuple
(
x
.
shape
.
eval
()),
dtype
=
x
.
dtype
)
# Wrap into a Theano variable
x__
=
theano
.
sparse
.
as_sparse_variable
(
x_sparse
)
x_
=
as_tensor_variable
(
x
)
x_
=
as_tensor_variable
(
x
)
y_
=
as_tensor_variable
(
y
)
y_
=
as_tensor_variable
(
y
)
ilist_
=
as_tensor_variable
(
ilist
)
ilist_
=
as_tensor_variable
(
ilist
)
...
@@ -6528,52 +6560,34 @@ class ConstructSparse(Op):
...
@@ -6528,52 +6560,34 @@ class ConstructSparse(Op):
if
x_
.
type
.
ndim
==
0
:
if
x_
.
type
.
ndim
==
0
:
raise
TypeError
(
'cannot index into a scalar'
)
raise
TypeError
(
'cannot index into a scalar'
)
if
y_
.
type
.
ndim
>
x_
.
type
.
ndim
:
if
y_
.
type
.
ndim
>
x_
.
type
.
ndim
:
if
self
.
set_instead_of_inc
:
raise
TypeError
(
'cannot construct sparse matrix as dimensions differ'
)
opname
=
'set'
return
Apply
(
self
,
[
x_
,
y_
,
ilist_
],
[
theano
.
sparse
.
csc_matrix
(
dtype
=
x
.
dtype
)])
else
:
opname
=
'increment'
raise
TypeError
(
'cannot
%
s x subtensor with ndim=
%
s'
' by y with ndim=
%
s to x subtensor with ndim=
%
s '
%
(
opname
,
x_
.
type
.
ndim
,
y_
.
type
.
ndim
))
# Return the Apply instance
return
Apply
(
self
,
[
x_
,
y_
,
ilist_
],
[
x__
.
type
()])
# Inp: Will contain x, values: that is y, and list of row indices of X,
# we want to copy the rows of y
def
perform
(
self
,
node
,
inp
,
out_
):
def
perform
(
self
,
node
,
inp
,
out_
):
x
,
values
,
idx
=
inp
#Get all the 3 inputs
import
scipy.sparse
as
ssparse
out
,
=
out_
#get the output
from
numpy.lib.stride_tricks
import
as_strided
rows
,
cols
=
values
.
shape
#Get the shape of Y
x
,
values
,
idx
=
inp
assert
rows
==
len
(
idx
)
#Each row is copied to a row in X.
out
,
=
out_
rows
,
cols
=
values
.
shape
# Setup the index pointer array
assert
rows
==
len
(
idx
)
indptr
=
numpy
.
arange
(
cols
+
1
)
*
rows
indptr
=
numpy
.
arange
(
cols
+
1
)
*
rows
#Set up the indices array
indices
=
as_strided
(
idx
,
indices
=
as_strided
(
idx
,
strides
=
(
0
,
idx
.
strides
[
0
]),
strides
=
(
0
,
idx
.
strides
[
0
]),
shape
=
(
cols
,
idx
.
shape
[
0
]))
.
flatten
()
shape
=
(
cols
,
idx
.
shape
[
0
]))
.
flatten
()
#The data values we need to construct the sparse matrix from
data
=
values
.
T
.
flatten
()
data
=
values
.
T
.
flatten
()
out
[
0
]
=
ssparse
.
csc_matrix
((
data
,
indices
,
indptr
),
shape
=
x
.
shape
,
dtype
=
x
.
dtype
)
#Construct the sparse CSC matrix using data, indices and index pointer
out
[
0
]
=
ssparse
.
csc_matrix
((
data
,
indices
,
indptr
),
shape
=
x
.
shape
,
dtype
=
x
.
dtype
)
#Same as advancedIncSubTensor
def
infer_shape
(
self
,
node
,
ishapes
):
def
infer_shape
(
self
,
node
,
ishapes
):
x
,
y
,
ilist
=
ishapes
x
,
y
,
ilist
=
ishapes
return
[
x
]
return
[
x
]
#Same as advancedIncSubTensor
def
R_op
(
self
,
inputs
,
eval_points
):
def
R_op
(
self
,
inputs
,
eval_points
):
if
None
in
eval_points
[:
2
]:
if
None
in
eval_points
[:
2
]:
return
[
None
]
return
[
None
]
return
self
.
make_node
(
eval_points
[
0
],
eval_points
[
1
],
return
self
.
make_node
(
eval_points
[
0
],
eval_points
[
1
],
*
inputs
[
2
:])
.
outputs
*
inputs
[
2
:])
.
outputs
#Same as advancedIncSubTensor
def
connection_pattern
(
self
,
node
):
def
connection_pattern
(
self
,
node
):
rval
=
[[
True
],
[
True
]]
rval
=
[[
True
],
[
True
]]
...
@@ -6583,7 +6597,6 @@ class ConstructSparse(Op):
...
@@ -6583,7 +6597,6 @@ class ConstructSparse(Op):
return
rval
return
rval
#Same as advancedIncSubTensor
def
grad
(
self
,
inputs
,
grads
):
def
grad
(
self
,
inputs
,
grads
):
g_output
,
=
grads
g_output
,
=
grads
x
,
y
=
inputs
[:
2
]
x
,
y
=
inputs
[:
2
]
...
@@ -6594,7 +6607,6 @@ class ConstructSparse(Op):
...
@@ -6594,7 +6607,6 @@ class ConstructSparse(Op):
return
[
gx
,
gy
]
+
[
DisconnectedType
()()]
*
len
(
idx_list
)
return
[
gx
,
gy
]
+
[
DisconnectedType
()()]
*
len
(
idx_list
)
advanced_subtensor1
=
AdvancedSubtensor1
()
advanced_subtensor1
=
AdvancedSubtensor1
()
...
@@ -6914,6 +6926,38 @@ class AdvancedIncSubtensor(Op):
...
@@ -6914,6 +6926,38 @@ class AdvancedIncSubtensor(Op):
*
inputs
[
2
:])
.
outputs
*
inputs
[
2
:])
.
outputs
advanced_inc_subtensor
=
AdvancedIncSubtensor
()
advanced_inc_subtensor
=
AdvancedIncSubtensor
()
def
take
(
a
,
indices
,
axis
=
None
,
mode
=
'raise'
):
a
=
as_tensor_variable
(
a
)
indices
=
as_tensor_variable
(
indices
)
# Reuse advanced_subtensor1 if indices is a vector
if
indices
.
ndim
==
1
:
if
mode
==
'clip'
:
indices
=
clip
(
indices
,
0
,
a
.
shape
[
axis
]
-
1
)
elif
mode
==
'wrap'
:
indices
=
indices
%
a
.
shape
[
axis
]
if
axis
is
None
:
return
advanced_subtensor1
(
a
.
flatten
(),
indices
)
elif
axis
==
0
:
return
advanced_subtensor1
(
a
,
indices
)
else
:
if
axis
<
0
:
axis
+=
a
.
ndim
assert
axis
>=
0
shuffle
=
range
(
a
.
ndim
)
shuffle
[
0
]
=
axis
shuffle
[
axis
]
=
0
return
advanced_subtensor1
(
a
.
dimshuffle
(
shuffle
),
indices
)
.
dimshuffle
(
shuffle
)
if
axis
is
None
:
shape
=
indices
.
shape
ndim
=
indices
.
ndim
else
:
shape
=
concatenate
(
[
a
.
shape
[:
axis
],
indices
.
shape
,
a
.
shape
[
axis
+
1
:]])
ndim
=
a
.
ndim
+
indices
.
ndim
-
1
return
take
(
a
,
indices
.
flatten
(),
axis
,
mode
)
.
reshape
(
shape
,
ndim
)
#########################
#########################
# Linalg : Dot
# Linalg : Dot
#########################
#########################
...
@@ -7340,6 +7384,7 @@ def all(x, axis=None, keepdims=False):
...
@@ -7340,6 +7384,7 @@ def all(x, axis=None, keepdims=False):
out
=
makeKeepDims
(
x
,
out
,
axis
)
out
=
makeKeepDims
(
x
,
out
,
axis
)
return
out
return
out
class
Diagonal
(
Op
):
class
Diagonal
(
Op
):
"""Return specified diagonals.
"""Return specified diagonals.
...
@@ -7347,23 +7392,27 @@ class Diagonal(Op):
...
@@ -7347,23 +7392,27 @@ class Diagonal(Op):
:return: A vector representing the diagonal elements.
:return: A vector representing the diagonal elements.
"""
"""
def
__init__
(
self
,
offset
=
0
,
axis1
=
0
,
axis2
=
1
):
def
__init__
(
self
,
offset
=
0
,
axis1
=
0
,
axis2
=
1
):
self
.
offset
=
offset
self
.
offset
=
offset
self
.
axis1
=
axis1
self
.
axis1
=
axis1
self
.
axis2
=
axis2
self
.
axis2
=
axis2
def
__eq__
(
self
,
other
):
def
__eq__
(
self
,
other
):
return
(
type
(
self
)
==
type
(
other
))
return
(
type
(
self
)
==
type
(
other
)
and
self
.
offset
==
other
.
offset
and
self
.
axis1
==
other
.
axis1
and
self
.
axis2
==
other
.
axis2
)
def
__hash__
(
self
):
def
__hash__
(
self
):
return
hash
(
type
(
self
))
return
(
hash
(
type
(
self
))
^
hash
(
self
.
offset
)
^
hash
(
self
.
axis1
)
^
hash
(
self
.
axis2
))
def
make_node
(
self
,
x
):
def
make_node
(
self
,
x
):
x
=
as_tensor_variable
(
x
)
x
=
as_tensor_variable
(
x
)
assert
x
.
ndim
>=
2
assert
x
.
ndim
>=
2
return
Apply
(
self
,
[
x
],
[
tensor
(
dtype
=
x
.
dtype
,
return
Apply
(
self
,
[
x
],
[
tensor
(
dtype
=
x
.
dtype
,
broadcastable
=
[
False
]
*
(
x
.
ndim
-
1
))])
broadcastable
=
[
False
]
*
(
x
.
ndim
-
1
))])
def
perform
(
self
,
node
,
(
x
,),
(
z
,)):
def
perform
(
self
,
node
,
(
x
,),
(
z
,)):
z
[
0
]
=
x
.
diagonal
(
self
.
offset
,
self
.
axis1
,
self
.
axis2
)
z
[
0
]
=
x
.
diagonal
(
self
.
offset
,
self
.
axis1
,
self
.
axis2
)
...
@@ -7375,14 +7424,14 @@ class Diagonal(Op):
...
@@ -7375,14 +7424,14 @@ class Diagonal(Op):
in_shape
,
=
shapes
in_shape
,
=
shapes
dim1
=
in_shape
[
self
.
axis1
]
dim1
=
in_shape
[
self
.
axis1
]
dim2
=
in_shape
[
self
.
axis2
]
dim2
=
in_shape
[
self
.
axis2
]
out_shape
=
[
d
for
i
,
d
in
enumerate
(
in_shape
)
out_shape
=
[
d
for
i
,
d
in
enumerate
(
in_shape
)
if
i
not
in
(
self
.
axis1
,
self
.
axis2
)]
if
i
not
in
(
self
.
axis1
,
self
.
axis2
)]
# The following logic is inspired by C code of PyArray_Diagonal().
# The following logic is inspired by C code of PyArray_Diagonal().
offset
=
self
.
offset
offset
=
self
.
offset
if
offset
>
0
:
if
offset
>
0
:
diag_size
=
clip
(
dim2
-
offset
,
0
,
dim1
)
diag_size
=
clip
(
dim2
-
offset
,
0
,
dim1
)
elif
offset
<
0
:
elif
offset
<
0
:
diag_size
=
clip
(
dim1
+
offset
,
0
,
dim2
)
diag_size
=
clip
(
dim1
+
offset
,
0
,
dim2
)
else
:
else
:
diag_size
=
minimum
(
dim1
,
dim2
)
diag_size
=
minimum
(
dim1
,
dim2
)
out_shape
.
append
(
diag_size
)
out_shape
.
append
(
diag_size
)
...
@@ -7391,12 +7440,14 @@ class Diagonal(Op):
...
@@ -7391,12 +7440,14 @@ class Diagonal(Op):
def
__str__
(
self
):
def
__str__
(
self
):
return
self
.
__class__
.
__name__
return
self
.
__class__
.
__name__
def
diagonal
(
a
,
offset
=
0
,
axis1
=
0
,
axis2
=
1
):
def
diagonal
(
a
,
offset
=
0
,
axis1
=
0
,
axis2
=
1
):
if
(
offset
,
axis1
,
axis2
)
==
(
0
,
0
,
1
):
if
(
offset
,
axis1
,
axis2
)
==
(
0
,
0
,
1
):
from
theano.sandbox.linalg
import
extract_diag
from
theano.sandbox.linalg
import
extract_diag
return
extract_diag
(
a
)
return
extract_diag
(
a
)
return
Diagonal
(
offset
,
axis1
,
axis2
)(
a
)
return
Diagonal
(
offset
,
axis1
,
axis2
)(
a
)
class
Diag
(
Op
):
class
Diag
(
Op
):
def
__eq__
(
self
,
other
):
def
__eq__
(
self
,
other
):
...
@@ -7424,6 +7475,7 @@ class Diag(Op):
...
@@ -7424,6 +7475,7 @@ class Diag(Op):
def
__str__
(
self
):
def
__str__
(
self
):
return
self
.
__class__
.
__name__
return
self
.
__class__
.
__name__
def
diag
(
v
,
k
=
0
):
def
diag
(
v
,
k
=
0
):
if
v
.
ndim
==
1
:
if
v
.
ndim
==
1
:
assert
k
==
0
,
"diagonals other than main are not implemented"
assert
k
==
0
,
"diagonals other than main are not implemented"
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论