Skip to content

Commit

Permalink
ENH: Add live monitoring
Browse files Browse the repository at this point in the history
  • Loading branch information
sinhrks committed Jun 21, 2015
1 parent dbfba46 commit fbc933f
Show file tree
Hide file tree
Showing 3 changed files with 170 additions and 0 deletions.
Empty file added chainer/sandbox/__init__.py
Empty file.
65 changes: 65 additions & 0 deletions chainer/sandbox/plotting.py
@@ -0,0 +1,65 @@
#!/usr/bin/env python

from chainer import cuda, Variable

import numpy as np

import bokeh.plotting as plotting
from bokeh.models import GlyphRenderer


class LiveMonitor(object):

SLICE_UNIT = 500

def __init__(self, server='chainer', **kwargs):
plotting.output_server(server)

self.data = {}

self.train_loss = self._initialize_figure(title='Train loss', color='#FF0000', **kwargs)
self.train_acc = self._initialize_figure(title='Train accuracy', color='#0000FF', **kwargs)
self.test_loss = self._initialize_figure(title='Test loss', color='#FF0000', **kwargs)
self.test_acc = self._initialize_figure(title='Test accuracy', color='#0000FF', **kwargs)

self.grid = plotting.gridplot([[self.train_loss, self.test_loss],
[self.train_acc, self.test_acc]])

plotting.show(self.grid)

def _initialize_figure(self, color=None, line_width=2,
title=None, title_text_font_size='9pt',
plot_width=400, plot_height=280):
figure = plotting.figure(title=title, title_text_font_size=title_text_font_size,
plot_width=plot_width, plot_height=plot_height)
x = np.array([])
y = np.array([])
self.data[figure.title] = y
figure.line(x, y, color=color, line_width=line_width)
return figure

def _maybe_update(self, figure, value):
if value is not None:
if isinstance(value, Variable):
value = cuda.to_cpu(value.data)
renderer = figure.select(dict(type=GlyphRenderer))
ds = renderer[0].data_source

y = np.append(self.data[figure.title], value)
self.data[figure.title] = y
length = len(y)
x = np.arange(length)
if length > self.SLICE_UNIT:
step = length // self.SLICE_UNIT
y = y[::step]
x = x[::step]
ds.data['y'] = y
ds.data['x'] = x
plotting.cursession().store_objects(ds)

def update(self, train_loss=None, train_accuracy=None,
test_loss=None, test_accuracy=None):
self._maybe_update(self.train_loss, train_loss)
self._maybe_update(self.train_acc, train_accuracy)
self._maybe_update(self.test_loss, test_loss)
self._maybe_update(self.test_acc, test_accuracy)
105 changes: 105 additions & 0 deletions examples/mnist/train_mnist_monitoring.py
@@ -0,0 +1,105 @@
#!/usr/bin/env python
"""Chainer example: train a multi-layer perceptron on MNIST
This is a minimal example to write a feed-forward net. It requires scikit-learn
to load MNIST dataset.
"""
import argparse
import numpy as np
from sklearn.datasets import fetch_mldata
from chainer import cuda, Variable, FunctionSet, optimizers
import chainer.functions as F

parser = argparse.ArgumentParser(description='Chainer example: MNIST')
parser.add_argument('--gpu', '-g', default=-1, type=int,
help='GPU ID (negative value indicates CPU)')
args = parser.parse_args()

batchsize = 100
n_epoch = 20
n_units = 1000

# Prepare dataset
print 'fetch MNIST dataset'
mnist = fetch_mldata('MNIST original')
mnist.data = mnist.data.astype(np.float32)
mnist.data /= 255
mnist.target = mnist.target.astype(np.int32)

N = 60000
x_train, x_test = np.split(mnist.data, [N])
y_train, y_test = np.split(mnist.target, [N])
N_test = y_test.size

# Prepare multi-layer perceptron model
model = FunctionSet(l1=F.Linear(784, n_units),
l2=F.Linear(n_units, n_units),
l3=F.Linear(n_units, 10))
if args.gpu >= 0:
cuda.init(args.gpu)
model.to_gpu()

# Neural net architecture
def forward(x_data, y_data, train=True):
x, t = Variable(x_data), Variable(y_data)
h1 = F.dropout(F.relu(model.l1(x)), train=train)
h2 = F.dropout(F.relu(model.l2(h1)), train=train)
y = model.l3(h2)
return F.softmax_cross_entropy(y, t), F.accuracy(y, t)

# Setup optimizer
optimizer = optimizers.Adam()
optimizer.setup(model.collect_parameters())

# Live monitoring
from chainer.sandbox.plotting import LiveMonitor
monitor = LiveMonitor()

# Learning loop
for epoch in xrange(1, n_epoch+1):
print 'epoch', epoch

# training
perm = np.random.permutation(N)
sum_accuracy = 0
sum_loss = 0
for i in xrange(0, N, batchsize):
x_batch = x_train[perm[i:i+batchsize]]
y_batch = y_train[perm[i:i+batchsize]]
if args.gpu >= 0:
x_batch = cuda.to_gpu(x_batch)
y_batch = cuda.to_gpu(y_batch)

optimizer.zero_grads()
loss, acc = forward(x_batch, y_batch)
loss.backward()
optimizer.update()

monitor.update(train_loss=loss, train_accuracy=acc)

sum_loss += float(cuda.to_cpu(loss.data)) * batchsize
sum_accuracy += float(cuda.to_cpu(acc.data)) * batchsize

print 'train mean loss={}, accuracy={}'.format(
sum_loss / N, sum_accuracy / N)

# evaluation
sum_accuracy = 0
sum_loss = 0
for i in xrange(0, N_test, batchsize):
x_batch = x_test[i:i+batchsize]
y_batch = y_test[i:i+batchsize]
if args.gpu >= 0:
x_batch = cuda.to_gpu(x_batch)
y_batch = cuda.to_gpu(y_batch)

loss, acc = forward(x_batch, y_batch, train=False)

monitor.update(test_loss=loss, test_accuracy=acc)

sum_loss += float(cuda.to_cpu(loss.data)) * batchsize
sum_accuracy += float(cuda.to_cpu(acc.data)) * batchsize

print 'test mean loss={}, accuracy={}'.format(
sum_loss / N_test, sum_accuracy / N_test)

0 comments on commit fbc933f

Please sign in to comment.