Adding new caffe binary that does everything in one binary; deprecating device_query...
authorYangqing Jia <jiayq@google.com>
Fri, 25 Jul 2014 16:02:37 +0000 (09:02 -0700)
committerYangqing Jia <jiayq@google.com>
Fri, 25 Jul 2014 16:08:12 +0000 (09:08 -0700)
tools/caffe.cpp [new file with mode: 0644]
tools/device_query.cpp
tools/finetune_net.cpp
tools/net_speed_benchmark.cpp
tools/train_net.cpp

diff --git a/tools/caffe.cpp b/tools/caffe.cpp
new file mode 100644 (file)
index 0000000..4835248
--- /dev/null
@@ -0,0 +1,176 @@
+#include <gflags/gflags.h>
+#include <glog/logging.h>
+
+#include <cstring>
+#include <map>
+
+#include "caffe/caffe.hpp"
+
+using caffe::Blob;
+using caffe::Caffe;
+using caffe::Net;
+using caffe::Layer;
+using caffe::shared_ptr;
+using caffe::Timer;
+using caffe::string;
+using std::vector;
+
+
+// Used in device query
+DEFINE_int32(device_id, 0,
+             "[devicequery,speedtest] The device id to use.");
+// Used in training
+DEFINE_string(solver_proto_file, "",
+              "[train] The protobuf containing the solver definition.");
+DEFINE_string(net_proto_file, "",
+              "[speedtest] The net proto file to use.");
+DEFINE_string(resume_point_file, "",
+              "[train] (optional) The snapshot from which to resume training.");
+DEFINE_string(pretrained_net_file, "",
+              "[train] (optional) A pretrained network to run finetune from. "
+              "Cannot be set simultaneously with resume_point_file.");
+DEFINE_int32(run_iterations, 50,
+             "[speedtest] The number of iterations to run.");
+DEFINE_bool(speedtest_with_gpu, false,
+            "[speedtest] Test the model with GPU.");
+
+// A simple registry for caffe commands.
+typedef int (*BrewFunction)();
+typedef std::map<std::string, BrewFunction> BrewMap;
+BrewMap g_brew_map;
+
+#define RegisterBrewFunction(func) \
+  namespace { \
+  class __Registerer_##func { \
+   public: \
+    __Registerer_##func() { \
+      g_brew_map[#func] = &func; \
+    } \
+  }; \
+  __Registerer_##func g_registerer_##func; \
+  }
+
+static BrewFunction GetBrewFunction(const std::string& name) {
+  if (g_brew_map.count(name)) {
+    return g_brew_map[name];
+  } else {
+    LOG(ERROR) << "Available caffe actions:";
+    for (BrewMap::iterator it = g_brew_map.begin();
+         it != g_brew_map.end(); ++it) {
+      LOG(ERROR) << "\t" << it->first;
+    }
+    LOG(FATAL) << "Unknown action: " << name;
+    return NULL;  // not reachable, just to suppress old compiler warnings.
+  }
+}
+
+// caffe actions that could be called in the form
+//     caffe.bin action
+// To do so, define actions as "int action()" functions, and register it with
+// RegisterBrewFunction(action);
+
+int devicequery() {
+  LOG(INFO) << "Querying device_id = " << FLAGS_device_id;
+  caffe::Caffe::SetDevice(FLAGS_device_id);
+  caffe::Caffe::DeviceQuery();
+  return 0;
+}
+RegisterBrewFunction(devicequery);
+
+int train() {
+  CHECK_GT(FLAGS_solver_proto_file.size(), 0);
+
+  caffe::SolverParameter solver_param;
+  caffe::ReadProtoFromTextFileOrDie(FLAGS_solver_proto_file, &solver_param);
+
+  LOG(INFO) << "Starting Optimization";
+  caffe::SGDSolver<float> solver(solver_param);
+  if (FLAGS_resume_point_file.size()) {
+    LOG(INFO) << "Resuming from " << FLAGS_resume_point_file;
+    solver.Solve(FLAGS_resume_point_file);
+  } else if (FLAGS_pretrained_net_file.size()) {
+    LOG(INFO) << "Finetuning from " << FLAGS_pretrained_net_file;
+    solver.net()->CopyTrainedLayersFrom(FLAGS_pretrained_net_file);
+    solver.Solve();
+  } else {
+    solver.Solve();
+  }
+  LOG(INFO) << "Optimization Done.";
+  return 0;
+}
+RegisterBrewFunction(train);
+
+int speedtest() {
+  // Set device id and mode
+  if (FLAGS_speedtest_with_gpu) {
+    LOG(INFO) << "Use GPU with device id " << FLAGS_device_id;
+    Caffe::SetDevice(FLAGS_device_id);
+    Caffe::set_mode(Caffe::GPU);
+  } else {
+    LOG(INFO) << "Use CPU.";
+    Caffe::set_mode(Caffe::CPU);
+  }
+  // Instantiate the caffe net.
+  Caffe::set_phase(Caffe::TRAIN);
+  Net<float> caffe_net(FLAGS_net_proto_file);
+
+  // Do a clean forward and backward pass, so that memory allocation are done
+  // and future iterations will be more stable.
+  LOG(INFO) << "Performing Forward";
+  // Note that for the speed benchmark, we will assume that the network does
+  // not take any input blobs.
+  float initial_loss;
+  caffe_net.Forward(vector<Blob<float>*>(), &initial_loss);
+  LOG(INFO) << "Initial loss: " << initial_loss;
+  LOG(INFO) << "Performing Backward";
+  caffe_net.Backward();
+
+  const vector<shared_ptr<Layer<float> > >& layers = caffe_net.layers();
+  vector<vector<Blob<float>*> >& bottom_vecs = caffe_net.bottom_vecs();
+  vector<vector<Blob<float>*> >& top_vecs = caffe_net.top_vecs();
+  const vector<vector<bool> >& bottom_need_backward =
+      caffe_net.bottom_need_backward();
+  LOG(INFO) << "*** Benchmark begins ***";
+  LOG(INFO) << "Testing for " << FLAGS_run_iterations << " iterations.";
+  Timer total_timer;
+  total_timer.Start();
+  Timer forward_timer;
+  forward_timer.Start();
+  Timer timer;
+  for (int i = 0; i < layers.size(); ++i) {
+    const string& layername = layers[i]->layer_param().name();
+    timer.Start();
+    for (int j = 0; j < FLAGS_run_iterations; ++j) {
+      layers[i]->Forward(bottom_vecs[i], &top_vecs[i]);
+    }
+    LOG(INFO) << layername << "\tforward: " << timer.MilliSeconds() <<
+        " milli seconds.";
+  }
+  LOG(INFO) << "Forward pass: " << forward_timer.MilliSeconds() <<
+      " milli seconds.";
+  Timer backward_timer;
+  backward_timer.Start();
+  for (int i = layers.size() - 1; i >= 0; --i) {
+    const string& layername = layers[i]->layer_param().name();
+    timer.Start();
+    for (int j = 0; j < FLAGS_run_iterations; ++j) {
+      layers[i]->Backward(top_vecs[i], bottom_need_backward[i],
+                          &bottom_vecs[i]);
+    }
+    LOG(INFO) << layername << "\tbackward: "
+        << timer.MilliSeconds() << " milli seconds.";
+  }
+  LOG(INFO) << "Backward pass: " << backward_timer.MilliSeconds() <<
+      " milli seconds.";
+  LOG(INFO) << "Total Time: " << total_timer.MilliSeconds() <<
+      " milli seconds.";
+  LOG(INFO) << "*** Benchmark ends ***";
+  return 0;
+}
+RegisterBrewFunction(speedtest);
+
+int main(int argc, char** argv) {
+  caffe::GlobalInit(&argc, &argv);
+  CHECK_EQ(argc, 2);
+  return GetBrewFunction(std::string(argv[1]))();
+}
index 5040b8e..224a314 100644 (file)
@@ -1,23 +1,8 @@
 // Copyright 2014 BVLC and contributors.
 
-
 #include "caffe/common.hpp"
-#include "caffe/net.hpp"
-
-
-using namespace caffe;  // NOLINT(build/namespaces)
 
 int main(int argc, char** argv) {
-  if (argc > 2) {
-    LOG(ERROR) << "device_query [device_id=0]";
-    return 1;
-  }
-  if (argc == 2) {
-    LOG(INFO) << "Querying device_id=" << argv[1];
-    Caffe::SetDevice(atoi(argv[1]));
-    Caffe::DeviceQuery();
-  } else {
-    Caffe::DeviceQuery();
-  }
+  LOG(ERROR) << "Deprecated. Use caffe.bin devicequery [--device_id=0] instead.";
   return 0;
 }
index 4d80be9..dff9721 100644 (file)
@@ -1,31 +1,9 @@
 // Copyright 2014 BVLC and contributors.
-//
-// This is a simple script that allows one to quickly finetune a network.
-// Usage:
-//    finetune_net solver_proto_file pretrained_net
-
-#include <string>
 
 #include "caffe/caffe.hpp"
 
-using namespace caffe;  // NOLINT(build/namespaces)
-
 int main(int argc, char** argv) {
-  ::google::InitGoogleLogging(argv[0]);
-  if (argc != 3) {
-    LOG(ERROR) << "Usage: finetune_net solver_proto_file pretrained_net";
-    return 1;
-  }
-
-  SolverParameter solver_param;
-  ReadProtoFromTextFileOrDie(argv[1], &solver_param);
-
-  LOG(INFO) << "Starting Optimization";
-  SGDSolver<float> solver(solver_param);
-  LOG(INFO) << "Loading from " << argv[2];
-  solver.net()->CopyTrainedLayersFrom(string(argv[2]));
-  solver.Solve();
-  LOG(INFO) << "Optimization Done.";
-
+  LOG(ERROR) << "Deprecated. Use caffe.bin train --solver_proto_file=... "
+                "[pretrained_net_file=...] instead.";
   return 0;
 }
index bdec391..9e6bb4c 100644 (file)
@@ -1,103 +1,9 @@
 // Copyright 2014 BVLC and contributors.
 
-#include <fcntl.h>
-#include <google/protobuf/text_format.h>
-
-#include <cstring>
-#include <ctime>
-#include <string>
-#include <vector>
-
-#include "caffe/blob.hpp"
-#include "caffe/common.hpp"
-#include "caffe/net.hpp"
-#include "caffe/filler.hpp"
-#include "caffe/proto/caffe.pb.h"
-#include "caffe/util/benchmark.hpp"
-#include "caffe/util/io.hpp"
-#include "caffe/solver.hpp"
-
-using namespace caffe;  // NOLINT(build/namespaces)
+#include "caffe/caffe.hpp"
 
 int main(int argc, char** argv) {
-  int total_iter = 50;
-  if (argc < 2 || argc > 5) {
-    LOG(ERROR) << "net_speed_benchmark net_proto [iterations=50]"
-        " [CPU/GPU] [Device_id=0]";
-    return 1;
-  }
-
-  if (argc >=3) {
-    total_iter = atoi(argv[2]);
-  }
-
-  LOG(ERROR) << "Testing for " << total_iter << "Iterations.";
-
-  if (argc >= 4 && strcmp(argv[3], "GPU") == 0) {
-    LOG(ERROR) << "Using GPU";
-    uint device_id = 0;
-    if (argc >= 5 && strcmp(argv[3], "GPU") == 0) {
-      device_id = atoi(argv[4]);
-    }
-    LOG(ERROR) << "Using Device_id=" << device_id;
-    Caffe::SetDevice(device_id);
-    Caffe::set_mode(Caffe::GPU);
-  } else {
-    LOG(ERROR) << "Using CPU";
-    Caffe::set_mode(Caffe::CPU);
-  }
-
-  Caffe::set_phase(Caffe::TRAIN);
-  Net<float> caffe_net(argv[1]);
-
-  // Run the network without training.
-  LOG(ERROR) << "Performing Forward";
-  // Note that for the speed benchmark, we will assume that the network does
-  // not take any input blobs.
-  float initial_loss;
-  caffe_net.Forward(vector<Blob<float>*>(), &initial_loss);
-  LOG(ERROR) << "Initial loss: " << initial_loss;
-  LOG(ERROR) << "Performing Backward";
-  caffe_net.Backward();
-
-  const vector<shared_ptr<Layer<float> > >& layers = caffe_net.layers();
-  vector<vector<Blob<float>*> >& bottom_vecs = caffe_net.bottom_vecs();
-  vector<vector<Blob<float>*> >& top_vecs = caffe_net.top_vecs();
-  const vector<vector<bool> >& bottom_need_backward =
-      caffe_net.bottom_need_backward();
-  LOG(ERROR) << "*** Benchmark begins ***";
-  Timer total_timer;
-  total_timer.Start();
-  Timer forward_timer;
-  forward_timer.Start();
-  Timer timer;
-  for (int i = 0; i < layers.size(); ++i) {
-    const string& layername = layers[i]->layer_param().name();
-    timer.Start();
-    for (int j = 0; j < total_iter; ++j) {
-      layers[i]->Forward(bottom_vecs[i], &top_vecs[i]);
-    }
-    LOG(ERROR) << layername << "\tforward: " << timer.MilliSeconds() <<
-        " milli seconds.";
-  }
-  LOG(ERROR) << "Forward pass: " << forward_timer.MilliSeconds() <<
-      " milli seconds.";
-  Timer backward_timer;
-  backward_timer.Start();
-  for (int i = layers.size() - 1; i >= 0; --i) {
-    const string& layername = layers[i]->layer_param().name();
-    timer.Start();
-    for (int j = 0; j < total_iter; ++j) {
-      layers[i]->Backward(top_vecs[i], bottom_need_backward[i],
-                          &bottom_vecs[i]);
-    }
-    LOG(ERROR) << layername << "\tbackward: "
-        << timer.MilliSeconds() << " milli seconds.";
-  }
-  LOG(ERROR) << "Backward pass: " << backward_timer.MilliSeconds() <<
-      " milli seconds.";
-  LOG(ERROR) << "Total Time: " << total_timer.MilliSeconds() <<
-      " milli seconds.";
-  LOG(ERROR) << "*** Benchmark ends ***";
+  LOG(ERROR) << "Deprecated. Use caffe.bin speedtest --net_proto_file=... "
+             "[--run_iterations=50] [--speedtest_with_gpu] [--device_id=0]";
   return 0;
 }
index 41a3324..568260c 100644 (file)
@@ -1,35 +1,9 @@
 // Copyright 2014 BVLC and contributors.
-//
-// This is a simple script that allows one to quickly train a network whose
-// parameters are specified by text format protocol buffers.
-// Usage:
-//    train_net net_proto_file solver_proto_file [resume_point_file]
-
-#include <cstring>
 
 #include "caffe/caffe.hpp"
 
-using namespace caffe;  // NOLINT(build/namespaces)
-
 int main(int argc, char** argv) {
-  ::google::InitGoogleLogging(argv[0]);
-  if (argc < 2 || argc > 3) {
-    LOG(ERROR) << "Usage: train_net solver_proto_file [resume_point_file]";
-    return 1;
-  }
-
-  SolverParameter solver_param;
-  ReadProtoFromTextFileOrDie(argv[1], &solver_param);
-
-  LOG(INFO) << "Starting Optimization";
-  SGDSolver<float> solver(solver_param);
-  if (argc == 3) {
-    LOG(INFO) << "Resuming from " << argv[2];
-    solver.Solve(argv[2]);
-  } else {
-    solver.Solve();
-  }
-  LOG(INFO) << "Optimization Done.";
-
+  LOG(ERROR) << "Deprecated. Use caffe.bin train --solver_proto_file=... "
+                "[resume_point_file=...] instead.";
   return 0;
 }