Commit 5f0860fc authored by Benjamin Thomas Graham's avatar Benjamin Thomas Graham
Browse files

DenseToSparse, tidying

parent 6de372c3
...@@ -10,14 +10,15 @@ from .inputBatch import InputBatch ...@@ -10,14 +10,15 @@ from .inputBatch import InputBatch
from .sparseConvNetTensor import SparseConvNetTensor from .sparseConvNetTensor import SparseConvNetTensor
from .sparseModule import SparseModule from .sparseModule import SparseModule
from .averagePooling import AveragePooling from .averagePooling import AveragePooling
from .batchNormalization import BatchNormalization from .batchNormalization import BatchNormReLU, BatchNormLeakyReLU, BatchNormalizationInTensor
from .concatTable import ConcatTable from .concatTable import ConcatTable
from .convolution import Convolution from .convolution import Convolution
from .cAddTable import CAddTable from .cAddTable import CAddTable
from .deconvolution import Deconvolution from .deconvolution import Deconvolution
from .denseToSparse import DenseToSparse
from .identity import Identity from .identity import Identity
from .joinTable import JoinTable from .joinTable import JoinTable
from .leakyReLU import LeakyReLU from .leakyReLU import LeakyReLU, Tanh
from .maxPooling import MaxPooling from .maxPooling import MaxPooling
from .networkInNetwork import NetworkInNetwork from .networkInNetwork import NetworkInNetwork
from .reLU import ReLU from .reLU import ReLU
......
...@@ -28,13 +28,11 @@ class AffineReLUTrivialConvolution(SparseModule): ...@@ -28,13 +28,11 @@ class AffineReLUTrivialConvolution(SparseModule):
self.nOut = nOut self.nOut = nOut
self.affineWeight = torch.Tensor(nIn).fill_(1) self.affineWeight = torch.Tensor(nIn).fill_(1)
self.affineBias = torch.Tensor(nIn).zero_() self.affineBias = torch.Tensor(nIn).zero_()
self.convWeight = torch.Tensor( std = math.sqrt(2.0 / nIn)
nIn, nOut).normal_( self.convWeight = torch.Tensor(nIn, nOut).normal_(0, std)
0, math.sqrt(
2.0 / nIn))
self.gradAffineWeight = torch.Tensor(nIn).fill_(0) self.gradAffineWeight = torch.Tensor(nIn).fill_(0)
self.gradAffineBias = torch.Tensor(nIn).zero_() self.gradAffineBias = torch.Tensor(nIn).zero_(0.333)
self.gradConvWeight = torch.Tensor(nIn, nOut).zero_() self.gradConvWeight = torch.Tensor(nIn, nOut).fill_(std)
self.additiveGrad = additiveGrad self.additiveGrad = additiveGrad
self.output = SparseConvNetTensor(torch.Tensor()) self.output = SparseConvNetTensor(torch.Tensor())
self.gradInput = torch.Tensor() self.gradInput = torch.Tensor()
...@@ -46,7 +44,7 @@ class AffineReLUTrivialConvolution(SparseModule): ...@@ -46,7 +44,7 @@ class AffineReLUTrivialConvolution(SparseModule):
def updateOutput(self, input): def updateOutput(self, input):
self.output.metadata = input.metadata self.output.metadata = input.metadata
self.output.spatial_size = input.spatial_size self.output.spatial_size = input.spatial_size
typed_fn(input, 'AffineReluTrivialConvolution_updateOutput')( typed_fn(input.features, 'AffineReluTrivialConvolution_updateOutput')(
input.features, input.features,
self.output.features, self.output.features,
self.affineWeight, self.affineWeight,
...@@ -59,7 +57,7 @@ class AffineReLUTrivialConvolution(SparseModule): ...@@ -59,7 +57,7 @@ class AffineReLUTrivialConvolution(SparseModule):
def backward(self, input, gradOutput, scale=1): def backward(self, input, gradOutput, scale=1):
assert scale == 1 assert scale == 1
typed_fn(input, 'AffineReluTrivialConvolution_backward')( typed_fn(input.features, 'AffineReluTrivialConvolution_backward')(
input.features, input.features,
self.gradInput, self.gradInput,
gradOutput, gradOutput,
......
...@@ -17,7 +17,6 @@ class AveragePooling(SparseModule): ...@@ -17,7 +17,6 @@ class AveragePooling(SparseModule):
self.dimension = dimension self.dimension = dimension
self.pool_size = toLongTensor(dimension, pool_size) self.pool_size = toLongTensor(dimension, pool_size)
self.pool_stride = toLongTensor(dimension, pool_stride) self.pool_stride = toLongTensor(dimension, pool_stride)
self.pool_volume = self.pool_size.prod()
self.nFeaturesToDrop = nFeaturesToDrop self.nFeaturesToDrop = nFeaturesToDrop
self.output = SparseConvNetTensor(torch.Tensor()) self.output = SparseConvNetTensor(torch.Tensor())
self.gradInput = torch.Tensor() self.gradInput = torch.Tensor()
...@@ -26,7 +25,7 @@ class AveragePooling(SparseModule): ...@@ -26,7 +25,7 @@ class AveragePooling(SparseModule):
self.output.metadata = input.metadata self.output.metadata = input.metadata
self.output.spatial_size =\ self.output.spatial_size =\
(input.spatial_size - self.pool_size) / self.pool_stride + 1 (input.spatial_size - self.pool_size) / self.pool_stride + 1
dim_typed_fn(self.dimension, input, 'AveragePooling_updateOutput')( dim_typed_fn(self.dimension, input.features, 'AveragePooling_updateOutput')(
input.spatial_size, input.spatial_size,
self.output.spatial_size, self.output.spatial_size,
self.pool_size, self.pool_size,
...@@ -40,7 +39,7 @@ class AveragePooling(SparseModule): ...@@ -40,7 +39,7 @@ class AveragePooling(SparseModule):
def updateGradInput(self, input, gradOutput): def updateGradInput(self, input, gradOutput):
dim_typed_fn( dim_typed_fn(
self.dimension, input, 'AveragePooling_updateGradInput')( self.dimension, input.features, 'AveragePooling_updateGradInput')(
input.spatial_size, input.spatial_size,
self.output.spatial_size, self.output.spatial_size,
self.pool_size, self.pool_size,
......
...@@ -31,7 +31,6 @@ class BatchNormalization(SparseModule): ...@@ -31,7 +31,6 @@ class BatchNormalization(SparseModule):
affine=True, affine=True,
leakiness=1): leakiness=1):
SparseModule.__init__(self) SparseModule.__init__(self)
assert nPlanes % 4 == 0
self.nPlanes = nPlanes self.nPlanes = nPlanes
self.eps = eps self.eps = eps
self.momentum = momentum self.momentum = momentum
...@@ -44,16 +43,16 @@ class BatchNormalization(SparseModule): ...@@ -44,16 +43,16 @@ class BatchNormalization(SparseModule):
if affine: if affine:
self.weight = torch.Tensor(nPlanes).fill_(1) self.weight = torch.Tensor(nPlanes).fill_(1)
self.bias = torch.Tensor(nPlanes).fill_(0) self.bias = torch.Tensor(nPlanes).fill_(0)
self.gradWeight = torch.Tensor(nPlanes) self.gradWeight = torch.Tensor(nPlanes).fill_(0)
self.gradBias = torch.Tensor(nPlanes) self.gradBias = torch.Tensor(nPlanes).fill_(0.333)
self.output = SparseConvNetTensor(torch.Tensor()) self.output = SparseConvNetTensor(torch.Tensor())
self.gradInput = torch.Tensor() self.gradInput = torch.Tensor()
def updateOutput(self, input): def updateOutput(self, input):
assert input.features.size(1) == self.nPlanes assert input.features.ndimension()==0 or input.features.size(1) == self.nPlanes
self.output.metadata = input.metadata self.output.metadata = input.metadata
self.output.spatial_size = input.spatial_size self.output.spatial_size = input.spatial_size
typed_fn(input, 'BatchNormalization_updateOutput')( typed_fn(input.features, 'BatchNormalization_updateOutput')(
input.features, input.features,
self.output.features, self.output.features,
self.saveMean, self.saveMean,
...@@ -71,7 +70,7 @@ class BatchNormalization(SparseModule): ...@@ -71,7 +70,7 @@ class BatchNormalization(SparseModule):
def backward(self, input, gradOutput, scale=1): def backward(self, input, gradOutput, scale=1):
assert scale == 1 assert scale == 1
assert self.train assert self.train
typed_fn(input, 'BatchNormalization_backward')( typed_fn(input.features, 'BatchNormalization_backward')(
input.features, input.features,
self.gradInput, self.gradInput,
self.output.features, self.output.features,
...@@ -114,6 +113,14 @@ class BatchNormReLU(BatchNormalization): ...@@ -114,6 +113,14 @@ class BatchNormReLU(BatchNormalization):
s = 'BatchNormReLU(' + str(self.nPlanes) + ',eps=' + str(self.eps) + \ s = 'BatchNormReLU(' + str(self.nPlanes) + ',eps=' + str(self.eps) + \
',momentum=' + str(self.momentum) + ',affine=' + str(self.affine) + ')' ',momentum=' + str(self.momentum) + ',affine=' + str(self.affine) + ')'
return s return s
class BatchNormLeakyReLU(BatchNormalization):
def __init__(self, nPlanes, eps=1e-4, momentum=0.9):
BatchNormalization.__init__(self, nPlanes, eps, momentum, True, 0.333)
def __repr__(self):
s = 'BatchNormReLU(' + str(self.nPlanes) + ',eps=' + str(self.eps) + \
',momentum=' + str(self.momentum) + ',affine=' + str(self.affine) + ')'
return s
class BatchNormalizationInTensor(BatchNormalization): class BatchNormalizationInTensor(BatchNormalization):
...@@ -131,7 +138,7 @@ class BatchNormalizationInTensor(BatchNormalization): ...@@ -131,7 +138,7 @@ class BatchNormalizationInTensor(BatchNormalization):
1, self.output_column_offset, self.nPlanes) 1, self.output_column_offset, self.nPlanes)
self.output.metadata = input.metadata self.output.metadata = input.metadata
self.output.spatial_size = input.spatial_size self.output.spatial_size = input.spatial_size
typed_fn(input, 'BatchNormalizationInTensor_updateOutput')( typed_fn(input.features, 'BatchNormalizationInTensor_updateOutput')(
input.features, input.features,
o, o,
self.saveMean, self.saveMean,
...@@ -152,7 +159,7 @@ class BatchNormalizationInTensor(BatchNormalization): ...@@ -152,7 +159,7 @@ class BatchNormalizationInTensor(BatchNormalization):
o = self.output.features.narrow( o = self.output.features.narrow(
1, self.output_column_offset, self.nPlanes) 1, self.output_column_offset, self.nPlanes)
d_o = gradOutput.narrow(1, self.output_column_offset, self.nPlanes) d_o = gradOutput.narrow(1, self.output_column_offset, self.nPlanes)
typed_fn(input, 'BatchNormalization_backward')( typed_fn(input.features, 'BatchNormalization_backward')(
input.features, input.features,
self.gradInput, self.gradInput,
o, o,
......
...@@ -20,24 +20,29 @@ class Convolution(SparseModule): ...@@ -20,24 +20,29 @@ class Convolution(SparseModule):
self.filter_size = toLongTensor(dimension, filter_size) self.filter_size = toLongTensor(dimension, filter_size)
self.filter_volume = self.filter_size.prod() self.filter_volume = self.filter_size.prod()
self.filter_stride = toLongTensor(dimension, filter_stride) self.filter_stride = toLongTensor(dimension, filter_stride)
std = (2.0 / nIn / self.filter_volume)**0.5
self.weight = torch.Tensor( self.weight = torch.Tensor(
nIn * self.filter_volume, nOut nIn *
).normal_(0, (2.0 / nIn / self.filter_volume)**0.5) self.filter_volume,
self.gradWeight = torch.Tensor(nIn * self.filter_volume, nOut) nOut).normal_(
0,
std)
self.gradWeight = torch.Tensor(
nIn * self.filter_volume, nOut).fill_(std)
if bias: if bias:
self.bias = torch.Tensor(nOut).zero_() self.bias = torch.Tensor(nOut).zero_()
self.gradBias = torch.Tensor(nOut) self.gradBias = torch.Tensor(nOut).zero_()
self.output = SparseConvNetTensor(torch.Tensor()) self.output = SparseConvNetTensor(torch.Tensor())
self.gradInput = torch.Tensor() self.gradInput = torch.Tensor()
def updateOutput(self, input): def updateOutput(self, input):
assert input.features.size(1) == self.nIn assert input.features.ndimension()==0 or input.features.size(1) == self.nIn
self.output.metadata = input.metadata self.output.metadata = input.metadata
self.output.spatial_size =\ self.output.spatial_size =\
(input.spatial_size - self.filter_size) / self.filter_stride + 1 (input.spatial_size - self.filter_size) / self.filter_stride + 1
s.forward_pass_multiplyAdd_count +=\ s.forward_pass_multiplyAdd_count +=\
dim_typed_fn( dim_typed_fn(
self.dimension, input, 'Convolution_updateOutput')( self.dimension, input.features, 'Convolution_updateOutput')(
input.spatial_size, input.spatial_size,
self.output.spatial_size, self.output.spatial_size,
self.filter_size, self.filter_size,
...@@ -55,7 +60,7 @@ class Convolution(SparseModule): ...@@ -55,7 +60,7 @@ class Convolution(SparseModule):
def backward(self, input, gradOutput, scale=1): def backward(self, input, gradOutput, scale=1):
assert scale == 1 assert scale == 1
dim_typed_fn( dim_typed_fn(
self.dimension, input, 'Convolution_backward')( self.dimension, input.features, 'Convolution_backward')(
input.spatial_size, input.spatial_size,
self.output.spatial_size, self.output.spatial_size,
self.filter_size, self.filter_size,
......
...@@ -22,24 +22,26 @@ class Deconvolution(SparseModule): ...@@ -22,24 +22,26 @@ class Deconvolution(SparseModule):
self.filter_size = toLongTensor(dimension, filter_size) self.filter_size = toLongTensor(dimension, filter_size)
self.filter_stride = toLongTensor(dimension, filter_stride) self.filter_stride = toLongTensor(dimension, filter_stride)
self.filter_volume = self.filter_size.prod() self.filter_volume = self.filter_size.prod()
std = (2.0 / nIn / self.filter_volume)**0.5
self.weight = torch.Tensor( self.weight = torch.Tensor(
nIn * self.filter_volume, nOut nIn * self.filter_volume, nOut
).normal_(0, (2.0 / nIn / self.filter_volume)**0.5) ).normal_(0, std)
self.gradWeight = torch.Tensor(nIn * self.filter_volume, nOut) self.gradWeight = torch.Tensor(
nIn * self.filter_volume, nOut).fill_(std)
if bias: if bias:
self.bias = torch.Tensor(nOut).zero_() self.bias = torch.Tensor(nOut).zero_()
self.gradBias = torch.Tensor(nOut) self.gradBias = torch.Tensor(nOut).zero_()
self.output = SparseConvNetTensor(torch.Tensor()) self.output = SparseConvNetTensor(torch.Tensor())
self.gradInput = torch.Tensor() self.gradInput = torch.Tensor()
def updateOutput(self, input): def updateOutput(self, input):
assert input.features.size(1) == self.nIn assert input.features.ndimension()==0 or input.features.size(1) == self.nIn
self.output.metadata = input.metadata self.output.metadata = input.metadata
self.output.spatial_size =\ self.output.spatial_size =\
(input.spatial_size - 1) * self.filter_stride + self.filter_size (input.spatial_size - 1) * self.filter_stride + self.filter_size
s.forward_pass_multiplyAdd_count +=\ s.forward_pass_multiplyAdd_count +=\
dim_typed_fn( dim_typed_fn(
self.dimension, input, 'Deconvolution_updateOutput')( self.dimension, input.features, 'Deconvolution_updateOutput')(
input.spatial_size, input.spatial_size,
self.output.spatial_size, self.output.spatial_size,
self.filter_size, self.filter_size,
...@@ -57,7 +59,7 @@ class Deconvolution(SparseModule): ...@@ -57,7 +59,7 @@ class Deconvolution(SparseModule):
def backward(self, input, gradOutput, scale=1): def backward(self, input, gradOutput, scale=1):
assert scale == 1 assert scale == 1
dim_typed_fn( dim_typed_fn(
self.dimension, input, 'Deconvolution_backward')( self.dimension, input.features, 'Deconvolution_backward')(
input.spatial_size, input.spatial_size,
self.output.spatial_size, self.output.spatial_size,
self.filter_size, self.filter_size,
......
# Copyright 2016-present, Facebook, Inc.
# All rights reserved.
#
# This source code is licensed under the license found in the
# LICENSE file in the root directory of this source tree.
"""
Function to convert a Dense Input into a sparse input.
If possible, avoid using this module; build the hidden layer using InputBatch.
Parameters:
dimension : of the input field
"""
import torch
from . import SparseModule
from ..utils import dim_fn, nullptr
from .sparseConvNetTensor import SparseConvNetTensor
from .metadata import Metadata
class DenseToSparse(SparseModule):
def __init__(self, dimension):
SparseModule.__init__(self)
self.dimension = dimension
self.output = SparseConvNetTensor(torch.Tensor(),Metadata(dimension))
self.gradInput = torch.Tensor()
def updateOutput(self, input):
a=input
aa=a.permute(*([0,]+list(range(2,2+self.dimension))+[1,])).clone()
self.aas=aa.size()
nz=aa.abs().sum(self.dimension+1).view(aa.size()[0:-1])
s=torch.LongTensor(nz.stride()).view(1,self.dimension+1)
nz=nz.nonzero()
s=s.type_as(nz)
aa=aa.view(-1,a.size(1))
self.aas2=aa.size()
self.r=(nz*s.expand_as(nz)).sum(1).view(-1)
self.output.features=aa.index_select(0,self.r)
self.output.spatial_size=torch.LongTensor(list(input.size()[2:]))
dim_fn(self.dimension, 'createMetadataForDenseToSparse')(
self.output.metadata.ffi,
self.output.spatial_size,
nz.cpu(),
input.size(0))
return self.output
def updateGradInput(self, input, gradOutput):
self.gradInput.resize_(self.aas2).zero_()
self.gradInput.index_copy_(0,self.r,gradOutput)
self.gradInput=self.gradInput.view(self.aas).permute(*([0,self.dimension+1]+list(range(1,self.dimension+1))))
return self.gradInput
def clearState(self):
SparseModule.clearState(self)
self.aas=None
self.r=None
def __repr__(self):
return 'DenseToSparse(' + str(self.dimension) + ')'
...@@ -22,7 +22,7 @@ class LeakyReLU(SparseModule): ...@@ -22,7 +22,7 @@ class LeakyReLU(SparseModule):
def updateOutput(self, input): def updateOutput(self, input):
self.output.metadata = input.metadata self.output.metadata = input.metadata
self.output.spatial_size = input.spatial_size self.output.spatial_size = input.spatial_size
typed_fn(input, 'LeakyReLU_updateOutput')( typed_fn(input.features, 'LeakyReLU_updateOutput')(
input.features, input.features,
self.output.features, self.output.features,
self.leakage) self.leakage)
...@@ -42,3 +42,28 @@ class LeakyReLU(SparseModule): ...@@ -42,3 +42,28 @@ class LeakyReLU(SparseModule):
if t: if t:
self.output.type(t) self.output.type(t)
self.gradInput = self.gradInput.type(t) self.gradInput = self.gradInput.type(t)
class Tanh(SparseModule):
def __init__(self):
SparseModule.__init__(self)
self.output = SparseConvNetTensor(torch.Tensor())
#self.gradInput = None if ip else torch.Tensor()
self.gradInput = torch.Tensor()
def updateOutput(self, input):
self.output.metadata = input.metadata
self.output.spatial_size = input.spatial_size
self.output.features=torch.tanh(input.features)
return self.output
def updateGradInput(self, input, gradOutput):
self.gradInput.resize_as_(gradOutput).copy_(gradOutput)
self.gradInput.mul(1+self.output.features)
self.gradInput.mul(1-self.output.features)
return self.gradInput
def type(self, t, tensorCache=None):
if t:
self.output.type(t)
self.gradInput = self.gradInput.type(t)
...@@ -26,7 +26,7 @@ class MaxPooling(SparseModule): ...@@ -26,7 +26,7 @@ class MaxPooling(SparseModule):
self.output.metadata = input.metadata self.output.metadata = input.metadata
self.output.spatial_size =\ self.output.spatial_size =\
(input.spatial_size - self.pool_size) / self.pool_stride + 1 (input.spatial_size - self.pool_size) / self.pool_stride + 1
dim_typed_fn(self.dimension, input, 'MaxPooling_updateOutput')( dim_typed_fn(self.dimension, input.features, 'MaxPooling_updateOutput')(
input.spatial_size, input.spatial_size,
self.output.spatial_size, self.output.spatial_size,
self.pool_size, self.pool_size,
...@@ -39,7 +39,7 @@ class MaxPooling(SparseModule): ...@@ -39,7 +39,7 @@ class MaxPooling(SparseModule):
return self.output return self.output
def updateGradInput(self, input, gradOutput): def updateGradInput(self, input, gradOutput):
dim_typed_fn(self.dimension, input, 'MaxPooling_updateGradInput')( dim_typed_fn(self.dimension, input.features, 'MaxPooling_updateGradInput')(
input.spatial_size, input.spatial_size,
self.output.spatial_size, self.output.spatial_size,
self.pool_size, self.pool_size,
......
...@@ -24,16 +24,16 @@ ffi = cffi.FFI() ...@@ -24,16 +24,16 @@ ffi = cffi.FFI()
class Metadata(object): class Metadata(object):
def __init__(self, dimension, ptr=0): def __init__(self, dimension, ptr=0):
#print('make meta',dimension, ptr)
self.dimension = dimension self.dimension = dimension
self.ffi = ffi.new('void *[1]') self.ffi = ffi.new('void *[1]')
scn_writePtr(ptr, self.ffi) scn_writePtr(ptr, self.ffi)
self.ffigc = ffi.gc(self.ffi, dim_fn(self.dimension, 'freeMetadata')) self.ffigc = ffi.gc(self.ffi, dim_fn(self.dimension, 'freeMetadata'))
def set_(self): def set_(self):
if hasattr(self, 'ffi'): dim_fn(self.dimension, 'freeMetadata')(self.ffi)
del self.ffigc # if hasattr(self, 'ffi'):
del self.ffi # del self.ffigc
# del self.ffi
def __reduce__(self): def __reduce__(self):
if hasattr(self, 'ffi'): if hasattr(self, 'ffi'):
......
...@@ -116,7 +116,7 @@ def SparseVggNet(dimension, nInputPlanes, layers): ...@@ -116,7 +116,7 @@ def SparseVggNet(dimension, nInputPlanes, layers):
.add(ValidConvolution(dimension, x[3], x[3], 3, False)) .add(ValidConvolution(dimension, x[3], x[3], 3, False))
.add(BatchNormReLU(x[3])) .add(BatchNormReLU(x[3]))
.add(Deconvolution(dimension, x[3], x[3], 3, 2, False)) .add(Deconvolution(dimension, x[3], x[3], 3, 2, False))
)).add(JoinTable({x[1], x[2], x[3]})) )).add(JoinTable([x[1], x[2], x[3]]))
nPlanes = x[1] + x[2] + x[3] nPlanes = x[1] + x[2] + x[3]
m.add(BatchNormReLU(nPlanes)) m.add(BatchNormReLU(nPlanes))
return m return m
......
...@@ -16,11 +16,12 @@ class NetworkInNetwork(SparseModule): ...@@ -16,11 +16,12 @@ class NetworkInNetwork(SparseModule):
SparseModule.__init__(self) SparseModule.__init__(self)
self.nIn = nIn self.nIn = nIn
self.nOut = nOut self.nOut = nOut
self.weight = torch.Tensor(nIn, nOut).normal_(0, (2.0 / self.nIn)**0.5) std = (2.0 / self.nIn)**0.5
self.gradWeight = torch.Tensor(nIn, nOut) self.weight = torch.Tensor(nIn, nOut).normal_(0, std)
self.gradWeight = torch.Tensor(nIn, nOut).fill_(std)
if bias: if bias:
self.bias = torch.Tensor(nOut).fill_(0) self.bias = torch.Tensor(nOut).zero_()
self.gradBias = torch.Tensor(nOut) self.gradBias = torch.Tensor(nOut).zero_()
self.output = SparseConvNetTensor(torch.Tensor()) self.output = SparseConvNetTensor(torch.Tensor())
self.gradInput = torch.Tensor() self.gradInput = torch.Tensor()
...@@ -28,7 +29,7 @@ class NetworkInNetwork(SparseModule): ...@@ -28,7 +29,7 @@ class NetworkInNetwork(SparseModule):
self.output.metadata = input.metadata self.output.metadata = input.metadata
self.output.spatial_size = input.spatial_size self.output.spatial_size = input.spatial_size
s.forward_pass_multiplyAdd_count +=\ s.forward_pass_multiplyAdd_count +=\
typed_fn(input, 'NetworkInNetwork_updateOutput')( typed_fn(input.features, 'NetworkInNetwork_updateOutput')(
input.features, input.features,
self.output.features, self.output.features,
self.weight, self.weight,
...@@ -37,7 +38,7 @@ class NetworkInNetwork(SparseModule): ...@@ -37,7 +38,7 @@ class NetworkInNetwork(SparseModule):
return self.output return self.output
def updateGradInput(self, input, gradOutput): def updateGradInput(self, input, gradOutput):
typed_fn(input, 'NetworkInNetwork_updateGradInput')( typed_fn(input.features, 'NetworkInNetwork_updateGradInput')(
self.gradInput, self.gradInput,
gradOutput, gradOutput,
self.weight) self.weight)
...@@ -45,7 +46,7 @@ class NetworkInNetwork(SparseModule): ...@@ -45,7 +46,7 @@ class NetworkInNetwork(SparseModule):
def accGradParameters(self, input, gradOutput, scale=1): def accGradParameters(self, input, gradOutput, scale=1):
assert scale == 1 assert scale == 1
typed_fn(input, 'NetworkInNetwork_accGradParameters')( typed_fn(input.features, 'NetworkInNetwork_accGradParameters')(
input.features, input.features,
gradOutput, gradOutput,
self.gradWeight, self.gradWeight,
......
...@@ -29,7 +29,7 @@ class SparseConvNetTensor(object): ...@@ -29,7 +29,7 @@ class SparseConvNetTensor(object):
def set_(self): def set_(self):
self.features.set_(self.features.storage_type()()) self.features.set_(self.features.storage_type()())
self.metadata = None self.metadata.set_()
self.spatialSize = None self.spatialSize = None
def __repr__(self): def __repr__(self):
......
...@@ -22,23 +22,27 @@ from .sparseConvNetTensor import SparseConvNetTensor ...@@ -22,23 +22,27 @@ from .sparseConvNetTensor import SparseConvNetTensor
class SparseToDense(SparseModule): class SparseToDense(SparseModule):
def __init__(self, dimension): def __init__(self, dimension, nPlanes=None):
SparseModule.__init__(self) SparseModule.__init__(self)
self.dimension = dimension self.dimension = dimension
self.output = torch.Tensor() self.output = torch.Tensor()
self.gradInput = torch.FloatTensor() self.gradInput = torch.FloatTensor()
self.nPlanes=nPlanes
def updateOutput(self, input): def updateOutput(self, input):
dim_typed_fn(self.dimension, input, 'SparseToDense_updateOutput')( if not self.nPlanes:
self.nPlanes=input.features.size(1)
dim_typed_fn(self.dimension, input.features, 'SparseToDense_updateOutput')(
input.spatial_size, input.spatial_size,
input.metadata.ffi, input.metadata.ffi,
input.features, input.features,
self.output, self.output,
torch.cuda.IntTensor() if input.features.is_cuda else nullptr) torch.cuda.IntTensor() if input.features.is_cuda else nullptr,
self.nPlanes)
return self.output return self.output
def updateGradInput(self, input, gradOutput): def updateGradInput(self, input, gradOutput):
dim_typed_fn(self.dimension, input, 'SparseToDense_updateGradInput')( dim_typed_fn(self.dimension, input.features, 'SparseToDense_updateGradInput')(
input.spatial_size, input.spatial_size,
input.metadata.ffi, input.metadata.ffi,
input.features, input.features,
......
...@@ -19,22 +19,24 @@ class ValidConvolution(SparseModule): ...@@ -19,22 +19,24 @@ class ValidConvolution(SparseModule):
self.nOut = nOut self.nOut = nOut
self.filter_size = toLongTensor(dimension, filter_size) self.filter_size = toLongTensor(dimension, filter_size)
self.filter_volume = self.filter_size.prod() self.filter_volume = self.filter_size.prod()
std = (2.0 / nIn / self.filter_volume)**0.5
self.weight = torch.Tensor( self.weight = torch.Tensor(
nIn * self.filter_volume, nOut nIn * self.filter_volume, nOut
).normal_(0, (2.0 / nIn / self.filter_volume)**0.5) ).normal_(0, std)
self.gradWeight = torch.Tensor(nIn * self.filter_volume, nOut) self.gradWeight = torch.Tensor(
nIn * self.filter_volume, nOut).fill_(std)
if bias: if bias:
self.bias = torch.Tensor(nOut).zero_() self.bias = torch.Tensor(nOut).zero_()
self.gradBias = torch.Tensor(nOut) self.gradBias = torch.Tensor(nOut).zero_()
self.output = SparseConvNetTensor(torch.Tensor()) self.output = SparseConvNetTensor(torch.Tensor())
self.gradInput = torch.Tensor() self.gradInput = torch.Tensor()
def updateOutput(self, input): def updateOutput(self, input):
assert input.features.size(1) == self.nIn assert input.features.ndimension()==0 or input.features.size(1) == self.nIn
self.output.metadata = input.metadata self.output.metadata = input.metadata
self.output.spatial_size = input.spatial_size self.output.spatial_size = input.spatial_size
s.forward_pass_multiplyAdd_count +=\ s.forward_pass_multiplyAdd_count +=\
dim_typed_fn(self.dimension, input, 'ValidConvolution_updateOutput')( dim_typed_fn(self.dimension, input.features, 'ValidConvolution_updateOutput')(
input.spatial_size, input.spatial_size,
self.filter_size, self.filter_size,
input.metadata.ffi, input.metadata.ffi,
...@@ -49,7 +51,7 @@ class ValidConvolution(SparseModule): ...@@ -49,7 +51,7 @@ class ValidConvolution(SparseModule):
def backward(self, input, gradOutput, scale=1): def backward(self, input, gradOutput, scale=1):
assert scale == 1 assert scale == 1
dim_typed_fn(self.dimension, input, 'ValidConvolution_backward')( dim_typed_fn(self.dimension, input.features, 'ValidConvolution_backward')(
input.spatial_size, input.spatial_size,
self.filter_size, self.filter_size,
input.metadata.ffi, input.metadata.ffi,
......
...@@ -30,18 +30,16 @@ def dim_fn(dimension, name): ...@@ -30,18 +30,16 @@ def dim_fn(dimension, name):
def typed_fn(t, name): def typed_fn(t, name):
# print('typed_fn',dimension,name) # print('typed_fn',t.features.type(),name)
return getattr(scn, 'scn_' + typeTable[t.features.type()] + '_' + name) return getattr(scn, 'scn_' + typeTable[t.type()] + '_' + name)
def dim_typed_fn(dimension, t, name): def dim_typed_fn(dimension, t, name):
# print('dim_typed_fn',dimension,t,name) # print('dim_typed_fn',dimension,t.features.type(),name)
return getattr(scn, 'scn_' + return getattr(scn, 'scn_' +
typeTable[t.features.type()] + typeTable[t.type()] +
str(dimension) + str(dimension) +
name) name)
ffi = FFI() ffi = FFI()
nullptr = ffi.NULL nullptr = ffi.NULL
......
...@@ -52,12 +52,16 @@ void scn_DIMENSION_setInputSpatialLocations(void **m, THFloatTensor *features, ...@@ -52,12 +52,16 @@ void scn_DIMENSION_setInputSpatialLocations(void **m, THFloatTensor *features,
THLongTensor *locations, THFloatTensor *vecs, bool overwrite); THLongTensor *locations, THFloatTensor *vecs, bool overwrite);
void scn_DIMENSION_getSpatialLocations(void **m, THLongTensor *spatialSize, void scn_DIMENSION_getSpatialLocations(void **m, THLongTensor *spatialSize,
THLongTensor *locations); THLongTensor *locations);
]]
]]
for DIMENSION = 1,10 do for DIMENSION = 1,10 do
local def = string.gsub(cdef, 'DIMENSION', DIMENSION) local def = string.gsub(cdef, 'DIMENSION', DIMENSION)
if fc then fc:write(def) end
ffi.cdef(def) ffi.cdef(def)
if fc then
def=string.gsub(def,'bool','_Bool')
fc:write(def)
end
end end
--types CPU float, double; --types CPU float, double;
...@@ -128,21 +132,29 @@ void scn_ARCH_REAL_NetworkInNetwork_accGradParameters( ...@@ -128,21 +132,29 @@ void scn_ARCH_REAL_NetworkInNetwork_accGradParameters(
def = string.gsub(def, 'THITensor', 'void') def = string.gsub(def, 'THITensor', 'void')
def = string.gsub(def, 'REAL', v[1]) def = string.gsub(def, 'REAL', v[1])
def = string.gsub(def, 'THTensor', v[2]) def = string.gsub(def, 'THTensor', v[2])
if fc then fc:write(def) end
ffi.cdef(def) ffi.cdef(def)
if fc then
def=string.gsub(def,'bool','_Bool')
fc:write(def)
end
end end
if sparseconvnet.cutorch then if sparseconvnet.cutorch then
for k,v in ipairs({ for k,v in ipairs({
{'float', 'THCudaTensor'}, {'float', 'THCudaTensor'},
{'double', 'THCudaDoubleTensor'}}) do --{'double', 'THCudaDoubleTensor'}
})
do
local def = cdef local def = cdef
def = string.gsub(def, 'ARCH', 'gpu') def = string.gsub(def, 'ARCH', 'gpu')
def = string.gsub(def, 'THITensor', sparseconvnet.ruleBookBits==64 and def = string.gsub(def, 'THITensor', sparseconvnet.ruleBookBits==64 and
'THCudaLongTensor' or 'THCudaIntTensor') 'THCudaLongTensor' or 'THCudaIntTensor')
def = string.gsub(def, 'REAL', v[1]) def = string.gsub(def, 'REAL', v[1])
def = string.gsub(def, 'THTensor', v[2]) def = string.gsub(def, 'THTensor', v[2])
if fg then fg:write(def) end
ffi.cdef(def) ffi.cdef(def)
if fg then
def=string.gsub(def,'bool','_Bool')
fg:write(def)
end
end end
end end
...@@ -226,7 +238,7 @@ void scn_ARCH_REAL_DIMENSIONValidConvolution_backward( ...@@ -226,7 +238,7 @@ void scn_ARCH_REAL_DIMENSIONValidConvolution_backward(
THTensor *d_bias, long filterVolume, THITensor *rulesBuffer); THTensor *d_bias, long filterVolume, THITensor *rulesBuffer);
]] ]]
for _,v in ipairs({{'float', 'THFloatTensor'}, {'double','THDoubleTensor'}}) do for _,v in ipairs({{'float', 'THFloatTensor'}, {'double', 'THDoubleTensor'}}) do
for DIMENSION = 1,10 do for DIMENSION = 1,10 do
local def = cdef local def = cdef
def = string.gsub(def, 'ARCH', 'cpu') def = string.gsub(def, 'ARCH', 'cpu')
...@@ -234,24 +246,31 @@ void scn_ARCH_REAL_DIMENSIONValidConvolution_backward( ...@@ -234,24 +246,31 @@ void scn_ARCH_REAL_DIMENSIONValidConvolution_backward(
def = string.gsub(def, 'THITensor', 'void') def = string.gsub(def, 'THITensor', 'void')
def = string.gsub(def, 'REAL', v[1]) def = string.gsub(def, 'REAL', v[1])
def = string.gsub(def, 'THTensor', v[2]) def = string.gsub(def, 'THTensor', v[2])
if fc then fc:write(def) end
ffi.cdef(def) ffi.cdef(def)
if fc then
def=string.gsub(def,'bool','_Bool')
fc:write(def)
end
end end
end end
if sparseconvnet.cutorch then if sparseconvnet.cutorch then
for k,v in ipairs({ for k,v in ipairs({
{'float', 'THCudaTensor'}, {'float', 'THCudaTensor'},
{'double', 'THCudaDoubleTensor'}}) do --{'double', 'THCudaDoubleTensor'}
}) do
for DIMENSION = 1,10 do for DIMENSION = 1,10 do
local def = cdef local def = cdef
def = string.gsub(def, 'ARCH', 'gpu') def = string.gsub(def, 'ARCH', 'gpu')
def = string.gsub(def, '_DIMENSION', DIMENSION) def = string.gsub(def, '_DIMENSION', DIMENSION)
def = string.gsub(def, 'THITensor', sparseconvnet.ruleBookBits==64 and def = string.gsub(def, 'THITensor', sparseconvnet.ruleBookBits==64 and
'THCudaLongTensor' or 'THCudaIntTensor') 'THCudaLongTensor' or 'THCudaIntTensor')
def = string.gsub(def, 'REAL', v[1]) def = string.gsub(def, 'REAL', v[1])
def = string.gsub(def, 'THTensor', v[2]) def = string.gsub(def, 'THTensor', v[2])
if fg then fg:write(def) end
ffi.cdef(def) ffi.cdef(def)
if fg then
def=string.gsub(def,'bool','_Bool')
fg:write(def)
end
end end
end end
end end
......
...@@ -5,14 +5,14 @@ ...@@ -5,14 +5,14 @@
-- LICENSE file in the root directory of this source tree. -- LICENSE file in the root directory of this source tree.
--[[ --[[
Function to convert a SparseConvNet hidden layer to a dense convolutional Function to convert a SparseConvNet hidden layer to a dense convolutional
layer. Put a SparseToDense convolutional layer (or an ActivePooling layer) at layer. Put a SparseToDense convolutional layer (or an ActivePooling layer) at
the top of your sparse network. The output can then pass to a dense the top of your sparse network. The output can then pass to a dense
convolutional layers or (if the spatial dimensions have become trivial) a convolutional layers or (if the spatial dimensions have become trivial) a
linear classifier. linear classifier.
Parameters: Parameters:
dimension : of the input field dimension : of the input field
]] ]]
return function(sparseconvnet) return function(sparseconvnet)
...@@ -20,11 +20,12 @@ return function(sparseconvnet) ...@@ -20,11 +20,12 @@ return function(sparseconvnet)
local SparseToDense, parent = torch.class( local SparseToDense, parent = torch.class(
'sparseconvnet.SparseToDense', 'nn.Module', sparseconvnet) 'sparseconvnet.SparseToDense', 'nn.Module', sparseconvnet)
function SparseToDense:__init(dimension) function SparseToDense:__init(dimension, nPlanes)
parent.__init(self) parent.__init(self)
self.dimension = dimension self.dimension = dimension
self.output=torch.Tensor() self.output=torch.Tensor()
self.gradInput={features=torch.Tensor()} self.gradInput={features=torch.Tensor()}
self.nPlanes=nPlanes
end end
function SparseToDense:updateOutput(input) function SparseToDense:updateOutput(input)
...@@ -34,7 +35,8 @@ return function(sparseconvnet) ...@@ -34,7 +35,8 @@ return function(sparseconvnet)
input.metadata.ffi, input.metadata.ffi,
input.features:cdata(), input.features:cdata(),
self.output:cdata(), self.output:cdata(),
self.shared.rulesBuffer and self.shared.rulesBuffer:cdata()) self.shared.rulesBuffer and self.shared.rulesBuffer:cdata(),
self.nPlanes or input.features.size(2))
return self.output return self.output
end end
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment