提交 d327e49e authored 作者: Gijs van Tulder's avatar Gijs van Tulder

CorrMM and Corr3dMM should always check provided output shapes.

上级 8edcf207
...@@ -123,7 +123,7 @@ class BaseCorrMM(gof.OpenMPOp): ...@@ -123,7 +123,7 @@ class BaseCorrMM(gof.OpenMPOp):
def c_code_cache_version(self): def c_code_cache_version(self):
# raise this whenever modifying any of the support_code_files # raise this whenever modifying any of the support_code_files
return (1, self.openmp, blas_header_version()) return (2, self.openmp, blas_header_version())
def c_support_code_apply(self, node, nodename): def c_support_code_apply(self, node, nodename):
# REMEMBER TO RAISE c_code_cache_version when changing any of # REMEMBER TO RAISE c_code_cache_version when changing any of
...@@ -234,17 +234,17 @@ class BaseCorrMM(gof.OpenMPOp): ...@@ -234,17 +234,17 @@ class BaseCorrMM(gof.OpenMPOp):
# When subsampling, we cannot unambiguously infer the height and width # When subsampling, we cannot unambiguously infer the height and width
# of bottom and weights from top, so we require them to be given. # of bottom and weights from top, so we require them to be given.
# Similarly, when border_mode="half", we cannot infer the weight size. # Similarly, when border_mode="half", we cannot infer the weight size.
if ((direction != 0) and (dH != 1)) or ((direction == 1) and (padH == -1)): if height:
if not height:
raise ValueError("height must be given for backprop with vertical sampling or border_mode='half'")
height = '(*(npy_int64 *)(PyArray_DATA(%s)))' % height height = '(*(npy_int64 *)(PyArray_DATA(%s)))' % height
else: else:
if ((direction != 0) and (dH != 1)) or ((direction == 1) and (padH == -1)):
raise ValueError("height must be given for backprop with vertical sampling or border_mode='half'")
height = '-1' height = '-1'
if ((direction != 0) and (dW != 1)) or ((direction == 1) and (padW == -1)): if width:
if not width:
raise ValueError("width must be given for backprop with horizontal sampling or border_mode='half'")
width = '(*(npy_int64 *)(PyArray_DATA(%s)))' % width width = '(*(npy_int64 *)(PyArray_DATA(%s)))' % width
else: else:
if ((direction != 0) and (dW != 1)) or ((direction == 1) and (padW == -1)):
raise ValueError("width must be given for backprop with horizontal sampling or border_mode='half'")
width = '-1' width = '-1'
sub = sub.copy() sub = sub.copy()
sub.update(locals()) sub.update(locals())
...@@ -268,7 +268,7 @@ class BaseCorrMM(gof.OpenMPOp): ...@@ -268,7 +268,7 @@ class BaseCorrMM(gof.OpenMPOp):
// Obtain or infer kernel width and height // Obtain or infer kernel width and height
// (we need to know it early to be able to handle auto-padding) // (we need to know it early to be able to handle auto-padding)
int kH, kW; int kH, kW, dil_kH, dil_kW;
if (direction != 1) { if (direction != 1) {
// weight is an input variable, we can just read its shape // weight is an input variable, we can just read its shape
kH = PyArray_DIMS(weights)[2]; kH = PyArray_DIMS(weights)[2];
...@@ -296,11 +296,20 @@ class BaseCorrMM(gof.OpenMPOp): ...@@ -296,11 +296,20 @@ class BaseCorrMM(gof.OpenMPOp):
else { else {
kW = (PyArray_DIMS(bottom)[3] + 2*padW - (PyArray_DIMS(top)[3] - 1) * dW - 1) / dilW + 1; kW = (PyArray_DIMS(bottom)[3] + 2*padW - (PyArray_DIMS(top)[3] - 1) * dW - 1) / dilW + 1;
} }
if ((%(height)s != -1 && %(height)s != kH) ||
(%(width)s != -1 && %(width)s != kW))
{
PyErr_Format(PyExc_ValueError,
"BaseCorrMM: computed kernel shape %%lldx%%lld "
"does not match given shape %%lldx%%lld",
(long long)kH, (long long)kW, (long long)%(height)s, (long long)%(width)s);
%(fail)s
}
} }
// Implicit dilated kernel size // Implicit dilated kernel size
int dil_kH = (kH - 1) * dilH + 1; dil_kH = (kH - 1) * dilH + 1;
int dil_kW = (kW - 1) * dilW + 1; dil_kW = (kW - 1) * dilW + 1;
// Auto-padding if requested // Auto-padding if requested
if (padH == -1) { // vertical half padding if (padH == -1) { // vertical half padding
...@@ -350,12 +359,32 @@ class BaseCorrMM(gof.OpenMPOp): ...@@ -350,12 +359,32 @@ class BaseCorrMM(gof.OpenMPOp):
out_dim[1] = (npy_intp)PyArray_DIMS(weights)[1]; out_dim[1] = (npy_intp)PyArray_DIMS(weights)[1];
out_dim[2] = (npy_intp)((dH != 1) ? %(height)s : (PyArray_DIMS(top)[2] - 1) * dH + (PyArray_DIMS(weights)[2]-1)*dilH + 1 - 2*padH); out_dim[2] = (npy_intp)((dH != 1) ? %(height)s : (PyArray_DIMS(top)[2] - 1) * dH + (PyArray_DIMS(weights)[2]-1)*dilH + 1 - 2*padH);
out_dim[3] = (npy_intp)((dW != 1) ? %(width)s : (PyArray_DIMS(top)[3] - 1) * dW + (PyArray_DIMS(weights)[3]-1)*dilW + 1 - 2*padW); out_dim[3] = (npy_intp)((dW != 1) ? %(width)s : (PyArray_DIMS(top)[3] - 1) * dW + (PyArray_DIMS(weights)[3]-1)*dilW + 1 - 2*padW);
if ((%(height)s != -1 && %(height)s != out_dim[2]) ||
(%(width)s != -1 && %(width)s != out_dim[3]))
{
PyErr_Format(PyExc_ValueError,
"BaseCorrMM: computed output shape %%lldx%%lld "
"does not match given shape %%lldx%%lld",
(long long)out_dim[2], (long long)out_dim[3],
(long long)%(height)s, (long long)%(width)s);
%(fail)s
}
break; break;
default: default:
PyErr_SetString(PyExc_ValueError, "BaseCorrMM: direction must be 0, 1, or 2\\n"); PyErr_SetString(PyExc_ValueError, "BaseCorrMM: direction must be 0, 1, or 2\\n");
%(fail)s %(fail)s
} }
if (out_dim[0] < 0 || out_dim[1] < 0 || out_dim[2] < 0 || out_dim[3] < 0)
{
PyErr_Format(PyExc_ValueError,
"BaseCorrMM: impossible output shape: "
"%%lldx%%lldx%%lldx%%lld",
(long long)out_dim[0], (long long)out_dim[1],
(long long)out_dim[2], (long long)out_dim[3]);
%(fail)s
}
// Prepare output array // Prepare output array
int typenum; int typenum;
if ( !(%(out)s if ( !(%(out)s
...@@ -491,13 +520,13 @@ class CorrMM_gradWeights(BaseCorrMM): ...@@ -491,13 +520,13 @@ class CorrMM_gradWeights(BaseCorrMM):
raise TypeError('img must be 4D tensor') raise TypeError('img must be 4D tensor')
if topgrad.type.ndim != 4: if topgrad.type.ndim != 4:
raise TypeError('topgrad must be 4D tensor') raise TypeError('topgrad must be 4D tensor')
if self.subsample != (1, 1) or self.border_mode == "half": if shape is None:
if shape is None: if self.subsample != (1, 1) or self.border_mode == "half":
raise ValueError('shape must be given if subsample != (1, 1)' raise ValueError('shape must be given if subsample != (1, 1)'
' or border_mode == "half"') ' or border_mode == "half"')
height_width = [as_tensor_variable(shape[0]).astype('int64'), as_tensor_variable(shape[1]).astype('int64')]
else:
height_width = [] height_width = []
else:
height_width = [as_tensor_variable(shape[0]).astype('int64'), as_tensor_variable(shape[1]).astype('int64')]
broadcastable = [topgrad.type.broadcastable[1], img.type.broadcastable[1], broadcastable = [topgrad.type.broadcastable[1], img.type.broadcastable[1],
False, False] False, False]
...@@ -588,9 +617,13 @@ class CorrMM_gradInputs(BaseCorrMM): ...@@ -588,9 +617,13 @@ class CorrMM_gradInputs(BaseCorrMM):
raise TypeError('kern must be 4D tensor') raise TypeError('kern must be 4D tensor')
if topgrad.type.ndim != 4: if topgrad.type.ndim != 4:
raise TypeError('topgrad must be 4D tensor') raise TypeError('topgrad must be 4D tensor')
if self.subsample != (1, 1) and shape is None: if shape is None:
raise ValueError('shape must be given if subsample != (1, 1)') if self.subsample != (1, 1):
height_width = [as_tensor_variable(shape[0]).astype('int64'), as_tensor_variable(shape[1]).astype('int64')] if self.subsample != (1, 1) else [] raise ValueError('shape must be given if subsample != (1, 1)')
height_width = []
else:
height_width = [as_tensor_variable(shape[0]).astype('int64'),
as_tensor_variable(shape[1]).astype('int64')]
broadcastable = [topgrad.type.broadcastable[0], kern.type.broadcastable[1], broadcastable = [topgrad.type.broadcastable[0], kern.type.broadcastable[1],
False, False] False, False]
......
...@@ -123,7 +123,7 @@ class BaseCorr3dMM(gof.OpenMPOp): ...@@ -123,7 +123,7 @@ class BaseCorr3dMM(gof.OpenMPOp):
def c_code_cache_version(self): def c_code_cache_version(self):
# raise this whenever modifying any of the support_code_files # raise this whenever modifying any of the support_code_files
return (1, self.openmp, blas_header_version()) return (2, self.openmp, blas_header_version())
def c_support_code_apply(self, node, nodename): def c_support_code_apply(self, node, nodename):
# REMEMBER TO RAISE c_code_cache_version when changing any of # REMEMBER TO RAISE c_code_cache_version when changing any of
...@@ -241,23 +241,23 @@ class BaseCorr3dMM(gof.OpenMPOp): ...@@ -241,23 +241,23 @@ class BaseCorr3dMM(gof.OpenMPOp):
# When subsampling, we cannot unambiguously infer the height and width # When subsampling, we cannot unambiguously infer the height and width
# of bottom and weights from top, so we require them to be given. # of bottom and weights from top, so we require them to be given.
# Similarly, when border_mode="half", we cannot infer the weight size. # Similarly, when border_mode="half", we cannot infer the weight size.
if ((direction != 0) and (dH != 1)) or ((direction == 1) and (padH == -1)): if height:
if not height:
raise ValueError("height must be given for backprop with vertical sampling or border_mode='half'")
height = '(*(npy_int64 *)(PyArray_DATA(%s)))' % height height = '(*(npy_int64 *)(PyArray_DATA(%s)))' % height
else: else:
if ((direction != 0) and (dH != 1)) or ((direction == 1) and (padH == -1)):
raise ValueError("height must be given for backprop with vertical sampling or border_mode='half'")
height = '-1' height = '-1'
if ((direction != 0) and (dW != 1)) or ((direction == 1) and (padW == -1)): if width:
if not width:
raise ValueError("width must be given for backprop with horizontal sampling or border_mode='half'")
width = '(*(npy_int64 *)(PyArray_DATA(%s)))' % width width = '(*(npy_int64 *)(PyArray_DATA(%s)))' % width
else: else:
if ((direction != 0) and (dW != 1)) or ((direction == 1) and (padW == -1)):
raise ValueError("width must be given for backprop with horizontal sampling or border_mode='half'")
width = '-1' width = '-1'
if ((direction != 0) and (dD != 1)) or ((direction == 1) and (padD == -1)): if depth:
if not depth:
raise ValueError("depth must be given for backprop with depth sampling or border_mode='half'")
depth = '(*(npy_int64 *)(PyArray_DATA(%s)))' % depth depth = '(*(npy_int64 *)(PyArray_DATA(%s)))' % depth
else: else:
if ((direction != 0) and (dD != 1)) or ((direction == 1) and (padD == -1)):
raise ValueError("depth must be given for backprop with depth sampling or border_mode='half'")
depth = '-1' depth = '-1'
sub = sub.copy() sub = sub.copy()
sub.update(locals()) sub.update(locals())
...@@ -284,7 +284,7 @@ class BaseCorr3dMM(gof.OpenMPOp): ...@@ -284,7 +284,7 @@ class BaseCorr3dMM(gof.OpenMPOp):
// Obtain or infer kernel width, height and depth // Obtain or infer kernel width, height and depth
// (we need to know it early to be able to handle auto-padding) // (we need to know it early to be able to handle auto-padding)
int kH, kW, kD; int kH, kW, kD, dil_kH, dil_kW, dil_kD;
if (direction != 1) { if (direction != 1) {
// weight is an input variable, we can just read its shape // weight is an input variable, we can just read its shape
kH = PyArray_DIMS(weights)[2]; kH = PyArray_DIMS(weights)[2];
...@@ -322,12 +322,23 @@ class BaseCorr3dMM(gof.OpenMPOp): ...@@ -322,12 +322,23 @@ class BaseCorr3dMM(gof.OpenMPOp):
else { else {
kD = (PyArray_DIMS(bottom)[4] + 2*padD - (PyArray_DIMS(top)[4] - 1) * dD - 1) / dilD + 1; kD = (PyArray_DIMS(bottom)[4] + 2*padD - (PyArray_DIMS(top)[4] - 1) * dD - 1) / dilD + 1;
} }
if ((%(height)s != -1 && %(height)s != kH) ||
(%(width)s != -1 && %(width)s != kW) ||
(%(depth)s != -1 && %(depth)s != kD))
{
PyErr_Format(PyExc_ValueError,
"BaseCorr3dMM: computed kernel shape %%lldx%%lldx%%lld "
"does not match given shape %%lldx%%lldx%%lld",
(long long)kH, (long long)kW, (long long)kD,
(long long)%(height)s, (long long)%(width)s, (long long)%(depth)s);
%(fail)s
}
} }
// Implicit dilated kernel size // Implicit dilated kernel size
int dil_kH = (kH - 1) * dilH + 1; dil_kH = (kH - 1) * dilH + 1;
int dil_kW = (kW - 1) * dilW + 1; dil_kW = (kW - 1) * dilW + 1;
int dil_kD = (kD - 1) * dilD + 1; dil_kD = (kD - 1) * dilD + 1;
// Auto-padding if requested // Auto-padding if requested
if (padH == -1) { // vertical half padding if (padH == -1) { // vertical half padding
...@@ -390,12 +401,33 @@ class BaseCorr3dMM(gof.OpenMPOp): ...@@ -390,12 +401,33 @@ class BaseCorr3dMM(gof.OpenMPOp):
out_dim[2] = (npy_intp)((dH != 1) ? %(height)s : (PyArray_DIMS(top)[2] - 1) * dH + (PyArray_DIMS(weights)[2]-1)*dilH + 1 - 2*padH); out_dim[2] = (npy_intp)((dH != 1) ? %(height)s : (PyArray_DIMS(top)[2] - 1) * dH + (PyArray_DIMS(weights)[2]-1)*dilH + 1 - 2*padH);
out_dim[3] = (npy_intp)((dW != 1) ? %(width)s : (PyArray_DIMS(top)[3] - 1) * dW + (PyArray_DIMS(weights)[3]-1)*dilW + 1 - 2*padW); out_dim[3] = (npy_intp)((dW != 1) ? %(width)s : (PyArray_DIMS(top)[3] - 1) * dW + (PyArray_DIMS(weights)[3]-1)*dilW + 1 - 2*padW);
out_dim[4] = (npy_intp)((dD != 1) ? %(depth)s : (PyArray_DIMS(top)[4] - 1) * dD + (PyArray_DIMS(weights)[4]-1)*dilD + 1 - 2*padD); out_dim[4] = (npy_intp)((dD != 1) ? %(depth)s : (PyArray_DIMS(top)[4] - 1) * dD + (PyArray_DIMS(weights)[4]-1)*dilD + 1 - 2*padD);
if ((%(height)s != -1 && %(height)s != out_dim[2]) ||
(%(width)s != -1 && %(width)s != out_dim[3]) ||
(%(depth)s != -1 && %(depth)s != out_dim[4]))
{
PyErr_Format(PyExc_ValueError,
"BaseCorr3dMM: computed output shape %%lldx%%lldx%%lld "
"does not match given shape %%lldx%%lldx%%lld",
(long long)out_dim[2], (long long)out_dim[3], (long long)out_dim[4],
(long long)%(height)s, (long long)%(width)s, (long long)%(depth)s);
%(fail)s
}
break; break;
default: default:
PyErr_SetString(PyExc_ValueError, "BaseCorr3dMM: direction must be 0, 1, or 2\\n"); PyErr_SetString(PyExc_ValueError, "BaseCorr3dMM: direction must be 0, 1, or 2\\n");
%(fail)s %(fail)s
} }
if (out_dim[0] < 0 || out_dim[1] < 0 || out_dim[2] < 0 || out_dim[3] < 0 || out_dim[4] < 0)
{
PyErr_Format(PyExc_ValueError,
"BaseCorr3dMM: impossible output shape: "
"%%lldx%%lldx%%lldx%%lld%%lld",
(long long)out_dim[0], (long long)out_dim[1],
(long long)out_dim[2], (long long)out_dim[3], (long long)out_dim[4]);
%(fail)s
}
// Prepare output array // Prepare output array
int typenum; int typenum;
if ( !(%(out)s if ( !(%(out)s
...@@ -533,15 +565,15 @@ class Corr3dMM_gradWeights(BaseCorr3dMM): ...@@ -533,15 +565,15 @@ class Corr3dMM_gradWeights(BaseCorr3dMM):
raise TypeError('img must be 5D tensor') raise TypeError('img must be 5D tensor')
if topgrad.type.ndim != 5: if topgrad.type.ndim != 5:
raise TypeError('topgrad must be 5D tensor') raise TypeError('topgrad must be 5D tensor')
if self.subsample != (1, 1, 1) or self.border_mode == "half": if shape is None:
if shape is None: if self.subsample != (1, 1, 1) or self.border_mode == "half":
raise ValueError('shape must be given if subsample != (1, 1, 1)' raise ValueError('shape must be given if subsample != (1, 1, 1)'
' or border_mode == "half"') ' or border_mode == "half"')
height_width_depth = []
else:
height_width_depth = [as_tensor_variable(shape[0]).astype('int64'), height_width_depth = [as_tensor_variable(shape[0]).astype('int64'),
as_tensor_variable(shape[1]).astype('int64'), as_tensor_variable(shape[1]).astype('int64'),
as_tensor_variable(shape[2]).astype('int64')] as_tensor_variable(shape[2]).astype('int64')]
else:
height_width_depth = []
broadcastable = [topgrad.type.broadcastable[1], img.type.broadcastable[1], broadcastable = [topgrad.type.broadcastable[1], img.type.broadcastable[1],
False, False, False] False, False, False]
...@@ -638,14 +670,14 @@ class Corr3dMM_gradInputs(BaseCorr3dMM): ...@@ -638,14 +670,14 @@ class Corr3dMM_gradInputs(BaseCorr3dMM):
raise TypeError('kern must be 5D tensor') raise TypeError('kern must be 5D tensor')
if topgrad.type.ndim != 5: if topgrad.type.ndim != 5:
raise TypeError('topgrad must be 5D tensor') raise TypeError('topgrad must be 5D tensor')
if self.subsample != (1, 1, 1) and shape is None: if shape is None:
raise ValueError('shape must be given if subsample != (1, 1, 1)') if self.subsample != (1, 1, 1):
if self.subsample != (1, 1, 1): raise ValueError('shape must be given if subsample != (1, 1, 1)')
height_width_depth = []
else:
height_width_depth = [as_tensor_variable(shape[0]).astype('int64'), height_width_depth = [as_tensor_variable(shape[0]).astype('int64'),
as_tensor_variable(shape[1]).astype('int64'), as_tensor_variable(shape[1]).astype('int64'),
as_tensor_variable(shape[2]).astype('int64')] as_tensor_variable(shape[2]).astype('int64')]
else:
height_width_depth = []
broadcastable = [topgrad.type.broadcastable[0], kern.type.broadcastable[1], broadcastable = [topgrad.type.broadcastable[0], kern.type.broadcastable[1],
False, False, False] False, False, False]
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论