Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
P
pytensor
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
testgroup
pytensor
Commits
5136b268
提交
5136b268
authored
3月 13, 2017
作者:
abergeron
提交者:
GitHub
3月 13, 2017
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #5524 from hantek/allocdiag
Diag --> AllocDiag
上级
0e4c6a75
9ae243d3
全部展开
显示空白字符变更
内嵌
并排
正在显示
5 个修改的文件
包含
206 行增加
和
24 行删除
+206
-24
subtensor.py
theano/gpuarray/subtensor.py
+41
-5
test_subtensor.py
theano/gpuarray/tests/test_subtensor.py
+67
-6
basic.py
theano/tensor/basic.py
+89
-12
nlinalg.py
theano/tensor/nlinalg.py
+9
-1
test_basic.py
theano/tensor/tests/test_basic.py
+0
-0
没有找到文件。
theano/gpuarray/subtensor.py
浏览文件 @
5136b268
...
@@ -21,7 +21,6 @@ from .type import GpuArrayType, gpu_context_type
...
@@ -21,7 +21,6 @@ from .type import GpuArrayType, gpu_context_type
from
.basic_ops
import
(
as_gpuarray_variable
,
HideC
,
GpuKernelBase
,
Kernel
,
from
.basic_ops
import
(
as_gpuarray_variable
,
HideC
,
GpuKernelBase
,
Kernel
,
infer_context_name
,
gpu_contiguous
)
infer_context_name
,
gpu_contiguous
)
iadd_reg
=
{}
iadd_reg
=
{}
...
@@ -1080,7 +1079,7 @@ __device__ ga_half atomicExch(ga_half *addr, ga_half val) {
...
@@ -1080,7 +1079,7 @@ __device__ ga_half atomicExch(ga_half *addr, ga_half val) {
"""
%
locals
()
"""
%
locals
()
class
Gpu
Diagonal
(
Subtensor
):
class
Gpu
ExtractDiag
(
Op
):
__props__
=
(
"offset"
,
"axis1"
,
"axis2"
,
"view"
)
__props__
=
(
"offset"
,
"axis1"
,
"axis2"
,
"view"
)
def
__init__
(
self
,
offset
=
0
,
axis1
=
0
,
axis2
=
1
,
view
=
False
):
def
__init__
(
self
,
offset
=
0
,
axis1
=
0
,
axis2
=
1
,
view
=
False
):
...
@@ -1102,9 +1101,7 @@ class GpuDiagonal(Subtensor):
...
@@ -1102,9 +1101,7 @@ class GpuDiagonal(Subtensor):
broadcastable
=
x
.
broadcastable
[:
axis_small
]
+
\
broadcastable
=
x
.
broadcastable
[:
axis_small
]
+
\
x
.
broadcastable
[
axis_small
+
1
:
axis_large
]
+
\
x
.
broadcastable
[
axis_small
+
1
:
axis_large
]
+
\
x
.
broadcastable
[
axis_large
+
1
:]
+
(
False
,)
x
.
broadcastable
[
axis_large
+
1
:]
+
(
False
,)
return
gof
.
Apply
(
self
,
[
x
],
[
x
.
type
.
__class__
(
return
gof
.
Apply
(
self
,
[
x
],
[
x
.
type
.
clone
(
broadcastable
=
broadcastable
)()])
dtype
=
x
.
dtype
,
broadcastable
=
broadcastable
)()])
def
perform
(
self
,
node
,
inputs
,
outputs
):
def
perform
(
self
,
node
,
inputs
,
outputs
):
(
x
,)
=
inputs
(
x
,)
=
inputs
...
@@ -1183,3 +1180,42 @@ class GpuDiagonal(Subtensor):
...
@@ -1183,3 +1180,42 @@ class GpuDiagonal(Subtensor):
diag_size
=
T
.
minimum
(
dim1
,
dim2
)
diag_size
=
T
.
minimum
(
dim1
,
dim2
)
out_shape
.
append
(
diag_size
)
out_shape
.
append
(
diag_size
)
return
[
tuple
(
out_shape
)]
return
[
tuple
(
out_shape
)]
class
GpuAllocDiag
(
Op
):
__props__
=
(
"offset"
,)
def
__init__
(
self
,
offset
=
0
):
self
.
offset
=
offset
def
make_node
(
self
,
_x
):
ctx_name
=
infer_context_name
(
_x
)
x
=
as_gpuarray_variable
(
_x
,
ctx_name
)
if
x
.
ndim
!=
1
:
raise
ValueError
(
'AllocDiag argument must be a vector!'
,
x
)
return
gof
.
Apply
(
self
,
[
x
],
[
x
.
type
.
clone
(
broadcastable
=
(
False
,
False
))()])
def
perform
(
self
,
node
,
inputs
,
outputs
):
(
x
,)
=
inputs
(
z
,)
=
outputs
dim
=
x
.
shape
[
0
]
+
abs
(
self
.
offset
)
z
[
0
]
=
gpuarray
.
zeros
((
dim
,
dim
),
dtype
=
x
.
dtype
,
context
=
x
.
context
)
if
self
.
offset
<=
0
:
# diag in the lower triangle
diag_z
=
z
[
0
][
-
self
.
offset
,
:(
dim
+
self
.
offset
)]
else
:
# diag in the upper triangle
diag_z
=
z
[
0
][:(
dim
-
self
.
offset
),
self
.
offset
]
diag_z
.
strides
=
(
sum
(
z
[
0
]
.
strides
),)
diag_z
[:]
=
x
[:]
def
grad
(
self
,
inputs
,
gout
):
(
gz
,)
=
gout
return
[
GpuExtractDiag
(
offset
=
self
.
offset
,
axis1
=
0
,
axis2
=
1
)(
gz
)]
def
infer_shape
(
self
,
node
,
shapes
):
dim
=
shapes
[
0
][
0
]
+
abs
(
self
.
offset
)
return
[[
dim
,
dim
]]
theano/gpuarray/tests/test_subtensor.py
浏览文件 @
5136b268
...
@@ -15,7 +15,8 @@ from ..subtensor import (GpuIncSubtensor, GpuSubtensor,
...
@@ -15,7 +15,8 @@ from ..subtensor import (GpuIncSubtensor, GpuSubtensor,
GpuAdvancedSubtensor
,
GpuAdvancedSubtensor
,
GpuAdvancedIncSubtensor1
,
GpuAdvancedIncSubtensor1
,
GpuAdvancedIncSubtensor1_dev20
,
GpuAdvancedIncSubtensor1_dev20
,
GpuDiagonal
)
GpuExtractDiag
,
GpuAllocDiag
)
from
..type
import
gpuarray_shared_constructor
from
..type
import
gpuarray_shared_constructor
from
.config
import
mode_with_gpu
from
.config
import
mode_with_gpu
...
@@ -191,15 +192,15 @@ def test_adv_subtensor():
...
@@ -191,15 +192,15 @@ def test_adv_subtensor():
assert
np
.
allclose
(
rval
,
rep
)
assert
np
.
allclose
(
rval
,
rep
)
class
test_gpu
diagonal
(
unittest
.
TestCase
):
class
test_gpu
extractdiag
(
unittest
.
TestCase
):
def
test_matrix
(
self
):
def
test_matrix
(
self
):
x
=
tensor
.
matrix
()
x
=
tensor
.
matrix
()
np_x
=
np
.
arange
(
77
)
.
reshape
(
7
,
11
)
.
astype
(
theano
.
config
.
floatX
)
np_x
=
np
.
arange
(
77
)
.
reshape
(
7
,
11
)
.
astype
(
theano
.
config
.
floatX
)
fn
=
theano
.
function
([
x
],
Gpu
Diagonal
()(
x
),
mode
=
mode_with_gpu
)
fn
=
theano
.
function
([
x
],
Gpu
ExtractDiag
()(
x
),
mode
=
mode_with_gpu
)
assert
np
.
allclose
(
fn
(
np_x
),
np_x
.
diagonal
())
assert
np
.
allclose
(
fn
(
np_x
),
np_x
.
diagonal
())
fn
=
theano
.
function
([
x
],
Gpu
Diagonal
(
2
)(
x
),
mode
=
mode_with_gpu
)
fn
=
theano
.
function
([
x
],
Gpu
ExtractDiag
(
2
)(
x
),
mode
=
mode_with_gpu
)
assert
np
.
allclose
(
fn
(
np_x
),
np_x
.
diagonal
(
2
))
assert
np
.
allclose
(
fn
(
np_x
),
np_x
.
diagonal
(
2
))
fn
=
theano
.
function
([
x
],
Gpu
Diagonal
(
-
3
)(
x
),
mode
=
mode_with_gpu
)
fn
=
theano
.
function
([
x
],
Gpu
ExtractDiag
(
-
3
)(
x
),
mode
=
mode_with_gpu
)
assert
np
.
allclose
(
fn
(
np_x
),
np_x
.
diagonal
(
-
3
))
assert
np
.
allclose
(
fn
(
np_x
),
np_x
.
diagonal
(
-
3
))
def
test_tensor
(
self
):
def
test_tensor
(
self
):
...
@@ -210,5 +211,65 @@ class test_gpudiagonal(unittest.TestCase):
...
@@ -210,5 +211,65 @@ class test_gpudiagonal(unittest.TestCase):
(
-
3
,
1
,
0
),
(
-
2
,
2
,
0
),
(
3
,
3
,
0
),
(
-
1
,
3
,
2
),
(
-
3
,
1
,
0
),
(
-
2
,
2
,
0
),
(
3
,
3
,
0
),
(
-
1
,
3
,
2
),
(
2
,
2
,
3
),
(
-
1
,
2
,
1
),
(
1
,
3
,
1
),
(
-
1
,
1
,
3
)]:
(
2
,
2
,
3
),
(
-
1
,
2
,
1
),
(
1
,
3
,
1
),
(
-
1
,
1
,
3
)]:
assert
np
.
allclose
(
assert
np
.
allclose
(
Gpu
Diagonal
(
offset
,
axis1
,
axis2
)(
x
)
.
eval
({
x
:
np_x
}),
Gpu
ExtractDiag
(
offset
,
axis1
,
axis2
)(
x
)
.
eval
({
x
:
np_x
}),
np_x
.
diagonal
(
offset
,
axis1
,
axis2
))
np_x
.
diagonal
(
offset
,
axis1
,
axis2
))
class
test_gpuallocdiag
(
unittest
.
TestCase
):
def
test_matrix
(
self
):
x
=
tensor
.
vector
()
np_x
=
np
.
arange
(
7
)
.
astype
(
theano
.
config
.
floatX
)
fn
=
theano
.
function
([
x
],
GpuAllocDiag
()(
x
),
mode
=
mode_with_gpu
)
assert
np
.
allclose
(
fn
(
np_x
),
np
.
diag
(
np_x
))
fn
=
theano
.
function
([
x
],
GpuAllocDiag
(
2
)(
x
),
mode
=
mode_with_gpu
)
assert
np
.
allclose
(
fn
(
np_x
),
np
.
diag
(
np_x
,
2
))
fn
=
theano
.
function
([
x
],
GpuAllocDiag
(
-
3
)(
x
),
mode
=
mode_with_gpu
)
assert
np
.
allclose
(
fn
(
np_x
),
np
.
diag
(
np_x
,
-
3
))
def
test_grad
(
self
):
x
=
tensor
.
vector
()
np_x
=
np
.
random
.
randn
(
7
)
.
astype
(
theano
.
config
.
floatX
)
# offset = 0 case:
mtx_x
=
GpuAllocDiag
()(
x
)
sum_mtx_x
=
tensor
.
sum
(
mtx_x
)
grad_x
=
tensor
.
grad
(
sum_mtx_x
,
x
)
grad_mtx_x
=
tensor
.
grad
(
sum_mtx_x
,
mtx_x
)
fn_grad_x
=
theano
.
function
([
x
],
grad_x
)
fn_grad_mtx_x
=
theano
.
function
([
x
],
grad_mtx_x
)
computed_grad_x
=
fn_grad_x
(
np_x
)
computed_grad_mtx_x
=
fn_grad_mtx_x
(
np_x
)
true_grad_x
=
np
.
diagonal
(
computed_grad_mtx_x
,
0
)
assert
np
.
allclose
(
computed_grad_x
,
true_grad_x
)
# offset > 0 case:
mtx_x
=
GpuAllocDiag
(
2
)(
x
)
sum_mtx_x
=
tensor
.
sum
(
mtx_x
)
grad_x
=
tensor
.
grad
(
sum_mtx_x
,
x
)
grad_mtx_x
=
tensor
.
grad
(
sum_mtx_x
,
mtx_x
)
fn_grad_x
=
theano
.
function
([
x
],
grad_x
)
fn_grad_mtx_x
=
theano
.
function
([
x
],
grad_mtx_x
)
computed_grad_x
=
fn_grad_x
(
np_x
)
computed_grad_mtx_x
=
fn_grad_mtx_x
(
np_x
)
true_grad_x
=
np
.
diagonal
(
computed_grad_mtx_x
,
2
)
assert
np
.
allclose
(
computed_grad_x
,
true_grad_x
)
# offset < 0 case:
mtx_x
=
GpuAllocDiag
(
-
3
)(
x
)
sum_mtx_x
=
tensor
.
sum
(
mtx_x
)
grad_x
=
tensor
.
grad
(
sum_mtx_x
,
x
)
grad_mtx_x
=
tensor
.
grad
(
sum_mtx_x
,
mtx_x
)
fn_grad_x
=
theano
.
function
([
x
],
grad_x
)
fn_grad_mtx_x
=
theano
.
function
([
x
],
grad_mtx_x
)
computed_grad_x
=
fn_grad_x
(
np_x
)
computed_grad_mtx_x
=
fn_grad_mtx_x
(
np_x
)
true_grad_x
=
np
.
diagonal
(
computed_grad_mtx_x
,
-
3
)
assert
np
.
allclose
(
computed_grad_x
,
true_grad_x
)
# assert
theano/tensor/basic.py
浏览文件 @
5136b268
...
@@ -6285,6 +6285,17 @@ class ExtractDiag(Op):
...
@@ -6285,6 +6285,17 @@ class ExtractDiag(Op):
def
grad
(
self
,
inputs
,
gout
):
def
grad
(
self
,
inputs
,
gout
):
(
x
,)
=
inputs
(
x
,)
=
inputs
(
gz
,)
=
gout
(
gz
,)
=
gout
if
x
.
ndim
==
2
:
# The following code is moved from tensor.nlinalg.ExtractDiag, only
# works for matrices.
x
=
theano
.
tensor
.
zeros_like
(
x
)
xdiag
=
theano
.
tensor
.
AllocDiag
(
offset
=
self
.
offset
)(
gz
)
return
[
theano
.
tensor
.
set_subtensor
(
x
[:
xdiag
.
shape
[
0
],
:
xdiag
.
shape
[
1
]],
xdiag
)]
else
:
warnings
.
warn
(
"gradient of theano.tensor.nlinalg.ExtractDiag only"
"works for matrices."
)
return
[
grad_not_implemented
(
self
,
0
,
x
)]
return
[
grad_not_implemented
(
self
,
0
,
x
)]
def
infer_shape
(
self
,
node
,
shapes
):
def
infer_shape
(
self
,
node
,
shapes
):
...
@@ -6306,42 +6317,108 @@ class ExtractDiag(Op):
...
@@ -6306,42 +6317,108 @@ class ExtractDiag(Op):
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
):
"""
return
theano
.
tensor
.
nlinalg
.
extract_diag
(
a
)
A helper function for `theano.tensor.ExtractDiag`. It accepts tensor with
`ndim >= 2` as input. The name `diagonal` is just meant to keep it
consistent with numpy.
Parameters
----------
a : symbolic tensor
offset : int
offset
axis1 : int
axis2 : int
Returns
-------
tensor : symbolic tensor
"""
return
ExtractDiag
(
offset
,
axis1
,
axis2
)(
a
)
return
ExtractDiag
(
offset
,
axis1
,
axis2
)(
a
)
class
Diag
(
Op
):
class
AllocDiag
(
Op
):
"""
An op that copies a vector to the diagonal of an empty matrix. It does the
inverse of ExtractDiag.
__props__
=
()
Usage: T.AllocDiag()(x)
`x` should be a tensor vector. The parenthesis in the front should indicate
which main diagonal the vector value goes into. By default it is set to
`0`, which corresponds to setting the values of x to the main diagonal in
the returned matrix.
Parameters
----------
offset : int
Indicates which diagonal to put `x` into. Defaults to `0`.
x: symbolic vector
A tensor vector consists of diagonal values.
Returns
-------
tensor : symbolic tenstor
A tensor with passed vector values at its corresponding diagonal.
"""
__props__
=
(
"offset"
,
)
default_offset
=
0
def
__init__
(
self
,
offset
=
0
):
if
numpy_diagonal_return_view
:
self
.
view_map
=
{
0
:
[
0
]}
self
.
offset
=
offset
def
make_node
(
self
,
diag
):
def
make_node
(
self
,
diag
):
diag
=
as_tensor_variable
(
diag
)
diag
=
as_tensor_variable
(
diag
)
if
diag
.
type
.
ndim
!=
1
:
if
diag
.
type
.
ndim
!=
1
:
raise
TypeError
(
'data argument must be a vector'
,
diag
.
type
)
raise
TypeError
(
'data argument must be a vector'
,
diag
.
type
)
return
Apply
(
self
,
[
diag
],
[
matrix
(
dtype
=
diag
.
dtype
)])
return
Apply
(
self
,
[
diag
],
[
matrix
(
dtype
=
diag
.
dtype
)])
def
perform
(
self
,
node
,
inputs
,
outputs
):
def
perform
(
self
,
node
,
inputs
,
outputs
):
(
z
,)
=
outputs
(
z
,)
=
outputs
z
[
0
]
=
numpy
.
diag
(
inputs
[
0
])
z
[
0
]
=
numpy
.
diag
(
inputs
[
0
]
,
self
.
offset
)
def
grad
(
self
,
inputs
,
gout
):
def
grad
(
self
,
inputs
,
gout
):
(
gz
,)
=
gout
(
gz
,)
=
gout
return
[
diagonal
(
gz
)]
return
[
diagonal
(
gz
,
offset
=
self
.
offset
,
axis1
=
0
,
axis2
=
1
)]
def
infer_shape
(
self
,
nodes
,
shapes
):
def
infer_shape
(
self
,
nodes
,
shapes
):
return
[(
shapes
[
0
][
0
],)
*
2
]
return
[(
shapes
[
0
][
0
],)
*
2
]
def
diag
(
v
,
k
=
0
):
def
diag
(
v
,
k
=
0
):
"""
A helper function for two ops: `theano.tensor.ExtractDiag` and
`theano.tensor.AllocDiag`. The name `diag` is meant to keep it consistent
with numpy. It both accepts tensor vector and tensor matrix.
While the passed tensor variable `v` has `v.ndim>=2`, it builds a
`ExtractDiag` instance, and returns a vector with its entries equal to
`v`'s main diagonal; otherwise if `v.ndim` is `1`, it builds an `AllocDiag`
instance, and returns a matrix with `v` at its k-th diaogonal.
Parameters
----------
v : symbolic tensor
k : int
offset
Returns
-------
tensor : symbolic tensor
"""
if
v
.
ndim
==
1
:
if
v
.
ndim
==
1
:
assert
k
==
0
,
"diagonals other than main are not implemented"
return
AllocDiag
(
k
)(
v
)
return
Diag
()(
v
)
elif
v
.
ndim
>=
2
:
elif
v
.
ndim
==
2
:
return
diagonal
(
v
,
offset
=
k
)
return
diagonal
(
v
,
k
)
else
:
else
:
raise
ValueError
(
"Input must
be 1- or 2-d
."
)
raise
ValueError
(
"Input must
has v.ndim >= 1
."
)
def
stacklists
(
arg
):
def
stacklists
(
arg
):
...
...
theano/tensor/nlinalg.py
浏览文件 @
5136b268
from
__future__
import
absolute_import
,
print_function
,
division
from
__future__
import
absolute_import
,
print_function
,
division
import
logging
import
logging
import
warnings
import
numpy
import
numpy
from
six.moves
import
xrange
from
six.moves
import
xrange
...
@@ -145,6 +145,10 @@ class AllocDiag(Op):
...
@@ -145,6 +145,10 @@ class AllocDiag(Op):
__props__
=
()
__props__
=
()
def
make_node
(
self
,
_x
):
def
make_node
(
self
,
_x
):
warnings
.
warn
(
"DeprecationWarning: theano.tensor.nlinalg.AllocDiag"
"is deprecated, please use theano.tensor.AllocDiag"
"instead."
,
category
=
DeprecationWarning
)
x
=
as_tensor_variable
(
_x
)
x
=
as_tensor_variable
(
_x
)
if
x
.
type
.
ndim
!=
1
:
if
x
.
type
.
ndim
!=
1
:
raise
TypeError
(
'AllocDiag only works on vectors'
,
_x
)
raise
TypeError
(
'AllocDiag only works on vectors'
,
_x
)
...
@@ -184,6 +188,10 @@ class ExtractDiag(Op):
...
@@ -184,6 +188,10 @@ class ExtractDiag(Op):
self
.
view_map
=
{
0
:
[
0
]}
self
.
view_map
=
{
0
:
[
0
]}
def
make_node
(
self
,
_x
):
def
make_node
(
self
,
_x
):
warnings
.
warn
(
"DeprecationWarning: theano.tensor.nlinalg.ExtractDiag"
"is deprecated, please use theano.tensor.ExtractDiag"
"instead."
,
category
=
DeprecationWarning
)
if
not
isinstance
(
_x
,
theano
.
Variable
):
if
not
isinstance
(
_x
,
theano
.
Variable
):
x
=
as_tensor_variable
(
_x
)
x
=
as_tensor_variable
(
_x
)
else
:
else
:
...
...
theano/tensor/tests/test_basic.py
浏览文件 @
5136b268
差异被折叠。
点击展开。
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论