Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
P
pytensor
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
testgroup
pytensor
Commits
123d9007
提交
123d9007
authored
9月 02, 2016
作者:
Frédéric Bastien
提交者:
GitHub
9月 02, 2016
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #4756 from Thrandis/ccw2
Theano variable arguments for pooling 2
上级
0d478806
166cac0a
隐藏空白字符变更
内嵌
并排
正在显示
12 个修改的文件
包含
577 行增加
和
428 行删除
+577
-428
Theano.pyproj
Theano.pyproj
+1
-1
downsample.txt
doc/library/tensor/signal/downsample.txt
+2
-5
index.txt
doc/library/tensor/signal/index.txt
+1
-1
dnn.py
theano/gpuarray/dnn.py
+7
-16
dnn.py
theano/sandbox/cuda/dnn.py
+6
-15
opt.py
theano/sandbox/cuda/opt.py
+50
-26
test_blas.py
theano/sandbox/cuda/tests/test_blas.py
+6
-6
test_mlp.py
theano/sandbox/cuda/tests/test_mlp.py
+3
-2
downsample.py
theano/tensor/signal/downsample.py
+0
-26
pool.py
theano/tensor/signal/pool.py
+376
-217
old_pool_interface.pkl
theano/tensor/signal/tests/old_pool_interface.pkl
+0
-0
test_pool.py
theano/tensor/signal/tests/test_pool.py
+125
-113
没有找到文件。
Theano.pyproj
浏览文件 @
123d9007
...
...
@@ -187,7 +187,7 @@
<Compile
Include=
"theano\tensor\sharedvar.py"
/>
<Compile
Include=
"theano\tensor\shared_randomstreams.py"
/>
<Compile
Include=
"theano\tensor\signal\conv.py"
/>
<Compile
Include=
"theano\tensor\signal\
downsample
.py"
/>
<Compile
Include=
"theano\tensor\signal\
pool
.py"
/>
<Compile
Include=
"theano\tensor\signal\__init__.py"
/>
<Compile
Include=
"theano\tensor\tensor_grad.py"
/>
<Compile
Include=
"theano\tensor\xlogx.py"
/>
...
...
doc/library/tensor/signal/downsample.txt
浏览文件 @
123d9007
...
...
@@ -9,9 +9,6 @@
:synopsis: ops for performing various forms of downsampling
.. moduleauthor:: LISA
.. seealso:: :func:`theano.tensor.nnet.neighbours.images2neibs`
.. function:: fft(*todo)
[James has some code for this, but hasn't gotten it into the source tree yet.]
.. note::
This module is deprecated. Use the functions in :func:`theano.tensor.nnet.signal.pool`
doc/library/tensor/signal/index.txt
浏览文件 @
123d9007
...
...
@@ -20,5 +20,5 @@ forms of signal processing.
:maxdepth: 1
conv
downsample
pool
downsample
theano/gpuarray/dnn.py
浏览文件 @
123d9007
...
...
@@ -1859,13 +1859,10 @@ def local_gpua_pool_dnn_alternative(op, ctx_name, inputs, outputs):
raise_no_cudnn
()
if
not
op
.
ignore_border
:
return
img
,
=
inputs
img
,
ws
,
stride
,
pad
=
inputs
img
=
as_gpuarray_variable
(
img
,
ctx_name
)
ds
=
op
.
ds
stride
=
op
.
st
pad
=
op
.
padding
mode
=
op
.
mode
return
dnn_pool
(
gpu_contiguous
(
img
),
d
s
,
stride
=
stride
,
pad
=
pad
,
mode
=
mode
)
return
dnn_pool
(
gpu_contiguous
(
img
),
w
s
,
stride
=
stride
,
pad
=
pad
,
mode
=
mode
)
@register_opt
(
'cudnn'
,
'fast_compile'
)
...
...
@@ -1876,20 +1873,17 @@ def local_gpua_pool_dnn_grad_stride(op, ctx_name, inputs, outputs):
raise_no_cudnn
()
if
not
op
.
ignore_border
:
return
inp
,
out
,
out_grad
=
inputs
inp
,
out
,
out_grad
,
ws
,
stride
,
pad
=
inputs
inp
=
as_gpuarray_variable
(
inp
,
ctx_name
)
out
=
as_gpuarray_variable
(
out
,
ctx_name
)
out_grad
=
as_gpuarray_variable
(
out_grad
,
ctx_name
)
ds
=
op
.
ds
st
=
op
.
st
pad
=
op
.
padding
mode
=
op
.
mode
return
GpuDnnPoolGrad
(
mode
=
mode
)(
gpu_contiguous
(
inp
),
gpu_contiguous
(
out
),
gpu_contiguous
(
out_grad
),
d
s
,
st
,
w
s
,
st
ride
,
pad
)
...
...
@@ -1901,12 +1895,9 @@ def local_gpua_avg_pool_dnn_grad_stride(op, ctx_name, inputs, outputs):
raise_no_cudnn
()
if
not
op
.
ignore_border
:
return
inp
,
out_grad
=
inputs
inp
,
out_grad
,
ws
,
stride
,
pad
=
inputs
inp
=
as_gpuarray_variable
(
inp
,
ctx_name
)
out_grad
=
as_gpuarray_variable
(
out_grad
,
ctx_name
)
ds
=
op
.
ds
st
=
op
.
st
pad
=
op
.
padding
mode
=
op
.
mode
cg
=
gpu_contiguous
(
out_grad
)
...
...
@@ -1914,7 +1905,7 @@ def local_gpua_avg_pool_dnn_grad_stride(op, ctx_name, inputs, outputs):
# We reuse cg because cuDNN does not use the value of the `out`
# argument but still checks its shape for average pooling. This
# has been observed in v2 and v3 as far as I know.
return
GpuDnnPoolGrad
(
mode
=
mode
)(
gpu_contiguous
(
inp
),
cg
,
cg
,
ds
,
st
,
pad
)
return
GpuDnnPoolGrad
(
mode
=
mode
)(
gpu_contiguous
(
inp
),
cg
,
cg
,
ws
,
stride
,
pad
)
@register_opt
(
'cudnn'
,
'fast_compile'
)
...
...
theano/sandbox/cuda/dnn.py
浏览文件 @
123d9007
...
...
@@ -2962,14 +2962,11 @@ if True:
if
isinstance
(
node
.
op
,
Pool
):
if
not
node
.
op
.
ignore_border
:
return
img
,
=
node
.
inputs
ds
=
node
.
op
.
ds
stride
=
node
.
op
.
st
pad
=
node
.
op
.
padding
img
,
ws
,
stride
,
pad
=
node
.
inputs
mode
=
node
.
op
.
mode
if
(
img
.
owner
and
isinstance
(
img
.
owner
.
op
,
HostFromGpu
)):
ret
=
dnn_pool
(
gpu_contiguous
(
img
.
owner
.
inputs
[
0
]),
d
s
,
stride
=
stride
,
pad
=
pad
,
mode
=
mode
)
w
s
,
stride
=
stride
,
pad
=
pad
,
mode
=
mode
)
return
[
host_from_gpu
(
ret
)]
@register_opt
(
'cudnn'
)
...
...
@@ -2996,10 +2993,7 @@ if True:
if
isinstance
(
node
.
op
,
MaxPoolGrad
):
if
not
node
.
op
.
ignore_border
:
return
inp
,
out
,
inp_grad
=
node
.
inputs
ds
=
node
.
op
.
ds
st
=
node
.
op
.
st
pad
=
node
.
op
.
padding
inp
,
out
,
inp_grad
,
ws
,
stride
,
pad
=
node
.
inputs
mode
=
node
.
op
.
mode
if
((
inp
.
owner
and
isinstance
(
inp
.
owner
.
op
,
HostFromGpu
))
or
...
...
@@ -3010,7 +3004,7 @@ if True:
ret
=
GpuDnnPoolGrad
(
mode
=
mode
)(
gpu_contiguous
(
inp
),
gpu_contiguous
(
out
),
gpu_contiguous
(
inp_grad
),
ds
,
st
,
pad
)
ws
,
stride
,
pad
)
return
[
host_from_gpu
(
ret
)]
@register_opt
(
'cudnn'
)
...
...
@@ -3021,10 +3015,7 @@ if True:
if
isinstance
(
node
.
op
,
AveragePoolGrad
):
if
not
node
.
op
.
ignore_border
:
return
inp
,
inp_grad
=
node
.
inputs
ds
=
node
.
op
.
ds
st
=
node
.
op
.
st
pad
=
node
.
op
.
padding
inp
,
inp_grad
,
ws
,
stride
,
pad
=
node
.
inputs
mode
=
node
.
op
.
mode
if
((
inp
.
owner
and
isinstance
(
inp
.
owner
.
op
,
HostFromGpu
))
or
...
...
@@ -3034,7 +3025,7 @@ if True:
ret
=
GpuDnnPoolGrad
(
mode
=
mode
)(
gpu_contiguous
(
inp
),
contiguous_inp_grad
,
contiguous_inp_grad
,
ds
,
st
,
pad
)
ws
,
stride
,
pad
)
return
[
host_from_gpu
(
ret
)]
@register_opt
(
'cudnn'
)
...
...
theano/sandbox/cuda/opt.py
浏览文件 @
123d9007
...
...
@@ -1891,37 +1891,61 @@ def local_convtransp3d_gemm(node):
gpu_optimizer
.
register
(
"convtransp3d_gemm"
,
local_convtransp3d_gemm
)
def
_check_constant_args_pool
(
ws
,
stride
,
pad
,
node
):
"""Check if the args of pool are constants. Warns if not."""
try
:
ws_w
=
tensor
.
get_scalar_constant_value
(
ws
[
0
])
ws_h
=
tensor
.
get_scalar_constant_value
(
ws
[
1
])
stride_w
=
tensor
.
get_scalar_constant_value
(
stride
[
0
])
stride_h
=
tensor
.
get_scalar_constant_value
(
stride
[
1
])
pad_w
=
tensor
.
get_scalar_constant_value
(
pad
[
0
])
pad_h
=
tensor
.
get_scalar_constant_value
(
pad
[
1
])
except
tensor
.
NotScalarConstantError
:
msg
=
(
"Pool with tensor variable for the window size, stride or "
"padding is only supported in the new GPU backend, so this op "
"will run on CPU. (op
%
s)"
%
node
)
if
config
.
assert_no_cpu_op
==
"warn"
:
_logger
.
warning
(
msg
)
elif
config
.
assert_no_cpu_op
==
"raise"
:
raise
AssertionError
(
msg
)
return
None
ws
=
(
ws_w
,
ws_h
)
stride
=
(
stride_w
,
stride_h
)
pad
=
(
pad_w
,
pad_h
)
return
ws
,
stride
,
pad
@register_opt
()
@local_optimizer
([
pool
.
Pool
])
def
local_gpu_downsample_factor_max
(
node
):
if
(
isinstance
(
node
.
op
,
pool
.
Pool
)
and
node
.
op
.
ds
==
node
.
op
.
st
):
assert
node
.
op
.
__props__
==
(
'ds'
,
'ignore_border'
,
'st'
,
'padding'
,
'mode'
)
if
node
.
op
.
padding
!=
(
0
,
0
)
or
node
.
op
.
mode
!=
'max'
:
if
isinstance
(
node
.
op
,
pool
.
Pool
):
assert
node
.
op
.
__props__
==
(
'ignore_border'
,
'mode'
)
x
,
ws
,
stride
,
pad
=
node
.
inputs
ret
=
_check_constant_args_pool
(
ws
,
stride
,
pad
,
node
)
if
ret
is
None
:
return
ws
,
stride
,
pad
=
ret
if
(
pad
)
!=
(
0
,
0
)
or
node
.
op
.
mode
!=
'max'
or
stride
!=
ws
:
return
x
,
=
node
.
inputs
if
(
x
.
owner
and
isinstance
(
x
.
owner
.
op
,
HostFromGpu
)):
gpu_ds
=
GpuDownsampleFactorMax
(
node
.
op
.
d
s
,
node
.
op
.
ignore_border
)
gpu_ds
=
GpuDownsampleFactorMax
(
w
s
,
node
.
op
.
ignore_border
)
return
[
host_from_gpu
(
gpu_ds
(
x
.
owner
.
inputs
[
0
]))]
@register_opt
()
@local_optimizer
([
pool
.
MaxPoolGrad
])
def
local_gpu_downsample_factor_max_grad
(
node
):
if
(
isinstance
(
node
.
op
,
pool
.
MaxPoolGrad
)
and
node
.
op
.
ds
==
node
.
op
.
st
):
assert
node
.
op
.
__props__
==
(
'ds'
,
'ignore_border'
,
'st'
,
'padding'
,
'mode'
)
if
(
node
.
op
.
padding
!=
(
0
,
0
)
or
node
.
op
.
mode
!=
'max'
or
node
.
op
.
st
!=
node
.
op
.
ds
):
if
isinstance
(
node
.
op
,
pool
.
MaxPoolGrad
):
assert
node
.
op
.
__props__
==
(
'ignore_border'
,
'mode'
)
x
,
z
,
gz
,
ws
,
stride
,
pad
=
node
.
inputs
ret
=
_check_constant_args_pool
(
ws
,
stride
,
pad
,
node
)
if
ret
is
None
:
return
ws
,
stride
,
pad
=
ret
if
pad
!=
(
0
,
0
)
or
node
.
op
.
mode
!=
'max'
or
stride
!=
ws
:
return
x
,
z
,
gz
=
node
.
inputs
if
(
x
.
owner
and
isinstance
(
x
.
owner
.
op
,
HostFromGpu
)):
gpu_ds_grad
=
GpuDownsampleFactorMaxGrad
(
node
.
op
.
ds
,
node
.
op
.
ignore_border
)
gpu_ds_grad
=
GpuDownsampleFactorMaxGrad
(
ws
,
node
.
op
.
ignore_border
)
return
[
host_from_gpu
(
gpu_ds_grad
(
x
.
owner
.
inputs
[
0
],
as_cuda_ndarray_variable
(
z
),
as_cuda_ndarray_variable
(
gz
)))]
...
...
@@ -1931,16 +1955,16 @@ def local_gpu_downsample_factor_max_grad(node):
@local_optimizer
([
pool
.
DownsampleFactorMaxGradGrad
])
def
local_gpu_downsample_factor_max_grad_grad
(
node
):
if
isinstance
(
node
.
op
,
pool
.
DownsampleFactorMaxGradGrad
):
assert
node
.
op
.
__props__
==
(
'ds'
,
'ignore_border'
,
'st'
,
'padding'
,
'mode'
)
if
(
node
.
op
.
padding
!=
(
0
,
0
)
or
node
.
op
.
mode
!=
'max'
or
node
.
op
.
st
!=
node
.
op
.
ds
):
assert
node
.
op
.
__props__
==
(
'ignore_border'
,
'mode'
)
x
,
z
,
gx
,
ws
,
stride
,
pad
=
node
.
inputs
ret
=
_check_constant_args_pool
(
ws
,
stride
,
pad
,
node
)
if
ret
is
None
:
return
ws
,
stride
,
pad
=
ret
if
pad
!=
(
0
,
0
)
or
node
.
op
.
mode
!=
'max'
or
stride
!=
ws
:
return
x
,
z
,
gx
=
node
.
inputs
if
(
x
.
owner
and
isinstance
(
x
.
owner
.
op
,
HostFromGpu
)):
op
=
GpuDownsampleFactorMaxGradGrad
(
node
.
op
.
ds
,
node
.
op
.
ignore_border
)
op
=
GpuDownsampleFactorMaxGradGrad
(
ws
,
node
.
op
.
ignore_border
)
return
[
host_from_gpu
(
op
(
x
.
owner
.
inputs
[
0
],
as_cuda_ndarray_variable
(
z
),
as_cuda_ndarray_variable
(
gx
)))]
...
...
theano/sandbox/cuda/tests/test_blas.py
浏览文件 @
123d9007
...
...
@@ -369,12 +369,12 @@ def test_downsample():
continue
for
ignore_border
in
(
True
,
False
):
# print 'test_downsample', shp, ds, ignore_border
ds_op
=
Pool
(
ds
,
ignore_border
=
ignore_border
)
ds_op
=
Pool
(
ignore_border
=
ignore_border
)
a
=
tcn
.
shared_constructor
(
my_rand
(
*
shp
),
'a'
)
f
=
pfunc
([],
ds_op
(
tensor
.
as_tensor_variable
(
a
)),
f
=
pfunc
([],
ds_op
(
tensor
.
as_tensor_variable
(
a
)
,
ds
),
mode
=
mode_with_gpu
.
excluding
(
'cudnn'
))
f2
=
pfunc
([],
ds_op
(
tensor
.
as_tensor_variable
(
a
)),
f2
=
pfunc
([],
ds_op
(
tensor
.
as_tensor_variable
(
a
)
,
ds
),
mode
=
mode_without_gpu
)
assert
any
([
isinstance
(
node
.
op
,
tcn
.
blas
.
GpuDownsampleFactorMax
)
...
...
@@ -393,12 +393,12 @@ def test_downsample():
g
=
pfunc
(
[],
tensor
.
grad
(
ds_op
(
tensor
.
as_tensor_variable
(
a
))
.
sum
(),
tensor
.
grad
(
ds_op
(
tensor
.
as_tensor_variable
(
a
)
,
ds
)
.
sum
(),
a
),
mode
=
mode_with_gpu
.
excluding
(
'cudnn'
))
g2
=
pfunc
(
[],
tensor
.
grad
(
ds_op
(
tensor
.
as_tensor_variable
(
a
))
.
sum
(),
tensor
.
grad
(
ds_op
(
tensor
.
as_tensor_variable
(
a
)
,
ds
)
.
sum
(),
a
),
mode
=
mode_without_gpu
)
assert
any
([
isinstance
(
node
.
op
,
...
...
@@ -409,7 +409,7 @@ def test_downsample():
assert
numpy
.
allclose
(
g
(),
g2
()),
shp
ggf
=
gradient
.
Lop
(
tensor
.
grad
((
ds_op
(
tensor
.
as_tensor_variable
(
a
))
**
2
)
.
sum
(),
a
),
a
,
a
)
tensor
.
as_tensor_variable
(
a
)
,
ds
)
**
2
)
.
sum
(),
a
),
a
,
a
)
ref_mode
=
copy
.
copy
(
mode_without_gpu
)
ref_mode
.
check_py_code
=
False
...
...
theano/sandbox/cuda/tests/test_mlp.py
浏览文件 @
123d9007
...
...
@@ -381,9 +381,10 @@ def build_conv_nnet2_classif(use_gpu, isize, ksize, n_batch,
(
n_kern
,
logical_hid_shape
[
0
]
//
2
,
logical_hid_shape
[
1
]
//
2
),
shape_kern1
[
2
:],
n_kern1
,
n_batch
,
1
,
1
,
verbose
=
verbose
,
version
=
version
)
ds_op
=
pool
.
Pool
(
(
2
,
2
),
ignore_border
=
False
)
ds_op
=
pool
.
Pool
(
ignore_border
=
False
)
if
downsample_ops
:
hid
=
tensor
.
tanh
(
ds_op
(
conv_op
(
x
,
w0
)
+
b0
.
dimshuffle
((
0
,
'x'
,
'x'
))))
hid
=
tensor
.
tanh
(
ds_op
(
conv_op
(
x
,
w0
)
+
b0
.
dimshuffle
((
0
,
'x'
,
'x'
)),
(
2
,
2
)))
else
:
hid
=
tensor
.
tanh
(
(
conv_op
(
x
,
w0
)
+
b0
.
dimshuffle
(
...
...
theano/tensor/signal/downsample.py
deleted
100644 → 0
浏览文件 @
0d478806
from
__future__
import
absolute_import
,
print_function
,
division
from
.
import
pool
import
warnings
warnings
.
warn
(
"downsample module has been moved to the theano.tensor.signal.pool module."
)
max_pool_2d_same_size
=
pool
.
max_pool_2d_same_size
max_pool_2d
=
pool
.
pool_2d
DownsampleFactorMax
=
pool
.
Pool
PoolGrad
=
pool
.
PoolGrad
MaxPoolGrad
=
pool
.
MaxPoolGrad
AveragePoolGrad
=
pool
.
AveragePoolGrad
# This is for compatibility with pickled things. It should go away at
# some point.
class
DownsampleFactorMaxGrad
(
object
):
def
__new__
(
self
,
ds
,
ignore_border
,
st
=
None
,
padding
=
(
0
,
0
),
mode
=
'max'
):
if
mode
==
'max'
:
return
MaxPoolGrad
(
ds
=
ds
,
ignore_border
=
ignore_border
,
st
=
st
,
padding
=
padding
)
else
:
return
AveragePoolGrad
(
ds
=
ds
,
ignore_border
=
ignore_border
,
st
=
st
,
padding
=
padding
,
mode
=
mode
)
DownsampleFactorMaxGradGrad
=
pool
.
DownsampleFactorMaxGradGrad
theano/tensor/signal/pool.py
浏览文件 @
123d9007
...
...
@@ -9,11 +9,11 @@ from __future__ import absolute_import, print_function, division
import
warnings
import
numpy
from
six
import
integer_types
from
six.moves
import
xrange
import
six.moves.builtins
as
builtins
import
theano
from
theano
import
gof
,
OpenMPOp
,
tensor
,
Variable
,
Apply
from
theano.gradient
import
DisconnectedType
def
max_pool_2d_same_size
(
input
,
patch_size
):
...
...
@@ -27,13 +27,13 @@ def max_pool_2d_same_size(input, patch_size):
----------
input : 4-D theano tensor of input images
Input images. Max pooling will be done over the 2 last dimensions.
patch_size : tuple of length 2
patch_size : tuple of length 2
or theano vector of ints of size 2.
Size of the patch (patch height, patch width).
(2,2) will retain only one non-zero value per patch of 4 values.
"""
output
=
Pool
(
patch_size
,
True
)(
input
)
outs
=
MaxPoolGrad
(
patch_size
,
True
)(
input
,
output
,
output
)
output
=
Pool
(
True
)(
input
,
patch_size
)
outs
=
MaxPoolGrad
(
True
)(
input
,
output
,
output
,
patch_size
)
return
outs
...
...
@@ -49,17 +49,17 @@ def pool_2d(input, ds, ignore_border=None, st=None, padding=(0, 0),
----------
input : N-D theano tensor of input images
Input images. Max pooling will be done over the 2 last dimensions.
ds : tuple of length 2
ds : tuple of length 2
or theano vector of ints of size 2.
Factor by which to downscale (vertical ds, horizontal ds).
(2,2) will halve the image in each dimension.
ignore_border : bool (default None, will print a warning and set to False)
When True, (5,5) input with ds=(2,2) will generate a (2,2) output.
(3,3) otherwise.
st : tuple of two ints
st : tuple of two ints
or theano vector of ints of size 2.
Stride size, which is the number of shifts over rows/cols to get the
next pool region. If st is None, it is considered equal to ds
(no overlap on pooling regions).
padding : tuple of two ints
padding : tuple of two ints
or theano vector of ints of size 2.
(pad_h, pad_w), pad zeros to extend beyond four borders of the
images, pad_h is the size of the top and bottom margins, and
pad_w is the size of the left and right margins.
...
...
@@ -85,9 +85,8 @@ def pool_2d(input, ds, ignore_border=None, st=None, padding=(0, 0),
stacklevel
=
2
)
ignore_border
=
False
if
input
.
ndim
==
4
:
op
=
Pool
(
ds
,
ignore_border
,
st
=
st
,
padding
=
padding
,
mode
=
mode
)
output
=
op
(
input
)
op
=
Pool
(
ignore_border
,
mode
=
mode
)
output
=
op
(
input
,
ds
,
st
,
padding
)
return
output
# extract image dimensions
...
...
@@ -104,9 +103,8 @@ def pool_2d(input, ds, ignore_border=None, st=None, padding=(0, 0),
input_4D
=
tensor
.
reshape
(
input
,
new_shape
,
ndim
=
4
)
# downsample mini-batch of images
op
=
Pool
(
ds
,
ignore_border
,
st
=
st
,
padding
=
padding
,
mode
=
mode
)
output
=
op
(
input_4D
)
op
=
Pool
(
ignore_border
,
mode
=
mode
)
output
=
op
(
input_4D
,
ds
,
st
,
padding
)
# restore to original shape
outshp
=
tensor
.
join
(
0
,
input
.
shape
[:
-
2
],
output
.
shape
[
-
2
:])
...
...
@@ -143,7 +141,7 @@ class Pool(OpenMPOp):
"""
__props__
=
(
'
ds'
,
'ignore_border'
,
'st'
,
'padding
'
,
'mode'
)
__props__
=
(
'
ignore_border
'
,
'mode'
)
@staticmethod
def
out_shape
(
imgshape
,
ds
,
ignore_border
=
False
,
st
=
None
,
padding
=
(
0
,
0
)):
...
...
@@ -188,9 +186,9 @@ class Pool(OpenMPOp):
r
=
tensor
.
extract_constant
(
r
)
c
=
tensor
.
extract_constant
(
c
)
if
padding
[
0
]:
r
+=
padding
[
0
]
*
2
r
=
r
+
padding
[
0
]
*
2
if
padding
[
1
]:
c
+=
padding
[
1
]
*
2
c
=
c
+
padding
[
1
]
*
2
if
ignore_border
:
if
ds
[
0
]
==
st
[
0
]:
...
...
@@ -234,50 +232,84 @@ class Pool(OpenMPOp):
rval
=
list
(
imgshape
[:
-
2
])
+
[
nr
,
nc
]
return
rval
def
__init__
(
self
,
ds
,
ignore_border
=
False
,
st
=
None
,
padding
=
(
0
,
0
),
mode
=
'max'
,
openmp
=
None
):
def
__init__
(
self
,
ignore_border
=
False
,
mode
=
'max'
,
openmp
=
None
):
super
(
Pool
,
self
)
.
__init__
(
openmp
=
openmp
)
self
.
ds
=
tuple
(
ds
)
if
not
all
([
isinstance
(
d
,
integer_types
)
for
d
in
ds
]):
raise
ValueError
(
"Pool downsample parameters must be ints."
" Got
%
s"
%
str
(
ds
))
if
st
is
None
:
st
=
ds
assert
isinstance
(
st
,
(
tuple
,
list
))
self
.
st
=
tuple
(
st
)
self
.
ignore_border
=
ignore_border
self
.
padding
=
tuple
(
padding
)
if
self
.
padding
!=
(
0
,
0
)
and
not
ignore_border
:
raise
NotImplementedError
(
'padding works only with ignore_border=True'
)
if
self
.
padding
[
0
]
>=
self
.
ds
[
0
]
or
self
.
padding
[
1
]
>=
self
.
ds
[
1
]:
raise
NotImplementedError
(
'padding_h and padding_w must be smaller than strides'
)
if
mode
not
in
[
'max'
,
'average_inc_pad'
,
'average_exc_pad'
,
'sum'
]:
raise
ValueError
(
"Pool mode parameter only support 'max', 'sum',"
" 'average_inc_pad' and 'average_exc_pad'. Got
%
s"
%
mode
)
self
.
mode
=
mode
def
make_node
(
self
,
x
):
def
prepare_node
(
self
,
node
,
storage_map
,
compute_map
):
if
len
(
node
.
inputs
)
==
1
:
# Old interface
self
.
mode
=
node
.
op
.
mode
ws
=
theano
.
tensor
.
constant
(
node
.
op
.
ds
)
st
=
theano
.
tensor
.
constant
(
node
.
op
.
st
)
pad
=
theano
.
tensor
.
constant
(
node
.
op
.
padding
)
node
.
inputs
.
append
(
ws
)
node
.
inputs
.
append
(
st
)
node
.
inputs
.
append
(
pad
)
if
isinstance
(
ws
,
theano
.
Constant
):
storage_map
[
ws
]
=
[
ws
.
data
]
compute_map
[
ws
]
=
[
True
]
else
:
storage_map
[
ws
]
=
[
None
]
compute_map
[
ws
]
=
[
False
]
if
isinstance
(
st
,
theano
.
Constant
):
storage_map
[
st
]
=
[
st
.
data
]
compute_map
[
st
]
=
[
True
]
else
:
storage_map
[
st
]
=
[
None
]
compute_map
[
st
]
=
[
False
]
if
isinstance
(
pad
,
theano
.
Constant
):
storage_map
[
pad
]
=
[
pad
.
data
]
compute_map
[
pad
]
=
[
True
]
else
:
storage_map
[
pad
]
=
[
None
]
compute_map
[
pad
]
=
[
False
]
def
make_node
(
self
,
x
,
ws
,
stride
=
None
,
pad
=
(
0
,
0
)):
# TODO: consider restricting the dtype?
x
=
tensor
.
as_tensor_variable
(
x
)
if
stride
is
None
:
stride
=
ws
if
isinstance
(
pad
,
(
tuple
,
list
)):
if
tuple
(
pad
)
!=
(
0
,
0
)
and
not
self
.
ignore_border
:
raise
NotImplementedError
(
'padding works only with ignore_border=True'
)
if
isinstance
(
ws
,
(
tuple
,
list
)):
if
pad
[
0
]
>=
ws
[
0
]
or
pad
[
1
]
>=
ws
[
1
]:
raise
NotImplementedError
(
'padding_h and padding_w must be smaller than strides'
)
ws
=
tensor
.
as_tensor_variable
(
ws
)
stride
=
tensor
.
as_tensor_variable
(
stride
)
pad
=
tensor
.
as_tensor_variable
(
pad
)
assert
ws
.
ndim
==
1
assert
stride
.
ndim
==
1
assert
pad
.
ndim
==
1
if
x
.
type
.
ndim
!=
4
:
raise
TypeError
()
if
not
ws
.
dtype
.
startswith
(
'int'
):
raise
TypeError
(
'Pool downsample parameters must be ints.'
)
if
not
stride
.
dtype
.
startswith
(
'int'
):
raise
TypeError
(
'Stride parameters must be ints.'
)
if
not
pad
.
dtype
.
startswith
(
'int'
):
raise
TypeError
(
'Padding parameters must be ints.'
)
# If the input shape are broadcastable we can have 0 in the output shape
broad
=
x
.
broadcastable
[:
2
]
+
(
False
,
False
)
out
=
tensor
.
TensorType
(
x
.
dtype
,
broad
)
return
gof
.
Apply
(
self
,
[
x
],
[
out
()])
return
gof
.
Apply
(
self
,
[
x
,
ws
,
stride
,
pad
],
[
out
()])
def
perform
(
self
,
node
,
inp
,
out
):
x
,
=
inp
x
,
ws
,
stride
,
pad
=
inp
z
,
=
out
assert
ws
.
shape
==
stride
.
shape
==
pad
.
shape
==
(
2
,)
if
len
(
x
.
shape
)
!=
4
:
raise
NotImplementedError
(
'Pool requires 4D input for now'
)
z_shape
=
self
.
out_shape
(
x
.
shape
,
self
.
ds
,
self
.
ignore_border
,
self
.
st
,
self
.
padding
)
z_shape
=
self
.
out_shape
(
x
.
shape
,
ws
,
self
.
ignore_border
,
stride
,
pad
)
if
not
self
.
ignore_border
:
assert
z_shape
[
2
]
>
0
assert
z_shape
[
3
]
>
0
...
...
@@ -288,16 +320,16 @@ class Pool(OpenMPOp):
pr
=
zz
.
shape
[
-
2
]
# number of pooling output cols
pc
=
zz
.
shape
[
-
1
]
ds0
,
ds1
=
self
.
d
s
st0
,
st1
=
s
elf
.
st
pad_h
=
self
.
padding
[
0
]
pad_w
=
self
.
padding
[
1
]
ws0
,
ws1
=
w
s
st0
,
st1
=
s
tride
pad_h
=
pad
[
0
]
pad_w
=
pad
[
1
]
img_rows
=
x
.
shape
[
-
2
]
+
2
*
pad_h
img_cols
=
x
.
shape
[
-
1
]
+
2
*
pad_w
inc_pad
=
self
.
mode
==
'average_inc_pad'
# pad the image
if
self
.
padding
!=
(
0
,
0
):
if
(
pad_h
,
pad_w
)
!=
(
0
,
0
):
y
=
numpy
.
zeros
(
(
x
.
shape
[
0
],
x
.
shape
[
1
],
img_rows
,
img_cols
),
dtype
=
x
.
dtype
)
...
...
@@ -314,40 +346,41 @@ class Pool(OpenMPOp):
for
k
in
xrange
(
x
.
shape
[
1
]):
for
r
in
xrange
(
pr
):
row_st
=
r
*
st0
row_end
=
builtins
.
min
(
row_st
+
d
s0
,
img_rows
)
row_end
=
builtins
.
min
(
row_st
+
w
s0
,
img_rows
)
if
not
inc_pad
:
row_st
=
builtins
.
max
(
row_st
,
self
.
padding
[
0
]
)
row_st
=
builtins
.
max
(
row_st
,
pad_h
)
row_end
=
builtins
.
min
(
row_end
,
x
.
shape
[
-
2
]
+
pad_h
)
for
c
in
xrange
(
pc
):
col_st
=
c
*
st1
col_end
=
builtins
.
min
(
col_st
+
d
s1
,
img_cols
)
col_end
=
builtins
.
min
(
col_st
+
w
s1
,
img_cols
)
if
not
inc_pad
:
col_st
=
builtins
.
max
(
col_st
,
self
.
padding
[
1
]
)
col_st
=
builtins
.
max
(
col_st
,
pad_w
)
col_end
=
builtins
.
min
(
col_end
,
x
.
shape
[
-
1
]
+
pad_w
)
zz
[
n
,
k
,
r
,
c
]
=
func
(
y
[
n
,
k
,
row_st
:
row_end
,
col_st
:
col_end
])
def
infer_shape
(
self
,
node
,
in_shapes
):
shp
=
self
.
out_shape
(
in_shapes
[
0
],
self
.
ds
,
self
.
ignore_border
,
self
.
st
,
self
.
padding
)
ws
,
stride
,
pad
=
[
node
.
inputs
[
1
],
node
.
inputs
[
2
],
node
.
inputs
[
3
]]
shp
=
self
.
out_shape
(
in_shapes
[
0
],
ws
,
self
.
ignore_border
,
stride
,
pad
)
return
[
shp
]
def
grad
(
self
,
inp
,
grads
):
x
,
=
inp
x
,
ws
,
stride
,
pad
=
inp
gz
,
=
grads
disc
=
[
DisconnectedType
()()
for
i
in
inp
[
1
:]]
if
self
.
mode
==
'max'
:
maxout
=
self
(
x
)
return
[
MaxPoolGrad
(
self
.
ds
,
ignore_border
=
self
.
ignore_border
,
st
=
self
.
st
,
padding
=
self
.
padding
)(
x
,
maxout
,
gz
)]
maxout
=
self
(
x
,
ws
,
stride
,
pad
)
return
[
MaxPoolGrad
(
ignore_border
=
self
.
ignore_border
)(
x
,
maxout
,
gz
,
ws
=
ws
,
stride
=
stride
,
pad
=
pad
)]
+
disc
else
:
return
[
AveragePoolGrad
(
self
.
ds
,
ignore_border
=
self
.
ignore_border
,
st
=
self
.
st
,
padding
=
self
.
padding
,
return
[
AveragePoolGrad
(
ignore_border
=
self
.
ignore_border
,
mode
=
self
.
mode
)(
x
,
gz
)]
x
,
gz
,
ws
=
ws
,
stride
=
stride
,
pad
=
pad
)]
+
disc
def
connection_pattern
(
self
,
node
):
return
[[
1
],
[
0
],
[
0
],
[
0
]]
def
c_headers
(
self
):
headers
=
[
'<algorithm>'
]
...
...
@@ -357,21 +390,41 @@ class Pool(OpenMPOp):
def
c_code
(
self
,
node
,
name
,
inp
,
out
,
sub
):
if
self
.
mode
not
in
(
'max'
,
'sum'
,
'average_exc_pad'
,
'average_inc_pad'
):
raise
theano
.
gof
.
utils
.
MethodNotDefined
()
x
,
=
inp
x
,
ws
,
stride
,
pad
=
inp
z
,
=
out
fail
=
sub
[
'fail'
]
ignore_border
=
int
(
self
.
ignore_border
)
ds0
,
ds1
=
self
.
ds
st0
,
st1
=
self
.
st
pd0
,
pd1
=
self
.
padding
if
self
.
openmp
:
omp_parallel
=
'#pragma omp parallel for private(r_st, r_end, c_st, c_end, collector) schedule(static)'
else
:
omp_parallel
=
''
ccode
=
"""
int ws0, ws1, st0, st1, pd0, pd1;
int typenum = PyArray_ObjectType((PyObject*)
%(x)
s, 0);
int z_r, z_c; // shape of the output
int r, c; // shape of the padded_input
if(PyArray_DIM(
%(ws)
s, 0)!=2)
{
PyErr_SetString(PyExc_ValueError, "ws must be a vector of size 2");
%(fail)
s;
}
if(PyArray_DIM(
%(stride)
s, 0)!=2)
{
PyErr_SetString(PyExc_ValueError, "stride must be a vector of size 2");
%(fail)
s;
}
if(PyArray_DIM(
%(pad)
s, 0)!=2)
{
PyErr_SetString(PyExc_ValueError, "pad must be a vector of size 2");
%(fail)
s;
}
// Getting ws, stride and pad
ws0 = *((npy_intp*)PyArray_GETPTR1(
%(ws)
s, 0));
ws1 = *((npy_intp*)PyArray_GETPTR1(
%(ws)
s, 1));
st0 = *((npy_intp*)PyArray_GETPTR1(
%(stride)
s, 0));
st1 = *((npy_intp*)PyArray_GETPTR1(
%(stride)
s, 1));
pd0 = *((npy_intp*)PyArray_GETPTR1(
%(pad)
s, 0));
pd1 = *((npy_intp*)PyArray_GETPTR1(
%(pad)
s, 1));
if(PyArray_NDIM(
%(x)
s)!=4)
{
PyErr_SetString(PyExc_ValueError, "x must be a 4d ndarray");
...
...
@@ -379,9 +432,9 @@ class Pool(OpenMPOp):
}
r = PyArray_DIMS(
%(x)
s)[2];
c = PyArray_DIMS(
%(x)
s)[3];
r +=
%(pd0)
s
* 2;
c +=
%(pd1)
s
* 2;
if (
%(pd0)
s != 0 &&
%(pd1)
s
!= 0 && !
%(ignore_border)
s)
r +=
pd0
* 2;
c +=
pd1
* 2;
if (
pd0 != 0 && pd1
!= 0 && !
%(ignore_border)
s)
{
PyErr_SetString(PyExc_ValueError,
"padding must be (0,0) when ignore border is False");
...
...
@@ -390,42 +443,42 @@ class Pool(OpenMPOp):
if (
%(ignore_border)
s)
{
// '/' in C is different from '/' in python
if (r -
%(ds0)
s
< 0)
if (r -
ws0
< 0)
{
z_r = 0;
}
else
{
z_r = (r -
%(ds0)
s) /
%(st0)
s
+ 1;
z_r = (r -
ws0) / st0
+ 1;
}
if (c -
%(ds1)
s
< 0)
if (c -
ws1
< 0)
{
z_c = 0;
}
else
{
z_c = (c -
%(ds1)
s) /
%(st1)
s
+ 1;
z_c = (c -
ws1) / st1
+ 1;
}
}
else
{
// decide how many rows the output has
if (
%(st0)
s >=
%(ds0)
s
)
if (
st0 >= ws0
)
{
z_r = (r - 1) /
%(st0)
s
+ 1;
z_r = (r - 1) /
st0
+ 1;
}
else
{
z_r = std::max(0, (r - 1 -
%(ds0)
s +
%(st0)
s) /
%(st0)
s
) + 1;
z_r = std::max(0, (r - 1 -
ws0 + st0) / st0
) + 1;
}
// decide how many columns the output has
if (
%(st1)
s >=
%(ds1)
s
)
if (
st1 >= ws1
)
{
z_c = (c - 1) /
%(st1)
s
+ 1;
z_c = (c - 1) /
st1
+ 1;
}
else
{
z_c = std::max(0, (c - 1 -
%(ds1)
s +
%(st0)
s) /
%(st1)
s
) + 1;
z_c = std::max(0, (c - 1 -
ws1 + st0) / st1
) + 1;
}
assert(z_r > 0);
assert(z_c > 0);
...
...
@@ -458,30 +511,30 @@ class Pool(OpenMPOp):
int b = t
%%
PyArray_DIMS(
%(x)
s)[0];
int k = t / PyArray_DIMS(
%(x)
s)[0];
for(int i=0; i < z_r; i++){
r_st = i *
%(st0)
s
;
r_end = r_st +
%(ds0)
s
;
r_st = i *
st0
;
r_end = r_st +
ws0
;
// skip the padding
r_st = r_st <
%(pd0)
s ?
%(pd0)
s
: r_st;
r_end = r_end > (r -
%(pd0)
s) ? r -
%(pd0)
s
: r_end;
r_st = r_st <
pd0 ? pd0
: r_st;
r_end = r_end > (r -
pd0) ? r - pd0
: r_end;
// from padded_img space to img space
r_st -=
%(pd0)
s
;
r_end -=
%(pd0)
s
;
r_st -=
pd0
;
r_end -=
pd0
;
// handle the case where no padding, ignore border is True
if (
%(ignore_border)
s)
{
r_end = r_end > r ? r : r_end;
}
for(int j=0; j<z_c; j++){
c_st = j *
%(st1)
s
;
c_end = c_st +
%(ds1)
s
;
c_st = j *
st1
;
c_end = c_st +
ws1
;
// skip the padding
c_st = c_st <
%(pd1)
s ?
%(pd1)
s
: c_st;
c_end = c_end > (c -
%(pd1)
s) ? c -
%(pd1)
s
: c_end;
c_st = c_st <
pd1 ? pd1
: c_st;
c_end = c_end > (c -
pd1) ? c - pd1
: c_end;
dtype_
%(z)
s * z = (
(dtype_
%(z)
s*)(PyArray_GETPTR4(
%(z)
s, b, k, i, j)));
// change coordinates from padding_img space into img space
c_st -=
%(pd1)
s
;
c_end -=
%(pd1)
s
;
c_st -=
pd1
;
c_end -=
pd1
;
// handle the case where no padding, ignore border is True
if (
%(ignore_border)
s)
{
...
...
@@ -523,7 +576,7 @@ class Pool(OpenMPOp):
"""
elif
self
.
mode
==
'average_inc_pad'
and
self
.
ignore_border
:
ccode
+=
"""
z[0] = collector / (
%(ds0)
s *
%(ds1)
s
);
z[0] = collector / (
ws0 * ws1
);
"""
else
:
ccode
+=
"""
...
...
@@ -538,11 +591,11 @@ class Pool(OpenMPOp):
return
ccode
%
locals
()
def
c_code_cache_version
(
self
):
return
(
0
,
6
,
8
,
4
,
self
.
openmp
)
return
(
0
,
6
,
8
,
6
,
self
.
openmp
)
class
PoolGrad
(
OpenMPOp
):
__props__
=
(
'
ds'
,
'ignore_border'
,
'st'
,
'padding
'
,
'mode'
)
__props__
=
(
'
ignore_border
'
,
'mode'
)
@staticmethod
def
out_shape
(
imgshape
,
ds
,
ignore_border
=
False
,
st
=
None
,
padding
=
(
0
,
0
)):
...
...
@@ -624,13 +677,8 @@ class PoolGrad(OpenMPOp):
rval
=
list
(
imgshape
[:
-
2
])
+
[
nr
,
nc
]
return
rval
def
__init__
(
self
,
ds
,
ignore_border
,
st
=
None
,
padding
=
(
0
,
0
),
mode
=
'max'
,
openmp
=
None
):
self
.
ds
=
tuple
(
ds
)
def
__init__
(
self
,
ignore_border
,
mode
=
'max'
,
openmp
=
None
):
self
.
ignore_border
=
ignore_border
if
st
is
None
:
st
=
ds
self
.
st
=
tuple
(
st
)
self
.
padding
=
tuple
(
padding
)
if
mode
not
in
[
'max'
,
'sum'
,
'average_inc_pad'
,
'average_exc_pad'
]:
raise
ValueError
(
"Pool mode parameter only support 'max', 'sum',"
...
...
@@ -638,43 +686,86 @@ class PoolGrad(OpenMPOp):
self
.
mode
=
mode
super
(
PoolGrad
,
self
)
.
__init__
(
openmp
=
openmp
)
def
prepare_node
(
self
,
node
,
storage_map
,
compute_map
):
if
len
(
node
.
inputs
)
<
5
:
# 5 for AveragePoolGrad, 6 for MaxPoolGrad
# Old interface
self
.
mode
=
node
.
op
.
mode
ws
=
theano
.
tensor
.
constant
(
node
.
op
.
ds
)
st
=
theano
.
tensor
.
constant
(
node
.
op
.
st
)
pad
=
theano
.
tensor
.
constant
(
node
.
op
.
padding
)
node
.
inputs
.
append
(
ws
)
node
.
inputs
.
append
(
st
)
node
.
inputs
.
append
(
pad
)
if
isinstance
(
ws
,
theano
.
Constant
):
storage_map
[
ws
]
=
[
ws
.
data
]
compute_map
[
ws
]
=
[
True
]
else
:
storage_map
[
ws
]
=
[
None
]
compute_map
[
ws
]
=
[
False
]
if
isinstance
(
st
,
theano
.
Constant
):
storage_map
[
st
]
=
[
st
.
data
]
compute_map
[
st
]
=
[
True
]
else
:
storage_map
[
st
]
=
[
None
]
compute_map
[
st
]
=
[
False
]
if
isinstance
(
pad
,
theano
.
Constant
):
storage_map
[
pad
]
=
[
pad
.
data
]
compute_map
[
pad
]
=
[
True
]
else
:
storage_map
[
pad
]
=
[
None
]
compute_map
[
pad
]
=
[
False
]
def
infer_shape
(
self
,
node
,
in_shapes
):
return
[
in_shapes
[
0
]]
class
MaxPoolGrad
(
PoolGrad
):
def
__init__
(
self
,
ds
,
ignore_border
,
st
=
None
,
padding
=
(
0
,
0
)
,
openmp
=
None
):
PoolGrad
.
__init__
(
self
,
ds
,
ignore_border
,
st
,
padding
,
'max'
,
openmp
)
def
__init__
(
self
,
ignore_border
,
openmp
=
None
):
PoolGrad
.
__init__
(
self
,
ignore_border
,
mode
=
'max'
,
openmp
=
openmp
)
def
make_node
(
self
,
x
,
maxout
,
gz
):
def
make_node
(
self
,
x
,
maxout
,
gz
,
ws
,
stride
=
None
,
pad
=
(
0
,
0
)
):
# make_node should only be called by the grad function of
# Pool, so these asserts should not fail.
x
=
tensor
.
as_tensor_variable
(
x
)
maxout
=
tensor
.
as_tensor_variable
(
maxout
)
gz
=
tensor
.
as_tensor_variable
(
gz
)
if
stride
is
None
:
stride
=
ws
ws
=
tensor
.
as_tensor_variable
(
ws
)
stride
=
tensor
.
as_tensor_variable
(
stride
)
pad
=
tensor
.
as_tensor_variable
(
pad
)
assert
isinstance
(
x
,
Variable
)
and
x
.
ndim
==
4
assert
isinstance
(
maxout
,
Variable
)
and
maxout
.
ndim
==
4
assert
isinstance
(
gz
,
Variable
)
and
gz
.
ndim
==
4
return
Apply
(
self
,
[
x
,
maxout
,
gz
],
[
x
.
type
()])
assert
isinstance
(
ws
,
Variable
)
and
ws
.
ndim
==
1
assert
isinstance
(
stride
,
Variable
)
and
stride
.
ndim
==
1
assert
isinstance
(
pad
,
Variable
)
and
pad
.
ndim
==
1
if
not
ws
.
dtype
.
startswith
(
'int'
):
raise
TypeError
(
'Pool downsample parameters must be ints.'
)
if
not
stride
.
dtype
.
startswith
(
'int'
):
raise
TypeError
(
'Stride parameters must be ints.'
)
if
not
pad
.
dtype
.
startswith
(
'int'
):
raise
TypeError
(
'Padding parameters must be ints.'
)
return
Apply
(
self
,
[
x
,
maxout
,
gz
,
ws
,
stride
,
pad
],
[
x
.
type
()])
def
perform
(
self
,
node
,
inp
,
out
):
assert
self
.
mode
==
'max'
x
,
maxout
,
gz
=
inp
x
,
maxout
,
gz
,
ws
,
stride
,
pad
=
inp
gx_stg
,
=
out
assert
ws
.
shape
==
stride
.
shape
==
pad
.
shape
==
(
2
,)
# number of pooling output rows
pr
=
maxout
.
shape
[
-
2
]
# number of pooling output cols
pc
=
maxout
.
shape
[
-
1
]
ds0
,
ds1
=
self
.
d
s
st0
,
st1
=
s
elf
.
st
pad_h
=
self
.
padding
[
0
]
pad_w
=
self
.
padding
[
1
]
ws0
,
ws1
=
w
s
st0
,
st1
=
s
tride
pad_h
=
pad
[
0
]
pad_w
=
pad
[
1
]
img_rows
=
x
.
shape
[
-
2
]
+
2
*
pad_h
img_cols
=
x
.
shape
[
-
1
]
+
2
*
pad_w
# pad the image
if
self
.
padding
!=
(
0
,
0
):
if
(
pad_h
,
pad_w
)
!=
(
0
,
0
):
y
=
numpy
.
zeros
(
(
x
.
shape
[
0
],
x
.
shape
[
1
],
img_rows
,
img_cols
),
dtype
=
x
.
dtype
)
...
...
@@ -685,11 +776,11 @@ class MaxPoolGrad(PoolGrad):
for
n
in
xrange
(
x
.
shape
[
0
]):
for
k
in
xrange
(
x
.
shape
[
1
]):
for
r
in
xrange
(
pr
):
row_st
=
builtins
.
max
(
r
*
st0
,
self
.
padding
[
0
]
)
row_end
=
builtins
.
min
(
row_st
+
d
s0
,
img_rows
)
row_st
=
builtins
.
max
(
r
*
st0
,
pad_h
)
row_end
=
builtins
.
min
(
row_st
+
w
s0
,
img_rows
)
for
c
in
xrange
(
pc
):
col_st
=
builtins
.
max
(
c
*
st1
,
self
.
padding
[
1
]
)
col_end
=
builtins
.
min
(
col_st
+
d
s1
,
img_cols
)
col_st
=
builtins
.
max
(
c
*
st1
,
pad_w
)
col_end
=
builtins
.
min
(
col_st
+
w
s1
,
img_cols
)
for
row_ind
in
xrange
(
row_st
,
row_end
):
for
col_ind
in
xrange
(
col_st
,
col_end
):
if
(
maxout
[
n
,
k
,
r
,
c
]
==
y
[
n
,
k
,
row_ind
,
col_ind
]):
...
...
@@ -699,23 +790,23 @@ class MaxPoolGrad(PoolGrad):
gx_stg
[
0
]
=
gx
def
grad
(
self
,
inp
,
grads
):
x
,
maxout
,
gz
=
inp
x
,
maxout
,
gz
,
ws
,
stride
,
pad
=
inp
ggx
,
=
grads
return
[
theano
.
tensor
.
zeros_like
(
x
),
theano
.
tensor
.
zeros_like
(
maxout
),
DownsampleFactorMaxGradGrad
(
self
.
ds
,
ignore_border
=
self
.
ignore_border
,
st
=
self
.
st
,
padding
=
self
.
padding
)(
x
,
maxout
,
ggx
)]
return
([
theano
.
tensor
.
zeros_like
(
x
),
theano
.
tensor
.
zeros_like
(
maxout
),
DownsampleFactorMaxGradGrad
(
ignore_border
=
self
.
ignore_border
)(
x
,
maxout
,
ggx
,
ws
,
stride
,
pad
)]
+
[
DisconnectedType
()()
for
i
in
inp
[
3
:]])
def
connection_pattern
(
self
,
node
):
return
[[
1
],
[
1
],
[
1
],
[
0
],
[
0
],
[
0
]]
def
c_code
(
self
,
node
,
name
,
inp
,
out
,
sub
):
assert
self
.
mode
==
'max'
x
,
z
,
gz
=
inp
x
,
z
,
gz
,
ws
,
stride
,
pad
=
inp
gx
,
=
out
fail
=
sub
[
'fail'
]
ignore_border
=
int
(
self
.
ignore_border
)
ds0
,
ds1
=
self
.
ds
st0
,
st1
=
self
.
st
pd0
,
pd1
=
self
.
padding
if
self
.
openmp
:
omp_parallel
=
'#pragma omp parallel for private(r_st, r_end, c_st, c_end, maximum) schedule(static)'
else
:
...
...
@@ -725,6 +816,9 @@ class MaxPoolGrad(PoolGrad):
int x_typenum = PyArray_ObjectType((PyObject*)
%(x)
s, 0);
int z_typenum = PyArray_ObjectType((PyObject*)
%(z)
s, 0);
int gz_typenum = PyArray_ObjectType((PyObject*)
%(gz)
s, 0);
int ws0, ws1, st0, st1, pd0, pd1;
int z_r, z_c;
int r, c; // shape of the padded_input
if ((x_typenum != z_typenum) || (x_typenum != gz_typenum))
{
PyErr_SetString(PyExc_ValueError, "input types must all match");
...
...
@@ -745,14 +839,34 @@ class MaxPoolGrad(PoolGrad):
PyErr_SetString(PyExc_ValueError, "gz must be a 4d ndarray");
%(fail)
s;
}
int z_r, z_c;
if(PyArray_DIM(
%(ws)
s, 0)!=2)
{
PyErr_SetString(PyExc_ValueError, "ws must be a vector of size 2");
%(fail)
s;
}
if(PyArray_DIM(
%(stride)
s, 0)!=2)
{
PyErr_SetString(PyExc_ValueError, "stride must be a vector of size 2");
%(fail)
s;
}
if(PyArray_DIM(
%(pad)
s, 0)!=2)
{
PyErr_SetString(PyExc_ValueError, "pad must be a vector of size 2");
%(fail)
s;
}
// Getting ws, stride and pad
ws0 = *((npy_intp*)PyArray_GETPTR1(
%(ws)
s, 0));
ws1 = *((npy_intp*)PyArray_GETPTR1(
%(ws)
s, 1));
st0 = *((npy_intp*)PyArray_GETPTR1(
%(stride)
s, 0));
st1 = *((npy_intp*)PyArray_GETPTR1(
%(stride)
s, 1));
pd0 = *((npy_intp*)PyArray_GETPTR1(
%(pad)
s, 0));
pd1 = *((npy_intp*)PyArray_GETPTR1(
%(pad)
s, 1));
z_r = PyArray_DIMS(
%(z)
s)[2];
z_c = PyArray_DIMS(
%(z)
s)[3];
int r, c; // shape of the padded_input
r = PyArray_DIMS(
%(x)
s)[2];
c = PyArray_DIMS(
%(x)
s)[3];
r +=
%(pd0)
s
* 2;
c +=
%(pd1)
s
* 2;
r +=
pd0
* 2;
c +=
pd1
* 2;
// allocating memory for gx
if ((!
%(gx)
s)
|| !PyArray_ISCONTIGUOUS(
%(gx)
s)
...
...
@@ -778,23 +892,23 @@ class MaxPoolGrad(PoolGrad):
int b = t
%%
PyArray_DIMS(
%(x)
s)[0];
int k = t / PyArray_DIMS(
%(x)
s)[0];
for(int i=0; i < z_r; i++){
r_st = i *
%(st0)
s
;
r_end = r_st +
%(ds0)
s
;
r_st = i *
st0
;
r_end = r_st +
ws0
;
// skip the padding
r_st = r_st <
%(pd0)
s ?
%(pd0)
s
: r_st;
r_end = r_end > (r -
%(pd0)
s) ? r -
%(pd0)
s
: r_end;
r_st = r_st <
pd0 ? pd0
: r_st;
r_end = r_end > (r -
pd0) ? r - pd0
: r_end;
// from padded_img space to img space
r_st -=
%(pd0)
s
;
r_end -=
%(pd0)
s
;
r_st -=
pd0
;
r_end -=
pd0
;
for(int j=0; j<z_c; j++){
c_st = j *
%(st1)
s
;
c_end = c_st +
%(ds1)
s
;
c_st = j *
st1
;
c_end = c_st +
ws1
;
// skip the padding
c_st = c_st <
%(pd1)
s ?
%(pd1)
s
: c_st;
c_end = c_end > (c -
%(pd1)
s) ? c -
%(pd1)
s
: c_end;
c_st = c_st <
pd1 ? pd1
: c_st;
c_end = c_end > (c -
pd1) ? c - pd1
: c_end;
// change coordinates from padding_img space into img space
c_st -=
%(pd1)
s
;
c_end -=
%(pd1)
s
;
c_st -=
pd1
;
c_end -=
pd1
;
// the maximum value
maximum = ((dtype_
%(z)
s*)(PyArray_GETPTR4(
%(z)
s,b,k,i,j)))[0];
// the gradient corresponding to this maximum value in z
...
...
@@ -820,36 +934,48 @@ class MaxPoolGrad(PoolGrad):
"""
%
locals
()
def
c_code_cache_version
(
self
):
return
(
0
,
7
,
self
.
openmp
)
return
(
0
,
9
,
self
.
openmp
)
class
AveragePoolGrad
(
PoolGrad
):
def
__init__
(
self
,
ds
,
ignore_border
,
st
=
None
,
padding
=
(
0
,
0
),
mode
=
'average_inc_pad'
):
def
__init__
(
self
,
ignore_border
,
mode
=
'average_inc_pad'
):
assert
mode
in
[
'sum'
,
'average_inc_pad'
,
'average_exc_pad'
]
PoolGrad
.
__init__
(
self
,
ds
,
ignore_border
,
st
,
padding
,
mode
)
PoolGrad
.
__init__
(
self
,
ignore_border
,
mode
)
# There is an extra dummy parameter to match the parameter count
# of MaxPoolGrad. They have to keep the same interface because of
# the DownsampleFactorMaxGrad trick to keep old scripts working
# (see downsample.py for details on this).
def
make_node
(
self
,
x
,
gz
,
dummy
=
None
):
def
make_node
(
self
,
x
,
gz
,
ws
,
stride
=
None
,
pad
=
(
0
,
0
),
dummy
=
None
):
# make_node should only be called by the grad function of
# Pool, so these asserts should not fail.
x
=
tensor
.
as_tensor_variable
(
x
)
gz
=
tensor
.
as_tensor_variable
(
gz
)
if
stride
is
None
:
stride
=
ws
ws
=
tensor
.
as_tensor_variable
(
ws
)
stride
=
tensor
.
as_tensor_variable
(
stride
)
pad
=
tensor
.
as_tensor_variable
(
pad
)
assert
isinstance
(
x
,
Variable
)
and
x
.
ndim
==
4
assert
isinstance
(
gz
,
Variable
)
and
gz
.
ndim
==
4
return
Apply
(
self
,
[
x
,
gz
],
[
x
.
type
()])
assert
isinstance
(
ws
,
Variable
)
and
ws
.
ndim
==
1
assert
isinstance
(
stride
,
Variable
)
and
stride
.
ndim
==
1
assert
isinstance
(
pad
,
Variable
)
and
pad
.
ndim
==
1
if
not
ws
.
dtype
.
startswith
(
'int'
):
raise
TypeError
(
'Pool downsample parameters must be ints.'
)
if
not
stride
.
dtype
.
startswith
(
'int'
):
raise
TypeError
(
'Stride parameters must be ints.'
)
if
not
pad
.
dtype
.
startswith
(
'int'
):
raise
TypeError
(
'Padding parameters must be ints.'
)
return
Apply
(
self
,
[
x
,
gz
,
ws
,
stride
,
pad
],
[
x
.
type
()])
def
perform
(
self
,
node
,
inp
,
out
):
if
self
.
mode
==
'average_exc_pad'
and
self
.
padding
!=
(
0
,
0
):
raise
NotImplementedError
()
x
,
gz
=
inp
x
,
gz
,
ws
,
stride
,
pad
=
inp
gx_stg
,
=
out
z_shape
=
self
.
out_shape
(
x
.
shape
,
self
.
ds
,
self
.
ignore_border
,
self
.
st
,
self
.
padding
)
assert
ws
.
shape
==
stride
.
shape
==
pad
.
shape
==
(
2
,)
if
self
.
mode
==
'average_exc_pad'
and
pad
[
0
]
!=
0
and
pad
[
1
]
!=
0
:
raise
NotImplementedError
()
z_shape
=
self
.
out_shape
(
x
.
shape
,
ws
,
self
.
ignore_border
,
stride
,
pad
)
if
(
gx_stg
[
0
]
is
None
)
or
(
gx_stg
[
0
]
.
shape
!=
z_shape
):
gx_stg
[
0
]
=
numpy
.
empty
(
z_shape
,
dtype
=
x
.
dtype
)
zz
=
gx_stg
[
0
]
...
...
@@ -857,17 +983,17 @@ class AveragePoolGrad(PoolGrad):
pr
=
zz
.
shape
[
-
2
]
# number of pooling output cols
pc
=
zz
.
shape
[
-
1
]
ds0
,
ds1
=
self
.
d
s
st0
,
st1
=
s
elf
.
st
pad_h
=
self
.
padding
[
0
]
pad_w
=
self
.
padding
[
1
]
ws0
,
ws1
=
w
s
st0
,
st1
=
s
tride
pad_h
=
pad
[
0
]
pad_w
=
pad
[
1
]
img_rows
=
x
.
shape
[
-
2
]
+
2
*
pad_h
img_cols
=
x
.
shape
[
-
1
]
+
2
*
pad_w
inc_pad
=
self
.
mode
==
'average_inc_pad'
sum_mode
=
self
.
mode
==
'sum'
# pad the image
if
self
.
padding
!=
(
0
,
0
):
if
(
pad_h
,
pad_w
)
!=
(
0
,
0
):
y
=
numpy
.
zeros
(
(
x
.
shape
[
0
],
x
.
shape
[
1
],
img_rows
,
img_cols
),
dtype
=
x
.
dtype
)
...
...
@@ -881,15 +1007,14 @@ class AveragePoolGrad(PoolGrad):
if
sum_mode
or
inc_pad
:
row_st
=
r
*
st0
else
:
row_st
=
builtins
.
max
(
r
*
st0
,
self
.
padding
[
0
]
)
row_end
=
builtins
.
min
(
row_st
+
d
s0
,
img_rows
)
row_st
=
builtins
.
max
(
r
*
st0
,
pad_h
)
row_end
=
builtins
.
min
(
row_st
+
w
s0
,
img_rows
)
for
c
in
xrange
(
pc
):
if
sum_mode
or
inc_pad
:
col_st
=
c
*
st1
else
:
col_st
=
builtins
.
max
(
c
*
st1
,
self
.
padding
[
1
])
col_end
=
builtins
.
min
(
col_st
+
ds1
,
img_cols
)
col_st
=
builtins
.
max
(
c
*
st1
,
pad_w
)
col_end
=
builtins
.
min
(
col_st
+
ws1
,
img_cols
)
if
sum_mode
:
val
=
gz
[
n
,
k
,
r
,
c
]
else
:
...
...
@@ -901,39 +1026,26 @@ class AveragePoolGrad(PoolGrad):
gx_stg
[
0
]
=
gx
def
grad
(
self
,
inp
,
grads
):
x
,
gz
=
inp
x
,
gz
,
ws
,
stride
,
pad
=
inp
ggx
,
=
grads
return
[
theano
.
tensor
.
zeros_like
(
x
),
Pool
(
self
.
ds
,
ignore_border
=
self
.
ignore_border
,
st
=
self
.
st
,
padding
=
self
.
padding
,
mode
=
self
.
mode
)(
ggx
)]
return
([
theano
.
tensor
.
zeros_like
(
x
),
Pool
(
ignore_border
=
self
.
ignore_border
,
mode
=
self
.
mode
)(
ggx
,
ws
,
stride
,
pad
)]
+
[
DisconnectedType
()()
for
i
in
inp
[
2
:]])
def
connection_pattern
(
self
,
node
):
return
[[
1
],
[
1
],
[
0
],
[
0
],
[
0
]]
class
DownsampleFactorMaxGradGrad
(
OpenMPOp
):
__props__
=
(
'
ds'
,
'ignore_border'
,
'st'
,
'padding
'
,
'mode'
)
__props__
=
(
'
ignore_border
'
,
'mode'
)
def
__init__
(
self
,
ds
,
ignore_border
,
st
=
None
,
padding
=
(
0
,
0
),
mode
=
'max'
,
openmp
=
None
):
self
.
ds
=
tuple
(
ds
)
if
not
all
([
isinstance
(
d
,
integer_types
)
for
d
in
ds
]):
raise
ValueError
(
"Pool downsample parameters must be ints."
" Got
%
s"
%
str
(
ds
))
if
st
is
None
:
st
=
ds
assert
isinstance
(
st
,
(
tuple
,
list
))
self
.
st
=
tuple
(
st
)
def
__init__
(
self
,
ignore_border
,
mode
=
'max'
,
openmp
=
None
):
self
.
ignore_border
=
ignore_border
self
.
padding
=
tuple
(
padding
)
if
self
.
padding
!=
(
0
,
0
)
and
not
ignore_border
:
raise
NotImplementedError
(
'padding works only with ignore_border=True'
)
if
self
.
padding
[
0
]
>=
self
.
ds
[
0
]
or
self
.
padding
[
1
]
>=
self
.
ds
[
1
]:
raise
NotImplementedError
(
'padding_h and padding_w must be smaller than strides'
)
self
.
mode
=
mode
super
(
DownsampleFactorMaxGradGrad
,
self
)
.
__init__
(
openmp
=
openmp
)
assert
self
.
mode
==
'max'
def
make_node
(
self
,
x
,
maxout
,
gz
):
def
make_node
(
self
,
x
,
maxout
,
gz
,
ws
,
stride
=
None
,
pad
=
(
0
,
0
)
):
# make_node should only be called by the grad function of
# MaxPoolGrad, so these asserts should not fail.
x
=
tensor
.
as_tensor_variable
(
x
)
...
...
@@ -942,12 +1054,34 @@ class DownsampleFactorMaxGradGrad(OpenMPOp):
assert
x
.
ndim
==
4
assert
maxout
.
ndim
==
4
assert
gz
.
ndim
==
4
return
Apply
(
self
,
[
x
,
maxout
,
gz
],
[
x
.
type
()])
if
stride
is
None
:
stride
=
ws
if
isinstance
(
pad
,
(
tuple
,
list
)):
if
tuple
(
pad
)
!=
(
0
,
0
)
and
not
self
.
ignore_border
:
raise
NotImplementedError
(
'padding works only with ignore_border=True'
)
if
isinstance
(
ws
,
(
tuple
,
list
)):
if
pad
[
0
]
>=
ws
[
0
]
or
pad
[
1
]
>=
ws
[
1
]:
raise
NotImplementedError
(
'padding_h and padding_w must be smaller than strides'
)
ws
=
tensor
.
as_tensor_variable
(
ws
)
stride
=
tensor
.
as_tensor_variable
(
stride
)
pad
=
tensor
.
as_tensor_variable
(
pad
)
assert
ws
.
ndim
==
1
assert
stride
.
ndim
==
1
assert
pad
.
ndim
==
1
if
not
ws
.
dtype
.
startswith
(
'int'
):
raise
TypeError
(
'Pool downsample parameters must be ints.'
)
if
not
stride
.
dtype
.
startswith
(
'int'
):
raise
TypeError
(
'Stride parameters must be ints.'
)
if
not
pad
.
dtype
.
startswith
(
'int'
):
raise
TypeError
(
'Padding parameters must be ints.'
)
return
Apply
(
self
,
[
x
,
maxout
,
gz
,
ws
,
stride
,
pad
],
[
x
.
type
()])
def
perform
(
self
,
node
,
inp
,
out
):
x
,
maxout
,
ggx
=
inp
x
,
maxout
,
ggx
,
ws
,
stride
,
pad
=
inp
z
,
=
out
assert
ws
.
shape
==
stride
.
shape
==
pad
.
shape
==
(
2
,)
if
len
(
x
.
shape
)
!=
4
:
raise
NotImplementedError
(
'DownsampleFactorMaxGradGrad requires 4D input for now'
)
...
...
@@ -958,14 +1092,14 @@ class DownsampleFactorMaxGradGrad(OpenMPOp):
pr
=
ggz
.
shape
[
-
2
]
# number of pooling output cols
pc
=
ggz
.
shape
[
-
1
]
ds0
,
ds1
=
self
.
d
s
st0
,
st1
=
s
elf
.
st
pd0
,
pd1
=
self
.
padding
ws0
,
ws1
=
w
s
st0
,
st1
=
s
tride
pd0
,
pd1
=
pad
img_rows
=
x
.
shape
[
-
2
]
+
2
*
pd0
img_cols
=
x
.
shape
[
-
1
]
+
2
*
pd1
# pad the image and its gradients
if
self
.
padding
!=
(
0
,
0
)
:
if
pd0
!=
0
and
pd1
!=
0
:
y_padded
=
numpy
.
zeros
(
(
x
.
shape
[
0
],
x
.
shape
[
1
],
img_rows
,
img_cols
),
dtype
=
x
.
dtype
)
+
x
.
min
()
-
1
...
...
@@ -982,10 +1116,10 @@ class DownsampleFactorMaxGradGrad(OpenMPOp):
for
k
in
xrange
(
x
.
shape
[
1
]):
for
r
in
xrange
(
pr
):
row_st
=
r
*
st0
row_end
=
builtins
.
min
(
row_st
+
d
s0
,
img_rows
)
row_end
=
builtins
.
min
(
row_st
+
w
s0
,
img_rows
)
for
c
in
xrange
(
pc
):
col_st
=
c
*
st1
col_end
=
builtins
.
min
(
col_st
+
d
s1
,
img_cols
)
col_end
=
builtins
.
min
(
col_st
+
w
s1
,
img_cols
)
for
row_ind
in
xrange
(
row_st
,
row_end
):
for
col_ind
in
xrange
(
col_st
,
col_end
):
if
(
maxout
[
n
,
k
,
r
,
c
]
==
y_padded
[
n
,
k
,
row_ind
,
col_ind
]):
...
...
@@ -995,38 +1129,63 @@ class DownsampleFactorMaxGradGrad(OpenMPOp):
return
[
in_shapes
[
1
]]
def
grad
(
self
,
inp
,
grads
):
x
,
maxout
,
ggx
=
inp
x
,
maxout
,
ggx
,
ws
,
stride
,
pad
=
inp
gz
,
=
grads
return
[
theano
.
tensor
.
zeros_like
(
x
),
theano
.
tensor
.
zeros_like
(
maxout
),
MaxPoolGrad
(
self
.
ds
,
ignore_border
=
self
.
ignore_border
,
st
=
self
.
st
,
padding
=
self
.
padding
)(
x
,
maxout
,
gz
)]
MaxPoolGrad
(
ignore_border
=
self
.
ignore_border
)(
x
,
maxout
,
gz
,
ws
,
stride
,
pad
),
DisconnectedType
()(),
DisconnectedType
()(),
DisconnectedType
()()]
def
connection_pattern
(
self
,
node
):
return
[[
1
],
[
1
],
[
1
],
[
0
],
[
0
],
[
0
]]
def
c_code
(
self
,
node
,
name
,
inp
,
out
,
sub
):
if
self
.
mode
!=
'max'
:
raise
theano
.
gof
.
utils
.
MethodNotDefined
()
x
,
maxout
,
ggx
=
inp
x
,
maxout
,
ggx
,
ws
,
stride
,
pad
=
inp
z
,
=
out
# the grad of grad
fail
=
sub
[
'fail'
]
ignore_border
=
int
(
self
.
ignore_border
)
ds0
,
ds1
=
self
.
ds
st0
,
st1
=
self
.
st
pd0
,
pd1
=
self
.
padding
if
self
.
openmp
:
omp_parallel
=
'#pragma omp parallel for private(r_st, r_end, c_st, c_end, maximum) schedule(static)'
else
:
omp_parallel
=
''
return
"""
int ws0, ws1, st0, st1, pd0, pd1;
int z_typenum = PyArray_ObjectType((PyObject*)
%(maxout)
s, 0);
int z_r, z_c;
int r, c; // shape of the padded_input
if(PyArray_DIM(
%(ws)
s, 0)!=2)
{
PyErr_SetString(PyExc_ValueError, "ws must be a vector of size 2");
%(fail)
s;
}
if(PyArray_DIM(
%(stride)
s, 0)!=2)
{
PyErr_SetString(PyExc_ValueError, "stride must be a vector of size 2");
%(fail)
s;
}
if(PyArray_DIM(
%(pad)
s, 0)!=2)
{
PyErr_SetString(PyExc_ValueError, "pad must be a vector of size 2");
%(fail)
s;
}
// Getting ws, stride and pad
ws0 = *((npy_intp*)PyArray_GETPTR1(
%(ws)
s, 0));
ws1 = *((npy_intp*)PyArray_GETPTR1(
%(ws)
s, 1));
st0 = *((npy_intp*)PyArray_GETPTR1(
%(stride)
s, 0));
st1 = *((npy_intp*)PyArray_GETPTR1(
%(stride)
s, 1));
pd0 = *((npy_intp*)PyArray_GETPTR1(
%(pad)
s, 0));
pd1 = *((npy_intp*)PyArray_GETPTR1(
%(pad)
s, 1));
z_r = PyArray_DIMS(
%(maxout)
s)[2];
z_c = PyArray_DIMS(
%(maxout)
s)[3];
int r, c; // shape of the padded_input
r = PyArray_DIMS(
%(x)
s)[2];
c = PyArray_DIMS(
%(x)
s)[3];
r +=
%(pd0)
s
* 2;
c +=
%(pd1)
s
* 2;
r +=
pd0
* 2;
c +=
pd1
* 2;
// allocating memory for output
if ((!
%(z)
s)
|| !PyArray_ISCONTIGUOUS(
%(z)
s)
...
...
@@ -1050,23 +1209,23 @@ class DownsampleFactorMaxGradGrad(OpenMPOp):
int b = t
%%
PyArray_DIMS(
%(x)
s)[0];
int k = t / PyArray_DIMS(
%(x)
s)[0];
for(int i=0; i < z_r; i++){
r_st = i *
%(st0)
s
;
r_end = r_st +
%(ds0)
s
;
r_st = i *
st0
;
r_end = r_st +
ws0
;
// skip the padding
r_st = r_st <
%(pd0)
s ?
%(pd0)
s
: r_st;
r_end = r_end > (r -
%(pd0)
s) ? r -
%(pd0)
s
: r_end;
r_st = r_st <
pd0 ? pd0
: r_st;
r_end = r_end > (r -
pd0) ? r - pd0
: r_end;
// from padded_img space to img space
r_st -=
%(pd0)
s
;
r_end -=
%(pd0)
s
;
r_st -=
pd0
;
r_end -=
pd0
;
for(int j=0; j<z_c; j++){
c_st = j *
%(st1)
s
;
c_end = c_st +
%(ds1)
s
;
c_st = j *
st1
;
c_end = c_st +
ws1
;
// skip the padding
c_st = c_st <
%(pd1)
s ?
%(pd1)
s
: c_st;
c_end = c_end > (c -
%(pd1)
s) ? c -
%(pd1)
s
: c_end;
c_st = c_st <
pd1 ? pd1
: c_st;
c_end = c_end > (c -
pd1) ? c - pd1
: c_end;
// from padding_img space into img space
c_st -=
%(pd1)
s
;
c_end -=
%(pd1)
s
;
c_st -=
pd1
;
c_end -=
pd1
;
// the maximum value
maximum = ((dtype_
%(maxout)
s*)(PyArray_GETPTR4(
%(maxout)
s,b,k,i,j)))[0];
// z at this position
...
...
@@ -1090,4 +1249,4 @@ class DownsampleFactorMaxGradGrad(OpenMPOp):
"""
%
locals
()
def
c_code_cache_version
(
self
):
return
(
0
,
1
,
self
.
openmp
)
return
(
0
,
3
,
self
.
openmp
)
theano/tensor/signal/tests/old_pool_interface.pkl
0 → 100644
浏览文件 @
123d9007
File added
theano/tensor/signal/tests/test_pool.py
浏览文件 @
123d9007
from
__future__
import
absolute_import
,
print_function
,
division
from
nose.plugins.skip
import
SkipTest
from
itertools
import
product
import
os
import
unittest
from
six
import
reraise
from
six.moves
import
cPickle
import
six.moves.builtins
as
builtins
import
sys
import
numpy
...
...
@@ -14,8 +19,6 @@ from theano.tensor.signal.pool import (Pool, pool_2d,
max_pool_2d_same_size
,
DownsampleFactorMaxGradGrad
)
from
theano.tensor.signal.downsample
import
DownsampleFactorMaxGrad
from
theano
import
function
...
...
@@ -197,9 +200,8 @@ class TestDownsampleFactorMax(utt.InferShapeTester):
utt
.
assert_allclose
(
output_val
,
numpy_output_val
)
# Pool op
maxpool_op
=
Pool
(
maxpoolshp
,
ignore_border
=
ignore_border
,
mode
=
mode
)(
images
)
maxpool_op
=
Pool
(
ignore_border
=
ignore_border
,
mode
=
mode
)(
images
,
maxpoolshp
)
output_shape
=
Pool
.
out_shape
(
imval
.
shape
,
maxpoolshp
,
ignore_border
=
ignore_border
)
...
...
@@ -245,9 +247,8 @@ class TestDownsampleFactorMax(utt.InferShapeTester):
"outshape is
%
s, calculated shape is
%
s"
%
(
outputshp
,
numpy_output_val
.
shape
))
maxpool_op
=
\
Pool
(
maxpoolshp
,
ignore_border
=
ignore_border
,
st
=
stride
,
mode
=
mode
)(
images
)
Pool
(
ignore_border
=
ignore_border
,
mode
=
mode
)(
images
,
maxpoolshp
,
stride
)
f
=
function
([
images
],
maxpool_op
)
output_val
=
f
(
imval
)
utt
.
assert_allclose
(
output_val
,
numpy_output_val
)
...
...
@@ -286,9 +287,8 @@ class TestDownsampleFactorMax(utt.InferShapeTester):
"outshape is
%
s, calculated shape is
%
s"
%
(
outputshp
,
numpy_output_val
.
shape
))
maxpool_op
=
\
Pool
(
maxpoolshp
,
ignore_border
=
ignore_border
,
st
=
stride
,
mode
=
mode
)(
images
)
Pool
(
ignore_border
=
ignore_border
,
mode
=
mode
)(
images
,
maxpoolshp
,
stride
)
f
=
function
([
images
],
maxpool_op
)
output_val
=
f
(
imval
)
utt
.
assert_allclose
(
output_val
,
numpy_output_val
)
...
...
@@ -315,10 +315,8 @@ class TestDownsampleFactorMax(utt.InferShapeTester):
numpy_output_val
=
self
.
numpy_max_pool_2d_stride_padding
(
imval
,
maxpoolsize
,
ignore_border
,
stridesize
,
paddingsize
,
mode
)
maxpool_op
=
Pool
(
maxpoolsize
,
ignore_border
=
ignore_border
,
st
=
stridesize
,
padding
=
paddingsize
,
mode
=
mode
)(
images
)
maxpool_op
=
Pool
(
ignore_border
=
ignore_border
,
mode
=
mode
)(
images
,
maxpoolsize
,
stridesize
,
paddingsize
)
f
=
function
([
images
],
maxpool_op
)
output_val
=
f
(
imval
)
utt
.
assert_allclose
(
output_val
,
numpy_output_val
)
...
...
@@ -340,12 +338,8 @@ class TestDownsampleFactorMax(utt.InferShapeTester):
paddingsize
=
paddingsizes
[
i
]
def
mp
(
input
):
return
Pool
(
maxpoolsize
,
ignore_border
=
True
,
st
=
stridesize
,
padding
=
paddingsize
,
mode
=
mode
,
)(
input
)
return
Pool
(
ignore_border
=
True
,
mode
=
mode
)(
input
,
maxpoolsize
,
stridesize
,
paddingsize
)
utt
.
verify_grad
(
mp
,
[
imval
],
rng
=
rng
)
def
test_DownsampleFactorMax_grad
(
self
):
...
...
@@ -361,9 +355,8 @@ class TestDownsampleFactorMax(utt.InferShapeTester):
'average_inc_pad'
,
'average_exc_pad'
]):
def
mp
(
input
):
return
Pool
(
maxpoolshp
,
ignore_border
=
ignore_border
,
mode
=
mode
)(
input
)
return
Pool
(
ignore_border
=
ignore_border
,
mode
=
mode
)(
input
,
maxpoolshp
)
utt
.
verify_grad
(
mp
,
[
imval
],
rng
=
rng
)
def
test_DownsampleFactorMax_grad_st
(
self
):
...
...
@@ -381,9 +374,8 @@ class TestDownsampleFactorMax(utt.InferShapeTester):
'average_exc_pad'
],
stridesizes
):
def
mp
(
input
):
return
Pool
(
maxpoolshp
,
ignore_border
=
ignore_border
,
st
=
stride
,
mode
=
mode
)(
input
)
return
Pool
(
ignore_border
=
ignore_border
,
mode
=
mode
)(
input
,
maxpoolshp
,
stride
)
utt
.
verify_grad
(
mp
,
[
imval
],
rng
=
rng
)
def
test_DownsampleFactorMax_grad_st_extra
(
self
):
...
...
@@ -404,10 +396,8 @@ class TestDownsampleFactorMax(utt.InferShapeTester):
maxpoolshp
=
maxpoolshps
[
indx
]
for
ignore_border
in
[
True
,
False
]:
def
mp
(
input
):
return
Pool
(
maxpoolshp
,
ignore_border
=
ignore_border
,
st
=
stride
,
mode
=
mode
)(
input
)
return
Pool
(
ignore_border
=
ignore_border
,
mode
=
mode
)(
input
,
maxpoolshp
,
stride
)
utt
.
verify_grad
(
mp
,
[
imval
],
rng
=
rng
)
def
test_DownsampleFactorMaxGrad_grad
(
self
):
...
...
@@ -426,11 +416,9 @@ class TestDownsampleFactorMax(utt.InferShapeTester):
grad_val
=
rng
.
rand
(
*
grad_shape
)
*
10.0
def
mp
(
input
,
grad
):
out
=
Pool
(
maxpoolshp
,
ignore_border
=
ignore_border
)(
input
)
grad_op
=
MaxPoolGrad
(
maxpoolshp
,
ignore_border
=
ignore_border
)
return
grad_op
(
input
,
out
,
grad
)
out
=
Pool
(
ignore_border
=
ignore_border
)(
input
,
maxpoolshp
)
grad_op
=
MaxPoolGrad
(
ignore_border
=
ignore_border
)
return
grad_op
(
input
,
out
,
grad
,
maxpoolshp
)
utt
.
verify_grad
(
mp
,
[
imval
,
grad_val
],
rng
=
rng
)
...
...
@@ -451,9 +439,9 @@ class TestDownsampleFactorMax(utt.InferShapeTester):
grad_val
=
rng
.
rand
(
*
grad_shape
)
*
10.0
def
mp
(
input
,
grad
):
grad_op
=
AveragePoolGrad
(
avgpoolshp
,
ignore_border
=
ignore_border
,
mode
=
mode
)
return
grad_op
(
input
,
grad
)
grad_op
=
AveragePoolGrad
(
ignore_border
=
ignore_border
,
mode
=
mode
)
return
grad_op
(
input
,
grad
,
avgpoolshp
)
utt
.
verify_grad
(
mp
,
[
imval
,
grad_val
],
rng
=
rng
)
...
...
@@ -474,13 +462,10 @@ class TestDownsampleFactorMax(utt.InferShapeTester):
grad_val
=
rng
.
rand
(
*
grad_shape
)
def
mp
(
input
,
grad
):
out
=
Pool
(
maxpoolshp
,
ignore_border
=
ignore_border
,
st
=
stride
)(
input
)
grad_op
=
MaxPoolGrad
(
maxpoolshp
,
ignore_border
=
ignore_border
,
st
=
stride
)
return
grad_op
(
input
,
out
,
grad
)
out
=
Pool
(
ignore_border
=
ignore_border
)(
input
,
maxpoolshp
,
stride
)
grad_op
=
MaxPoolGrad
(
ignore_border
=
ignore_border
)
return
grad_op
(
input
,
out
,
grad
,
maxpoolshp
,
stride
)
utt
.
verify_grad
(
mp
,
[
imval
,
grad_val
],
rng
=
rng
)
...
...
@@ -503,9 +488,8 @@ class TestDownsampleFactorMax(utt.InferShapeTester):
def
mp
(
input
,
grad
):
grad_op
=
AveragePoolGrad
(
avgpoolshp
,
ignore_border
=
ignore_border
,
st
=
stride
,
mode
=
mode
)
return
grad_op
(
input
,
grad
)
ignore_border
=
ignore_border
,
mode
=
mode
)
return
grad_op
(
input
,
grad
,
avgpoolshp
,
stride
)
utt
.
verify_grad
(
mp
,
[
imval
,
grad_val
],
rng
=
rng
)
...
...
@@ -531,13 +515,10 @@ class TestDownsampleFactorMax(utt.InferShapeTester):
grad_val
=
rng
.
rand
(
*
grad_shape
)
def
mp
(
input
,
grad
):
out
=
Pool
(
maxpoolshp
,
ignore_border
=
ignore_border
,
st
=
stride
)(
input
)
grad_op
=
MaxPoolGrad
(
maxpoolshp
,
ignore_border
=
ignore_border
,
st
=
stride
)
return
grad_op
(
input
,
out
,
grad
)
out
=
Pool
(
ignore_border
=
ignore_border
)(
input
,
maxpoolshp
,
stride
)
grad_op
=
MaxPoolGrad
(
ignore_border
=
ignore_border
)
return
grad_op
(
input
,
out
,
grad
,
maxpoolshp
,
stride
)
# skip the grad verification when the output is empty
if
numpy
.
prod
(
grad_shape
)
==
0
:
...
...
@@ -567,10 +548,9 @@ class TestDownsampleFactorMax(utt.InferShapeTester):
grad_val
=
rng
.
rand
(
*
grad_shape
)
def
mp
(
input
,
grad
):
grad_op
=
AveragePoolGrad
(
avgpoolshp
,
ignore_border
=
ignore_border
,
st
=
stride
,
mode
=
mode
)
return
grad_op
(
input
,
grad
)
grad_op
=
AveragePoolGrad
(
ignore_border
=
ignore_border
,
mode
=
mode
)
return
grad_op
(
input
,
grad
,
avgpoolshp
,
stride
)
# skip the grad verification when the output is empty
if
numpy
.
prod
(
grad_shape
)
==
0
:
...
...
@@ -598,14 +578,11 @@ class TestDownsampleFactorMax(utt.InferShapeTester):
grad_val
=
rng
.
rand
(
*
grad_shape
)
*
10.0
def
mp
(
input
,
grad
):
out
=
Pool
(
maxpoolsize
,
ignore_border
=
True
,
st
=
stridesize
,
padding
=
paddingsize
,
)(
input
)
grad_op
=
MaxPoolGrad
(
maxpoolsize
,
ignore_border
=
True
,
st
=
stridesize
,
padding
=
paddingsize
)
return
grad_op
(
input
,
out
,
grad
)
out
=
Pool
(
ignore_border
=
True
)(
input
,
maxpoolsize
,
stridesize
,
paddingsize
)
grad_op
=
MaxPoolGrad
(
ignore_border
=
True
)
return
grad_op
(
input
,
out
,
grad
,
maxpoolsize
,
stridesize
,
paddingsize
)
utt
.
verify_grad
(
mp
,
[
imval
,
grad_val
],
rng
=
rng
)
def
test_AveragePoolPaddingStride_grad_grad
(
self
):
...
...
@@ -630,10 +607,8 @@ class TestDownsampleFactorMax(utt.InferShapeTester):
grad_val
=
rng
.
rand
(
*
grad_shape
)
*
10.0
def
mp
(
input
,
grad
):
grad_op
=
AveragePoolGrad
(
avgpoolsize
,
ignore_border
=
True
,
st
=
stridesize
,
padding
=
paddingsize
,
mode
=
mode
)
return
grad_op
(
input
,
grad
)
grad_op
=
AveragePoolGrad
(
ignore_border
=
True
,
mode
=
mode
)
return
grad_op
(
input
,
grad
,
avgpoolsize
,
stridesize
,
paddingsize
)
utt
.
verify_grad
(
mp
,
[
imval
,
grad_val
],
rng
=
rng
)
def
test_DownsampleFactorMax_hessian
(
self
):
...
...
@@ -669,16 +644,12 @@ class TestDownsampleFactorMax(utt.InferShapeTester):
paddingsize
=
paddingsizes
[
i
]
def
mp
(
input1
,
input2
):
pooled_out
=
Pool
(
maxpoolsize
,
ignore_border
=
True
,
st
=
stridesize
,
padding
=
paddingsize
,
)(
input1
)
out
=
DownsampleFactorMaxGradGrad
(
ds
=
maxpoolsize
,
ignore_border
=
True
,
st
=
stridesize
,
padding
=
paddingsize
)(
input1
,
pooled_out
,
input2
)
op1
=
Pool
(
ignore_border
=
True
)
pooled_out
=
op1
(
input1
,
maxpoolsize
,
stride
=
stridesize
,
pad
=
paddingsize
)
op2
=
DownsampleFactorMaxGradGrad
(
ignore_border
=
True
)
out
=
op2
(
input1
,
pooled_out
,
input2
,
ws
=
maxpoolsize
,
stride
=
stridesize
,
pad
=
paddingsize
)
return
out
utt
.
verify_grad
(
mp
,
[
imval1
,
imval2
],
rng
=
rng
)
...
...
@@ -813,19 +784,18 @@ class TestDownsampleFactorMax(utt.InferShapeTester):
continue
# checking shapes generated by Pool
self
.
_compile_and_check
([
image
],
[
Pool
(
maxpoolshp
,
ignore_border
=
ignore_border
,
padding
=
padding
)(
image
)],
[
Pool
(
ignore_border
=
ignore_border
)
(
image
,
maxpoolshp
,
pad
=
padding
)],
[
image_val
],
Pool
)
# checking shapes generated by MaxPoolGrad
maxout_val
=
rng
.
rand
(
*
out_shapes
[
k
][
i
][
j
])
gz_val
=
rng
.
rand
(
*
out_shapes
[
k
][
i
][
j
])
self
.
_compile_and_check
([
image
,
maxout
,
gz
],
[
MaxPoolGrad
(
maxpoolshp
,
ignore_border
=
ignore_border
,
padding
=
padding
)
(
image
,
maxout
,
gz
)],
[
MaxPoolGrad
(
ignore_border
=
ignore_border
)
(
image
,
maxout
,
gz
,
maxpoolshp
,
pad
=
padding
)],
[
image_val
,
maxout_val
,
gz_val
],
MaxPoolGrad
,
warn
=
False
)
...
...
@@ -835,33 +805,75 @@ class TestDownsampleFactorMax(utt.InferShapeTester):
image_val
=
rng
.
rand
(
4
,
6
,
1
,
1
)
self
.
_compile_and_check
(
[
image
],
[
Pool
((
2
,
2
),
ignore_border
=
True
,
padding
=
(
0
,
0
))(
image
)],
[
Pool
(
ignore_border
=
True
)(
image
,
(
2
,
2
),
pad
=
(
0
,
0
))],
[
image_val
],
Pool
)
def
test_DownsampleFactorMaxGrad
(
self
):
im
=
theano
.
tensor
.
tensor4
()
maxout
=
theano
.
tensor
.
tensor4
()
grad
=
theano
.
tensor
.
tensor4
()
def
test_pooling_with_tensor_vars
(
self
):
x
=
tensor
.
ftensor4
()
window_size
=
tensor
.
ivector
()
stride
=
tensor
.
ivector
()
padding
=
tensor
.
ivector
()
data
=
numpy
.
random
.
normal
(
0
,
1
,
(
1
,
1
,
5
,
5
))
.
astype
(
'float32'
)
# checking variable params vs fixed params
for
ignore_border
in
[
True
,
False
]:
for
mode
in
[
'max'
,
'sum'
,
'average_inc_pad'
,
'average_exc_pad'
]:
y
=
pool_2d
(
x
,
window_size
,
ignore_border
,
stride
,
padding
,
mode
)
dx
=
theano
.
gradient
.
grad
(
y
.
sum
(),
x
)
var_fct
=
theano
.
function
([
x
,
window_size
,
stride
,
padding
],
[
y
,
dx
])
for
ws
in
(
4
,
2
,
5
):
for
st
in
(
2
,
3
):
for
pad
in
(
0
,
1
):
if
(
pad
>
st
or
st
>
ws
or
(
pad
!=
0
and
not
ignore_border
)
or
(
mode
==
'average_exc_pad'
and
pad
!=
0
)):
continue
y
=
pool_2d
(
x
,
(
ws
,
ws
),
ignore_border
,
(
st
,
st
),
(
pad
,
pad
),
mode
)
dx
=
theano
.
gradient
.
grad
(
y
.
sum
(),
x
)
fix_fct
=
theano
.
function
([
x
],
[
y
,
dx
])
var_y
,
var_dx
=
var_fct
(
data
,
(
ws
,
ws
),
(
st
,
st
),
(
pad
,
pad
))
fix_y
,
fix_dx
=
fix_fct
(
data
)
utt
.
assert_allclose
(
var_y
,
fix_y
)
utt
.
assert_allclose
(
var_dx
,
fix_dx
)
def
test_old_pool_interface
(
self
):
if
sys
.
version_info
[
0
]
!=
3
:
# Only tested with python 3 because of pickling issues.
raise
SkipTest
(
'Skip old pool interface with python 2.x'
)
# 1. Load the old version
testfile_dir
=
os
.
path
.
dirname
(
os
.
path
.
realpath
(
__file__
))
fname
=
'old_pool_interface.pkl'
with
open
(
os
.
path
.
join
(
testfile_dir
,
fname
),
'rb'
)
as
fp
:
try
:
old_fct
=
cPickle
.
load
(
fp
,
encoding
=
'latin1'
)
except
ImportError
:
# Windows sometimes fail with nonsensical errors like:
# ImportError: No module named type
# ImportError: No module named copy_reg
# when "type" and "copy_reg" are builtin modules.
if
sys
.
platform
==
'win32'
:
exc_type
,
exc_value
,
exc_trace
=
sys
.
exc_info
()
reraise
(
SkipTest
,
exc_value
,
exc_trace
)
raise
# 2. Create the new version
x
=
theano
.
tensor
.
ftensor4
()
y
=
pool_2d
(
x
,
(
2
,
2
),
mode
=
'max'
,
ignore_border
=
True
)
z
=
pool_2d
(
x
,
(
2
,
2
),
mode
=
'average_exc_pad'
,
ignore_border
=
True
)
dy_dx
=
theano
.
gradient
.
grad
(
y
.
sum
(),
x
)
dz_dx
=
theano
.
gradient
.
grad
(
z
.
sum
(),
x
)
new_fct
=
theano
.
function
([
x
],
[
y
,
z
,
dy_dx
,
dz_dx
])
# 3. Assert that the answer is the same
rng
=
numpy
.
random
.
RandomState
(
utt
.
fetch_seed
())
image_val
=
rng
.
rand
(
4
,
6
,
7
,
9
)
.
astype
(
numpy
.
float32
)
old_out
=
old_fct
(
image_val
)
new_out
=
new_fct
(
image_val
)
for
o
,
n
in
zip
(
old_out
,
new_out
):
utt
.
assert_allclose
(
o
,
n
)
for
mode
in
[
'max'
,
'sum'
,
'average_inc_pad'
,
'average_exc_pad'
]:
f
=
theano
.
function
([
im
,
maxout
,
grad
],
DownsampleFactorMaxGrad
(
ds
=
(
3
,
3
),
ignore_border
=
False
,
mode
=
mode
)(
im
,
maxout
,
grad
),
on_unused_input
=
'ignore'
)
if
mode
==
'max'
:
assert
any
(
isinstance
(
n
.
op
,
MaxPoolGrad
)
for
n
in
f
.
maker
.
fgraph
.
toposort
())
assert
not
any
(
isinstance
(
n
.
op
,
AveragePoolGrad
)
for
n
in
f
.
maker
.
fgraph
.
toposort
())
else
:
assert
not
any
(
isinstance
(
n
.
op
,
MaxPoolGrad
)
for
n
in
f
.
maker
.
fgraph
.
toposort
())
assert
any
(
isinstance
(
n
.
op
,
AveragePoolGrad
)
for
n
in
f
.
maker
.
fgraph
.
toposort
())
if
__name__
==
'__main__'
:
unittest
.
main
()
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论