a bunch of updates.
authorYangqing Jia <jiayq84@gmail.com>
Sun, 29 Sep 2013 18:08:11 +0000 (11:08 -0700)
committerYangqing Jia <jiayq84@gmail.com>
Sun, 29 Sep 2013 18:08:11 +0000 (11:08 -0700)
13 files changed:
src/caffe/net.cpp
src/caffe/net.hpp
src/caffe/optimization/solver.cpp
src/caffe/proto/caffe.proto
src/caffe/test/data/lena_256.jpg [new file with mode: 0644]
src/caffe/test/data/lenet.prototxt
src/caffe/test/data/simple_conv.prototxt [new file with mode: 0644]
src/caffe/test/lenet.hpp
src/caffe/test/test_net_proto.cpp
src/caffe/test/test_simple_conv.cpp [new file with mode: 0644]
src/caffe/util/io.cpp
src/caffe/util/io.hpp
src/examples/convolution.cpp [new file with mode: 0644]

index 22d27436e77422bf418bf126af12709ec6eb6aa1..bc699fa2c62756e5636ebb041d672d3ed8a929e1 100644 (file)
@@ -23,11 +23,11 @@ Net<Dtype>::Net(const NetParameter& param,
   map<string, int> blob_name_to_idx;
   set<string> available_blobs;
   int num_layers = param.layers_size();
-  CHECK_EQ(bottom.size(), param.bottom_size())
+  CHECK_EQ(bottom.size(), param.input_size())
       << "Incorrect bottom blob size.";
   // set the input blobs
-  for (int i = 0; i < param.bottom_size(); ++i) {
-    const string& blob_name = param.bottom(i);
+  for (int i = 0; i < param.input_size(); ++i) {
+    const string& blob_name = param.input(i);
     CHECK_GT(bottom[i]->count(), 0);
     shared_ptr<Blob<Dtype> > blob_pointer(
         new Blob<Dtype>(bottom[i]->num(), bottom[i]->channels(),
@@ -77,25 +77,15 @@ Net<Dtype>::Net(const NetParameter& param,
       top_id_vecs_[i].push_back(blob_names_.size() - 1);
     }
   }
-  LOG(INFO) << "Checking top blobs.";
-  // In the end, check if all remaining available blobs are top blobs.
-  for (int i = 0; i < param.top_size(); ++i) {
-    const string& blob_name = param.top(i);
-    if (blob_name_to_idx.find(blob_name) == blob_name_to_idx.end()) {
-      LOG(FATAL) << "Unknown blob output " << blob_name;
-    }
-    net_output_blob_indices_.push_back(blob_name_to_idx[blob_name]);
-    available_blobs.erase(blob_name);
-  }
-  if (!available_blobs.empty()) {
-    LOG(WARNING) << "There are some internal blobs not used:";
-    for (set<string>::iterator it = available_blobs.begin();
-        it != available_blobs.end(); ++it) {
-      LOG(WARNING) << "    " << *it;
-    }
+  // In the end, all remaining blobs are considered output blobs.
+  for (set<string>::iterator it = available_blobs.begin();
+      it != available_blobs.end(); ++it) {
+    LOG(ERROR) << "This network produces output " << *it;
+    net_output_blob_indices_.push_back(blob_name_to_idx[*it]);
+    net_output_blobs_.push_back(blobs_[blob_name_to_idx[*it]].get());
   }
 
-  LOG(INFO) << "Setting up the layers.";
+  LOG(ERROR) << "Setting up the layers.";
   for (int i = 0; i < layers_.size(); ++i) {
     LOG(INFO) << "Setting up " << layer_names_[i];
     layers_[i]->SetUp(bottom_vecs_[i], &top_vecs_[i]);
@@ -105,12 +95,12 @@ Net<Dtype>::Net(const NetParameter& param,
     }
   }
 
-  LOG(INFO) << "Network initialization done.";
+  LOG(ERROR) << "Network initialization done.";
 }
 
 template <typename Dtype>
-void Net<Dtype>::Forward(const vector<Blob<Dtype>*> & bottom,
-    vector<Blob<Dtype>*>* top) {
+const vector<Blob<Dtype>*>& Net<Dtype>::Forward(
+    const vector<Blob<Dtype>*> & bottom) {
   // Copy bottom to internal bottom
   for (int i = 0; i < bottom.size(); ++i) {
     blobs_[net_input_blob_indices_[i]]->CopyFrom(*bottom[i]);
@@ -118,10 +108,7 @@ void Net<Dtype>::Forward(const vector<Blob<Dtype>*> & bottom,
   for (int i = 0; i < layers_.size(); ++i) {
     layers_[i]->Forward(bottom_vecs_[i], &top_vecs_[i]);
   }
-  // Copy internal top to top
-  for (int i = 0; i < (*top).size(); ++i) {
-    (*top)[i]->CopyFrom(*blobs_[net_output_blob_indices_[i]]);
-  }
+  return net_output_blobs_;
 }
 
 template <typename Dtype>
@@ -168,10 +155,7 @@ void Net<Dtype>::ToProto(NetParameter* param, bool write_diff) {
   param->set_name(name_);
   // Add bottom and top
   for (int i = 0; i < net_input_blob_indices_.size(); ++i) {
-    param->add_bottom(blob_names_[net_input_blob_indices_[i]]);
-  }
-  for (int i = 0; i < net_output_blob_indices_.size(); ++i) {
-    param->add_top(blob_names_[net_output_blob_indices_[i]]);
+    param->add_input(blob_names_[net_input_blob_indices_[i]]);
   }
   for (int i = 0; i < layers_.size(); ++i) {
     LayerConnection* layer_connection = param->add_layers();
index 1f1a80309256ae84eb284e63ae5617f844d78120..3ac5fb81382832cb39ad24e00f112bfc1b97cccd 100644 (file)
@@ -24,16 +24,14 @@ class Net {
   Net(const NetParameter& param,
       const vector<Blob<Dtype>* >& bottom);
   ~Net() {}
-  void Forward(const vector<Blob<Dtype>* > & bottom,
-      vector<Blob<Dtype>*>* top);
+  const vector<Blob<Dtype>*>& Forward(const vector<Blob<Dtype>* > & bottom);
   // The network backward should take no input and output, since it solely
   // computes the gradient w.r.t the parameters, and the data has already
   // been provided during the forward pass.
   Dtype Backward();
 
-  Dtype ForwardBackWard(const vector<Blob<Dtype>* > & bottom,
-      vector<Blob<Dtype>*>* top) {
-    Forward(bottom, top);
+  Dtype ForwardBackWard(const vector<Blob<Dtype>* > & bottom) {
+    Forward(bottom);
     return Backward();
   }
 
@@ -66,17 +64,16 @@ class Net {
   // layers.
   vector<shared_ptr<Blob<Dtype> > > blobs_;
   vector<string> blob_names_;
-  // bottom_vecs stores the vectors containing the input for each layer, except
-  // for the first layer whose bottom vec is provided by the network's input.
+  // bottom_vecs stores the vectors containing the input for each layer
   vector<vector<Blob<Dtype>*> > bottom_vecs_;
   vector<vector<int> > bottom_id_vecs_;
-  // top_vecs stores the vectors containing the output for each layer, except
-  // for the last layer (likewise)
+  // top_vecs stores the vectors containing the output for each layer
   vector<vector<Blob<Dtype>*> > top_vecs_;
   vector<vector<int> > top_id_vecs_;
   // blob indices for the input and the output of the net.
   vector<int> net_input_blob_indices_;
   vector<int> net_output_blob_indices_;
+  vector<Blob<Dtype>*> net_output_blobs_;
   string name_;
   // The parameters in the network.
   vector<shared_ptr<Blob<Dtype> > > params_;
index b9055d26eace5f50a1a8c05865c0ed64413f04ab..4f343c81ce902f8b8311c956ae4874de8bc298d5 100644 (file)
@@ -20,9 +20,8 @@ void Solver<Dtype>::Solve(Net<Dtype>* net) {
   // For a network that is trained by the solver, no bottom or top vecs
   // should be given, and we will just provide dummy vecs.
   vector<Blob<Dtype>*> bottom_vec;
-  vector<Blob<Dtype>*> top_vec;
   while (iter_++ < param_.max_iter()) {
-    Dtype loss = net_->ForwardBackWard(bottom_vec, &top_vec);
+    Dtype loss = net_->ForwardBackWard(bottom_vec);
     ComputeUpdateValue();
     net->Update();
 
index 9d691d271ca0c508c94763088fb8db5bf225aed6..70c399cf91045d4527cb405d8d8a387c8fa08ecc 100644 (file)
@@ -74,8 +74,7 @@ message LayerConnection {
 message NetParameter {
   optional string name = 1; // consider giving the network a name
   repeated LayerConnection layers = 2; // a bunch of layers.
-  repeated string bottom = 3; // The input to the network
-  repeated string top = 4; // The output of the network.
+  repeated string input = 3; // The input to the network
 }
 
 message SolverParameter {
diff --git a/src/caffe/test/data/lena_256.jpg b/src/caffe/test/data/lena_256.jpg
new file mode 100644 (file)
index 0000000..7b834b6
Binary files /dev/null and b/src/caffe/test/data/lena_256.jpg differ
index a7d578efddfcbee46302b0892a51952ccb7d4b03..8bb3ff790cd2cca607c77435d8822c031957d9d6 100644 (file)
@@ -1,6 +1,6 @@
 name: "LeNet"
-bottom: "data"
-bottom: "label"
+input: "data"
+input: "label"
 layers {
   layer {
     name: "conv1"
diff --git a/src/caffe/test/data/simple_conv.prototxt b/src/caffe/test/data/simple_conv.prototxt
new file mode 100644 (file)
index 0000000..4000da6
--- /dev/null
@@ -0,0 +1,18 @@
+name: "SimpleConv"
+input: "data"
+layers {
+  layer {
+    name: "conv"
+    type: "conv"
+    num_output: 1
+    kernelsize: 5
+    stride: 1
+    weight_filler {
+      type: "constant"
+      value: 0.01333333
+    }
+    biasterm: false
+  }
+  bottom: "data"
+  top: "smooth"
+}
index 017463a053e7007ffdc48fcd60ff5faeea4eea22..8b5b285549cc51a34ec5c55ec9ccec484576d0c2 100644 (file)
@@ -12,8 +12,8 @@
 namespace caffe {
 
 const char* kLENET = "name: \"LeNet\"\n"
-"bottom: \"data\"\n"
-"bottom: \"label\"\n"
+"input: \"data\"\n"
+"input: \"label\"\n"
 "layers {\n"
 "  layer {\n"
 "    name: \"conv1\"\n"
index b2403460138de4aae6e629eb3fcd0b42f813f695..cd16ed659091ee5fbb75a95b94fc4045f97b63da 100644 (file)
@@ -39,8 +39,7 @@ TYPED_TEST(NetProtoTest, TestSetup) {
       lenet_string, &net_param));
   // check if things are right
   EXPECT_EQ(net_param.layers_size(), 9);
-  EXPECT_EQ(net_param.bottom_size(), 2);
-  EXPECT_EQ(net_param.top_size(), 0);
+  EXPECT_EQ(net_param.input_size(), 2);
 
   // Now, initialize a network using the parameter
   shared_ptr<Blob<TypeParam> > data(new Blob<TypeParam>(10, 1, 28, 28));
@@ -71,7 +70,7 @@ TYPED_TEST(NetProtoTest, TestSetup) {
   // Run the network without training.
   vector<Blob<TypeParam>*> top_vec;
   LOG(ERROR) << "Performing Forward";
-  caffe_net.Forward(bottom_vec, &top_vec);
+  caffe_net.Forward(bottom_vec);
   LOG(ERROR) << "Performing Backward";
   LOG(ERROR) << caffe_net.Backward();
 }
diff --git a/src/caffe/test/test_simple_conv.cpp b/src/caffe/test/test_simple_conv.cpp
new file mode 100644 (file)
index 0000000..3d84962
--- /dev/null
@@ -0,0 +1,52 @@
+// Copyright 2013 Yangqing Jia
+
+#include <gtest/gtest.h>
+
+#include <cstring>
+
+#include "caffe/common.hpp"
+#include "caffe/blob.hpp"
+#include "caffe/net.hpp"
+#include "caffe/proto/caffe.pb.h"
+#include "caffe/util/io.hpp"
+
+#include "caffe/test/test_caffe_main.hpp"
+
+namespace caffe {
+
+template <typename Dtype>
+class NetProtoTest : public ::testing::Test {};
+
+typedef ::testing::Types<float> Dtypes;
+TYPED_TEST_CASE(NetProtoTest, Dtypes);
+
+TYPED_TEST(NetProtoTest, TestLoadFromText) {
+  NetParameter net_param;
+  ReadProtoFromTextFile("caffe/test/data/simple_conv.prototxt", &net_param);
+  Blob<TypeParam> lena_image;
+  ReadImageToBlob<TypeParam>(string("caffe/test/data/lena_256.jpg"), &lena_image);
+  vector<Blob<TypeParam>*> bottom_vec;
+  bottom_vec.push_back(&lena_image);
+
+  for (int i = 0; i < lena_image.count(); ++i) {
+    EXPECT_GE(lena_image.cpu_data()[i], 0);
+    EXPECT_LE(lena_image.cpu_data()[i], 1);
+  }
+
+  // Initialize the network, and then does smoothing
+  Net<TypeParam> caffe_net(net_param, bottom_vec);
+  const vector<Blob<TypeParam>*>& output = caffe_net.Forward(bottom_vec);
+  LOG(ERROR) << "Forward Done.";
+  EXPECT_EQ(output[0]->num(), 1);
+  EXPECT_EQ(output[0]->channels(), 1);
+  EXPECT_EQ(output[0]->height(), 252);
+  EXPECT_EQ(output[0]->width(), 252);
+  for (int i = 0; i < output[0]->count(); ++i) {
+    EXPECT_GE(output[0]->cpu_data()[i], 0);
+    EXPECT_LE(output[0]->cpu_data()[i], 1);
+  }
+  WriteBlobToImage<TypeParam>(string("lena_smoothed.png"), *output[0]);
+}
+
+
+}  // namespace caffe
index c1f5a962cf42a088d78045b1c5eb10e14aab75df..ca20962359cad826e939119b56ebb5e36d719763 100644 (file)
@@ -48,13 +48,23 @@ void WriteProtoToImage(const string& filename, const BlobProto& proto) {
   CHECK_GT(proto.height(), 0);
   CHECK_GT(proto.width(), 0);
   Mat cv_img(proto.height(), proto.width(), CV_8UC3);
-  for (int c = 0; c < 3; ++c) {
-    int source_c = max(c, proto.channels() - 1);
-    for (int h = 0; h < cv_img.rows; ++h) {
-      for (int w = 0; w < cv_img.cols; ++w) {
-        cv_img.at<Vec3b>(h, w)[c] =
-            uint8_t(proto.data((source_c * cv_img.rows + h) * cv_img.cols + w)
-                * 255.);
+  if (proto.channels() == 1) {
+    for (int c = 0; c < 3; ++c) {
+      for (int h = 0; h < cv_img.rows; ++h) {
+        for (int w = 0; w < cv_img.cols; ++w) {
+          cv_img.at<Vec3b>(h, w)[c] =
+              uint8_t(proto.data(h * cv_img.cols + w) * 255.);
+        }
+      }
+    }
+  } else {
+    for (int c = 0; c < 3; ++c) {
+      for (int h = 0; h < cv_img.rows; ++h) {
+        for (int w = 0; w < cv_img.cols; ++w) {
+          cv_img.at<Vec3b>(h, w)[c] =
+              uint8_t(proto.data((c * cv_img.rows + h) * cv_img.cols + w)
+                  * 255.);
+        }
       }
     }
   }
index 90617be1e67823d8096a3aedd4e1ac52e247df5d..29f7f4173845b5b9e39ef21cc767ee0221b15357 100644 (file)
@@ -7,6 +7,7 @@
 
 #include <string>
 
+#include "caffe/blob.hpp"
 #include "caffe/proto/caffe.pb.h"
 
 using std::string;
@@ -14,8 +15,23 @@ using std::string;
 namespace caffe {
 
 void ReadImageToProto(const string& filename, BlobProto* proto);
+
+template <typename Dtype>
+inline void ReadImageToBlob(const string& filename, Blob<Dtype>* blob) {
+  BlobProto proto;
+  ReadImageToProto(filename, &proto);
+  blob->FromProto(proto);
+}
+
 void WriteProtoToImage(const string& filename, const BlobProto& proto);
 
+template <typename Dtype>
+inline void WriteBlobToImage(const string& filename, const Blob<Dtype>& blob) {
+  BlobProto proto;
+  blob.ToProto(&proto);
+  WriteProtoToImage(filename, proto);
+}
+
 void ReadProtoFromTextFile(const char* filename,
     ::google::protobuf::Message* proto);
 inline void ReadProtoFromTextFile(const string& filename,
diff --git a/src/examples/convolution.cpp b/src/examples/convolution.cpp
new file mode 100644 (file)
index 0000000..e69de29