my
$batch_size
= 100;
my
$data
= mx->symbol->Variable(
'data'
);
my
$conv1
= mx->symbol->Convolution(
data
=>
$data
,
name
=>
'conv1'
,
num_filter
=> 32,
kernel
=> [3,3],
stride
=> [2,2]);
my
$bn1
= mx->symbol->BatchNorm(
data
=>
$conv1
,
name
=>
"bn1"
);
my
$act1
= mx->symbol->Activation(
data
=>
$bn1
,
name
=>
'relu1'
,
act_type
=>
"relu"
);
my
$mp1
= mx->symbol->Pooling(
data
=>
$act1
,
name
=>
'mp1'
,
kernel
=> [2,2],
stride
=>[2,2],
pool_type
=>
'max'
);
my
$conv2
= mx->symbol->Convolution(
data
=>
$mp1
,
name
=>
'conv2'
,
num_filter
=> 32,
kernel
=>[3,3],
stride
=>[2,2]);
my
$bn2
= mx->symbol->BatchNorm(
data
=>
$conv2
,
name
=>
"bn2"
);
my
$act2
= mx->symbol->Activation(
data
=>
$bn2
,
name
=>
'relu2'
,
act_type
=>
"relu"
);
my
$mp2
= mx->symbol->Pooling(
data
=>
$act2
,
name
=>
'mp2'
,
kernel
=>[2,2],
stride
=>[2,2],
pool_type
=>
'max'
);
my
$fl
= mx->symbol->Flatten(
data
=>
$mp2
,
name
=>
"flatten"
);
my
$fc1
= mx->symbol->FullyConnected(
data
=>
$fl
,
name
=>
"fc1"
,
num_hidden
=>30);
my
$act3
= mx->symbol->Activation(
data
=>
$fc1
,
name
=>
'relu3'
,
act_type
=>
"relu"
);
my
$fc2
= mx->symbol->FullyConnected(
data
=>
$act3
,
name
=>
'fc2'
,
num_hidden
=>10);
my
$softmax
= mx->symbol->SoftmaxOutput(
data
=>
$fc2
,
name
=>
'softmax'
);
GetMNIST_ubyte();
my
$train_dataiter
= mx->io->MNISTIter({
image
=>
"data/train-images-idx3-ubyte"
,
label
=>
"data/train-labels-idx1-ubyte"
,
data_shape
=>[1, 28, 28],
batch_size
=>
$batch_size
,
shuffle
=>1,
flat
=>0,
silent
=>0,
seed
=>10});
my
$val_dataiter
= mx->io->MNISTIter({
image
=>
"data/t10k-images-idx3-ubyte"
,
label
=>
"data/t10k-labels-idx1-ubyte"
,
data_shape
=>[1, 28, 28],
batch_size
=>
$batch_size
,
shuffle
=>1,
flat
=>0,
silent
=>0});
my
$n_epoch
= 1;
my
$mod
= mx->mod->new(
symbol
=>
$softmax
);
$mod
->fit(
$train_dataiter
,
eval_data
=>
$val_dataiter
,
optimizer_params
=>{
learning_rate
=>0.01,
momentum
=> 0.9},
num_epoch
=>
$n_epoch
);
my
$res
=
$mod
->score(
$val_dataiter
, mx->metric->create(
'acc'
));
ok(
$res
->{accuracy} > 0.8);
my
$net
= nn->Sequential();
$net
->name_scope(
sub
{
$net
->add(nn->Dense(128,
activation
=>
'relu'
));
$net
->add(nn->Dense(64,
activation
=>
'relu'
));
$net
->add(nn->Dense(10));
});
$net
->hybridize;
sub
transformer
{
my
(
$data
,
$label
) =
@_
;
$data
=
$data
->reshape([-1])->astype(
'float32'
)/255;
return
(
$data
,
$label
);
}
my
$train_data
= gluon->data->DataLoader(
gluon->data->vision->MNIST(
'./data'
,
train
=>1,
transform
=> \
&transformer
),
batch_size
=>
$batch_size
,
shuffle
=>1,
last_batch
=>
'discard'
);
sub
train
{
my
(
$epochs
,
$ctx
) =
@_
;
$net
->initialize(mx->init->Xavier(
magnitude
=>2.24),
ctx
=>
$ctx
);
my
$trainer
= gluon->Trainer(
$net
->collect_params(),
'sgd'
, {
learning_rate
=>
$lr
,
momentum
=>
$momentum
});
my
$metric
= mx->metric->Accuracy();
my
$loss
= gluon->loss->SoftmaxCrossEntropyLoss();
for
my
$epoch
(0..
$epochs
-1)
{
$metric
->
reset
();
enumerate(
sub
{
my
(
$i
,
$d
) =
@_
;
my
(
$data
,
$label
) =
@$d
;
$data
=
$data
->as_in_context(
$ctx
);
$label
=
$label
->as_in_context(
$ctx
);
my
$output
;
autograd->record(
sub
{
$output
=
$net
->(
$data
);
my
$L
=
$loss
->(
$output
,
$label
);
$L
->backward;
});
$trainer
->step(
$data
->shape->[0]);
$metric
->update([
$label
], [
$output
]);
if
(
$i
%
$log_interval
== 0 and
$i
> 0)
{
my
(
$name
,
$acc
) =
$metric
->get();
print
"[Epoch $epoch Batch $i] Training: $name=$acc\n"
;
}
}, \@{
$train_data
});
my
(
$name
,
$acc
) =
$metric
->get();
print
"[Epoch $epoch] Training: $name=$acc\n"
;
my
(
$val_name
,
$val_acc
) = test(
$ctx
);
print
"[Epoch $epoch] Validation: $val_name=$val_acc\n"
}
$net
->save_parameters(
'mnist.params'
);
}
train(
$epochs
,
$cuda
? mx->gpu(0) : mx->cpu);