Skip to content

Commit

Permalink
Merge branch 'develop' of github.com:PaddlePaddle/VisualDL into develop
Browse files Browse the repository at this point in the history
  • Loading branch information
BingBlog committed Jan 3, 2018
2 parents 345b137 + 9444f05 commit 514629c
Show file tree
Hide file tree
Showing 18 changed files with 235 additions and 50 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -106,3 +106,7 @@ ENV/
node_modules
/.vscode
package-lock.json

# PyCharm IDE
.idea/

4 changes: 3 additions & 1 deletion server/build.sh
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
#!/bin/bash

script=$(readlink -f "$0")
script_path=$(dirname "$script")

pushd $script_path
protoc visualdl/onnx/onnx.proto --python_out .
protoc3/bin/protoc visualdl/onnx/onnx.proto --python_out .
python setup.py bdist_wheel
popd
6 changes: 5 additions & 1 deletion server/visualdl/graph.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import onnx
import json

from google.protobuf.json_format import MessageToJson

import onnx


def reorganize_inout(json_obj, key):
"""
Expand Down Expand Up @@ -29,6 +31,8 @@ def reorganize_inout(json_obj, key):


def add_edges(json_obj):
# TODO(daming-lu): should try to de-duplicate node's out-edge
# Currently it is counted twice: 1 as out-edge, 1 as in-edge
json_obj['edges'] = []
label_incrementer = 0

Expand Down
74 changes: 74 additions & 0 deletions server/visualdl/graph_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import unittest
import graph
import json


class GraphTest(unittest.TestCase):
def setUp(self):
self.mock_dir = "./mock"

def test_graph_edges_squeezenet(self):
json_str = graph.load_model(self.mock_dir + '/squeezenet_model.pb')
json_obj = json.loads(json_str)

# 126 edges + 66 nodes (out-edge of each node is counted twice)
self.assertEqual(len(json_obj['edges']), 126 + 66)

# label_0: (in-edge)
# {u'source': u'data_0', u'target': u'node_0', u'label': u'label_0'}
self.assertEqual(json_obj['edges'][0]['source'], 'data_0')
self.assertEqual(json_obj['edges'][0]['target'], 'node_0')
self.assertEqual(json_obj['edges'][0]['label'], 'label_0')

# label_50: (in-edge)
# {u'source': u'fire3/concat_1', u'target': u'node_17', u'label': u'label_50'}
self.assertEqual(json_obj['edges'][50]['source'], 'fire3/concat_1')
self.assertEqual(json_obj['edges'][50]['target'], 'node_17')
self.assertEqual(json_obj['edges'][50]['label'], 'label_50')

# label_100: (in-edge)
# {u'source': u'fire6/squeeze1x1_1', u'target': u'node_34', u'label': u'label_100'}
self.assertEqual(json_obj['edges'][100]['source'], 'fire6/squeeze1x1_1')
self.assertEqual(json_obj['edges'][100]['target'], 'node_34')
self.assertEqual(json_obj['edges'][100]['label'], 'label_100')

# label_111: (out-edge)
# {u'source': u'node_37', u'target': u'fire6/expand3x3_1', u'label': u'label_111'}
self.assertEqual(json_obj['edges'][111]['source'], 'node_37')
self.assertEqual(json_obj['edges'][111]['target'], 'fire6/expand3x3_1')
self.assertEqual(json_obj['edges'][111]['label'], 'label_111')

def test_graph_edges_inception_v1(self):
json_str = graph.load_model(self.mock_dir + '/inception_v1_model.pb')
json_obj = json.loads(json_str)

# 286 edges + 143 nodes (out-edge of each node is counted twice)
self.assertEqual(len(json_obj['edges']), 286 + 143)

# label_0: (in-edge)
# {u'source': u'data_0', u'target': u'node_0', u'label': u'label_0'}
self.assertEqual(json_obj['edges'][0]['source'], 'data_0')
self.assertEqual(json_obj['edges'][0]['target'], 'node_0')
self.assertEqual(json_obj['edges'][0]['label'], 'label_0')

# label_50: (in-edge)
# {u'source': u'inception_3a/5x5_reduce_2', u'target': u'node_18', u'label': u'label_50'}
self.assertEqual(json_obj['edges'][50]['source'], 'inception_3a/5x5_reduce_2')
self.assertEqual(json_obj['edges'][50]['target'], 'node_18')
self.assertEqual(json_obj['edges'][50]['label'], 'label_50')

# label_100: (out-edge)
# {u'source': u'node_34', u'target': u'inception_3b/pool_1', u'label': u'label_100'}
self.assertEqual(json_obj['edges'][100]['source'], 'node_34')
self.assertEqual(json_obj['edges'][100]['target'], 'inception_3b/pool_1')
self.assertEqual(json_obj['edges'][100]['label'], 'label_100')

# label_420: (out-edge)
# {u'source': u'node_139', u'target': u'pool5/7x7_s1_2', u'label': u'label_420'}
self.assertEqual(json_obj['edges'][420]['source'], 'node_139')
self.assertEqual(json_obj['edges'][420]['target'], 'pool5/7x7_s1_2')
self.assertEqual(json_obj['edges'][420]['label'], 'label_420')


if __name__ == '__main__':
unittest.main()
12 changes: 12 additions & 0 deletions server/visualdl/graph_test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#!/bin/bash
set -ex

cd mock
bash download_mock_models.sh

cd ..

python graph_test.py

rm ./mock/*.pb

26 changes: 20 additions & 6 deletions server/visualdl/lib.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import pprint
import random
import re
import urllib
from tempfile import NamedTemporaryFile
Expand All @@ -22,22 +23,26 @@ def get_scalar_tags(storage, mode):
result[mode] = {}
for tag in tags:
result[mode][tag] = {
'displayName': reader.scalar(tag).caption(),
'displayName': tag,
'description': "",
}
return result


def get_scalar(storage, mode, tag):
def get_scalar(storage, mode, tag, num_records=100):
with storage.mode(mode) as reader:
scalar = reader.scalar(tag)

records = scalar.records()
ids = scalar.ids()
timestamps = scalar.timestamps()

result = zip(timestamps, ids, records)
return result
data = zip(timestamps, ids, records)
if len(data) <= num_records:
return data

samples = sorted(random.sample(xrange(len(data)), num_records))
return [data[i] for i in samples]


def get_image_tags(storage):
Expand Down Expand Up @@ -77,7 +82,9 @@ def get_image_tag_steps(storage, mode, tag):
for step_index in range(image.num_records()):
record = image.record(step_index, sample_index)
shape = record.shape()
assert shape, "%s,%s" % (mode, tag)
# TODO(ChunweiYan) remove this trick, some shape will be empty
if not shape: continue
# assert shape, "%s,%s" % (mode, tag)
query = urllib.urlencode({
'sample': 0,
'index': step_index,
Expand All @@ -94,7 +101,7 @@ def get_image_tag_steps(storage, mode, tag):
return res


def get_invididual_image(storage, mode, tag, step_index):
def get_invididual_image(storage, mode, tag, step_index, max_size=80):
with storage.mode(mode) as reader:
res = re.search(r".*/([0-9]+$)", tag)
# remove suffix '/x'
Expand All @@ -105,9 +112,16 @@ def get_invididual_image(storage, mode, tag, step_index):
image = reader.image(tag)
record = image.record(step_index, offset)

shape = record.shape()

data = np.array(record.data(), dtype='uint8').reshape(record.shape())
tempfile = NamedTemporaryFile(mode='w+b', suffix='.png')
with Image.fromarray(data) as im:
size = max(shape[0], shape[1])
if size > max_size:
scale = max_size * 1. / size
scaled_shape = (int(shape[0]*scale), int(shape[1]*scale))
im = im.resize(scaled_shape)
im.save(tempfile)
tempfile.seek(0, 0)
return tempfile
Expand Down
9 changes: 5 additions & 4 deletions server/visualdl/lib_test.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import lib
import pprint
import unittest

import lib
import storage
import pprint
from storage_mock import add_scalar, add_image
from storage_mock import add_image, add_scalar


class LibTest(unittest.TestCase):
Expand All @@ -28,7 +29,7 @@ def setUp(self):

def test_modes(self):
modes = lib.get_modes(self.reader)
self.assertEqual(sorted(modes), sorted(["train", "test", "valid"]))
self.assertEqual(sorted(modes), sorted(["default", "train", "test", "valid"]))

def test_scalar(self):

Expand Down
4 changes: 2 additions & 2 deletions server/visualdl/mock/download_mock_models.sh
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

# Download inception_v1 model
curl -LOk http://visualdl.bj.bcebos.com/inception_v1.tar.gz

#curl -LOk https://www.dropbox.com/s/twbfdqgvowzy762/inception_v1.tar.gz?dl=0
tar -xvzf inception_v1.tar.gz
cp inception_v1/model.pb inception_v1_model.pb

Expand All @@ -11,7 +11,7 @@ rm inception_v1.tar.gz

# Download squeezenet model
curl -LOk http://visualdl.bj.bcebos.com/squeezenet.tar.gz

#curl -LOk https://www.dropbox.com/s/fip3jzxsjf2g6zc/squeezenet.tar.gz?dl=0
tar -xvzf squeezenet.tar.gz
cp squeezenet/model.pb squeezenet_model.pb

Expand Down
24 changes: 10 additions & 14 deletions server/visualdl/visual_dl.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,12 @@
from flask import (Flask, Response, redirect, request, send_file,
send_from_directory)

import graph
import lib
import storage
import visualdl.mock.data as mock_data
import visualdl.mock.tags as mock_tags
from visualdl.log import logger
import storage
import graph

app = Flask(__name__, static_url_path="")
# set static expires in a short time to reduce browser's memory usage.
Expand Down Expand Up @@ -51,7 +50,7 @@ def option_parser():
static_file_path = "./frontend/dist/"
mock_data_path = "./mock_data/"

storage = storage.StorageReader(options.logdir)
log_reader = storage.LogReader(options.logdir)


# return data
Expand Down Expand Up @@ -88,8 +87,7 @@ def logdir():

@app.route('/data/runs')
def runs():
modes = storage.modes()
result = gen_result(0, "", lib.get_modes())
result = gen_result(0, "", lib.get_modes(log_reader))
return Response(json.dumps(result), mimetype='application/json')


Expand All @@ -100,7 +98,7 @@ def scalar_tags():
if is_debug:
result = mock_tags.data()
else:
result = lib.get_scalar_tags(storage, mode)
result = lib.get_scalar_tags(log_reader, mode)
print 'scalar tags (mode: %s)' % mode, result
result = gen_result(0, "", result)
return Response(json.dumps(result), mimetype='application/json')
Expand All @@ -109,7 +107,7 @@ def scalar_tags():
@app.route("/data/plugin/images/tags")
def image_tags():
mode = request.args.get('run')
result = lib.get_image_tags(storage)
result = lib.get_image_tags(log_reader)
print 'image tags (mode: %s)'%mode, result
result = gen_result(0, "", result)
return Response(json.dumps(result), mimetype='application/json')
Expand All @@ -123,7 +121,7 @@ def scalars():
if is_debug:
result = mock_data.sequence_data()
else:
result = lib.get_scalar(storage, run, tag)
result = lib.get_scalar(log_reader, run, tag)

result = gen_result(0, "", result)
return Response(json.dumps(result), mimetype='application/json')
Expand All @@ -132,11 +130,9 @@ def scalars():
@app.route('/data/plugin/images/images')
def images():
mode = request.args.get('run')
# TODO(ChunweiYan) update this when frontend fix the field name
#tag = request.args.get('tag')
tag = request.args.get('displayName')
tag = request.args.get('tag')

result = lib.get_image_tag_steps(storage, mode, tag)
result = lib.get_image_tag_steps(log_reader, mode, tag)
result = gen_result(0, "", result)

return Response(json.dumps(result), mimetype='application/json')
Expand All @@ -149,7 +145,7 @@ def individual_image():
step_index = int(request.args.get('index')) # index of step
offset = 0

imagefile = lib.get_invididual_image(storage, mode, tag, step_index)
imagefile = lib.get_invididual_image(log_reader, mode, tag, step_index)
response = send_file(
imagefile, as_attachment=True, attachment_filename='img.png')
return response
Expand All @@ -163,4 +159,4 @@ def graph():

if __name__ == '__main__':
logger.info(" port=" + str(options.port))
app.run(debug=True, host=options.host, port=options.port)
app.run(debug=False, host=options.host, port=options.port)
13 changes: 13 additions & 0 deletions tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,21 @@ frontend_test() {
}

server_test() {
sudo pip install google
sudo pip install protobuf==3.1.0

cd $cur/server
curl -OL https://github.com/google/protobuf/releases/download/v3.1.0/protoc-3.1.0-linux-x86_64.zip
unzip protoc-3.1.0-linux-x86_64.zip -d protoc3
export PATH=$PATH:protoc3/bin
sudo chmod +x protoc3/bin/protoc
sudo chown `whoami` protoc3/bin/protoc

bash build.sh

cd visualdl
bash graph_test.sh

cd $cur/server/visualdl
python lib_test.py
}
Expand Down
2 changes: 2 additions & 0 deletions visualdl/logic/pybind.cc
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ PYBIND11_PLUGIN(core) {
new (&instance) vs::LogReader(dir);
})
.def("as_mode", &vs::LogReader::AsMode)
.def("set_mode", &vs::LogReader::SetMode)
.def("modes", [](vs::LogReader& self) { return self.storage().modes(); })
.def("tags", &vs::LogReader::tags)
// clang-format off
Expand All @@ -46,6 +47,7 @@ PYBIND11_PLUGIN(core) {
[](vs::LogWriter& instance, const std::string& dir, int sync_cycle) {
new (&instance) vs::LogWriter(dir, sync_cycle);
})
.def("set_mode", &vs::LogWriter::SetMode)
.def("as_mode", &vs::LogWriter::AsMode)
// clang-format off
WRITER_ADD_SCALAR(float)
Expand Down
Loading

0 comments on commit 514629c

Please sign in to comment.