Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
one
spconv
Commits
9a23d934
Commit
9a23d934
authored
Jun 01, 2020
by
yanyan
Browse files
add a mnist example
parent
731545bd
Changes
3
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
160 additions
and
3 deletions
+160
-3
example/mnist_sparse.py
example/mnist_sparse.py
+139
-0
spconv/__init__.py
spconv/__init__.py
+16
-0
spconv/pool.py
spconv/pool.py
+5
-3
No files found.
example/mnist_sparse.py
0 → 100644
View file @
9a23d934
from
__future__
import
print_function
import
argparse
import
torch
import
spconv
import
torch.nn
as
nn
import
torch.nn.functional
as
F
import
torch.optim
as
optim
from
torchvision
import
datasets
,
transforms
from
torch.optim.lr_scheduler
import
StepLR
class
Net
(
nn
.
Module
):
def
__init__
(
self
):
super
(
Net
,
self
).
__init__
()
self
.
net
=
spconv
.
SparseSequential
(
nn
.
BatchNorm1d
(
1
),
spconv
.
SparseConv2d
(
1
,
32
,
3
,
1
),
nn
.
ReLU
(),
spconv
.
SparseConv2d
(
32
,
64
,
3
,
1
),
nn
.
ReLU
(),
spconv
.
SparseMaxPool2d
(
2
,
2
),
spconv
.
ToDense
(),
)
self
.
fc1
=
nn
.
Linear
(
9216
,
128
)
self
.
fc2
=
nn
.
Linear
(
128
,
10
)
self
.
dropout1
=
nn
.
Dropout2d
(
0.25
)
self
.
dropout2
=
nn
.
Dropout2d
(
0.5
)
def
forward
(
self
,
x
:
torch
.
Tensor
):
# x: [N, 28, 28, 1], must be NHWC tensor
x_sp
=
spconv
.
SparseConvTensor
.
from_dense
(
x
.
reshape
(
-
1
,
28
,
28
,
1
))
# create SparseConvTensor manually: see SparseConvTensor.from_dense
x
=
self
.
net
(
x_sp
)
x
=
torch
.
flatten
(
x
,
1
)
x
=
self
.
dropout1
(
x
)
x
=
self
.
fc1
(
x
)
x
=
F
.
relu
(
x
)
x
=
self
.
dropout2
(
x
)
x
=
self
.
fc2
(
x
)
output
=
F
.
log_softmax
(
x
,
dim
=
1
)
return
output
def
train
(
args
,
model
,
device
,
train_loader
,
optimizer
,
epoch
):
model
.
train
()
for
batch_idx
,
(
data
,
target
)
in
enumerate
(
train_loader
):
data
,
target
=
data
.
to
(
device
),
target
.
to
(
device
)
optimizer
.
zero_grad
()
output
=
model
(
data
)
loss
=
F
.
nll_loss
(
output
,
target
)
loss
.
backward
()
optimizer
.
step
()
if
batch_idx
%
args
.
log_interval
==
0
:
print
(
'Train Epoch: {} [{}/{} ({:.0f}%)]
\t
Loss: {:.6f}'
.
format
(
epoch
,
batch_idx
*
len
(
data
),
len
(
train_loader
.
dataset
),
100.
*
batch_idx
/
len
(
train_loader
),
loss
.
item
()))
def
test
(
model
,
device
,
test_loader
):
model
.
eval
()
test_loss
=
0
correct
=
0
with
torch
.
no_grad
():
for
data
,
target
in
test_loader
:
data
,
target
=
data
.
to
(
device
),
target
.
to
(
device
)
output
=
model
(
data
)
test_loss
+=
F
.
nll_loss
(
output
,
target
,
reduction
=
'sum'
).
item
()
# sum up batch loss
pred
=
output
.
argmax
(
dim
=
1
,
keepdim
=
True
)
# get the index of the max log-probability
correct
+=
pred
.
eq
(
target
.
view_as
(
pred
)).
sum
().
item
()
test_loss
/=
len
(
test_loader
.
dataset
)
print
(
'
\n
Test set: Average loss: {:.4f}, Accuracy: {}/{} ({:.0f}%)
\n
'
.
format
(
test_loss
,
correct
,
len
(
test_loader
.
dataset
),
100.
*
correct
/
len
(
test_loader
.
dataset
)))
def
main
():
# Training settings
parser
=
argparse
.
ArgumentParser
(
description
=
'PyTorch MNIST Example'
)
parser
.
add_argument
(
'--batch-size'
,
type
=
int
,
default
=
64
,
metavar
=
'N'
,
help
=
'input batch size for training (default: 64)'
)
parser
.
add_argument
(
'--test-batch-size'
,
type
=
int
,
default
=
1000
,
metavar
=
'N'
,
help
=
'input batch size for testing (default: 1000)'
)
parser
.
add_argument
(
'--epochs'
,
type
=
int
,
default
=
14
,
metavar
=
'N'
,
help
=
'number of epochs to train (default: 14)'
)
parser
.
add_argument
(
'--lr'
,
type
=
float
,
default
=
1.0
,
metavar
=
'LR'
,
help
=
'learning rate (default: 1.0)'
)
parser
.
add_argument
(
'--gamma'
,
type
=
float
,
default
=
0.7
,
metavar
=
'M'
,
help
=
'Learning rate step gamma (default: 0.7)'
)
parser
.
add_argument
(
'--no-cuda'
,
action
=
'store_true'
,
default
=
False
,
help
=
'disables CUDA training'
)
parser
.
add_argument
(
'--seed'
,
type
=
int
,
default
=
1
,
metavar
=
'S'
,
help
=
'random seed (default: 1)'
)
parser
.
add_argument
(
'--log-interval'
,
type
=
int
,
default
=
10
,
metavar
=
'N'
,
help
=
'how many batches to wait before logging training status'
)
parser
.
add_argument
(
'--save-model'
,
action
=
'store_true'
,
default
=
False
,
help
=
'For Saving the current Model'
)
args
=
parser
.
parse_args
()
use_cuda
=
not
args
.
no_cuda
and
torch
.
cuda
.
is_available
()
torch
.
manual_seed
(
args
.
seed
)
device
=
torch
.
device
(
"cuda"
if
use_cuda
else
"cpu"
)
kwargs
=
{
'num_workers'
:
1
,
'pin_memory'
:
True
}
if
use_cuda
else
{}
train_loader
=
torch
.
utils
.
data
.
DataLoader
(
datasets
.
MNIST
(
'../data'
,
train
=
True
,
download
=
True
,
transform
=
transforms
.
Compose
([
transforms
.
ToTensor
(),
# here we remove norm to get sparse tensor with lots of zeros
# transforms.Normalize((0.1307,), (0.3081,))
])),
batch_size
=
args
.
batch_size
,
shuffle
=
True
,
**
kwargs
)
test_loader
=
torch
.
utils
.
data
.
DataLoader
(
datasets
.
MNIST
(
'../data'
,
train
=
False
,
transform
=
transforms
.
Compose
([
transforms
.
ToTensor
(),
# here we remove norm to get sparse tensor with lots of zeros
# transforms.Normalize((0.1307,), (0.3081,))
])),
batch_size
=
args
.
test_batch_size
,
shuffle
=
True
,
**
kwargs
)
model
=
Net
().
to
(
device
)
optimizer
=
optim
.
Adadelta
(
model
.
parameters
(),
lr
=
args
.
lr
)
scheduler
=
StepLR
(
optimizer
,
step_size
=
1
,
gamma
=
args
.
gamma
)
for
epoch
in
range
(
1
,
args
.
epochs
+
1
):
train
(
args
,
model
,
device
,
train_loader
,
optimizer
,
epoch
)
test
(
model
,
device
,
test_loader
)
scheduler
.
step
()
if
args
.
save_model
:
torch
.
save
(
model
.
state_dict
(),
"mnist_cnn.pt"
)
if
__name__
==
'__main__'
:
main
()
spconv/__init__.py
View file @
9a23d934
...
...
@@ -56,6 +56,10 @@ class SparseConvTensor(object):
grid
=
None
):
"""
Args:
features: [num_points, num_features] feature tensor
indices: [num_points, ndim + 1] indice tensor. batch index saved in indices[:, 0]
spatial_shape: spatial shape of your sparse data
batch_size: batch size of your sparse data
grid: pre-allocated grid tensor. should be used when the volume of spatial shape
is very large.
"""
...
...
@@ -66,6 +70,18 @@ class SparseConvTensor(object):
self
.
indice_dict
=
{}
self
.
grid
=
grid
@
classmethod
def
from_dense
(
cls
,
x
:
torch
.
Tensor
):
"""create sparse tensor fron channel last dense tensor by to_sparse
x must be NHWC tensor, channel last
"""
x
=
x
.
to_sparse
(
x
.
ndim
-
1
)
spatial_shape
=
x
.
shape
[
1
:
-
1
]
batch_size
=
x
.
shape
[
0
]
indices_th
=
x
.
indices
().
permute
(
1
,
0
).
contiguous
().
int
()
features_th
=
x
.
values
()
return
cls
(
features_th
,
indices_th
,
spatial_shape
,
batch_size
)
@
property
def
spatial_size
(
self
):
return
np
.
prod
(
self
.
spatial_shape
)
...
...
spconv/pool.py
View file @
9a23d934
...
...
@@ -31,13 +31,15 @@ class SparseMaxPool(SparseModule):
def
__init__
(
self
,
ndim
,
kernel_size
,
stride
=
1
,
stride
=
None
,
padding
=
0
,
dilation
=
1
,
subm
=
False
):
super
(
SparseMaxPool
,
self
).
__init__
()
if
not
isinstance
(
kernel_size
,
(
list
,
tuple
)):
kernel_size
=
[
kernel_size
]
*
ndim
if
stride
is
None
:
stride
=
kernel_size
.
copy
()
if
not
isinstance
(
stride
,
(
list
,
tuple
)):
stride
=
[
stride
]
*
ndim
if
not
isinstance
(
padding
,
(
list
,
tuple
)):
...
...
@@ -80,12 +82,12 @@ class SparseMaxPool(SparseModule):
class
SparseMaxPool2d
(
SparseMaxPool
):
def
__init__
(
self
,
kernel_size
,
stride
=
1
,
padding
=
0
,
dilation
=
1
):
def
__init__
(
self
,
kernel_size
,
stride
=
None
,
padding
=
0
,
dilation
=
1
):
super
(
SparseMaxPool2d
,
self
).
__init__
(
2
,
kernel_size
,
stride
,
padding
,
dilation
)
class
SparseMaxPool3d
(
SparseMaxPool
):
def
__init__
(
self
,
kernel_size
,
stride
=
1
,
padding
=
0
,
dilation
=
1
):
def
__init__
(
self
,
kernel_size
,
stride
=
None
,
padding
=
0
,
dilation
=
1
):
super
(
SparseMaxPool3d
,
self
).
__init__
(
3
,
kernel_size
,
stride
,
padding
,
dilation
)
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment