提交 b8287408 authored 作者: Pascal Lamblin's avatar Pascal Lamblin

Auto indentation.

上级 d73bd46d
...@@ -134,7 +134,7 @@ class SquareDiagonal(Op): ...@@ -134,7 +134,7 @@ class SquareDiagonal(Op):
"""Return a square sparse (csc) matrix whose diagonal is given by the dense vector argument. """Return a square sparse (csc) matrix whose diagonal is given by the dense vector argument.
""" """
def make_node(self, diag): def make_node(self, diag):
return gof.Apply(self, [diag], return gof.Apply(self, [diag],
[sparse.SparseType(dtype = diag.dtype, [sparse.SparseType(dtype = diag.dtype,
format = 'csc')()]) format = 'csc')()])
def perform(self, node, (diag,), (z,)): def perform(self, node, (diag,), (z,)):
...@@ -142,7 +142,7 @@ class SquareDiagonal(Op): ...@@ -142,7 +142,7 @@ class SquareDiagonal(Op):
indptr = range(N+1) indptr = range(N+1)
indices = indptr[0:N] indices = indptr[0:N]
z[0] = scipy_sparse.csc_matrix((diag, indices, indptr), (N,N), copy=True) z[0] = scipy_sparse.csc_matrix((diag, indices, indptr), (N,N), copy=True)
def grad(self, input, (gz,)): def grad(self, input, (gz,)):
return [diag(gz)] return [diag(gz)]
...@@ -278,21 +278,21 @@ class ConvolutionIndices(Op): ...@@ -278,21 +278,21 @@ class ConvolutionIndices(Op):
when computing the dot product of M with image patch. Convolution is then when computing the dot product of M with image patch. Convolution is then
simply the dot product of (img x M) and the kernels. simply the dot product of (img x M) and the kernels.
""" """
@staticmethod @staticmethod
def sparse_eval(inshp, kshp, nkern, (dx,dy)=(1,1), mode='valid'): def sparse_eval(inshp, kshp, nkern, (dx,dy)=(1,1), mode='valid'):
return convolution_indices.evaluate(inshp,kshp,(dx,dy),nkern,mode=mode,ws=False) return convolution_indices.evaluate(inshp,kshp,(dx,dy),nkern,mode=mode,ws=False)
@staticmethod @staticmethod
def conv_eval(inshp, kshp, (dx,dy)=(1,1), mode='valid'): def conv_eval(inshp, kshp, (dx,dy)=(1,1), mode='valid'):
return convolution_indices.evaluate(inshp,kshp,(dx,dy),mode=mode,ws=True) return convolution_indices.evaluate(inshp,kshp,(dx,dy),mode=mode,ws=True)
# img_shape and ker_shape are (height,width) # img_shape and ker_shape are (height,width)
@staticmethod @staticmethod
def evaluate(inshp, kshp, (dx,dy)=(1,1), nkern=1, mode='valid', ws=True): def evaluate(inshp, kshp, (dx,dy)=(1,1), nkern=1, mode='valid', ws=True):
"""Build a sparse matrix which can be used for performing... """Build a sparse matrix which can be used for performing...
* convolution: in this case, the dot product of this matrix with the input * convolution: in this case, the dot product of this matrix with the input
images will generate a stack of images patches. Convolution is then a images will generate a stack of images patches. Convolution is then a
tensordot operation of the filters and the patch stack. tensordot operation of the filters and the patch stack.
* sparse local connections: in this case, the sparse matrix allows us to operate * sparse local connections: in this case, the sparse matrix allows us to operate
the weight matrix as if it were fully-connected. The structured-dot with the the weight matrix as if it were fully-connected. The structured-dot with the
...@@ -300,11 +300,11 @@ class ConvolutionIndices(Op): ...@@ -300,11 +300,11 @@ class ConvolutionIndices(Op):
@param ker_shape: shape of kernel to apply (smaller than image) @param ker_shape: shape of kernel to apply (smaller than image)
@param img_shape: shape of input images @param img_shape: shape of input images
@param mode: 'valid' generates output only when kernel and image overlap @param mode: 'valid' generates output only when kernel and image overlap
full' full convolution obtained by zero-padding the input full' full convolution obtained by zero-padding the input
@param ws: True if weight sharing, false otherwise @param ws: True if weight sharing, false otherwise
@param (dx,dy): offset parameter. In the case of no weight sharing, gives the @param (dx,dy): offset parameter. In the case of no weight sharing, gives the
pixel offset between two receptive fields. With weight sharing gives the pixel offset between two receptive fields. With weight sharing gives the
offset between the top-left pixels of the generated patches offset between the top-left pixels of the generated patches
@rtype: tuple(indices, indptr, logical_shape, sp_type, out_img_shp) @rtype: tuple(indices, indptr, logical_shape, sp_type, out_img_shp)
...@@ -323,7 +323,7 @@ class ConvolutionIndices(Op): ...@@ -323,7 +323,7 @@ class ConvolutionIndices(Op):
ksize = N.prod(kshp) ksize = N.prod(kshp)
kern = ksize-1 - N.arange(ksize) kern = ksize-1 - N.arange(ksize)
# size of output image if doing proper convolution (mode='full',dx=dy=0) # size of output image if doing proper convolution (mode='full',dx=dy=0)
# outshp is the actual output shape given the parameters # outshp is the actual output shape given the parameters
fulloutshp = inshp[1:] + kshp - 1 fulloutshp = inshp[1:] + kshp - 1
...@@ -370,7 +370,7 @@ class ConvolutionIndices(Op): ...@@ -370,7 +370,7 @@ class ConvolutionIndices(Op):
# FOR EACH OUTPUT PIXEL... # FOR EACH OUTPUT PIXEL...
for oy in N.arange(lbound[0],ubound[0],dy): # loop over output image height for oy in N.arange(lbound[0],ubound[0],dy): # loop over output image height
for ox in N.arange(lbound[1],ubound[1],dx): # loop over output image width for ox in N.arange(lbound[1],ubound[1],dx): # loop over output image width
l = 0 # kern[l] is filter value to apply at (oj,oi) for (iy,ix) l = 0 # kern[l] is filter value to apply at (oj,oi) for (iy,ix)
# ... ITERATE OVER INPUT UNITS IN RECEPTIVE FIELD # ... ITERATE OVER INPUT UNITS IN RECEPTIVE FIELD
...@@ -380,14 +380,14 @@ class ConvolutionIndices(Op): ...@@ -380,14 +380,14 @@ class ConvolutionIndices(Op):
# verify if we are still within image boundaries. Equivalent to # verify if we are still within image boundaries. Equivalent to
# zero-padding of the input image # zero-padding of the input image
if all((ky,kx) >= topleft) and all((ky,kx) < botright): if all((ky,kx) >= topleft) and all((ky,kx) < botright):
# convert to "valid" input space coords # convert to "valid" input space coords
# used to determine column index to write to in sparse mat # used to determine column index to write to in sparse mat
iy,ix = N.array((ky,kx)) - topleft iy,ix = N.array((ky,kx)) - topleft
# determine raster-index of input pixel... # determine raster-index of input pixel...
col = iy*inshp[2]+ix +\ col = iy*inshp[2]+ix +\
fmapi*N.prod(inshp[1:]) # taking into account multiple input features fmapi*N.prod(inshp[1:]) # taking into account multiple input features
# convert oy,ox values to output space coordinates # convert oy,ox values to output space coordinates
(y,x) = (oy,ox) if mode=='full' else (oy,ox) - topleft (y,x) = (oy,ox) if mode=='full' else (oy,ox) - topleft
(y,x) = N.array([y,x]) / (dy,dx) # taking into account step size (y,x) = N.array([y,x]) / (dy,dx) # taking into account step size
...@@ -400,10 +400,10 @@ class ConvolutionIndices(Op): ...@@ -400,10 +400,10 @@ class ConvolutionIndices(Op):
# will determine the way kernel taps are mapped onto # will determine the way kernel taps are mapped onto
# the sparse columns (idea of kernel map) # the sparse columns (idea of kernel map)
spmat[row + n*outsize, col] = tapi + 1 # n*... only for sparse spmat[row + n*outsize, col] = tapi + 1 # n*... only for sparse
# total number of active taps (used for kmap) # total number of active taps (used for kmap)
ntaps += 1 ntaps += 1
tapi += 1 # absolute tap index (total number of taps) tapi += 1 # absolute tap index (total number of taps)
l+=1 # move on to next filter tap l=(l+1)%ksize l+=1 # move on to next filter tap l=(l+1)%ksize
...@@ -455,27 +455,27 @@ def applySparseFilter(kerns, kshp, nkern, images, imgshp, step=(1,1), bias=None, ...@@ -455,27 +455,27 @@ def applySparseFilter(kerns, kshp, nkern, images, imgshp, step=(1,1), bias=None,
"images" is assumed to be a matrix of shape batch_size x img_size, where the second "images" is assumed to be a matrix of shape batch_size x img_size, where the second
dimension represents each image in raster order dimension represents each image in raster order
Output feature map will have shape: Output feature map will have shape:
batch_size x number of kernels * output_size batch_size x number of kernels * output_size
IMPORTANT: note that this means that each feature map is contiguous in memory. IMPORTANT: note that this means that each feature map is contiguous in memory.
The memory layout will therefore be: The memory layout will therefore be:
[ <feature_map_0> <feature_map_1> ... <feature_map_n>], [ <feature_map_0> <feature_map_1> ... <feature_map_n>],
where <feature_map> represents a "feature map" in raster order where <feature_map> represents a "feature map" in raster order
Note that the concept of feature map doesn't really apply to sparse filters without Note that the concept of feature map doesn't really apply to sparse filters without
weight sharing. Basically, nkern=1 will generate one output img/feature map, weight sharing. Basically, nkern=1 will generate one output img/feature map,
nkern=2 a second feature map, etc. nkern=2 a second feature map, etc.
kerns is a 1D tensor, and assume to be of shape: kerns is a 1D tensor, and assume to be of shape:
nkern * N.prod(outshp) x N.prod(kshp) nkern * N.prod(outshp) x N.prod(kshp)
Each filter is applied seperately to consecutive output pixels. Each filter is applied seperately to consecutive output pixels.
@param kerns: nkern*outsize*ksize vector containing kernels @param kerns: nkern*outsize*ksize vector containing kernels
@param kshp: tuple containing actual dimensions of kernel (not symbolic) @param kshp: tuple containing actual dimensions of kernel (not symbolic)
@param nkern: number of kernels to apply at each pixel in the input image. @param nkern: number of kernels to apply at each pixel in the input image.
nkern=1 will apply a single unique filter for each input pixel. nkern=1 will apply a single unique filter for each input pixel.
@param images: bsize x imgsize matrix containing images on which to apply filters @param images: bsize x imgsize matrix containing images on which to apply filters
@param imgshp: tuple containing actual image dimensions (not symbolic) @param imgshp: tuple containing actual image dimensions (not symbolic)
@param step: determines number of pixels between adjacent receptive fields @param step: determines number of pixels between adjacent receptive fields
(tuple containing dx,dy values) (tuple containing dx,dy values)
@param mode: 'full', 'valid' see CSM.evaluate function for details @param mode: 'full', 'valid' see CSM.evaluate function for details
@output out1: symbolic result @output out1: symbolic result
...@@ -497,7 +497,7 @@ def applySparseFilter(kerns, kshp, nkern, images, imgshp, step=(1,1), bias=None, ...@@ -497,7 +497,7 @@ def applySparseFilter(kerns, kshp, nkern, images, imgshp, step=(1,1), bias=None,
output = sparse.structured_dot(sparsew, images.T).T output = sparse.structured_dot(sparsew, images.T).T
if bias is not None: if bias is not None:
output += bias output += bias
return output, numpy.hstack((nkern,outshp)) return output, numpy.hstack((nkern,outshp))
...@@ -517,11 +517,11 @@ def convolve(kerns, kshp, nkern, images, imgshp, step=(1,1), bias=None,\ ...@@ -517,11 +517,11 @@ def convolve(kerns, kshp, nkern, images, imgshp, step=(1,1), bias=None,\
If flatten is "True", the output feature map will have shape: If flatten is "True", the output feature map will have shape:
batch_size x number of kernels * output_size batch_size x number of kernels * output_size
IMPORTANT: note that this means that each feature map (image generate by each IMPORTANT: note that this means that each feature map (image generate by each
kernel) is contiguous in memory. The memory layout will therefore be: kernel) is contiguous in memory. The memory layout will therefore be:
[ <feature_map_0> <feature_map_1> ... <feature_map_n>], [ <feature_map_0> <feature_map_1> ... <feature_map_n>],
where <feature_map> represents a "feature map" in raster order where <feature_map> represents a "feature map" in raster order
kerns is a 2D tensor of shape nkern x N.prod(kshp) kerns is a 2D tensor of shape nkern x N.prod(kshp)
@param kerns: 2D tensor containing kernels which are applied at every pixel @param kerns: 2D tensor containing kernels which are applied at every pixel
...@@ -530,24 +530,24 @@ def convolve(kerns, kshp, nkern, images, imgshp, step=(1,1), bias=None,\ ...@@ -530,24 +530,24 @@ def convolve(kerns, kshp, nkern, images, imgshp, step=(1,1), bias=None,\
nkern=1 will apply one common filter to all input pixels nkern=1 will apply one common filter to all input pixels
@param images: tensor containing images on which to apply convolution @param images: tensor containing images on which to apply convolution
@param imgshp: tuple containing image dimensions @param imgshp: tuple containing image dimensions
@param step: determines number of pixels between adjacent receptive fields @param step: determines number of pixels between adjacent receptive fields
(tuple containing dx,dy values) (tuple containing dx,dy values)
@param mode: 'full', 'valid' see CSM.evaluate function for details @param mode: 'full', 'valid' see CSM.evaluate function for details
@param sumdims: dimensions over which to sum for the tensordot operation. By default @param sumdims: dimensions over which to sum for the tensordot operation. By default
((2,),(1,)) assumes kerns is a nkern x kernsize matrix and images is a batchsize x ((2,),(1,)) assumes kerns is a nkern x kernsize matrix and images is a batchsize x
imgsize matrix containing flattened images in raster order imgsize matrix containing flattened images in raster order
@param flatten: flatten the last 2 dimensions of the output. By default, instead of @param flatten: flatten the last 2 dimensions of the output. By default, instead of
generating a batchsize x outsize x nkern tensor, will flatten to generating a batchsize x outsize x nkern tensor, will flatten to
batchsize x outsize*nkern batchsize x outsize*nkern
@output out1: symbolic result @output out1: symbolic result
@output out2: logical shape of the output img (nkern,heigt,width) @output out2: logical shape of the output img (nkern,heigt,width)
@TODO: test for 1D and think of how to do n-d convolutions @TODO: test for 1D and think of how to do n-d convolutions
""" """
N = numpy N = numpy
# start by computing output dimensions, size, etc # start by computing output dimensions, size, etc
kern_size = N.int64(N.prod(kshp)) kern_size = N.int64(N.prod(kshp))
# inshp contains either 2 entries (height,width) or 3 (nfeatures,h,w) # inshp contains either 2 entries (height,width) or 3 (nfeatures,h,w)
# in the first case, default nfeatures to 1 # in the first case, default nfeatures to 1
if N.size(imgshp)==2: if N.size(imgshp)==2:
...@@ -557,7 +557,7 @@ def convolve(kerns, kshp, nkern, images, imgshp, step=(1,1), bias=None,\ ...@@ -557,7 +557,7 @@ def convolve(kerns, kshp, nkern, images, imgshp, step=(1,1), bias=None,\
# with input images will generate a stack of image patches # with input images will generate a stack of image patches
indices, indptr, spmat_shape, sptype, outshp = \ indices, indptr, spmat_shape, sptype, outshp = \
convolution_indices.conv_eval(imgshp, kshp, step, mode) convolution_indices.conv_eval(imgshp, kshp, step, mode)
# build sparse matrix, then generate stack of image patches # build sparse matrix, then generate stack of image patches
csc = theano.sparse.CSM(sptype)(N.ones(indices.size), indices, indptr, spmat_shape) csc = theano.sparse.CSM(sptype)(N.ones(indices.size), indices, indptr, spmat_shape)
patches = (sparse.structured_dot(csc, images.T)).T patches = (sparse.structured_dot(csc, images.T)).T
...@@ -566,13 +566,13 @@ def convolve(kerns, kshp, nkern, images, imgshp, step=(1,1), bias=None,\ ...@@ -566,13 +566,13 @@ def convolve(kerns, kshp, nkern, images, imgshp, step=(1,1), bias=None,\
pshape = tensor.stack(images.shape[0] * tensor.as_tensor(N.prod(outshp)),\ pshape = tensor.stack(images.shape[0] * tensor.as_tensor(N.prod(outshp)),\
tensor.as_tensor(imgshp[0]*kern_size)) tensor.as_tensor(imgshp[0]*kern_size))
patch_stack = tensor.reshape(patches, pshape, ndim=2); patch_stack = tensor.reshape(patches, pshape, ndim=2);
# kern is of shape: nkern x ksize*number_of_input_features # kern is of shape: nkern x ksize*number_of_input_features
# output is thus of shape: bsize*outshp x nkern # output is thus of shape: bsize*outshp x nkern
output = tensor.dot(patch_stack,kerns.T) output = tensor.dot(patch_stack,kerns.T)
# add bias across each feature map (more efficient to do it now) # add bias across each feature map (more efficient to do it now)
if bias is not None: if bias is not None:
output += bias output += bias
# now to have feature maps in raster order ... # now to have feature maps in raster order ...
...@@ -584,10 +584,10 @@ def convolve(kerns, kshp, nkern, images, imgshp, step=(1,1), bias=None,\ ...@@ -584,10 +584,10 @@ def convolve(kerns, kshp, nkern, images, imgshp, step=(1,1), bias=None,\
output = tensor.DimShuffle((False,)*tensout.ndim, (0,2,1))(tensout) output = tensor.DimShuffle((False,)*tensout.ndim, (0,2,1))(tensout)
if flatten: if flatten:
output = tensor.flatten(output, 2) output = tensor.flatten(output, 2)
return output, N.hstack((nkern,outshp)) return output, N.hstack((nkern,outshp))
def max_pool(images, imgshp, maxpoolshp): def max_pool(images, imgshp, maxpoolshp):
"""Implements a max pooling layer """Implements a max pooling layer
...@@ -599,7 +599,7 @@ def max_pool(images, imgshp, maxpoolshp): ...@@ -599,7 +599,7 @@ def max_pool(images, imgshp, maxpoolshp):
Assumed to be of shape batch_size x img_size Assumed to be of shape batch_size x img_size
@param imgshp: tuple containing image dimensions @param imgshp: tuple containing image dimensions
@param maxpoolshp: tuple containing shape of area to max pool over @param maxpoolshp: tuple containing shape of area to max pool over
@output out1: symbolic result (2D tensor) @output out1: symbolic result (2D tensor)
@output out2: logical shape of the output @output out2: logical shape of the output
""" """
...@@ -620,7 +620,7 @@ def max_pool(images, imgshp, maxpoolshp): ...@@ -620,7 +620,7 @@ def max_pool(images, imgshp, maxpoolshp):
print 'imgshp = ', imgshp print 'imgshp = ', imgshp
print 'maxpoolshp = ', maxpoolshp print 'maxpoolshp = ', maxpoolshp
print 'outshp = ', outshp print 'outshp = ', outshp
# build sparse matrix, then generate stack of image patches # build sparse matrix, then generate stack of image patches
csc = theano.sparse.CSM(sptype)(N.ones(indices.size), indices, indptr, spmat_shape) csc = theano.sparse.CSM(sptype)(N.ones(indices.size), indices, indptr, spmat_shape)
patches = sparse.structured_dot(csc, images.T).T patches = sparse.structured_dot(csc, images.T).T
...@@ -630,14 +630,14 @@ def max_pool(images, imgshp, maxpoolshp): ...@@ -630,14 +630,14 @@ def max_pool(images, imgshp, maxpoolshp):
tensor.as_tensor(imgshp[0]), tensor.as_tensor(imgshp[0]),
tensor.as_tensor(poolsize)) tensor.as_tensor(poolsize))
patch_stack = tensor.reshape(patches, pshape, ndim=3); patch_stack = tensor.reshape(patches, pshape, ndim=3);
out1 = tensor.max(patch_stack, axis=2) out1 = tensor.max(patch_stack, axis=2)
pshape = tensor.stack(images.shape[0], pshape = tensor.stack(images.shape[0],
tensor.as_tensor(N.prod(outshp)), tensor.as_tensor(N.prod(outshp)),
tensor.as_tensor(imgshp[0])) tensor.as_tensor(imgshp[0]))
out2 = tensor.reshape(out1, pshape, ndim=3); out2 = tensor.reshape(out1, pshape, ndim=3);
out3 = tensor.DimShuffle(out2.broadcastable, (0,2,1))(out2) out3 = tensor.DimShuffle(out2.broadcastable, (0,2,1))(out2)
return tensor.flatten(out3,2), outshp return tensor.flatten(out3,2), outshp
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论