提交 71686318 编写于 作者: Y Yan Chunwei 提交者: GitHub

Merge pull request #50 from ChunweiYan/feature/support_pytorch_demo

import onnx
import json import json
from google.protobuf.json_format import MessageToJson from google.protobuf.json_format import MessageToJson
import onnx
def reorganize_inout(json_obj, key): def reorganize_inout(json_obj, key):
""" """
......
import pprint import pprint
import random
import re import re
import urllib import urllib
from tempfile import NamedTemporaryFile from tempfile import NamedTemporaryFile
...@@ -22,13 +23,13 @@ def get_scalar_tags(storage, mode): ...@@ -22,13 +23,13 @@ def get_scalar_tags(storage, mode):
result[mode] = {} result[mode] = {}
for tag in tags: for tag in tags:
result[mode][tag] = { result[mode][tag] = {
'displayName': reader.scalar(tag).caption(), 'displayName': tag,
'description': "", 'description': "",
} }
return result return result
def get_scalar(storage, mode, tag): def get_scalar(storage, mode, tag, num_records=100):
with storage.mode(mode) as reader: with storage.mode(mode) as reader:
scalar = reader.scalar(tag) scalar = reader.scalar(tag)
...@@ -36,8 +37,12 @@ def get_scalar(storage, mode, tag): ...@@ -36,8 +37,12 @@ def get_scalar(storage, mode, tag):
ids = scalar.ids() ids = scalar.ids()
timestamps = scalar.timestamps() timestamps = scalar.timestamps()
result = zip(timestamps, ids, records) data = zip(timestamps, ids, records)
return result 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): def get_image_tags(storage):
...@@ -77,7 +82,9 @@ def get_image_tag_steps(storage, mode, tag): ...@@ -77,7 +82,9 @@ def get_image_tag_steps(storage, mode, tag):
for step_index in range(image.num_records()): for step_index in range(image.num_records()):
record = image.record(step_index, sample_index) record = image.record(step_index, sample_index)
shape = record.shape() 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({ query = urllib.urlencode({
'sample': 0, 'sample': 0,
'index': step_index, 'index': step_index,
...@@ -94,7 +101,7 @@ def get_image_tag_steps(storage, mode, tag): ...@@ -94,7 +101,7 @@ def get_image_tag_steps(storage, mode, tag):
return res 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: with storage.mode(mode) as reader:
res = re.search(r".*/([0-9]+$)", tag) res = re.search(r".*/([0-9]+$)", tag)
# remove suffix '/x' # remove suffix '/x'
...@@ -105,9 +112,16 @@ def get_invididual_image(storage, mode, tag, step_index): ...@@ -105,9 +112,16 @@ def get_invididual_image(storage, mode, tag, step_index):
image = reader.image(tag) image = reader.image(tag)
record = image.record(step_index, offset) record = image.record(step_index, offset)
shape = record.shape()
data = np.array(record.data(), dtype='uint8').reshape(record.shape()) data = np.array(record.data(), dtype='uint8').reshape(record.shape())
tempfile = NamedTemporaryFile(mode='w+b', suffix='.png') tempfile = NamedTemporaryFile(mode='w+b', suffix='.png')
with Image.fromarray(data) as im: 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) im.save(tempfile)
tempfile.seek(0, 0) tempfile.seek(0, 0)
return tempfile return tempfile
......
import lib import pprint
import unittest import unittest
import lib
import storage import storage
import pprint from storage_mock import add_image, add_scalar
from storage_mock import add_scalar, add_image
class LibTest(unittest.TestCase): class LibTest(unittest.TestCase):
...@@ -28,7 +29,7 @@ class LibTest(unittest.TestCase): ...@@ -28,7 +29,7 @@ class LibTest(unittest.TestCase):
def test_modes(self): def test_modes(self):
modes = lib.get_modes(self.reader) 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): def test_scalar(self):
......
...@@ -7,13 +7,12 @@ from optparse import OptionParser ...@@ -7,13 +7,12 @@ from optparse import OptionParser
from flask import (Flask, Response, redirect, request, send_file, from flask import (Flask, Response, redirect, request, send_file,
send_from_directory) send_from_directory)
import graph
import lib import lib
import storage import storage
import visualdl.mock.data as mock_data import visualdl.mock.data as mock_data
import visualdl.mock.tags as mock_tags import visualdl.mock.tags as mock_tags
from visualdl.log import logger from visualdl.log import logger
import storage
import graph
app = Flask(__name__, static_url_path="") app = Flask(__name__, static_url_path="")
# set static expires in a short time to reduce browser's memory usage. # set static expires in a short time to reduce browser's memory usage.
...@@ -51,7 +50,7 @@ server_path = os.path.abspath(os.path.dirname(sys.argv[0])) ...@@ -51,7 +50,7 @@ server_path = os.path.abspath(os.path.dirname(sys.argv[0]))
static_file_path = "./frontend/dist/" static_file_path = "./frontend/dist/"
mock_data_path = "./mock_data/" mock_data_path = "./mock_data/"
storage = storage.StorageReader(options.logdir) log_reader = storage.LogReader(options.logdir)
# return data # return data
...@@ -88,8 +87,7 @@ def logdir(): ...@@ -88,8 +87,7 @@ def logdir():
@app.route('/data/runs') @app.route('/data/runs')
def runs(): def runs():
modes = storage.modes() result = gen_result(0, "", lib.get_modes(log_reader))
result = gen_result(0, "", lib.get_modes())
return Response(json.dumps(result), mimetype='application/json') return Response(json.dumps(result), mimetype='application/json')
...@@ -100,7 +98,7 @@ def scalar_tags(): ...@@ -100,7 +98,7 @@ def scalar_tags():
if is_debug: if is_debug:
result = mock_tags.data() result = mock_tags.data()
else: else:
result = lib.get_scalar_tags(storage, mode) result = lib.get_scalar_tags(log_reader, mode)
print 'scalar tags (mode: %s)' % mode, result print 'scalar tags (mode: %s)' % mode, result
result = gen_result(0, "", result) result = gen_result(0, "", result)
return Response(json.dumps(result), mimetype='application/json') return Response(json.dumps(result), mimetype='application/json')
...@@ -109,7 +107,7 @@ def scalar_tags(): ...@@ -109,7 +107,7 @@ def scalar_tags():
@app.route("/data/plugin/images/tags") @app.route("/data/plugin/images/tags")
def image_tags(): def image_tags():
mode = request.args.get('run') 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 print 'image tags (mode: %s)'%mode, result
result = gen_result(0, "", result) result = gen_result(0, "", result)
return Response(json.dumps(result), mimetype='application/json') return Response(json.dumps(result), mimetype='application/json')
...@@ -123,7 +121,7 @@ def scalars(): ...@@ -123,7 +121,7 @@ def scalars():
if is_debug: if is_debug:
result = mock_data.sequence_data() result = mock_data.sequence_data()
else: else:
result = lib.get_scalar(storage, run, tag) result = lib.get_scalar(log_reader, run, tag)
result = gen_result(0, "", result) result = gen_result(0, "", result)
return Response(json.dumps(result), mimetype='application/json') return Response(json.dumps(result), mimetype='application/json')
...@@ -132,11 +130,9 @@ def scalars(): ...@@ -132,11 +130,9 @@ def scalars():
@app.route('/data/plugin/images/images') @app.route('/data/plugin/images/images')
def images(): def images():
mode = request.args.get('run') mode = request.args.get('run')
# TODO(ChunweiYan) update this when frontend fix the field name tag = request.args.get('tag')
#tag = request.args.get('tag')
tag = request.args.get('displayName')
result = lib.get_image_tag_steps(storage, mode, tag) result = lib.get_image_tag_steps(log_reader, mode, tag)
result = gen_result(0, "", result) result = gen_result(0, "", result)
return Response(json.dumps(result), mimetype='application/json') return Response(json.dumps(result), mimetype='application/json')
...@@ -149,7 +145,7 @@ def individual_image(): ...@@ -149,7 +145,7 @@ def individual_image():
step_index = int(request.args.get('index')) # index of step step_index = int(request.args.get('index')) # index of step
offset = 0 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( response = send_file(
imagefile, as_attachment=True, attachment_filename='img.png') imagefile, as_attachment=True, attachment_filename='img.png')
return response return response
...@@ -163,4 +159,4 @@ def graph(): ...@@ -163,4 +159,4 @@ def graph():
if __name__ == '__main__': if __name__ == '__main__':
logger.info(" port=" + str(options.port)) 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)
...@@ -22,6 +22,7 @@ PYBIND11_PLUGIN(core) { ...@@ -22,6 +22,7 @@ PYBIND11_PLUGIN(core) {
new (&instance) vs::LogReader(dir); new (&instance) vs::LogReader(dir);
}) })
.def("as_mode", &vs::LogReader::AsMode) .def("as_mode", &vs::LogReader::AsMode)
.def("set_mode", &vs::LogReader::SetMode)
.def("modes", [](vs::LogReader& self) { return self.storage().modes(); }) .def("modes", [](vs::LogReader& self) { return self.storage().modes(); })
.def("tags", &vs::LogReader::tags) .def("tags", &vs::LogReader::tags)
// clang-format off // clang-format off
...@@ -46,6 +47,7 @@ PYBIND11_PLUGIN(core) { ...@@ -46,6 +47,7 @@ PYBIND11_PLUGIN(core) {
[](vs::LogWriter& instance, const std::string& dir, int sync_cycle) { [](vs::LogWriter& instance, const std::string& dir, int sync_cycle) {
new (&instance) vs::LogWriter(dir, sync_cycle); new (&instance) vs::LogWriter(dir, sync_cycle);
}) })
.def("set_mode", &vs::LogWriter::SetMode)
.def("as_mode", &vs::LogWriter::AsMode) .def("as_mode", &vs::LogWriter::AsMode)
// clang-format off // clang-format off
WRITER_ADD_SCALAR(float) WRITER_ADD_SCALAR(float)
......
...@@ -14,9 +14,15 @@ public: ...@@ -14,9 +14,15 @@ public:
storage_.SetDir(dir); storage_.SetDir(dir);
storage_.meta.cycle = sync_cycle; storage_.meta.cycle = sync_cycle;
} }
LogWriter(const LogWriter& other) { LogWriter(const LogWriter& other) {
storage_ = other.storage_;
mode_ = other.mode_; mode_ = other.mode_;
storage_ = other.storage_;
}
void SetMode(const std::string& mode) {
mode_ = mode;
storage_.AddMode(mode);
} }
LogWriter AsMode(const std::string& mode) { LogWriter AsMode(const std::string& mode) {
...@@ -47,6 +53,8 @@ class LogReader { ...@@ -47,6 +53,8 @@ class LogReader {
public: public:
LogReader(const std::string& dir) : reader_(dir) {} LogReader(const std::string& dir) : reader_(dir) {}
void SetMode(const std::string& mode) { mode_ = mode; }
LogReader AsMode(const std::string& mode) { LogReader AsMode(const std::string& mode) {
auto tmp = *this; auto tmp = *this;
tmp.mode_ = mode; tmp.mode_ = mode;
...@@ -122,6 +130,9 @@ struct Scalar { ...@@ -122,6 +130,9 @@ struct Scalar {
void AddRecord(int id, T value) { void AddRecord(int id, T value) {
auto record = tablet_.AddRecord(); auto record = tablet_.AddRecord();
record.SetId(id); record.SetId(id);
time_t time = std::time(nullptr);
record.SetTimeStamp(time);
auto entry = record.template AddData<T>(); auto entry = record.template AddData<T>();
entry.Set(value); entry.Set(value);
} }
......
...@@ -31,6 +31,8 @@ TEST(Scalar, write) { ...@@ -31,6 +31,8 @@ TEST(Scalar, write) {
// check the first entry of first record // check the first entry of first record
ASSERT_EQ(record.front(), 12); ASSERT_EQ(record.front(), 12);
ASSERT_TRUE(!reader.storage().modes().empty());
// check tags // check tags
ASSERT_EQ(reader_.all_tags().size(), 1); ASSERT_EQ(reader_.all_tags().size(), 1);
auto tags = reader.tags("scalar"); auto tags = reader.tags("scalar");
...@@ -79,4 +81,31 @@ TEST(Image, test) { ...@@ -79,4 +81,31 @@ TEST(Image, test) {
CHECK_EQ(image2read.num_records(), num_steps); CHECK_EQ(image2read.num_records(), num_steps);
} }
TEST(Scalar, more_than_one_mode) {
const auto dir = "./tmp/sdk_multi_mode";
LogWriter log(dir, 20);
std::vector<components::Scalar<float>> scalars;
for (int i = 0; i < 1; i++) {
std::stringstream ss;
ss << "mode-" << i;
auto mode = ss.str();
auto writer = log.AsMode(mode);
ASSERT_EQ(writer.storage().dir(), dir);
LOG(INFO) << "origin dir: " << dir;
LOG(INFO) << "changed dir: " << writer.storage().dir();
auto tablet = writer.AddTablet("add/scalar0");
scalars.emplace_back(tablet);
}
for (int i = 0; i < 1; i++) {
auto& scalar = scalars[i];
for (int j = 0; j < 100; j++) {
scalar.AddRecord(j, (float)j);
}
}
}
} // namespace visualdl } // namespace visualdl
...@@ -16,8 +16,8 @@ class LogReader(object): ...@@ -16,8 +16,8 @@ class LogReader(object):
self.reader = reader if reader else core.LogReader(dir) self.reader = reader if reader else core.LogReader(dir)
def mode(self, mode): def mode(self, mode):
LogReader.cur_mode = self.as_mode(mode) self.reader.set_mode(mode)
return LogReader.cur_mode return self
def as_mode(self, mode): def as_mode(self, mode):
tmp = LogReader(dir, self.reader.as_mode(mode)) tmp = LogReader(dir, self.reader.as_mode(mode))
...@@ -41,10 +41,10 @@ class LogReader(object): ...@@ -41,10 +41,10 @@ class LogReader(object):
return self.reader.get_image(tag) return self.reader.get_image(tag)
def __enter__(self): def __enter__(self):
return LogReader.cur_mode return self
def __exit__(self, type, value, traceback): def __exit__(self, type, value, traceback):
pass self.reader.set_mode("default")
class LogWriter(object): class LogWriter(object):
...@@ -57,8 +57,8 @@ class LogWriter(object): ...@@ -57,8 +57,8 @@ class LogWriter(object):
self.writer = writer if writer else core.LogWriter(dir, sync_cycle) self.writer = writer if writer else core.LogWriter(dir, sync_cycle)
def mode(self, mode): def mode(self, mode):
LogWriter.cur_mode = self.as_mode(mode) self.writer.set_mode(mode)
return LogWriter.cur_mode return self
def as_mode(self, mode): def as_mode(self, mode):
LogWriter.cur_mode = LogWriter(self.dir, self.sync_cycle, self.writer.as_mode(mode)) LogWriter.cur_mode = LogWriter(self.dir, self.sync_cycle, self.writer.as_mode(mode))
...@@ -76,7 +76,7 @@ class LogWriter(object): ...@@ -76,7 +76,7 @@ class LogWriter(object):
return self.writer.new_image(tag, num_samples, step_cycle) return self.writer.new_image(tag, num_samples, step_cycle)
def __enter__(self): def __enter__(self):
return LogWriter.cur_mode return self
def __exit__(self, type, value, traceback): def __exit__(self, type, value, traceback):
pass self.writer.set_mode("default")
import random import random
import time import time
import unittest import unittest
from PIL import Image
import numpy as np import numpy as np
from PIL import Image
import storage import storage
...@@ -115,6 +115,22 @@ class StorageTest(unittest.TestCase): ...@@ -115,6 +115,22 @@ class StorageTest(unittest.TestCase):
scalar = reader.scalar("model/scalar/average") scalar = reader.scalar("model/scalar/average")
self.assertEqual(scalar.caption(), "train") self.assertEqual(scalar.caption(), "train")
def test_modes(self):
dir = "./tmp/storagetest0"
store = storage.LogWriter(
self.dir, sync_cycle=1)
scalars = []
for i in range(10):
with store.mode("mode-%d" % i) as writer:
scalar = writer.scalar("add/scalar0")
scalars.append(scalar)
for scalar in scalars[:-1]:
for i in range(10):
scalar.add_record(i, float(i))
if __name__ == '__main__': if __name__ == '__main__':
......
...@@ -13,7 +13,6 @@ ...@@ -13,7 +13,6 @@
#include "visualdl/utils/guard.h" #include "visualdl/utils/guard.h"
namespace visualdl { namespace visualdl {
static const std::string meta_file_name = "storage.meta"; static const std::string meta_file_name = "storage.meta";
static std::string meta_path(const std::string& dir) { static std::string meta_path(const std::string& dir) {
...@@ -43,6 +42,7 @@ struct Storage { ...@@ -43,6 +42,7 @@ struct Storage {
mutable SimpleSyncMeta meta; mutable SimpleSyncMeta meta;
Storage() { Storage() {
dir_ = std::make_shared<std::string>();
data_ = std::make_shared<storage::Storage>(); data_ = std::make_shared<storage::Storage>();
tablets_ = std::make_shared<std::map<std::string, storage::Tablet>>(); tablets_ = std::make_shared<std::map<std::string, storage::Tablet>>();
modes_ = std::make_shared<std::set<std::string>>(); modes_ = std::make_shared<std::set<std::string>>();
...@@ -51,7 +51,9 @@ struct Storage { ...@@ -51,7 +51,9 @@ struct Storage {
data_->set_timestamp(t); data_->set_timestamp(t);
} }
Storage(const Storage& other) Storage(const Storage& other)
: data_(other.data_), tablets_(other.tablets_), modes_(other.modes_) {} : data_(other.data_), tablets_(other.tablets_), modes_(other.modes_) {
dir_ = other.dir_;
}
// write operations // write operations
void AddMode(const std::string& x) { void AddMode(const std::string& x) {
...@@ -72,13 +74,23 @@ struct Storage { ...@@ -72,13 +74,23 @@ struct Storage {
return Tablet(&(*tablets_)[x], this); return Tablet(&(*tablets_)[x], this);
} }
void SetDir(const std::string& dir) { dir_ = dir; } void SetDir(const std::string& dir) { *dir_ = dir; }
void PersistToDisk() { PersistToDisk(dir_); } std::string dir() const { return *dir_; }
void PersistToDisk() {
CHECK(!dir_->empty()) << "dir should be set.";
fs::TryRecurMkdir(*dir_);
fs::SerializeToFile(*data_, meta_path(*dir_));
for (auto tag : data_->tags()) {
auto it = tablets_->find(tag);
CHECK(it != tablets_->end()) << "tag " << tag << " not exist.";
fs::SerializeToFile(it->second, tablet_path(*dir_, tag));
}
}
/* /*
* Save memory to disk. * Save memory to disk.
*/ */
void PersistToDisk(const std::string& dir) { void PersistToDisk(const std::string& dir) {
// LOG(INFO) << "persist to disk " << dir;
CHECK(!dir.empty()) << "dir should be set."; CHECK(!dir.empty()) << "dir should be set.";
fs::TryRecurMkdir(dir); fs::TryRecurMkdir(dir);
...@@ -95,13 +107,11 @@ struct Storage { ...@@ -95,13 +107,11 @@ struct Storage {
protected: protected:
void AddTag(const std::string& x) { void AddTag(const std::string& x) {
*data_->add_tags() = x; *data_->add_tags() = x;
LOG(INFO) << "add tag " << x;
LOG(INFO) << "tag.size " << data_->tags_size();
WRITE_GUARD WRITE_GUARD
} }
private: private:
std::string dir_; std::shared_ptr<std::string> dir_;
std::shared_ptr<std::map<std::string, storage::Tablet>> tablets_; std::shared_ptr<std::map<std::string, storage::Tablet>> tablets_;
std::shared_ptr<storage::Storage> data_; std::shared_ptr<storage::Storage> data_;
std::shared_ptr<std::set<std::string>> modes_; std::shared_ptr<std::set<std::string>> modes_;
......
...@@ -100,7 +100,7 @@ struct TabletReader { ...@@ -100,7 +100,7 @@ struct TabletReader {
// read operations. // read operations.
std::string tag() const { return data_.tag(); } std::string tag() const { return data_.tag(); }
Tablet::Type type() const { return Tablet::Type(data_.component()); } Tablet::Type type() const { return Tablet::Type(data_.component()); }
int64_t total_records() const { return data_.total_records(); } int64_t total_records() const { return data_.records_size(); }
int32_t num_samples() const { return data_.num_samples(); } int32_t num_samples() const { return data_.num_samples(); }
RecordReader record(int i) const { return RecordReader(data_.records(i)); } RecordReader record(int i) const { return RecordReader(data_.records(i)); }
template <typename T> template <typename T>
......
...@@ -67,9 +67,6 @@ static void NormalizeImage(Uint8Image* image, ...@@ -67,9 +67,6 @@ static void NormalizeImage(Uint8Image* image,
scale = (image_max < kZeroThreshold ? 0.0f : 255.0f) / image_max; scale = (image_max < kZeroThreshold ? 0.0f : 255.0f) / image_max;
offset = 0.0f; offset = 0.0f;
} }
LOG(INFO) << "scale " << scale;
// Transform image, turning nonfinite values to bad_color // Transform image, turning nonfinite values to bad_color
for (int i = 0; i < depth; i++) { for (int i = 0; i < depth; i++) {
auto tmp = scale * values.row(i).array() + offset; auto tmp = scale * values.row(i).array() + offset;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册