singa-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From kaip...@apache.org
Subject [1/2] incubator-singa git commit: SINGA-295 - Add an example of image classification using GoogleNet
Date Tue, 24 Jan 2017 08:52:24 GMT
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 <omp.h>
-#include <cstdint>
-#include <fstream>
-#include <iostream>
-#include <opencv2/highgui/highgui.hpp>
-#include <opencv2/imgproc/imgproc.hpp>
-#include <string>
-#include <thread>
-#include <vector>
-#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 <images, labels> 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<string *> 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<string *> 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<cv::Vec3b>(i, j)[k];
-  image.CopyDataFromHostPtr<unsigned char>(data, kImageNBytes);
-  delete[] data;
-
-  return image;
-}
-
-void ILSVRC::WriteMean(Tensor &mean, string path) {
-  Tensor mean_lb(Shape{1}, kInt);
-  std::vector<Tensor> 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<std::pair<string, int>> 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<unsigned char>();
-    for (size_t i = 0; i < kImageNBytes; i++)
-      sum[i] += static_cast<size_t>(image_data[i]);
-    label = file_list[imageid].second;
-    Tensor lb(Shape{1}, kInt);
-    lb.CopyDataFromHostPtr<int>(&label, 1);
-    std::vector<Tensor> 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<unsigned char>(sum[i] / num_train_images);
-  mean.CopyDataFromHostPtr<unsigned char>(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<std::pair<string, int>> 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<int>(&label, 1);
-    std::vector<Tensor> 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<string *> 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<std::thread> 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<string *> 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<string *> 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<Tensor> 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<Tensor> 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<Tensor> &in);
+/// Return a tensor concatenated of the input tensors along the give axis.
+Tensor ConcatOn(const vector<Tensor> &in, int axis);
 /// Alias name for function ConcatenateRows
 Tensor ConcatRows(const vector<Tensor> &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<Tensor> &in, int axis) {
+  vector<Tensor> 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<Tensor> &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<Shape>& 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<Tensor> Concat::Forward(int flag, const vector<Tensor>&
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<Tensor>, vector<Tensor>> 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<Tensor>& 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<int>(ceil(static_cast<float>(
               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<Tensor> Slice::Forward(int flag, const vector<Tensor>&
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<Tensor>, vector<Tensor>> Slice::Backward(
     int flag, const vector<Tensor>& grads) {
   vector<Tensor> 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<Tensor>& 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<Shape> 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")


Mime
View raw message