|
try: |
|
import caffe2.python.predictor.predictor_exporter as pe |
|
except ImportError: |
|
print('Please check that Caffe2 is installed correctly to run this demo.') |
|
import numpy as np |
|
import os |
|
import shutil |
|
|
|
from caffe2.python import core, model_helper, workspace, brew |
|
from tensorboardX import TorchVis |
|
|
|
""" |
|
This is a demo showcasing specific functionality for Caffe2. Shown here are |
|
add_scalar (with both raw numerical data and Caffe2 blob names) |
|
add_scalars (with both raw numerical data and Caffe2 blob names) |
|
add_graph (visualizing a Caffe2 model as a graph) |
|
|
|
NOTE: lmdb must be installed and enabled with -DUSE_LMDB=ON for this demo to work. |
|
""" |
|
|
|
|
|
|
|
core.GlobalInit(['caffe2', '--caffe2_log_level=0']) |
|
print("Necessities imported!") |
|
|
|
|
|
|
|
def DownloadResource(url, path): |
|
'''Downloads resources from s3 by url and unzips them to the provided path''' |
|
import requests |
|
from six import BytesIO |
|
import zipfile |
|
print("Downloading... {} to {}".format(url, path)) |
|
r = requests.get(url, stream=True) |
|
z = zipfile.ZipFile(BytesIO(r.content)) |
|
z.extractall(path) |
|
print("Completed download and extraction.") |
|
|
|
|
|
current_folder = os.path.join(os.path.expanduser('~'), 'caffe2_notebooks') |
|
data_folder = os.path.join(current_folder, 'tutorial_data', 'mnist') |
|
root_folder = os.path.join(current_folder, 'tutorial_files', 'tutorial_mnist') |
|
db_missing = False |
|
|
|
if not os.path.exists(data_folder): |
|
os.makedirs(data_folder) |
|
print("Your data folder was not found!! This was generated: {}".format(data_folder)) |
|
|
|
|
|
if os.path.exists(os.path.join(data_folder, "mnist-train-nchw-lmdb")): |
|
print("lmdb train db found!") |
|
else: |
|
db_missing = True |
|
|
|
if os.path.exists(os.path.join(data_folder, "mnist-test-nchw-lmdb")): |
|
print("lmdb test db found!") |
|
else: |
|
db_missing = True |
|
|
|
|
|
if db_missing: |
|
print("one or both of the MNIST lmbd dbs not found!!") |
|
db_url = "http://download.caffe2.ai/databases/mnist-lmdb.zip" |
|
try: |
|
DownloadResource(db_url, data_folder) |
|
except Exception as ex: |
|
print( |
|
"Failed to download dataset. Please download it manually from {}".format(db_url)) |
|
print("Unzip it and place the two database folders here: {}".format(data_folder)) |
|
raise ex |
|
|
|
if os.path.exists(root_folder): |
|
print("Looks like you ran this before, so we need to cleanup those old files...") |
|
shutil.rmtree(root_folder) |
|
|
|
os.makedirs(root_folder) |
|
workspace.ResetWorkspace(root_folder) |
|
|
|
print("training data folder:" + data_folder) |
|
print("workspace root folder:" + root_folder) |
|
|
|
|
|
|
|
|
|
tv = TorchVis() |
|
|
|
|
|
def AddInput(model, batch_size, db, db_type): |
|
|
|
data_uint8, label = model.TensorProtosDBInput( |
|
[], ["data_uint8", "label"], batch_size=batch_size, |
|
db=db, db_type=db_type) |
|
|
|
data = model.Cast(data_uint8, "data", to=core.DataType.FLOAT) |
|
|
|
data = model.Scale(data, data, scale=float(1. / 256)) |
|
|
|
data = model.StopGradient(data, data) |
|
return data, label |
|
|
|
|
|
def AddLeNetModel(model, data): |
|
''' |
|
This part is the standard LeNet model: from data to the softmax prediction. |
|
|
|
For each convolutional layer we specify dim_in - number of input channels |
|
and dim_out - number or output channels. Also each Conv and MaxPool layer changes the |
|
image size. For example, kernel of size 5 reduces each side of an image by 4. |
|
|
|
While when we have kernel and stride sizes equal 2 in a MaxPool layer, it divides |
|
each side in half. |
|
''' |
|
|
|
conv1 = brew.conv(model, data, 'conv1', dim_in=1, dim_out=20, kernel=5) |
|
|
|
pool1 = brew.max_pool(model, conv1, 'pool1', kernel=2, stride=2) |
|
|
|
conv2 = brew.conv(model, pool1, 'conv2', dim_in=20, dim_out=100, kernel=5) |
|
|
|
pool2 = brew.max_pool(model, conv2, 'pool2', kernel=2, stride=2) |
|
|
|
|
|
fc3 = brew.fc(model, pool2, 'fc3', dim_in=100 * 4 * 4, dim_out=500) |
|
relu = brew.relu(model, fc3, fc3) |
|
pred = brew.fc(model, relu, 'pred', 500, 10) |
|
softmax = brew.softmax(model, pred, 'softmax') |
|
return softmax |
|
|
|
|
|
def AddAccuracy(model, softmax, label): |
|
"""Adds an accuracy op to the model""" |
|
accuracy = brew.accuracy(model, [softmax, label], "accuracy") |
|
return accuracy |
|
|
|
|
|
def AddTrainingOperators(model, softmax, label): |
|
"""Adds training operators to the model.""" |
|
xent = model.LabelCrossEntropy([softmax, label], 'xent') |
|
|
|
loss = model.AveragedLoss(xent, "loss") |
|
|
|
AddAccuracy(model, softmax, label) |
|
|
|
|
|
model.AddGradientOperators([loss]) |
|
|
|
ITER = brew.iter(model, "iter") |
|
|
|
LR = model.LearningRate( |
|
ITER, "LR", base_lr=-0.1, policy="step", stepsize=1, gamma=0.999) |
|
|
|
|
|
ONE = model.param_init_net.ConstantFill([], "ONE", shape=[1], value=1.0) |
|
|
|
for param in model.params: |
|
|
|
|
|
param_grad = model.param_to_grad[param] |
|
|
|
model.WeightedSum([param, ONE, param_grad, LR], param) |
|
|
|
|
|
def AddBookkeepingOperators(model): |
|
"""This adds a few bookkeeping operators that we can inspect later. |
|
|
|
These operators do not affect the training procedure: they only collect |
|
statistics and prints them to file or to logs. |
|
""" |
|
|
|
|
|
|
|
model.Print('accuracy', [], to_file=1) |
|
model.Print('loss', [], to_file=1) |
|
|
|
|
|
for param in model.params: |
|
model.Summarize(param, [], to_file=1) |
|
model.Summarize(model.param_to_grad[param], [], to_file=1) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
arg_scope = {"order": "NCHW"} |
|
train_model = model_helper.ModelHelper(name="mnist_train", arg_scope=arg_scope) |
|
data, label = AddInput( |
|
train_model, batch_size=64, |
|
db=os.path.join(data_folder, 'mnist-train-nchw-lmdb'), |
|
db_type='lmdb') |
|
softmax = AddLeNetModel(train_model, data) |
|
AddTrainingOperators(train_model, softmax, label) |
|
AddBookkeepingOperators(train_model) |
|
|
|
|
|
tv.add_graph(train_model, data) |
|
|
|
|
|
|
|
|
|
|
|
|
|
test_model = model_helper.ModelHelper( |
|
name="mnist_test", arg_scope=arg_scope, init_params=False) |
|
data, label = AddInput( |
|
test_model, batch_size=100, |
|
db=os.path.join(data_folder, 'mnist-test-nchw-lmdb'), |
|
db_type='lmdb') |
|
softmax = AddLeNetModel(test_model, data) |
|
AddAccuracy(test_model, softmax, label) |
|
|
|
|
|
deploy_model = model_helper.ModelHelper( |
|
name="mnist_deploy", arg_scope=arg_scope, init_params=False) |
|
AddLeNetModel(deploy_model, "data") |
|
|
|
|
|
|
|
|
|
with open(os.path.join(root_folder, "train_net.pbtxt"), 'w') as fid: |
|
fid.write(str(train_model.net.Proto())) |
|
with open(os.path.join(root_folder, "train_init_net.pbtxt"), 'w') as fid: |
|
fid.write(str(train_model.param_init_net.Proto())) |
|
with open(os.path.join(root_folder, "test_net.pbtxt"), 'w') as fid: |
|
fid.write(str(test_model.net.Proto())) |
|
with open(os.path.join(root_folder, "test_init_net.pbtxt"), 'w') as fid: |
|
fid.write(str(test_model.param_init_net.Proto())) |
|
with open(os.path.join(root_folder, "deploy_net.pbtxt"), 'w') as fid: |
|
fid.write(str(deploy_model.net.Proto())) |
|
print("Protocol buffers files have been created in your root folder: " + root_folder) |
|
|
|
|
|
workspace.RunNetOnce(train_model.param_init_net) |
|
|
|
workspace.CreateNet(train_model.net, overwrite=True) |
|
|
|
total_iters = 200 |
|
accuracy = np.zeros(total_iters) |
|
loss = np.zeros(total_iters) |
|
|
|
for i in range(total_iters): |
|
workspace.RunNet(train_model.net) |
|
accuracy[i] = workspace.FetchBlob('accuracy') |
|
loss[i] = workspace.FetchBlob('loss') |
|
scalar_dict_raw = {'accuracy': accuracy[i], 'loss': loss[i]} |
|
scalar_dict_blobname = {'accuracy': 'accuracy', 'loss': 'loss'} |
|
|
|
tv.add_scalars('training_raw', scalar_dict_raw, i) |
|
|
|
tv.add_scalars('training_blobname', scalar_dict_blobname, i) |
|
|
|
data = workspace.FetchBlob('data') |
|
softmax = workspace.FetchBlob('softmax') |
|
|
|
|
|
conv = workspace.FetchBlob('conv1') |
|
shape = list(conv.shape) |
|
shape[1] = 1 |
|
|
|
conv = conv[:, 15, :, :].reshape(shape) |
|
|
|
|
|
workspace.RunNetOnce(test_model.param_init_net) |
|
workspace.CreateNet(test_model.net, overwrite=True) |
|
test_accuracy = np.zeros(100) |
|
for i in range(100): |
|
workspace.RunNet(test_model.net.Proto().name) |
|
test_accuracy[i] = workspace.FetchBlob('accuracy') |
|
tv.add_scalar('test_accuracy_raw', test_accuracy[i], i) |
|
tv.add_scalar('test_accuracy_blobname', 'accuracy', i) |
|
|
|
print('test_accuracy: %f' % test_accuracy.mean()) |
|
|