-
Notifications
You must be signed in to change notification settings - Fork 835
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
10 changed files
with
1,909 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
MODEL_NAME=MnistClassifier | ||
API_TYPE=REST | ||
SERVICE_TYPE=MODEL | ||
PERSISTENCE=0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
#!/usr/bin/env python | ||
import chainer | ||
import numpy as np | ||
from train_mnist import MLP | ||
|
||
class MnistClassifier(object): | ||
def __init__(self, gpu=-1, model_path='result/snapshot_iter_12000', unit=1000): | ||
self.gpu = gpu | ||
|
||
# Create a same model object as what you used for training | ||
model = MLP(unit, 10) | ||
if gpu >= 0: | ||
model.to_gpu(gpu) | ||
|
||
# Load saved parameters from a NPZ file of the Trainer object | ||
try: | ||
chainer.serializers.load_npz( | ||
model_path, model, path='updater/model:main/predictor/') | ||
except Exception: | ||
chainer.serializers.load_npz( | ||
model_path, model, path='predictor/') | ||
|
||
self.model = model | ||
|
||
def predict(self, X, features_names, meta = None): | ||
X = np.float32(X) | ||
if self.gpu >= 0: | ||
X = chainer.cuda.cupy.asarray(X) | ||
with chainer.using_config('train', False): | ||
return self.model(X[None, ...]).array | ||
|
||
|
||
def main(): | ||
import argparse | ||
|
||
parser = argparse.ArgumentParser(description='Chainer example: MNIST') | ||
parser.add_argument('--gpu', '-g', type=int, default=-1, | ||
help='GPU ID (negative value indicates CPU)') | ||
parser.add_argument('--snapshot', '-s', | ||
default='result/snapshot_iter_12000', | ||
help='The path to a saved snapshot (NPZ)') | ||
parser.add_argument('--unit', '-u', type=int, default=1000, | ||
help='Number of units') | ||
args = parser.parse_args() | ||
|
||
print('GPU: {}'.format(args.gpu)) | ||
print('# unit: {}'.format(args.unit)) | ||
print('') | ||
|
||
# Prepare data | ||
train, test = chainer.datasets.get_mnist() | ||
x, answer = test[0] | ||
x = x.reshape(1, x.size) | ||
|
||
classifier = MnistClassifier(args.gpu, args.snapshot, args.unit) | ||
res = classifier.predict(x, []) | ||
prediction = res.argmax() | ||
|
||
print('Prediction:', prediction) | ||
print('Answer:', answer) | ||
|
||
|
||
if __name__ == '__main__': | ||
main() |
1,626 changes: 1,626 additions & 0 deletions
1,626
examples/models/chainer_mnist/chainer_mnist.ipynb
Large diffs are not rendered by default.
Oops, something went wrong.
53 changes: 53 additions & 0 deletions
53
examples/models/chainer_mnist/chainer_mnist_deployment.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
{ | ||
"apiVersion": "machinelearning.seldon.io/v1alpha2", | ||
"kind": "SeldonDeployment", | ||
"metadata": { | ||
"labels": { | ||
"app": "seldon" | ||
}, | ||
"name": "seldon-deployment-example" | ||
}, | ||
"spec": { | ||
"annotations": { | ||
"project_name": "Digits classification", | ||
"deployment_version": "0.0" | ||
}, | ||
"name": "chainer-mnist-deployment", | ||
"oauth_key": "oauth-key", | ||
"oauth_secret": "oauth-secret", | ||
"predictors": [ | ||
{ | ||
"componentSpecs": [{ | ||
"spec": { | ||
"containers": [ | ||
{ | ||
"image": "chainer-mnist:0.1", | ||
"imagePullPolicy": "IfNotPresent", | ||
"name": "chainer-mnist-classifier", | ||
"resources": { | ||
"requests": { | ||
"memory": "1Mi" | ||
} | ||
} | ||
} | ||
], | ||
"terminationGracePeriodSeconds": 20 | ||
} | ||
}], | ||
"graph": { | ||
"children": [], | ||
"name": "chainer-mnist-classifier", | ||
"endpoint": { | ||
"type" : "REST" | ||
}, | ||
"type": "MODEL" | ||
}, | ||
"name": "chainer-mnist-predictor", | ||
"replicas": 1, | ||
"annotations": { | ||
"predictor_version" : "0.0" | ||
} | ||
} | ||
] | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
{ | ||
"features":[ | ||
{ | ||
"name":"x", | ||
"dtype":"FLOAT", | ||
"ftype":"continuous", | ||
"range":[0,1], | ||
"repeat":784 | ||
} | ||
], | ||
"targets":[ | ||
{ | ||
"name":"class", | ||
"dtype":"FLOAT", | ||
"ftype":"continuous", | ||
"range":[0,1], | ||
"repeat":10 | ||
} | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
chainer==6.2.0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,134 @@ | ||
#!/usr/bin/env python | ||
import argparse | ||
|
||
import chainer | ||
import chainer.functions as F | ||
import chainer.links as L | ||
from chainer import training | ||
from chainer.training import extensions | ||
import chainerx | ||
|
||
|
||
# Network definition | ||
class MLP(chainer.Chain): | ||
|
||
def __init__(self, n_units, n_out): | ||
super(MLP, self).__init__() | ||
with self.init_scope(): | ||
# the size of the inputs to each layer will be inferred | ||
self.l1 = L.Linear(None, n_units) # n_in -> n_units | ||
self.l2 = L.Linear(None, n_units) # n_units -> n_units | ||
self.l3 = L.Linear(None, n_out) # n_units -> n_out | ||
|
||
def forward(self, x): | ||
h1 = F.relu(self.l1(x)) | ||
h2 = F.relu(self.l2(h1)) | ||
return self.l3(h2) | ||
|
||
|
||
def main(): | ||
parser = argparse.ArgumentParser(description='Chainer example: MNIST') | ||
parser.add_argument('--batchsize', '-b', type=int, default=100, | ||
help='Number of images in each mini-batch') | ||
parser.add_argument('--epoch', '-e', type=int, default=20, | ||
help='Number of sweeps over the dataset to train') | ||
parser.add_argument('--frequency', '-f', type=int, default=-1, | ||
help='Frequency of taking a snapshot') | ||
parser.add_argument('--device', '-d', type=str, default='-1', | ||
help='Device specifier. Either ChainerX device ' | ||
'specifier or an integer. If non-negative integer, ' | ||
'CuPy arrays with specified device id are used. If ' | ||
'negative integer, NumPy arrays are used') | ||
parser.add_argument('--out', '-o', default='result', | ||
help='Directory to output the result') | ||
parser.add_argument('--resume', '-r', type=str, | ||
help='Resume the training from snapshot') | ||
parser.add_argument('--unit', '-u', type=int, default=1000, | ||
help='Number of units') | ||
parser.add_argument('--noplot', dest='plot', action='store_false', | ||
help='Disable PlotReport extension') | ||
group = parser.add_argument_group('deprecated arguments') | ||
group.add_argument('--gpu', '-g', dest='device', | ||
type=int, nargs='?', const=0, | ||
help='GPU ID (negative value indicates CPU)') | ||
args = parser.parse_args() | ||
|
||
device = chainer.get_device(args.device) | ||
|
||
print('Device: {}'.format(device)) | ||
print('# unit: {}'.format(args.unit)) | ||
print('# Minibatch-size: {}'.format(args.batchsize)) | ||
print('# epoch: {}'.format(args.epoch)) | ||
print('') | ||
|
||
# Set up a neural network to train | ||
# Classifier reports softmax cross entropy loss and accuracy at every | ||
# iteration, which will be used by the PrintReport extension below. | ||
model = L.Classifier(MLP(args.unit, 10)) | ||
model.to_device(device) | ||
device.use() | ||
|
||
# Setup an optimizer | ||
optimizer = chainer.optimizers.Adam() | ||
optimizer.setup(model) | ||
|
||
# Load the MNIST dataset | ||
train, test = chainer.datasets.get_mnist() | ||
|
||
train_iter = chainer.iterators.SerialIterator(train, args.batchsize) | ||
test_iter = chainer.iterators.SerialIterator(test, args.batchsize, | ||
repeat=False, shuffle=False) | ||
|
||
# Set up a trainer | ||
updater = training.updaters.StandardUpdater( | ||
train_iter, optimizer, device=device) | ||
trainer = training.Trainer(updater, (args.epoch, 'epoch'), out=args.out) | ||
|
||
# Evaluate the model with the test dataset for each epoch | ||
trainer.extend(extensions.Evaluator(test_iter, model, device=device)) | ||
|
||
# Dump a computational graph from 'loss' variable at the first iteration | ||
# The "main" refers to the target link of the "main" optimizer. | ||
# TODO(niboshi): Temporarily disabled for chainerx. Fix it. | ||
if device.xp is not chainerx: | ||
trainer.extend(extensions.DumpGraph('main/loss')) | ||
|
||
# Take a snapshot for each specified epoch | ||
frequency = args.epoch if args.frequency == -1 else max(1, args.frequency) | ||
trainer.extend(extensions.snapshot(), trigger=(frequency, 'epoch')) | ||
|
||
# Write a log of evaluation statistics for each epoch | ||
trainer.extend(extensions.LogReport()) | ||
|
||
# Save two plot images to the result dir | ||
if args.plot and extensions.PlotReport.available(): | ||
trainer.extend( | ||
extensions.PlotReport(['main/loss', 'validation/main/loss'], | ||
'epoch', file_name='loss.png')) | ||
trainer.extend( | ||
extensions.PlotReport( | ||
['main/accuracy', 'validation/main/accuracy'], | ||
'epoch', file_name='accuracy.png')) | ||
|
||
# Print selected entries of the log to stdout | ||
# Here "main" refers to the target link of the "main" optimizer again, and | ||
# "validation" refers to the default name of the Evaluator extension. | ||
# Entries other than 'epoch' are reported by the Classifier link, called by | ||
# either the updater or the evaluator. | ||
trainer.extend(extensions.PrintReport( | ||
['epoch', 'main/loss', 'validation/main/loss', | ||
'main/accuracy', 'validation/main/accuracy', 'elapsed_time'])) | ||
|
||
# Print a progress bar to stdout | ||
trainer.extend(extensions.ProgressBar()) | ||
|
||
if args.resume is not None: | ||
# Resume from a snapshot | ||
chainer.serializers.load_npz(args.resume, trainer) | ||
|
||
# Run the training | ||
trainer.run() | ||
|
||
|
||
if __name__ == '__main__': | ||
main() |