Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
P
pytensor
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
testgroup
pytensor
Commits
c675144a
提交
c675144a
authored
5月 25, 2017
作者:
notoraptor
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Add special implementations for dnn_conv, dnn_gradinput, dnn_gradweight
that take algo, alpha and beta as parameters. Rewrite tests to handle both 2D and 3D conv correctly. Simplify gradinput and gradweight tests.
上级
546daeff
隐藏空白字符变更
内嵌
并排
正在显示
1 个修改的文件
包含
222 行增加
和
121 行删除
+222
-121
check_dnn.py
theano/gpuarray/tests/check_dnn.py
+222
-121
没有找到文件。
theano/gpuarray/tests/check_dnn.py
浏览文件 @
c675144a
...
@@ -6,38 +6,150 @@ import numpy as np
...
@@ -6,38 +6,150 @@ import numpy as np
import
theano
import
theano
import
theano.tests.unittest_tools
as
utt
import
theano.tests.unittest_tools
as
utt
from
theano.configdefaults
import
(
SUPPORTED_DNN_CONV_ALGO_FWD
,
SUPPORTED_DNN_CONV_ALGO_BWD_FILTER
,
SUPPORTED_DNN_CONV_ALGO_BWD_DATA
)
from
theano.compile.ops
import
shape_i_op
from
theano.configdefaults
import
(
SUPPORTED_DNN_CONV_ALGO_FWD
,
SUPPORTED_DNN_CONV3D_ALGO_FWD
,
SUPPORTED_DNN_CONV_ALGO_BWD_FILTER
,
SUPPORTED_DNN_CONV3D_ALGO_BWD_FILTER
,
SUPPORTED_DNN_CONV_ALGO_BWD_DATA
,
SUPPORTED_DNN_CONV3D_ALGO_BWD_DATA
)
from
theano.tensor.nnet.abstract_conv
import
get_conv_output_shape
,
assert_conv_shape
from
theano.tensor.opt
import
Assert
from
.config
import
mode_with_gpu
,
ref_cast
from
.config
import
mode_with_gpu
,
ref_cast
from
..
import
dnn
from
..basic_ops
import
infer_context_name
,
as_gpuarray_variable
,
gpu_contiguous
,
GpuAllocEmpty
from
..dnn
import
(
GpuDnnConvDesc
,
GpuDnnConv
,
GpuDnnConvGradW
,
GpuDnnConvGradI
,
version
,
get_precision
)
PRECISIONS
=
(
'float16'
,
'float32'
,
'float64'
)
SUPPORTED_DNN_CONV_PRECISION
=
(
'float16'
,
'float32'
,
'float64'
)
def
get_available_precisions
():
def
get_available_precisions
():
# Starting from floatX and up to max supported precision (float64).
# Starting from floatX up to max supported precision (float64).
return
SUPPORTED_DNN_CONV_PRECISION
[
SUPPORTED_DNN_CONV_PRECISION
.
index
(
theano
.
config
.
floatX
):]
return
PRECISIONS
[
PRECISIONS
.
index
(
theano
.
config
.
floatX
):]
def
array_like_conv_output
(
inputs_shape
,
filters_shape
,
border_mode
,
subsample
,
dilation
):
# Return an random array with inferred convolution output shape.
out_shp
=
get_conv_output_shape
(
inputs_shape
,
filters_shape
,
border_mode
,
subsample
,
filter_dilation
=
dilation
)
out_shp
=
assert_conv_shape
(
out_shp
)
return
np
.
random
.
random
(
out_shp
)
.
astype
(
theano
.
config
.
floatX
)
# We provide a special implementation of dnn_conv, dnn_gradweight and dnn_gradinput
# that take algo, alpha, beta and out as parameters.
def
dnn_conv
(
img
,
kerns
,
alpha
=
1
,
beta
=
0
,
out
=
None
,
border_mode
=
'valid'
,
subsample
=
(
1
,
1
),
dilation
=
(
1
,
1
),
conv_mode
=
'conv'
,
algo
=
None
,
precision
=
None
):
# Establish dtype in which to perform the computation of the convolution
precision
=
get_precision
(
precision
,
[
img
,
kerns
])
ctx_name
=
infer_context_name
(
img
,
kerns
)
img
=
gpu_contiguous
(
img
)
kerns
=
gpu_contiguous
(
kerns
)
desc
=
GpuDnnConvDesc
(
border_mode
=
border_mode
,
subsample
=
subsample
,
dilation
=
dilation
,
conv_mode
=
conv_mode
,
precision
=
precision
)(
kerns
.
shape
)
desc_op
=
desc
.
owner
.
op
# We can use Shape_i and bypass the infer_shape here as this is on
# the input of node and it will always be present.
ishape
=
[
shape_i_op
(
i
)(
img
)
for
i
in
range
(
img
.
ndim
)]
kshape
=
[
shape_i_op
(
i
)(
kerns
)
for
i
in
range
(
kerns
.
ndim
)]
out_shp
=
get_conv_output_shape
(
ishape
,
kshape
,
desc_op
.
border_mode
,
desc_op
.
subsample
,
filter_dilation
=
dilation
)
out_shp
=
assert_conv_shape
(
out_shp
)
if
beta
!=
0
:
assert
out
is
not
None
out
=
as_gpuarray_variable
(
out
,
ctx_name
)
out
=
gpu_contiguous
(
out
)
check
=
Assert
(
'GpuDnnConv: qiven output (for beta not null) does not have expected shape'
)
real_out
=
check
(
out
,
theano
.
tensor
.
all
(
theano
.
tensor
.
eq
(
out
.
shape
,
out_shp
)))
else
:
real_out
=
GpuAllocEmpty
(
dtype
=
img
.
dtype
,
context_name
=
ctx_name
)(
*
out_shp
)
return
GpuDnnConv
(
algo
=
algo
)(
img
,
kerns
,
real_out
,
desc
,
alpha
,
beta
)
def
dnn_gradweight
(
img
,
topgrad
,
kerns_shp
,
alpha
=
1
,
beta
=
0
,
out
=
None
,
border_mode
=
'valid'
,
subsample
=
(
1
,
1
),
dilation
=
(
1
,
1
),
conv_mode
=
'conv'
,
algo
=
None
,
precision
=
None
):
ctx_name
=
infer_context_name
(
img
,
topgrad
)
img
=
as_gpuarray_variable
(
img
,
ctx_name
)
topgrad
=
as_gpuarray_variable
(
topgrad
,
ctx_name
)
img
=
gpu_contiguous
(
img
)
topgrad
=
gpu_contiguous
(
topgrad
)
kerns_shp
=
theano
.
tensor
.
as_tensor_variable
(
kerns_shp
)
precision
=
get_precision
(
precision
,
[
img
,
topgrad
])
desc
=
GpuDnnConvDesc
(
border_mode
=
border_mode
,
subsample
=
subsample
,
dilation
=
dilation
,
conv_mode
=
conv_mode
,
precision
=
precision
)(
kerns_shp
)
if
beta
==
0
:
real_out
=
GpuAllocEmpty
(
dtype
=
img
.
dtype
,
context_name
=
ctx_name
)(
*
kerns_shp
)
else
:
assert
out
is
not
None
out
=
as_gpuarray_variable
(
out
,
ctx_name
)
out
=
gpu_contiguous
(
out
)
check
=
Assert
(
'GpuDnnConvGradW: qiven output (for beta not null) does not have expected shape'
)
real_out
=
check
(
out
,
theano
.
tensor
.
all
(
theano
.
tensor
.
eq
(
out
.
shape
,
kerns_shp
)))
return
GpuDnnConvGradW
(
algo
=
algo
)(
img
,
topgrad
,
real_out
,
desc
,
alpha
,
beta
)
def
dnn_gradinput
(
kerns
,
topgrad
,
img_shp
,
alpha
=
1
,
beta
=
0
,
out
=
None
,
border_mode
=
'valid'
,
subsample
=
(
1
,
1
),
dilation
=
(
1
,
1
),
conv_mode
=
'conv'
,
algo
=
None
,
precision
=
None
):
ctx_name
=
infer_context_name
(
kerns
,
topgrad
)
kerns
=
as_gpuarray_variable
(
kerns
,
ctx_name
)
topgrad
=
as_gpuarray_variable
(
topgrad
,
ctx_name
)
kerns
=
gpu_contiguous
(
kerns
)
topgrad
=
gpu_contiguous
(
topgrad
)
img_shp
=
theano
.
tensor
.
as_tensor_variable
(
img_shp
)
precision
=
get_precision
(
precision
,
[
kerns
,
topgrad
])
desc
=
GpuDnnConvDesc
(
border_mode
=
border_mode
,
subsample
=
subsample
,
dilation
=
dilation
,
conv_mode
=
conv_mode
,
precision
=
precision
)(
kerns
.
shape
)
if
beta
==
0
:
real_out
=
GpuAllocEmpty
(
dtype
=
kerns
.
dtype
,
context_name
=
ctx_name
)(
*
img_shp
)
else
:
assert
out
is
not
None
out
=
as_gpuarray_variable
(
out
,
ctx_name
)
out
=
gpu_contiguous
(
out
)
check
=
Assert
(
'GpuDnnConvGradI: qiven output (for beta not null) does not have expected shape'
)
real_out
=
check
(
out
,
theano
.
tensor
.
all
(
theano
.
tensor
.
eq
(
out
.
shape
,
img_shp
)))
return
GpuDnnConvGradI
(
algo
=
algo
)(
kerns
,
topgrad
,
real_out
,
desc
,
alpha
,
beta
)
class
BaseTestDnnConv
(
object
):
class
BaseTestDnnConv
(
object
):
functions_checked_for_fwd
=
False
_
functions_checked_for_fwd
=
False
functions_checked_for_gradinput
=
False
_
functions_checked_for_gradinput
=
False
functions_checked_for_gradweights
=
False
_functions_checked_for_gradweight
=
False
# Abstract
function
s.
# Abstract
attribute
s.
def
get_gpu_conv_function
(
self
):
fwd_algorithms
=
None
raise
NotImplementedError
bwd_filter_algorithms
=
None
bwd_data_algorithms
=
None
def
get_cpu_conv_class
(
self
):
cpu_conv_class
=
None
raise
NotImplementedError
cpu_gradinput_class
=
None
cpu_gradweight_class
=
None
# Abstract methods.
def
get_cases
(
self
):
def
get_cases
(
self
):
# Should return an iterable of test cases. Each test case is a tuple (or list) with following syntax:
# Should return an iterable of test cases. Each test case is a tuple (or list) with following syntax:
# ( (input shape, filter shape, subsample, dilation), border mode, convolution mode )
# ( (input shape, filter shape, subsample, dilation), border mode, convolution mode
, alpha, beta
)
raise
NotImplementedError
raise
NotImplementedError
def
run_conv3d_fwd
(
self
,
algo
,
precision
,
inputs_shape
,
filters_shape
,
subsample
,
dilation
,
border_mode
,
conv_mode
):
# Run methods.
def
run_conv_fwd
(
self
,
algo
,
precision
,
parameters
):
(
inputs_shape
,
filters_shape
,
subsample
,
dilation
),
border_mode
,
conv_mode
,
alpha
,
beta
=
parameters
inputs_val
=
np
.
random
.
random
(
inputs_shape
)
.
astype
(
theano
.
config
.
floatX
)
inputs_val
=
np
.
random
.
random
(
inputs_shape
)
.
astype
(
theano
.
config
.
floatX
)
filters_val
=
np
.
random
.
random
(
filters_shape
)
.
astype
(
theano
.
config
.
floatX
)
filters_val
=
np
.
random
.
random
(
filters_shape
)
.
astype
(
theano
.
config
.
floatX
)
...
@@ -49,92 +161,91 @@ class BaseTestDnnConv(object):
...
@@ -49,92 +161,91 @@ class BaseTestDnnConv(object):
inputs
=
theano
.
shared
(
inputs_val
)
inputs
=
theano
.
shared
(
inputs_val
)
filters
=
theano
.
shared
(
filters_val
)
filters
=
theano
.
shared
(
filters_val
)
out
=
None
if
beta
==
0
else
array_like_conv_output
(
inputs_shape
,
filters_shape
,
border_mode
,
subsample
,
dilation
)
# Compile a theano function for the cuDNN implementation
# Compile a theano function for the cuDNN implementation
conv
=
self
.
get_gpu_conv_function
()(
img
=
inputs
,
kerns
=
filters
,
conv
=
dnn_conv
(
img
=
inputs
,
kerns
=
filters
,
alpha
=
alpha
,
beta
=
beta
,
out
=
out
,
border_mode
=
border_mode
,
border_mode
=
border_mode
,
subsample
=
subsample
,
subsample
=
subsample
,
dilation
=
dilation
,
conv_mode
=
conv_mode
,
algo
=
algo
,
precision
=
precision
)
dilation
=
dilation
,
conv_mode
=
conv_mode
,
algo
=
algo
,
precision
=
precision
)
f
=
theano
.
function
([],
conv
,
mode
=
mode_with_gpu
)
f
=
theano
.
function
([],
conv
,
mode
=
mode_with_gpu
)
# If conv_mode is 'conv' the reference implementation should use
# If conv_mode is 'conv' the reference implementation should use
# filters filpped according to the width, height and time axis
# filters filpped according to the width, height and time axis
if
conv_mode
==
'conv'
:
if
conv_mode
==
'conv'
:
flipped_filters
=
filters
[:,
:,
::
-
1
,
::
-
1
,
::
-
1
]
if
inputs
.
ndim
==
5
:
flipped_filters
=
filters
[:,
:,
::
-
1
,
::
-
1
,
::
-
1
]
else
:
flipped_filters
=
filters
[:,
:,
::
-
1
,
::
-
1
]
else
:
else
:
flipped_filters
=
filters
flipped_filters
=
filters
# Compile a theano function for the reference implementation
# Compile a theano function for the reference implementation
conv_ref
=
self
.
get_cpu_conv_class
()(
border_mode
=
border_mode
,
conv_ref
=
self
.
cpu_conv_class
(
border_mode
=
border_mode
,
subsample
=
subsample
,
subsample
=
subsample
,
filter_dilation
=
dilation
,
filter_dilation
=
dilation
)(
ref_cast
(
inputs
),
flipped_filters
)
)(
ref_cast
(
inputs
),
flipped_filters
)
f_ref
=
theano
.
function
([],
conv_ref
,
mode
=
"FAST_RUN"
)
f_ref
=
theano
.
function
([],
conv_ref
,
mode
=
"FAST_RUN"
)
if
not
self
.
functions_checked_for_fwd
:
if
not
self
.
_
functions_checked_for_fwd
:
self
.
functions_checked_for_fwd
=
True
self
.
_
functions_checked_for_fwd
=
True
assert
any
(
isinstance
(
node
.
op
,
dnn
.
GpuDnnConv
)
for
node
in
f
.
maker
.
fgraph
.
apply_nodes
)
assert
any
(
isinstance
(
node
.
op
,
GpuDnnConv
)
for
node
in
f
.
maker
.
fgraph
.
apply_nodes
)
assert
not
any
(
isinstance
(
node
.
op
,
(
dnn
.
GpuDnnConvGradI
,
dnn
.
GpuDnnConvGradW
))
assert
not
any
(
isinstance
(
node
.
op
,
(
GpuDnnConvGradI
,
GpuDnnConvGradW
))
for
node
in
f
.
maker
.
fgraph
.
apply_nodes
)
for
node
in
f
.
maker
.
fgraph
.
apply_nodes
)
assert
not
any
(
isinstance
(
node
.
op
,
(
dnn
.
GpuDnnConv
,
dnn
.
GpuDnnConvGradW
,
dnn
.
GpuDnnConvGradI
))
assert
not
any
(
isinstance
(
node
.
op
,
(
GpuDnnConv
,
GpuDnnConvGradW
,
GpuDnnConvGradI
))
for
node
in
f_ref
.
maker
.
fgraph
.
apply_nodes
)
for
node
in
f_ref
.
maker
.
fgraph
.
apply_nodes
)
# Compare the results of the two implementations
# Compare the results of the two implementations
res_ref
=
f_ref
()
res_ref
=
f_ref
()
res
=
f
()
res
=
f
()
# raise rtol to make the test pass with more seed.
rtol
=
None
# Raise tolerance for float16
if
theano
.
config
.
floatX
==
'float16'
:
rtol
=
6e-2
utt
.
assert_allclose
(
res_ref
,
res
,
rtol
=
rtol
)
def
run_conv3d_gradinput
(
self
,
algo
,
precision
,
inputs_shape
,
filters_shape
,
subsample
,
dilation
,
border_mode
,
conv_mode
):
# Raise tolerance for float16
rtol
=
6e-2
if
theano
.
config
.
floatX
==
'float16'
else
None
if
beta
==
0
:
utt
.
assert_allclose
(
alpha
*
res_ref
,
res
,
rtol
=
rtol
)
else
:
print
(
'(conv: beta not null) '
,
end
=
''
)
utt
.
assert_allclose
(
alpha
*
res_ref
+
beta
*
out
,
res
,
rtol
=
rtol
)
theano
.
config
.
dnn
.
conv
.
algo_bwd_data
=
algo
def
run_conv_gradinput
(
self
,
algo
,
precision
,
parameters
):
theano
.
config
.
dnn
.
conv
.
precision
=
precision
(
inputs_shape
,
filters_shape
,
subsample
,
dilation
),
border_mode
,
conv_mode
,
alpha
,
beta
=
parameters
inputs_val
=
np
.
random
.
random
(
inputs_shape
)
.
astype
(
theano
.
config
.
floatX
)
inputs_val
=
np
.
random
.
random
(
inputs_shape
)
.
astype
(
theano
.
config
.
floatX
)
filters_val
=
np
.
random
.
random
(
filters_shape
)
.
astype
(
theano
.
config
.
floatX
)
filters_val
=
np
.
random
.
random
(
filters_shape
)
.
astype
(
theano
.
config
.
floatX
)
topgrad_val
=
array_like_conv_output
(
inputs_shape
,
filters_shape
,
border_mode
,
subsample
,
dilation
)
inputs
=
theano
.
shared
(
inputs_val
)
filters
=
theano
.
shared
(
filters_val
)
filters
=
theano
.
shared
(
filters_val
)
topgrad
=
theano
.
shared
(
topgrad_val
)
# Compile a theano function for the cuDNN implementation
# Compile a theano function for the cuDNN implementation
conv
=
self
.
get_gpu_conv_function
()(
img
=
inputs
,
kerns
=
filters
,
grad_i
=
dnn_gradinput
(
filters
,
topgrad
,
inputs_shape
,
alpha
=
alpha
,
beta
=
beta
,
out
=
inputs_val
,
border_mode
=
border_mode
,
border_mode
=
border_mode
,
subsample
=
subsample
,
dilation
=
dilation
,
conv_mode
=
conv_mode
,
subsample
=
subsample
,
algo
=
algo
,
precision
=
precision
)
dilation
=
dilation
,
conv_mode
=
conv_mode
)
grad_i
=
theano
.
tensor
.
grad
(
conv
.
sum
(),
[
inputs
])
f
=
theano
.
function
([],
grad_i
,
mode
=
mode_with_gpu
)
f
=
theano
.
function
([],
grad_i
,
mode
=
mode_with_gpu
)
# If conv_mode is 'conv' the reference implementation should use
# If conv_mode is 'conv' the reference implementation should use
# filters filpped according to the width, height and time axis
# filters filpped according to the width, height and time axis
if
conv_mode
==
'conv'
:
if
conv_mode
==
'conv'
:
flipped_filters
=
filters
[:,
:,
::
-
1
,
::
-
1
,
::
-
1
]
if
filters
.
ndim
==
5
:
flipped_filters
=
filters
[:,
:,
::
-
1
,
::
-
1
,
::
-
1
]
else
:
flipped_filters
=
filters
[:,
:,
::
-
1
,
::
-
1
]
else
:
else
:
flipped_filters
=
filters
flipped_filters
=
filters
# Compile a theano function for the reference implementation
# Compile a theano function for the reference implementation
conv_ref
=
self
.
get_cpu_conv_class
()(
border_mode
=
border_mode
,
grad_i_ref
=
self
.
cpu_gradinput_class
(
border_mode
=
border_mode
,
subsample
=
subsample
,
subsample
=
subsample
,
filter_dilation
=
dilation
,
filter_dilation
=
dilation
)(
ref_cast
(
inputs
),
flipped_filters
)
)(
ref_cast
(
flipped_filters
),
ref_cast
(
topgrad
),
inputs_shape
[
2
:])
grad_i_ref
,
=
theano
.
tensor
.
grad
(
conv_ref
.
sum
(),
[
inputs
])
f_ref
=
theano
.
function
([],
grad_i_ref
,
mode
=
"FAST_RUN"
)
f_ref
=
theano
.
function
([],
grad_i_ref
,
mode
=
"FAST_RUN"
)
if
not
self
.
functions_checked_for_gradinput
:
if
not
self
.
_
functions_checked_for_gradinput
:
self
.
functions_checked_for_gradinput
=
True
self
.
_
functions_checked_for_gradinput
=
True
assert
any
(
isinstance
(
node
.
op
,
dnn
.
GpuDnnConvGradI
)
for
node
in
f
.
maker
.
fgraph
.
apply_nodes
)
assert
any
(
isinstance
(
node
.
op
,
GpuDnnConvGradI
)
for
node
in
f
.
maker
.
fgraph
.
apply_nodes
)
assert
not
any
(
isinstance
(
node
.
op
,
(
dnn
.
GpuDnnConv
,
dnn
.
GpuDnnConvGradW
))
assert
not
any
(
isinstance
(
node
.
op
,
(
GpuDnnConv
,
GpuDnnConvGradW
))
for
node
in
f
.
maker
.
fgraph
.
apply_nodes
)
for
node
in
f
.
maker
.
fgraph
.
apply_nodes
)
assert
not
any
(
isinstance
(
node
.
op
,
(
dnn
.
GpuDnnConv
,
dnn
.
GpuDnnConvGradW
,
dnn
.
GpuDnnConvGradI
))
assert
not
any
(
isinstance
(
node
.
op
,
(
GpuDnnConv
,
GpuDnnConvGradW
,
GpuDnnConvGradI
))
for
node
in
f_ref
.
maker
.
fgraph
.
apply_nodes
)
for
node
in
f_ref
.
maker
.
fgraph
.
apply_nodes
)
# Compare the results of the two implementations
# Compare the results of the two implementations
...
@@ -142,56 +253,44 @@ class BaseTestDnnConv(object):
...
@@ -142,56 +253,44 @@ class BaseTestDnnConv(object):
res
=
f
()
res
=
f
()
# Needed for big size for some seed
# Needed for big size for some seed
# raise rtol to make the test pass with more seed.
# raise rtol to make the test pass with more seed.
rtol
=
None
# Raise tolerance for float16
if
theano
.
config
.
floatX
==
'float16'
:
rtol
=
5e-2
utt
.
assert_allclose
(
res_ref
,
res
,
rtol
=
rtol
)
def
run_conv3d_gradweights
(
self
,
algo
,
precision
,
inputs_shape
,
filters_shape
,
subsample
,
dilation
,
border_mode
,
conv_mode
):
# Raise tolerance for float16
rtol
=
5e-2
if
theano
.
config
.
floatX
==
'float16'
else
None
utt
.
assert_allclose
(
alpha
*
res_ref
+
beta
*
inputs_val
,
res
,
rtol
=
rtol
)
theano
.
config
.
dnn
.
conv
.
algo_bwd_filter
=
algo
def
run_conv_gradweight
(
self
,
algo
,
precision
,
parameters
):
theano
.
config
.
dnn
.
conv
.
precision
=
precision
(
inputs_shape
,
filters_shape
,
subsample
,
dilation
),
border_mode
,
conv_mode
,
alpha
,
beta
=
parameters
inputs_val
=
np
.
random
.
random
(
inputs_shape
)
.
astype
(
theano
.
config
.
floatX
)
inputs_val
=
np
.
random
.
random
(
inputs_shape
)
.
astype
(
theano
.
config
.
floatX
)
filters_val
=
np
.
random
.
random
(
filters_shape
)
.
astype
(
theano
.
config
.
floatX
)
filters_val
=
np
.
random
.
random
(
filters_shape
)
.
astype
(
theano
.
config
.
floatX
)
topgrad_val
=
array_like_conv_output
(
inputs_shape
,
filters_shape
,
border_mode
,
subsample
,
dilation
)
inputs
=
theano
.
shared
(
inputs_val
)
inputs
=
theano
.
shared
(
inputs_val
)
filters
=
theano
.
shared
(
filters
_val
)
topgrad
=
theano
.
shared
(
topgrad
_val
)
# Compile a theano function for the cuDNN implementation
# Compile a theano function for the cuDNN implementation
conv
=
self
.
get_gpu_conv_function
()(
img
=
inputs
,
kerns
=
filters
,
grad_w
=
dnn_gradweight
(
inputs
,
topgrad
,
filters_shape
,
alpha
=
alpha
,
beta
=
beta
,
out
=
filters_val
,
border_mode
=
border_mode
,
border_mode
=
border_mode
,
subsample
=
subsample
,
dilation
=
dilation
,
conv_mode
=
conv_mode
,
subsample
=
subsample
,
algo
=
algo
,
precision
=
precision
)
dilation
=
dilation
,
conv_mode
=
conv_mode
)
grad_w
,
=
theano
.
tensor
.
grad
(
conv
.
sum
(),
[
filters
])
f
=
theano
.
function
([],
grad_w
,
mode
=
mode_with_gpu
)
f
=
theano
.
function
([],
grad_w
,
mode
=
mode_with_gpu
)
# If conv_mode is 'conv' the reference implementation should use
# filters filpped according to the width, height and time axis
if
conv_mode
==
'conv'
:
flipped_filters
=
filters
[:,
:,
::
-
1
,
::
-
1
,
::
-
1
]
else
:
flipped_filters
=
filters
# Compile a theano function for the reference implementation
# Compile a theano function for the reference implementation
conv_ref
=
self
.
get_cpu_conv_class
()(
border_mode
=
border_mode
,
grad_w_ref
=
self
.
cpu_gradweight_class
(
border_mode
=
border_mode
,
subsample
=
subsample
,
subsample
=
subsample
,
filter_dilation
=
dilation
,
filter_dilation
=
dilation
)(
ref_cast
(
inputs
),
ref_cast
(
topgrad
),
)(
ref_cast
(
inputs
),
flipped_filters
)
filters_shape
[
2
:])
grad_w_ref
,
=
theano
.
tensor
.
grad
(
conv_ref
.
sum
(),
[
filters
])
if
conv_mode
==
'conv'
:
grad_w_ref
=
grad_w_ref
[:,
:,
::
-
1
,
::
-
1
,
::
-
1
]
f_ref
=
theano
.
function
([],
grad_w_ref
,
mode
=
"FAST_RUN"
)
f_ref
=
theano
.
function
([],
grad_w_ref
,
mode
=
"FAST_RUN"
)
if
not
self
.
functions_checked_for_gradweights
:
if
not
self
.
_functions_checked_for_gradweight
:
self
.
functions_checked_for_gradweights
=
True
self
.
_functions_checked_for_gradweight
=
True
assert
any
(
isinstance
(
node
.
op
,
dnn
.
GpuDnnConvGradW
)
for
node
in
f
.
maker
.
fgraph
.
apply_nodes
)
assert
any
(
isinstance
(
node
.
op
,
GpuDnnConvGradW
)
for
node
in
f
.
maker
.
fgraph
.
apply_nodes
)
assert
not
any
(
isinstance
(
node
.
op
,
(
dnn
.
GpuDnnConv
,
dnn
.
GpuDnnConvGradI
))
assert
not
any
(
isinstance
(
node
.
op
,
(
GpuDnnConv
,
GpuDnnConvGradI
))
for
node
in
f
.
maker
.
fgraph
.
apply_nodes
)
for
node
in
f
.
maker
.
fgraph
.
apply_nodes
)
assert
not
any
(
isinstance
(
node
.
op
,
(
dnn
.
GpuDnnConv
,
dnn
.
GpuDnnConvGradW
,
dnn
.
GpuDnnConvGradI
))
assert
not
any
(
isinstance
(
node
.
op
,
(
GpuDnnConv
,
GpuDnnConvGradW
,
GpuDnnConvGradI
))
for
node
in
f_ref
.
maker
.
fgraph
.
apply_nodes
)
for
node
in
f_ref
.
maker
.
fgraph
.
apply_nodes
)
# Compare the results of the two implementations
# Compare the results of the two implementations
...
@@ -199,40 +298,40 @@ class BaseTestDnnConv(object):
...
@@ -199,40 +298,40 @@ class BaseTestDnnConv(object):
res
=
f
()
res
=
f
()
# Needed for big size for some seed
# Needed for big size for some seed
# raise rtol to make the test pass with more seed.
# raise rtol to make the test pass with more seed.
rtol
=
None
# Raise tolerance for float16
# Raise tolerance for float16
if
theano
.
config
.
floatX
==
'float16'
:
rtol
=
5e-2
if
theano
.
config
.
floatX
==
'float16'
else
None
rtol
=
5e-2
utt
.
assert_allclose
(
alpha
*
res_ref
+
beta
*
filters_val
,
res
,
rtol
=
rtol
)
utt
.
assert_allclose
(
res_ref
,
res
,
rtol
=
rtol
)
# Iterable test methods.
def
test_fwd
(
self
):
def
test_fwd
(
self
):
for
precision
in
get_available_precisions
():
for
precision
in
get_available_precisions
():
for
algo
in
SUPPORTED_DNN_CONV_ALGO_FWD
:
for
algo
in
self
.
fwd_algorithms
:
for
(
inputs_shape
,
filters_shape
,
subsample
,
dilation
),
border_mode
,
conv_mode
in
self
.
get_cases
():
for
parameters
in
self
.
get_cases
():
yield
(
self
.
run_conv3d_fwd
,
algo
,
precision
,
inputs_shape
,
filters_shape
,
yield
(
self
.
run_conv_fwd
,
algo
,
precision
,
parameters
)
subsample
,
dilation
,
border_mode
,
conv_mode
)
def
test_gradinput
(
self
):
def
test_gradinput
(
self
):
for
precision
in
get_available_precisions
():
for
precision
in
get_available_precisions
():
for
algo
in
SUPPORTED_DNN_CONV_ALGO_BWD_DATA
:
for
algo
in
self
.
bwd_data_algorithms
:
for
(
inputs_shape
,
filters_shape
,
subsample
,
dilation
),
border_mode
,
conv_mode
in
self
.
get_cases
():
for
parameters
in
self
.
get_cases
():
yield
(
self
.
run_conv3d_gradinput
,
algo
,
precision
,
inputs_shape
,
filters_shape
,
yield
(
self
.
run_conv_gradinput
,
algo
,
precision
,
parameters
)
subsample
,
dilation
,
border_mode
,
conv_mode
)
def
test_gradweight
s
(
self
):
def
test_gradweight
(
self
):
for
precision
in
get_available_precisions
():
for
precision
in
get_available_precisions
():
for
algo
in
SUPPORTED_DNN_CONV_ALGO_BWD_FILTER
:
for
algo
in
self
.
bwd_filter_algorithms
:
for
(
inputs_shape
,
filters_shape
,
subsample
,
dilation
),
border_mode
,
conv_mode
in
self
.
get_cases
():
for
parameters
in
self
.
get_cases
():
yield
(
self
.
run_conv3d_gradweights
,
algo
,
precision
,
inputs_shape
,
filters_shape
,
yield
(
self
.
run_conv_gradweight
,
algo
,
precision
,
parameters
)
subsample
,
dilation
,
border_mode
,
conv_mode
)
class
TestDnnConv2D
(
BaseTestDnnConv
):
class
TestDnnConv2D
(
BaseTestDnnConv
):
def
get_gpu_conv_function
(
self
):
fwd_algorithms
=
SUPPORTED_DNN_CONV_ALGO_FWD
return
dnn
.
dnn_conv
bwd_filter_algorithms
=
SUPPORTED_DNN_CONV_ALGO_BWD_FILTER
bwd_data_algorithms
=
SUPPORTED_DNN_CONV_ALGO_BWD_DATA
def
get_cpu_conv_class
(
self
):
cpu_conv_class
=
theano
.
tensor
.
nnet
.
corr
.
CorrMM
return
theano
.
tensor
.
nnet
.
corr
.
CorrMM
cpu_gradinput_class
=
theano
.
tensor
.
nnet
.
corr
.
CorrMM_gradInputs
cpu_gradweight_class
=
theano
.
tensor
.
nnet
.
corr
.
CorrMM_gradWeights
def
get_cases
(
self
):
def
get_cases
(
self
):
# Inspired from:
# Inspired from:
...
@@ -265,17 +364,19 @@ class TestDnnConv2D(BaseTestDnnConv):
...
@@ -265,17 +364,19 @@ class TestDnnConv2D(BaseTestDnnConv):
local_dilations
=
[
default_dilation
]
local_dilations
=
[
default_dilation
]
iterables
+=
[
product
(
product
([
input_shape
],
[
filter_shape
],
local_subsamples
,
local_dilations
),
iterables
+=
[
product
(
product
([
input_shape
],
[
filter_shape
],
local_subsamples
,
local_dilations
),
border_modes
,
border_modes
,
conv_modes
)]
conv_modes
,
[
1
],
[
0
]
)]
return
chain
(
*
iterables
)
return
chain
(
*
iterables
)
class
TestDnnConv3D
(
BaseTestDnnConv
):
class
TestDnnConv3D
(
BaseTestDnnConv
):
def
get_gpu_conv_function
(
self
):
fwd_algorithms
=
SUPPORTED_DNN_CONV3D_ALGO_FWD
return
dnn
.
dnn_conv3d
bwd_filter_algorithms
=
SUPPORTED_DNN_CONV3D_ALGO_BWD_FILTER
bwd_data_algorithms
=
SUPPORTED_DNN_CONV3D_ALGO_BWD_DATA
def
get_cpu_conv_class
(
self
):
cpu_conv_class
=
theano
.
tensor
.
nnet
.
corr3d
.
Corr3dMM
return
theano
.
tensor
.
nnet
.
corr3d
.
Corr3dMM
cpu_gradinput_class
=
theano
.
tensor
.
nnet
.
corr3d
.
Corr3dMM_gradInputs
cpu_gradweight_class
=
theano
.
tensor
.
nnet
.
corr3d
.
Corr3dMM_gradWeights
def
get_cases
(
self
):
def
get_cases
(
self
):
# small case for quick test.
# small case for quick test.
...
@@ -285,7 +386,7 @@ class TestDnnConv3D(BaseTestDnnConv):
...
@@ -285,7 +386,7 @@ class TestDnnConv3D(BaseTestDnnConv):
dilation
=
(
1
,
1
,
1
)
dilation
=
(
1
,
1
,
1
)
border_mode
=
'valid'
border_mode
=
'valid'
conv_mode
=
'conv'
conv_mode
=
'conv'
return
(((
input_shape
,
filter_shape
,
subsample
,
dilation
),
border_mode
,
conv_mode
),)
return
(((
input_shape
,
filter_shape
,
subsample
,
dilation
),
border_mode
,
conv_mode
,
2.1
,
-
5.7
),)
def
get_cases_real
(
self
):
def
get_cases_real
(
self
):
# Copy of: theano.gpuarray.tests.test_dnn.get_conv3d_test_cases
# Copy of: theano.gpuarray.tests.test_dnn.get_conv3d_test_cases
...
@@ -315,7 +416,7 @@ class TestDnnConv3D(BaseTestDnnConv):
...
@@ -315,7 +416,7 @@ class TestDnnConv3D(BaseTestDnnConv):
[(
6
,
2
,
2
,
2
,
2
),
(
4
,
2
,
1
,
1
,
3
),
(
1
,
1
,
1
),
(
1
,
1
,
1
)],
[(
6
,
2
,
2
,
2
,
2
),
(
4
,
2
,
1
,
1
,
3
),
(
1
,
1
,
1
),
(
1
,
1
,
1
)],
[(
6
,
2
,
2
,
2
,
2
),
(
4
,
2
,
5
,
5
,
5
),
(
1
,
1
,
1
),
(
1
,
1
,
1
)]]
[(
6
,
2
,
2
,
2
,
2
),
(
4
,
2
,
5
,
5
,
5
),
(
1
,
1
,
1
),
(
1
,
1
,
1
)]]
if
dnn
.
version
()
>=
6000
:
if
version
()
>=
6000
:
test_shapes
.
extend
([
test_shapes
.
extend
([
[(
8
,
1
,
20
,
12
,
15
),
(
5
,
1
,
6
,
3
,
4
),
(
1
,
1
,
2
),
(
3
,
2
,
1
)],
[(
8
,
1
,
20
,
12
,
15
),
(
5
,
1
,
6
,
3
,
4
),
(
1
,
1
,
2
),
(
3
,
2
,
1
)],
[(
8
,
1
,
20
,
12
,
15
),
(
5
,
1
,
6
,
3
,
4
),
(
2
,
2
,
1
),
(
1
,
2
,
3
)]])
[(
8
,
1
,
20
,
12
,
15
),
(
5
,
1
,
6
,
3
,
4
),
(
2
,
2
,
1
),
(
1
,
2
,
3
)]])
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论