Return-Path: X-Original-To: archive-asf-public-internal@cust-asf2.ponee.io Delivered-To: archive-asf-public-internal@cust-asf2.ponee.io Received: from cust-asf.ponee.io (cust-asf.ponee.io [163.172.22.183]) by cust-asf2.ponee.io (Postfix) with ESMTP id F382A200C04 for ; Tue, 24 Jan 2017 09:52:34 +0100 (CET) Received: by cust-asf.ponee.io (Postfix) id F2247160B4B; Tue, 24 Jan 2017 08:52:34 +0000 (UTC) Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by cust-asf.ponee.io (Postfix) with SMTP id 9C52B160B3D for ; Tue, 24 Jan 2017 09:52:33 +0100 (CET) Received: (qmail 42986 invoked by uid 500); 24 Jan 2017 08:52:32 -0000 Mailing-List: contact commits-help@singa.incubator.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@singa.incubator.apache.org Delivered-To: mailing list commits@singa.incubator.apache.org Received: (qmail 42977 invoked by uid 99); 24 Jan 2017 08:52:32 -0000 Received: from pnap-us-west-generic-nat.apache.org (HELO spamd2-us-west.apache.org) (209.188.14.142) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 24 Jan 2017 08:52:32 +0000 Received: from localhost (localhost [127.0.0.1]) by spamd2-us-west.apache.org (ASF Mail Server at spamd2-us-west.apache.org) with ESMTP id 5C3591A0607 for ; Tue, 24 Jan 2017 08:52:32 +0000 (UTC) X-Virus-Scanned: Debian amavisd-new at spamd2-us-west.apache.org X-Spam-Flag: NO X-Spam-Score: -6.218 X-Spam-Level: X-Spam-Status: No, score=-6.218 tagged_above=-999 required=6.31 tests=[KAM_ASCII_DIVIDERS=0.8, KAM_LAZY_DOMAIN_SECURITY=1, RCVD_IN_DNSWL_HI=-5, RCVD_IN_MSPIKE_H3=-0.01, RCVD_IN_MSPIKE_WL=-0.01, RP_MATCHES_RCVD=-2.999, URIBL_BLOCKED=0.001] autolearn=disabled Received: from mx1-lw-eu.apache.org ([10.40.0.8]) by localhost (spamd2-us-west.apache.org [10.40.0.9]) (amavisd-new, port 10024) with ESMTP id CpgXHsPf0opL for ; Tue, 24 Jan 2017 08:52:26 +0000 (UTC) Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by mx1-lw-eu.apache.org (ASF Mail Server at mx1-lw-eu.apache.org) with SMTP id 1E40F5FC80 for ; Tue, 24 Jan 2017 08:52:24 +0000 (UTC) Received: (qmail 42878 invoked by uid 99); 24 Jan 2017 08:52:24 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 24 Jan 2017 08:52:24 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id 3B638DFC2A; Tue, 24 Jan 2017 08:52:24 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: kaiping@apache.org To: commits@singa.incubator.apache.org Date: Tue, 24 Jan 2017 08:52:24 -0000 Message-Id: <1ae43fac16574ecb861fee90774e9ab4@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: [1/2] incubator-singa git commit: SINGA-295 - Add an example of image classification using GoogleNet archived-at: Tue, 24 Jan 2017 08:52:35 -0000 Repository: incubator-singa Updated Branches: refs/heads/master 8101f0066 -> d190fa89a http://git-wip-us.apache.org/repos/asf/incubator-singa/blob/d190fa89/examples/imagenet/ilsvrc12.h ---------------------------------------------------------------------- diff --git a/examples/imagenet/ilsvrc12.h b/examples/imagenet/ilsvrc12.h deleted file mode 100644 index 74fffbb..0000000 --- a/examples/imagenet/ilsvrc12.h +++ /dev/null @@ -1,376 +0,0 @@ -/************************************************************ -* -* Licensed to the Apache Software Foundation (ASF) under one -* or more contributor license agreements. See the NOTICE file -* distributed with this work for additional information -* regarding copyright ownership. The ASF licenses this file -* to you under the Apache License, Version 2.0 (the -* "License"); you may not use this file except in compliance -* with the License. You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, -* software distributed under the License is distributed on an -* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -* KIND, either express or implied. See the License for the -* specific language governing permissions and limitations -* under the License. -* -*************************************************************/ -#include "singa/singa_config.h" -#ifdef USE_OPENCV -#ifndef SINGA_EXAMPLES_IMAGENET_ILSVRC12_H_ -#define SINGA_EXAMPLES_IMAGENET_ILSVRC12_H_ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "singa/core/tensor.h" -#include "singa/io/decoder.h" -#include "singa/io/encoder.h" -#include "singa/io/reader.h" -#include "singa/io/transformer.h" -#include "singa/io/writer.h" -#include "singa/proto/io.pb.h" -#include "singa/utils/timer.h" - -using std::string; -using namespace singa::io; -namespace singa { -/// For reading ILSVRC2012 image data as tensors. -class ILSVRC { - public: - /// Setup encoder, decoder - ILSVRC(); - ~ILSVRC() { - if (encoder != nullptr) delete encoder; - if (decoder != nullptr) delete decoder; - if (transformer != nullptr) delete transformer; - if (reader != nullptr) { - reader->Close(); - delete reader; - } - if (writer != nullptr) { - writer->Close(); - delete writer; - } - } - /// Create binary files for training data - /// train_image_list: list file of training images - /// train_image_folder: folder where stores original training images - /// train_bin_folder: folder to store binary files - /// train_file_size: number of images that are contain in one binary file - void CreateTrainData(string train_image_list, string train_image_folder, - string train_bin_folder, size_t train_file_size); - /// Create binary files for test data - /// train_image_list: list file of test images - /// train_image_folder: folder where saves original test images - /// train_bin_folder: folder to save binary files - void CreateTestData(string test_image_list, string test_image_folder, - string test_bin_folder); - /// Load data from a binary file, return pair - /// suppose the data will be loaded file by file. - /// flag: kTrain or kTest - /// file: binary file which stores the images - /// read_size: number of images to be loaded - /// offset: offset in the file - /// n_read: number of images which are read - size_t LoadData(int flag, string file, size_t read_size, Tensor *x, Tensor *y, - size_t *n_read, int nthreads); - /// A wrapper method to spawn a thread to execute LoadData() method. - std::thread AsyncLoadData(int flag, string file, size_t read_size, Tensor *x, - Tensor *y, size_t *n_read, int nthreads); - - void DecodeTransform(int flag, int thid, int nthreads, - vector images, Tensor *x, Tensor *y); - /// A wrapper method to spawn a thread to execute Decodetransform() method. - std::thread AsyncDecodeTransform(int flag, int thid, int nthreads, - vector images, Tensor *x, - Tensor *y); - - /// Read mean from path - void ReadMean(string path); - - protected: - /// Read one image at path, resize the image - Tensor ReadImage(string path); - /// Write buff to the file in kCreate/kAppend mode - void Write(string outfile, singa::io::Mode mode); - void WriteMean(Tensor &mean, string path); - - private: - /// size for resizing - const size_t kImageSize = 256; - const size_t kImageNBytes = 3 * kImageSize * kImageSize; - /// size for cropping - const size_t kCropSize = 227; - Tensor mean; - string last_read_file = ""; - - JPGEncoder *encoder = nullptr; - JPGDecoder *decoder = nullptr; - ImageTransformer *transformer = nullptr; - BinFileReader *reader = nullptr; - BinFileWriter *writer = nullptr; -}; - -ILSVRC::ILSVRC() { - EncoderConf en_conf; - en_conf.set_image_dim_order("CHW"); - encoder = new JPGEncoder(); - encoder->Setup(en_conf); - - DecoderConf de_conf; - de_conf.set_image_dim_order("CHW"); - decoder = new JPGDecoder(); - decoder->Setup(de_conf); - - TransformerConf trans_conf; - trans_conf.add_crop_shape(kCropSize); - trans_conf.add_crop_shape(kCropSize); - trans_conf.set_image_dim_order("CHW"); - trans_conf.set_horizontal_mirror(true); - transformer = new ImageTransformer(); - transformer->Setup(trans_conf); -} - -Tensor ILSVRC::ReadImage(string path) { - cv::Mat mat = cv::imread(path, CV_LOAD_IMAGE_COLOR); - CHECK(mat.data != NULL) << "OpenCV load image fail: " << path; - cv::Size size(kImageSize, kImageSize); - cv::Mat resized; - cv::resize(mat, resized, size); - CHECK_EQ((size_t)resized.size().height, kImageSize); - CHECK_EQ((size_t)resized.size().width, kImageSize); - // dimension_order: CHW - Shape shape{(size_t)resized.channels(), (size_t)resized.rows, - (size_t)resized.cols}; - Tensor image(shape, singa::kUChar); - unsigned char *data = new unsigned char[kImageNBytes]; - for (int i = 0; i < resized.rows; i++) - for (int j = 0; j < resized.cols; j++) - for (int k = 0; k < resized.channels(); k++) - data[k * kImageSize * kImageSize + i * kImageSize + j] = - resized.at(i, j)[k]; - image.CopyDataFromHostPtr(data, kImageNBytes); - delete[] data; - - return image; -} - -void ILSVRC::WriteMean(Tensor &mean, string path) { - Tensor mean_lb(Shape{1}, kInt); - std::vector input; - input.push_back(mean); - input.push_back(mean_lb); - BinFileWriter bfwriter; - bfwriter.Open(path, kCreate); - bfwriter.Write(path, encoder->Encode(input)); - bfwriter.Flush(); - bfwriter.Close(); -} - -void ILSVRC::CreateTrainData(string image_list, string input_folder, - string output_folder, size_t file_size = 12800) { - std::vector> file_list; - size_t *sum = new size_t[kImageNBytes]; - for (size_t i = 0; i < kImageNBytes; i++) sum[i] = 0u; - string image_file_name; - int label; - string outfile; - std::ifstream image_list_file(image_list.c_str(), std::ios::in); - while (image_list_file >> image_file_name >> label) - file_list.push_back(std::make_pair(image_file_name, label)); - LOG(INFO) << "Data Shuffling"; - std::shuffle(file_list.begin(), file_list.end(), - std::default_random_engine()); - LOG(INFO) << "Total number of training images is " << file_list.size(); - size_t num_train_images = file_list.size(); - if (file_size == 0) file_size = num_train_images; - for (size_t imageid = 0; imageid < num_train_images; imageid++) { - string path = input_folder + "/" + file_list[imageid].first; - Tensor image = ReadImage(path); - auto image_data = image.data(); - for (size_t i = 0; i < kImageNBytes; i++) - sum[i] += static_cast(image_data[i]); - label = file_list[imageid].second; - Tensor lb(Shape{1}, kInt); - lb.CopyDataFromHostPtr(&label, 1); - std::vector input; - input.push_back(image); - input.push_back(lb); - string encoded_str = encoder->Encode(input); - if (writer == nullptr) { - writer = new BinFileWriter(); - outfile = output_folder + "/train" + - std::to_string(imageid / file_size + 1) + ".bin"; - writer->Open(outfile, kCreate); - } - writer->Write(path, encoded_str); - if ((imageid + 1) % file_size == 0) { - writer->Flush(); - writer->Close(); - LOG(INFO) << "Write " << file_size << " images into " << outfile; - delete writer; - writer = nullptr; - } - } - if (writer != nullptr) { - writer->Flush(); - writer->Close(); - LOG(INFO) << "Write " << num_train_images % file_size << " images into " - << outfile; - delete writer; - writer = nullptr; - } - size_t num_file = - num_train_images / file_size + ((num_train_images % file_size) ? 1 : 0); - LOG(INFO) << "Write " << num_train_images << " images into " << num_file - << " binary files"; - Tensor mean = Tensor(Shape{3, kImageSize, kImageSize}, kUChar); - unsigned char *mean_data = new unsigned char[kImageNBytes]; - for (size_t i = 0; i < kImageNBytes; i++) - mean_data[i] = static_cast(sum[i] / num_train_images); - mean.CopyDataFromHostPtr(mean_data, kImageNBytes); - string mean_path = output_folder + "/mean.bin"; - WriteMean(mean, mean_path); - delete[] mean_data; - delete[] sum; -} - -void ILSVRC::CreateTestData(string image_list, string input_folder, - string output_folder) { - std::vector> file_list; - string image_file_name; - string outfile = output_folder + "/test.bin"; - int label; - std::ifstream image_list_file(image_list.c_str(), std::ios::in); - while (image_list_file >> image_file_name >> label) - file_list.push_back(std::make_pair(image_file_name, label)); - LOG(INFO) << "Total number of test images is " << file_list.size(); - size_t num_test_images = file_list.size(); - for (size_t imageid = 0; imageid < num_test_images; imageid++) { - string path = input_folder + "/" + file_list[imageid].first; - Tensor image = ReadImage(path); - label = file_list[imageid].second; - Tensor lb(Shape{1}, singa::kInt); - lb.CopyDataFromHostPtr(&label, 1); - std::vector input; - input.push_back(image); - input.push_back(lb); - string encoded_str = encoder->Encode(input); - if (writer == nullptr) { - writer = new BinFileWriter(); - writer->Open(outfile, kCreate); - } - writer->Write(path, encoded_str); - } - if (writer != nullptr) { - writer->Flush(); - writer->Close(); - delete writer; - writer = nullptr; - } - LOG(INFO) << "Write " << num_test_images << " images into " << outfile; -} - -void ILSVRC::ReadMean(string path) { - BinFileReader bfreader; - string key, value; - bfreader.Open(path); - bfreader.Read(&key, &value); - auto ret = decoder->Decode(value); - bfreader.Close(); - mean = ret[0]; -} - -std::thread ILSVRC::AsyncLoadData(int flag, string file, size_t read_size, - Tensor *x, Tensor *y, size_t *n_read, - int nthreads) { - return std::thread( - [=]() { LoadData(flag, file, read_size, x, y, n_read, nthreads); }); -} - -size_t ILSVRC::LoadData(int flag, string file, size_t read_size, Tensor *x, - Tensor *y, size_t *n_read, int nthreads) { - x->Reshape(Shape{read_size, 3, kCropSize, kCropSize}); - y->AsType(kInt); - y->Reshape(Shape{read_size}); - if (file != last_read_file) { - if (reader != nullptr) { - reader->Close(); - delete reader; - reader = nullptr; - } - reader = new BinFileReader(); - reader->Open(file, 100 << 20); - last_read_file = file; - } else if (reader == nullptr) { - reader = new BinFileReader(); - reader->Open(file, 100 << 20); - } - vector images; - for (size_t i = 0; i < read_size; i++) { - string image_path; - string *image = new string(); - bool ret = reader->Read(&image_path, image); - if (ret == false) { - reader->Close(); - delete reader; - reader = nullptr; - break; - } - images.push_back(image); - } - int nimg = images.size(); - *n_read = nimg; - - vector threads; - for (int i = 1; i < nthreads; i++) { - threads.push_back(AsyncDecodeTransform(flag, i, nthreads, images, x, y)); - } - DecodeTransform(flag, 0, nthreads, images, x, y); - for (size_t i = 0; i < threads.size(); i++) threads[i].join(); - for (int k = 0; k < nimg; k++) delete images.at(k); - return nimg; -} - -std::thread ILSVRC::AsyncDecodeTransform(int flag, int thid, int nthreads, - vector images, Tensor *x, - Tensor *y) { - return std::thread( - [=]() { DecodeTransform(flag, thid, nthreads, images, x, y); }); -} - -void ILSVRC::DecodeTransform(int flag, int thid, int nthreads, - vector images, Tensor *x, Tensor *y) { - int nimg = images.size(); - int start = nimg / nthreads * thid; - int end = start + nimg / nthreads; - for (int k = start; k < end; k++) { - std::vector pair = decoder->Decode(*images.at(k)); - auto tmp_image = pair[0] - mean; - Tensor aug_image = transformer->Apply(flag, tmp_image); - CopyDataToFrom(x, aug_image, aug_image.Size(), k * aug_image.Size()); - CopyDataToFrom(y, pair[1], 1, k); - } - if (thid == 0) { - for (int k = nimg / nthreads * nthreads; k < nimg; k++) { - std::vector pair = decoder->Decode(*images.at(k)); - auto tmp_image = pair[0] - mean; - Tensor aug_image = transformer->Apply(flag, tmp_image); - CopyDataToFrom(x, aug_image, aug_image.Size(), k * aug_image.Size()); - CopyDataToFrom(y, pair[1], 1, k); - } - } -} -} // namespace singa - -#endif // SINGA_EXAMPLES_IMAGENET_ILSVRC12_H_ -#endif // USE_OPENCV http://git-wip-us.apache.org/repos/asf/incubator-singa/blob/d190fa89/examples/imagenet/run.sh ---------------------------------------------------------------------- diff --git a/examples/imagenet/run.sh b/examples/imagenet/run.sh deleted file mode 100755 index 6277d23..0000000 --- a/examples/imagenet/run.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/usr/bin/env sh -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -../../build/bin/imagenet -epoch 90 -lr 0.01 -batchsize 256 -filesize 1280 -ntrain 1281167 -ntest 50000 \ - -data "imagenet_data" -pfreq 100 -nthreads 12 http://git-wip-us.apache.org/repos/asf/incubator-singa/blob/d190fa89/include/singa/core/tensor.h ---------------------------------------------------------------------- diff --git a/include/singa/core/tensor.h b/include/singa/core/tensor.h index 28d1619..c89fa83 100644 --- a/include/singa/core/tensor.h +++ b/include/singa/core/tensor.h @@ -458,6 +458,8 @@ void SoftmaxCrossEntropyBwd(const Tensor &t, Tensor *p); Tensor CopyRows(const Tensor &in, const size_t start, const size_t end); /// Alias of CopyRows Tensor SliceRows(const Tensor &in, const size_t start, const size_t end); +/// Slice the input tensor along the give axis to generate a new tensor +Tensor SliceOn(const Tensor &in, const size_t start, const size_t end, int axis); /// Return a tensor consisting of columns ([start, end)) from 'in'. It copies /// the values from 'in'. 'in' is a 2D Tensor. Tensor CopyColumns(const Tensor &in, const size_t start, const size_t end); @@ -466,6 +468,8 @@ Tensor SliceColumns(const Tensor &in, const size_t start, const size_t end); /// Return a tensor which is vertically stacked from tensors in 'in'. Each /// tensor in 'in' is a 2D tensor. Values are copied, no memory sharing. Tensor ConcatenateRows(const vector &in); +/// Return a tensor concatenated of the input tensors along the give axis. +Tensor ConcatOn(const vector &in, int axis); /// Alias name for function ConcatenateRows Tensor ConcatRows(const vector &in); /// Return a tensor which is horizontally stacked from tensors in 'in'. Each http://git-wip-us.apache.org/repos/asf/incubator-singa/blob/d190fa89/python/setup.py.in ---------------------------------------------------------------------- diff --git a/python/setup.py.in b/python/setup.py.in index 503ac8a..30be063 100644 --- a/python/setup.py.in +++ b/python/setup.py.in @@ -61,7 +61,10 @@ setup( install_requires=[ 'numpy>=1.11.0', 'protobuf>=2.5.0,<3', - 'unittest-xml-reporting' + 'unittest-xml-reporting', + 'flask>=0.10.1', + 'flask_cors>=3.0.2', + 'pillow>=2.3.0' ], #List additional groups of dependencies here (e.g. development http://git-wip-us.apache.org/repos/asf/incubator-singa/blob/d190fa89/python/singa/net.py ---------------------------------------------------------------------- diff --git a/python/singa/net.py b/python/singa/net.py index d6e313e..027e78c 100644 --- a/python/singa/net.py +++ b/python/singa/net.py @@ -409,7 +409,12 @@ class FeedForwardNet(object): params = pickle.load(fd) for (specs, val) in zip(self.param_specs(), self.param_values()): - val.copy_from_numpy(params[specs.name]) + try: + val.copy_from_numpy(params[specs.name]) + except AssertionError as err: + print 'Error from copying values for param: %s' % specs.name + print 'shape of param vs checkpoint', val.shape, params[specs.name].shape + raise err else: print 'NOTE: If your model was saved using pickle, '\ 'then set use_pickle=True for loading it' http://git-wip-us.apache.org/repos/asf/incubator-singa/blob/d190fa89/python/singa/tensor.py ---------------------------------------------------------------------- diff --git a/python/singa/tensor.py b/python/singa/tensor.py index 12d7c53..7dee9f5 100644 --- a/python/singa/tensor.py +++ b/python/singa/tensor.py @@ -578,9 +578,9 @@ def to_numpy(t): ''' th = to_host(t) if th.dtype == core_pb2.kFloat32: - np_array = ret.singa_tensor.GetFloatValue(int(th.size())) + np_array = th.singa_tensor.GetFloatValue(int(th.size())) elif th.dtype == core_pb2.kInt: - np_array = ret.singa_tensor.GetIntValue(int(th.size())) + np_array = th.singa_tensor.GetIntValue(int(th.size())) else: print 'Not implemented yet for ', th.dtype return np_array.reshape(th.shape) http://git-wip-us.apache.org/repos/asf/incubator-singa/blob/d190fa89/src/core/tensor/tensor.cc ---------------------------------------------------------------------- diff --git a/src/core/tensor/tensor.cc b/src/core/tensor/tensor.cc index d40fd88..ed4da96 100644 --- a/src/core/tensor/tensor.cc +++ b/src/core/tensor/tensor.cc @@ -742,6 +742,42 @@ void DivColumn(const Tensor &v, Tensor *M) { MultColumn(inv, M); } +Tensor ConcatOn(const vector &in, int axis) { + vector tmp; + Shape out_shape = in[0].shape(); + size_t dim = in[0].shape().size(); + CHECK_GE(dim, 2u) << " Only work for tensor of dim >=2 "; + size_t size = in[0].Size() / in[0].shape(axis); + size_t new_size = 0u; + for (const auto& t: in) { + CHECK_EQ(dim, t.shape().size()) << "All tensors should have the same dim"; + CHECK_EQ(size, t.Size() / t.shape(axis)) << "The size of all axis should " + <<" be the same except the concatenated axis"; + new_size += t.shape(axis); + } + out_shape[axis] = new_size; + if (axis == 0) { + size_t nrow = 0; + for (const auto& t: in) { + nrow += t.shape(0); + tmp.push_back(Reshape(t, {t.shape(0), t.Size() / t.shape(0)})); + } + auto ret = ConcatenateRows(tmp); + ret.Reshape(out_shape); + return ret; + } else { + for (const auto& t: in) { + size_t nrow = 1; + for (int i = 0; i < axis; i++) + nrow *= t.shape(i); + tmp.push_back(Reshape(t, {nrow, t.Size() / nrow})); + } + auto ret = ConcatenateColumns(tmp); + ret.Reshape(out_shape); + return ret; + } +} + Tensor ConcatenateRows(const vector &in) { size_t nrow = 0, ncol = 0; CHECK(in.size()); @@ -805,6 +841,27 @@ Tensor CopyRows(const Tensor &in, const size_t start, const size_t end) { return out; } + +Tensor SliceOn(const Tensor&in, const size_t start, const size_t end, int axis) { + Shape out_shape = in.shape(); + out_shape[axis] = end - start; + if (axis == 0) { + auto ret = SliceRows(Reshape(in, {in.shape(0), in.Size() / in.shape(0)}), + start, end); + ret.Reshape(out_shape); + return ret; + } else { + size_t nrow = 1; + for (int i = 0; i < axis; i++) + nrow *= in.shape(i); + auto suffix = in.Size() / nrow / in.shape(axis); + auto ret = SliceColumns(Reshape(in, {nrow, in.Size() / nrow}), + start * suffix, end * suffix); + ret.Reshape(out_shape); + return ret; + } +} + Tensor SliceRows(const Tensor &in, const size_t start, const size_t end) { return CopyRows(in, start, end); } http://git-wip-us.apache.org/repos/asf/incubator-singa/blob/d190fa89/src/io/network/endpoint.cc ---------------------------------------------------------------------- diff --git a/src/io/network/endpoint.cc b/src/io/network/endpoint.cc index e61acdb..f88edbf 100644 --- a/src/io/network/endpoint.cc +++ b/src/io/network/endpoint.cc @@ -227,6 +227,9 @@ void NetworkThread::doWork() { LOG(FATAL) << "Bind Error: " << strerror(errno); } + // TODO(wangwei) remove the hardcode setting, which would result erros if + // there are more than 10 connections + // reported by yaochang if (listen(socket_fd_, 10)) { LOG(FATAL) << "Listen Error: " << strerror(errno); } http://git-wip-us.apache.org/repos/asf/incubator-singa/blob/d190fa89/src/model/layer/concat.cc ---------------------------------------------------------------------- diff --git a/src/model/layer/concat.cc b/src/model/layer/concat.cc index 88c2409..a94b68e 100644 --- a/src/model/layer/concat.cc +++ b/src/model/layer/concat.cc @@ -30,14 +30,26 @@ void Concat::Setup(const vector& in_shapes, const LayerConf& conf) { out_sample_shape_.clear(); slice_point_.clear(); axis_ = conf.concat_conf().axis(); - if (axis_ == 0) - out_sample_shape_.push_back(in_shapes[0][0]); - else { + CHECK_GE(axis_, 0); + + if (axis_ == 0) { + out_sample_shape_ = in_shapes[0]; + size_t fea_size = Product(in_shapes[0]); + for (auto& s: in_shapes) { + CHECK_EQ(Product(s), fea_size) << "Feature length of all source samples " + << "must be the same"; + } + } else { + out_sample_shape_ = in_shapes[0]; + size_t fea_size = Product(in_shapes[0]) / in_shapes[0][axis_ - 1]; size_t l = 0; for (auto& s: in_shapes) { - l += s[0]; + CHECK_GE(s.size(), axis_); + l += s[axis_ - 1]; + CHECK_EQ(fea_size, Product(s) / s[axis_ - 1]) + << "Feature length for all axis except axis_ must be the same"; } - out_sample_shape_.push_back(l); + out_sample_shape_[axis_ - 1] = l; } } @@ -52,10 +64,7 @@ const vector Concat::Forward(int flag, const vector& inputs) { if (inputs.size() == 1u) { outputs = inputs; } else { - if(axis_ == 0) - outputs.push_back(ConcatRows(inputs)); - else - outputs.push_back(ConcatColumns(inputs)); + outputs.push_back(ConcatOn(inputs, axis_)); } return outputs; } @@ -66,10 +75,7 @@ const std::pair, vector> Concat::Backward( CHECK_EQ(grads.size(), 1u) << "Concat layer only have one output tensor."; size_t last_offset = 0u; for (auto p : slice_point_) { - if (axis_ == 0) - input_grad.push_back(SliceRows(grads.at(0), last_offset, p)); - else - input_grad.push_back(SliceColumns(grads.at(0), last_offset, p)); + input_grad.push_back(SliceOn(grads.at(0), last_offset, p, axis_)); last_offset = p; } return std::make_pair(input_grad, param_grad); http://git-wip-us.apache.org/repos/asf/incubator-singa/blob/d190fa89/src/model/layer/concat.h ---------------------------------------------------------------------- diff --git a/src/model/layer/concat.h b/src/model/layer/concat.h index 4e9a967..a759167 100644 --- a/src/model/layer/concat.h +++ b/src/model/layer/concat.h @@ -23,6 +23,9 @@ #include "singa/model/layer.h" namespace singa { +/** + * Cocnatenate tensors from the source layers along the give axis. + */ class Concat : public Layer { public: /// \copydoc Layer::layer_type() @@ -43,7 +46,7 @@ class Concat : public Layer { const vector& grad) override; protected: - /// 0 for concat rows; 1 for concat cols + /// >= 0 int axis_ = 0; /// slice_point_[i] the end offset of the i-th source tensor on the concat /// axis of the result tensor http://git-wip-us.apache.org/repos/asf/incubator-singa/blob/d190fa89/src/model/layer/pooling.cc ---------------------------------------------------------------------- diff --git a/src/model/layer/pooling.cc b/src/model/layer/pooling.cc index 75dc133..a8f3d3d 100644 --- a/src/model/layer/pooling.cc +++ b/src/model/layer/pooling.cc @@ -65,6 +65,8 @@ void Pooling::Setup(const Shape& in_sample, const LayerConf& conf) { width_ = in_sample.at(2); pooled_height_ = 1; if (pool_conf.ceil()) { + // TODO(wangwei): caffe also ensures the last pooling window starts strictly + // within the original area if (stride_h_ > 0) pooled_height_ = static_cast(ceil(static_cast( height_ + 2 * pad_h_ - kernel_h_) / stride_h_)) + 1; http://git-wip-us.apache.org/repos/asf/incubator-singa/blob/d190fa89/src/model/layer/slice.cc ---------------------------------------------------------------------- diff --git a/src/model/layer/slice.cc b/src/model/layer/slice.cc index 66c05ee..8a3e4bf 100644 --- a/src/model/layer/slice.cc +++ b/src/model/layer/slice.cc @@ -30,22 +30,26 @@ void Slice::Setup(const Shape& in_sample, const LayerConf& conf) { out_sample_shapes_.clear(); slice_point_.clear(); axis_ = conf.slice_conf().axis(); + CHECK_GE(axis_, 0u); int offset = 0; // #slice point = # out tensors - 1 for (size_t p : conf.slice_conf().slice_point()) { slice_point_.push_back(p); - if (axis_ == 1) { - out_sample_shapes_.push_back({p - offset}); - offset = p; - } else { + if (axis_ == 0) { out_sample_shapes_.push_back(in_sample); + } else { + auto s = in_sample; + s[axis_ - 1] = p - offset; + out_sample_shapes_.push_back(s); + offset = p; } } - slice_point_.push_back(in_sample[0]); - if (axis_ == 1) { - out_sample_shapes_.push_back({in_sample[0] - offset}); - } else { + if (axis_ == 0) { out_sample_shapes_.push_back(in_sample); + } else { + auto s = in_sample; + s[axis_ - 1] = in_sample[axis_ - 1] - offset; + out_sample_shapes_.push_back(s); } } @@ -54,12 +58,11 @@ const vector Slice::Forward(int flag, const vector& inputs) { CHECK_EQ(inputs.size(), 1u) << "Split layer only have one input tensor."; size_t offset = 0; for (auto& s : slice_point_) { - if (axis_ == 0) - outputs.push_back(SliceRows(inputs.at(0), offset, s)); - else - outputs.push_back(SliceColumns(inputs.at(0), offset, s)); + outputs.push_back(SliceOn(inputs.at(0), offset, s, axis_)); offset = s; } + outputs.push_back(SliceOn(inputs.at(0), offset, inputs.at(0).shape(axis_), + axis_)); return outputs; } @@ -67,10 +70,7 @@ const std::pair, vector> Slice::Backward( int flag, const vector& grads) { vector input_grad, param_grad; CHECK_EQ(grads.size(), out_sample_shapes_.size()); - if (axis_ == 0) - input_grad.push_back(ConcatRows(grads)); - else - input_grad.push_back(ConcatColumns(grads)); + input_grad.push_back(ConcatOn(grads, axis_)); return std::make_pair(input_grad, param_grad); } http://git-wip-us.apache.org/repos/asf/incubator-singa/blob/d190fa89/src/model/layer/slice.h ---------------------------------------------------------------------- diff --git a/src/model/layer/slice.h b/src/model/layer/slice.h index 7ed61fc..536fe64 100644 --- a/src/model/layer/slice.h +++ b/src/model/layer/slice.h @@ -23,6 +23,10 @@ #include "singa/model/layer.h" namespace singa { +/** + * Slice the tensor from the source layer along the give axis and according to + * the give slicep points. + */ class Slice : public Layer { public: /// \copydoc Layer::layer_type() @@ -44,7 +48,7 @@ class Slice : public Layer { const vector& grad) override; protected: - /// 0 for slice rows; 1 for slice cols + /// >= 0 int axis_ = 0; /// out_sample_shapes_[i] is the shape of the i-th output tensor vector out_sample_shapes_; http://git-wip-us.apache.org/repos/asf/incubator-singa/blob/d190fa89/test/CMakeLists.txt ---------------------------------------------------------------------- diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 79e481c..a056631 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -21,8 +21,8 @@ INCLUDE_DIRECTORIES(${CMAKE_BINARY_DIR}/include) IF(ENABLE_DIST) ADD_EXECUTABLE(test_ep "singa/test_ep.cc") - ADD_DEPENDENCIES(test_ep singa_io) - TARGET_LINK_LIBRARIES(test_ep singa_utils singa_io protobuf ${SINGA_LINKER_LIBS}) + ADD_DEPENDENCIES(test_ep singa) + TARGET_LINK_LIBRARIES(test_ep singa protobuf ${SINGA_LINKER_LIBS}) ENDIF() ADD_LIBRARY(gtest STATIC EXCLUDE_FROM_ALL "gtest/gtest.h" "gtest/gtest-all.cc")