caffevs2015怎么单步调试试

  方法是,将Makefile.config中"DEBUG := 1"前面的注释去掉再进行重新编译,这样就能得到Caffe版本就能够调试  要调试的话也需要一个IDE,经过这两天的摸索找到了一个比较满意的IDE:Anjuta。  Anjuta在Ubuntu下的安装方法为:sudo apt-get install anjuta  安装完后打开Anjuta,然后导入Caffe项目工程,这样就可以进行代码调试咯。设置断点后,运行-&调试程序,再按F5(单步跨入函数)、F6(单步跨过函数)、Shift+F5(单步跨出函数)进行调试。当然,也可以设置调试器命令的。Anjuta使用方法还是比较简单的,大家查看一下菜单就能知道怎么用,Anjuta真的很方便,不大清楚的欢迎留言咯,大家相互交流,哈哈。下面附一张我使用Anjuta调试Caffe代码的截图(左下方可以查看变量的值等,右下方是程序的运行结果)~LeNet(6)
本文地址:
1. Solver到Net
在SGDSolver的构造函数中,主要执行了其父类Solver的构造函数,接着执行Solver::Init()函数,在Init()中,有两个函数值得注意:InitTrainNet()和InitTestNets()分别初始化训练网络和测试网络。
1.1 InitTrainNet
首先,ReadNetParamsFromTextFileOrDie(param_.net(), &net_param)把param_.net()(即examples/mnist/lenet_train_test.prototxt)中的信息读入net_param。
其次,net_.reset(new Net&Dtype&(net_param))重新构建网络,调用Net的构造方法。
然后,在构造方法中执行Net::init(),开始正式创建网络。其主要代码如下:
template &typename Dtype&
void Net&Dtype&::Init(const NetParameter& in_param) {
for (int layer_id = 0; layer_id & param.layer_size(); ++layer_id) {
const LayerParameter& layer_param = param.layer(layer_id);
layers_.push_back(LayerRegistry&Dtype&::CreateLayer(layer_param));
for (int bottom_id = 0; bottom_id & layer_param.bottom_size();
++bottom_id) {
const int blob_id = AppendBottom(param, layer_id, bottom_id, &available_blobs, &blob_name_to_idx);
need_backward |= blob_need_backward_[blob_id];
int num_top = layer_param.top_size();
for (int top_id = 0; top_id & num_ ++top_id) {
AppendTop(param, layer_id, top_id, &available_blobs, &blob_name_to_idx);
layers_[layer_id]-&SetUp(bottom_vecs_[layer_id], top_vecs_[layer_id]);
for (int param_id = 0; param_id & num_param_ ++param_id) {
AppendParam(param, layer_id, param_id);
Lenet5在caffe中共有9层,即param.layer_size() == 5,以上代码每一次for循环创建一个网络层
每层网络是通过LayerRegistry::CreateLayer()创建的,类似与Solver的创建(详见本系列博文(二))
14行Net::AppendBottom(),对于layer_id这层,从Net::blob_中取出blob放入该层对应的bottom_vecs_[layer_id]中
20行Net::AppendTop(),对于layer_id这层,创建blob(未包含数据)并放入Net::blob_中
AppendParam中把每层网络的训练参数与网络变量learnable_params_绑定,在lenet中,只有conv1,conv2,ip1,ip2四层有参数,每层分别有参数与偏置参数两项参数,因而learnable_params_的size为8.
1.2 LayerRegistry::CreateLayer
工厂模式new出网络层对象,具体在后边每层详细说明。
1.3 Layer::SetUp
void SetUp(const vector&Blob&Dtype&*&& bottom,
const vector&Blob&Dtype&*&& top) {
InitMutex();
CheckBlobCounts(bottom, top);
LayerSetUp(bottom, top);
Reshape(bottom, top);
SetLossWeights(top);
其中,Reshape函数中通过compute_output_shape计算输出blob的函数,
对于Convolution 层,公式如下,其中,input等数均可代表height或者dilation默认为1,所以默认kernel_extent=kernel:
output=(input+2*pad-kernel_extent)stride+1
kernel_extent=dilation*(kernel-1)+1
对于Pooling层,公式如下,其中ceil取下限:
output=ceil(input+2*pad-kernelstride)+1
注意:Convolution、Pooling整体公式计算相同,但前者取下限(设局不够时舍弃)后者取上限(数据不够时不舍弃)。
1.4 InitTestNets
该部分内容见本系列博文:。
2 训练网络结构
layer Type Bottom
Blob Shape
data&&label
64 1 28 28 (50176) && 64 (64)
Convolution
64 20 24 24 (737280)
64 20 12 12 (184320)
Convolution
64 50 8 8 (204800)
64 50 4 4 (51200)
InnerProduct
64 500 (32000)
ip1(in-place)
64 500 (32000)
InnerProduct
64 10 (640)
SoftmaxWithLoss
ip2&&label
注:Top Blob Shape格式为:BatchSize,ChannelSize,Height,Width(Total Count)
3 第一层:Data Layer
3.1 protobuff定义
训练网络的第一层protobuff定义为:
name: "mnist"
type: "Data"
top: "data"
top: "label"
phase: TRAIN
source: "examples/mnist/mnist_train_lmdb"
batch_size: 64
backend: LMDB
3.2 函数LayerRegistry::CreateLayer
第1节中代码第一次通过调用LayerRegistry::CreateLayer()创建了DataLayer类,DataLayer类的继承关系如下图所示,详见[1]:
由继承图可知,调用DataLayer()的构造函数,依次执行的顺序为其基类构造函数:Layer()、BaseDataLayer()、InternalThread()(详见 )、BasePrefetchingDataLayer()、及DataLayer()。
其中,值得注意的是DataLayer(),在调用基类构造函数BasePrefetchingDataLayer()之后,对 DataReader reader_ 进行赋值,在该DataLayer对象中维护了一个DataReader对象reader_,其作用是添加读取数据任务至,一个专门读取数据库(examples/mnist/mnist_train_lmdb)的线程(若还不存在该线程,则创建该线程),此处一共取出了4*64个样本至BlockingQueue&Datum*& DataReader::QueuePair::full_。详见
template &typename Dtype&
DataLayer&Dtype&::DataLayer(const LayerParameter& param)
: BasePrefetchingDataLayer&Dtype&(param),
reader_(param) {
3.3 函数Layer::SetUp
此处按程序执行顺序值得关注的有:
在DataLayer::DataLayerSetUp中根据3.2DataReader中介绍的读取的数据中取出一个样本推测blob的形状
BasePrefetchingDataLayer::LayerSetUp如下代码prefetch_[i].data_.mutable_cpu_data()用到了涉及到gpu、cpu间复制数据的问题,见及引用[2]
// Before starting the prefetch thread, we make cpu_data and gpu_data
// calls so that the prefetch thread does not accidentally make simultaneous
// cudaMalloc calls when the main thread is running. In some GPUs this
// seems to cause failures if we do not so.
for (int i = 0; i & PREFETCH_COUNT; ++i) {
prefetch_[i].data_.mutable_cpu_data();
if (this-&output_labels_) {
prefetch_[i].label_.mutable_cpu_data();
BasePrefetchingDataLayer类继承了InternalThread,BasePrefetchingDataLayer&Dtype&::LayerSetUp中通过调用StartInternalThread()开启了一个新线程,从而执行BasePrefetchingDataLayer::InternalThreadEntry
BasePrefetchingDataLayer::InternalThreadEntry关键代码如下,其中load_batch(batch)为,从2.2介绍的BlockingQueue&Datum*& DataReader::QueuePair::full_(包含从数据库读出的数据)中读取一个batch_size的数据到BlockingQueue&Batch&Dtype&*& BasePrefetchingDataLayer::prefetch_full_中。由于该线程在prefetch_free_为空时将挂起等待(PREFETCH_COUNT=3),prefetch_full_中用完的Batch将放回prefetch_free_中。该线程何时停止?
while (!must_stop()) {
Batch&Dtype&* batch = prefetch_free_.pop();
load_batch(batch);
#ifndef CPU_ONLY
if (Caffe::mode() == Caffe::GPU) {
batch-&data_.data().get()-&async_gpu_push(stream);
CUDA_CHECK(cudaStreamSynchronize(stream));
prefetch_full_.push(batch);
关于线程的总结:
此外一共涉及到两个线程,分别为都是继承了InnerThread的BasePrefetchingDataLayer(DataLayer)类和DataReader中的Body类
Body为面向数据库的线程,不断从某个数据库中读出数据,存放至缓存为队列DataReader::QueuePair::BlockingQueue&Datum*&,一般保存4*64个单位数据,单位为Datum
BasePrefetchingDataLayer为面向网络的线程,从Body的缓存中不断读取数据。BasePrefetchingDataLayer的缓存为队列BlockingQueue&Batch*&,一般存放3个单位的数据,单位为Batch
static const int PREFETCH_COUNT = 3;
Batch&Dtype& prefetch_[PREFETCH_COUNT];
BlockingQueue&Batch&Dtype&*& prefetch_free_;
BlockingQueue&Batch&Dtype&*& prefetch_full_;
template &typename Dtype&
BasePrefetchingDataLayer&Dtype&::BasePrefetchingDataLayer(
const LayerParameter& param)
: BaseDataLayer&Dtype&(param),
prefetch_free_(), prefetch_full_() {
for (int i = 0; i & PREFETCH_COUNT; ++i) {
prefetch_free_.push(&prefetch_[i]);
prefetch_full_与prefetch_free_中的元素由prefetch_提供
4 第二层:Convolution Layer
4.1 protobuff定义
name: "conv1"
type: "Convolution"
bottom: "data"
top: "conv1"
lr_mult: 1
lr_mult: 2
num_output: 20
kernel_size: 5
weight_filler {
type: "xavier"
type: "constant"
4.2 函数LayerRegistry::CreateLayer
不像DataLayer 直接执行的是构造函数,此时执行的是GetConvolutuionLayer(),然后调用ConvolutionLayer(),原因如下:
REGISTER_LAYER_CREATOR(Convolution, GetConvolutionLayer);
4.3 Layer::SetUp
在`Layer::SetUp`中,调用了`ConvolutionLayer`的基类`BaseConvolutionLayer`的`LayerSetUp及Reshape`函数,该类的主要成员变量如下:
template &typename Dtype&
class BaseConvolutionLayer : public Layer&Dtype& {
explicit BaseConvolutionLayer(const LayerParameter& param)
: Layer&Dtype&(param) {}
virtual void LayerSetUp(const vector&Blob&Dtype&*&& bottom,
const vector&Blob&Dtype&*&& top);
virtual void Reshape(const vector&Blob&Dtype&*&& bottom,
const vector&Blob&Dtype&*&& top);
Blob&int& kernel_shape_;
Blob&int& stride_;
Blob&int& pad_;
Blob&int& dilation_;
Blob&int& conv_input_shape_;
vector&int& col_buffer_shape_;
vector&int& output_shape_;
const vector&int&* bottom_shape_;
**说明:**
LayerSetUp函数中,主要是初始化了kernel_shape_、stride_、pad_、dilation_以及初始化网络参数,并存放与Layer::blobs_中。
Reshape函数中,conv_input_shape_、bottom_shape_等
5 第三层:Pooling Layer
5.1 protobuff定义
name: "pool1"
type: "Pooling"
bottom: "conv1"
top: "pool1"
pooling_param {
kernel_size: 2
5.2 Layer::SetUp
通过调用虚函数LayerSetUp及Reshape对以下成员变量进行初始化
* Pools the input image by taking the max, average, etc. within regions.
* TODO(dox): thorough documentation for Forward, Backward, and proto params.
template &typename Dtype&
class PoolingLayer : public Layer&Dtype& {
int kernel_h_, kernel_w_;
int stride_h_, stride_w_;
int pad_h_, pad_w_;
int channels_;
int height_, width_;
int pooled_height_, pooled_width_;
bool global_pooling_;
Blob&Dtype& rand_idx_;
Blob&int& max_idx_;
6 第四层、第五层
基本同第二层、第三层
7 第六层:InnerProduct Layer
7.1 protobuff定义
name: "ip1"
type: "InnerProduct"
bottom: "pool2"
top: "ip1"
lr_mult: 1
lr_mult: 2
num_output: 500
weight_filler {
type: "xavier"
type: "constant"
7.2 Layer::SetUp
* Also known as a "fully-connected" layer, computes an inner product
with a set of learned weights, and (optionally) adds biases.
* TODO(dox): thorough documentation for Forward, Backward, and proto params.
template &typename Dtype&
class InnerProductLayer : public Layer&Dtype& {
bool bias_term_;
Blob&Dtype& bias_multiplier_;
N_为输出大小,即等于protobuff中定义的num_output
K_为输入大小,对于该层Bottom Blob形状为(N, C, H, W),N为batch_size,K_=C*H*W,M_=N。其中只有C、H、W跟内积相关
8 第七层:ReLU Layer
8.1 protobuff定义
name: "relu1"
type: "ReLU"
bottom: "ip1"
top: "ip1"
ReLULayer主要是用来做计算的,其继承关系如下,详细参加[4]、[5]
9 第八层:InnerProduct Layer
10 第九层:SoftmaxWithLoss Layer
10.1 protobuff定义
name: "loss"
type: "SoftmaxWithLoss"
bottom: "ip2"
bottom: "label"
top: "loss"
10.2 LayerRegistry::CreateLayer
10.3 Layer::SetUp
值得注意的是:
类SoftmaxWithLossLayer包含类SoftmaxLayer的实例
shared_ptr&Layer&Dtype& & softmax_layer_
softmax_layer_在LayerSetUp中赋值。
此函数内调用Layer::SetLossWeights初始化了该层的Top Blob(loss)
两个类间的关系如下图:
成员变量prob_作为Softmaxlayer的top blob
bottom blob[0]作为softmaxlayer的bottom blob
所以经过softmaxlayer计算之后,得出64*10(每个样本的每个类别上的概率)存放在prob_中
11 剩余的工作
至此,训练网络基本创建完毕,接下来剩下的工作主要有:
反向检查一次网络,看哪些blobs会对loss产生影响,在LeNet5中,前面的9层均有影响
初始化权值共享
Implementation Details
ReLU / Rectified-Linear and Leaky-ReLU
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:10942次
排名:千里之外
原创:27篇
(4)(12)(20)Caffe(13)
本文地址:
其对网络进行求解,其作用有:
提供优化日志支持、创建用于学习的训练网络、创建用于评估的测试网络
通过调用forward / backward迭代地优化,更新权值
周期性地评估测试网络
通过优化了解model及solver的状态
1.2 源代码
template &typename Dtype&
class Solver {
explicit Solver(const SolverParameter& param,
const Solver* root_solver = NULL);
explicit Solver(const string& param_file, const Solver* root_solver = NULL);
void Init(const SolverParameter& param);
void InitTrainNet();
void InitTestNets();
virtual void Solve(const char* resume_file = NULL);
inline void Solve(const string resume_file) { Solve(resume_file.c_str()); }
void Step(int iters);
protected:
virtual void ApplyUpdate() = 0;
SolverParameter param_;
int iter_;
int current_step_;
shared_ptr&Net&Dtype& & net_;
vector&shared_ptr&Net&Dtype& & & test_nets_;
vector&Callback*& callbacks_;
vector&Dtype& losses_;
Dtype smoothed_loss_;
const Solver* const root_solver_;
shared_ptr&Net&Dtype&& net_为训练网络的指针,vector&shared_ptr&Net&Dtype&&& test_nets为测试网络的指针组,可见测试网络可以有多个
一般来说训练网络跟测试网络在实现上会有区别,但是绝大部分网络层是相同的。
不同的模型训练方法通过重载函数ComputeUpdateValue( )实现计算update参数的核心功能
caffe.cpp中的train( )函数训练模型,在这里实例化一个Solver对象,初始化后调用了Solver中的Solve( )方法。而这个Solve( )函数主要就是在迭代运行下面这两个函数。ComputeUpdateValue();
net_-&Update();
1.3 Solver的方法
Stochastic Gradient Descent (type: “SGD”)
AdaDelta (type: “AdaDelta”)
Adaptive Gradient (type: “AdaGrad”)
Adam (type: “Adam”)
Nesterov’s Accelerated Gradient (type: “Nesterov”)
RMSprop (type: “RMSProp”)
详细参见引用1
Caffe类为一个包含常用的caffe成员的单例类。如caffe使用的cuda库cublas,curand的句柄等,以及生成Caffe中的随机数等。
class Caffe {
static Caffe& Get();
enum Brew { CPU, GPU };
protected:
#ifndef CPU_ONLY
cublasHandle_t cublas_handle_;
curandGenerator_t curand_generator_;
shared_ptr&RNG& random_generator_;
Brew mode_;
int solver_count_;
bool root_solver_;
// The private constructor to avoid duplicate instantiation.
DISABLE_COPY_AND_ASSIGN(Caffe);
//common.cpp
namespace caffe {
// Make sure each thread can have different values.
static boost::thread_specific_ptr&Caffe& thread_instance_;
Caffe& Caffe::Get() {
if (!thread_instance_.get()) {
thread_instance_.reset(new Caffe());
return *(thread_instance_.get());
Caffe::Caffe()
: cublas_handle_(NULL), curand_generator_(NULL), random_generator_(),
mode_(Caffe::CPU), solver_count_(1), root_solver_(true) {
// Try to create a cublas handler, and report an error if failed (but we will
// keep the program running as one might just want to run CPU code).
if (cublasCreate(&cublas_handle_) != CUBLAS_STATUS_SUCCESS) {
LOG(ERROR) && "Cannot create Cublas handle. Cublas won't be available.";
// Try to create a curand handler.
if (curandCreateGenerator(&curand_generator_, CURAND_RNG_PSEUDO_DEFAULT)
!= CURAND_STATUS_SUCCESS ||
curandSetPseudoRandomGeneratorSeed(curand_generator_, cluster_seedgen())
!= CURAND_STATUS_SUCCESS) {
LOG(ERROR) && "Cannot create Curand generator. Curand won't be available.";
// namespace caffe
Caffe类为一个单例类,构造方法私有
该单例由static boost::thread_specific_ptr&Caffe& thread_instance_维护,确保多线程环境下,不同的线程有不同的Caffe单例版本
获取该单例由Get()方法执行,即Caffe::Get()方法返回thread_instance_维护的单例,
thread_instance_的初值为NULL,若是第一次访问,则new Caffe()
new Caffe()执行构造方法,其实只是创建了cublas,curand的句柄
单步调试可发现cublasCreate()创建cublas的句柄,生成了额外的两个线程
Blob&Dtype& data_, label_;
Batch是对一个样本的封装,与Datum不同,Datum是面向数据库的,且一个Datum对应一个样本(图像、标签);而Batch是面向网络的,一个Batch对应一批样本
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:10944次
排名:千里之外
原创:27篇
(4)(12)(20)Caffe(13)
1. Cuda中要处理单位数据N大于可用的线程数量N’时
以向量乘函数为例,mul_kernel(n,a,b,y)对长为n的a,b求内积,结果放入y
template &typename Dtype&
__global__ void mul_kernel(const int n, const Dtype* a,
const Dtype* b, Dtype* y) {
CUDA_KERNEL_LOOP(index, n) {
y[index] = a[index] * b[index];
展开CUDA_KERNEL_LOOP(index, n)得
template &typename Dtype&
__global__ void mul_kernel(const int n, const Dtype* a,
for (int i = blockIdx.x * blockDim.x + threadIdx.x; \
i & (n); \
i += blockDim.x * gridDim.x)
y[i] = a[i] * b[i];
Caffe中,Grid、Block都是一维的,其中Block的维度为512(也就是一个Block有512个Thread)
n为单位总数
blockDim.x* gridDim.x为该Grid所有线程的数量
可见,一个线程可能处理了多个单位
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:10946次
排名:千里之外
原创:27篇
(4)(12)(20)caffe学习(25)
在这篇博客里,我来说一下如何使用CodeBlocks去执行和调试caffe的代码。
在之前的文章中,我们都是直接调用caffe中的代码,但是其内部是如何运行的,我们并没有看到,这里,我们将caffe代码放到codeblocks创建的工程中,就可以单步调试代码了。我们以运行examples/mnist/convert_mnist_data.cpp的代码为例。关于mnist的训练,请参考
在mnist文件中,有一个cpp文件,即convert_mnist_data.cpp,这里的代码主要用于数据类型的转换。
一. 使用codeblocks运行caffe代码
首先,看一下如何在codeblocks下调试和调用这个函数(因为在ubuntu下不好截图,所以尽量把步骤写清楚一些):
在梳理caffe的配置文件中,我们提到将make的打印信息保存下来,参考结尾部分
因为在codeblock下需要配置一些链接,可以根据打印的文件的一些配置来做,在输出的文件中找到convert_mnist_data.cpp,结果如下:
CXX examples/mnist/convert_mnist_data.cpp
g++ examples/mnist/convert_mnist_data.cpp -MMD -MP -pthread -fPIC -DDEBUG -g -O0 -DUSE_OPENCV -DUSE_LEVELDB -DUSE_LMDB -I/usr/include/python2.7 -I/usr/lib/python2.7/dist-packages/numpy/core/include -I/usr/local/include -I.build_debug/src -I./src -I./include -I/usr/local/cuda-7.5/include -Wall -Wno-sign-compare -c -o .build_debug/examples/mnist/convert_mnist_data.o 2& .build_debug/examples/mnist/convert_mnist_data.o.warnings.txt \
|| (cat .build_debug/examples/mnist/convert_mnist_data.o.warnings. exit 1)
CXX/LD -o .build_debug/examples/mnist/convert_mnist_data.bin
g++ .build_debug/examples/mnist/convert_mnist_data.o -o .build_debug/examples/mnist/convert_mnist_data.bin -pthread -fPIC -DDEBUG -g -O0 -DUSE_OPENCV -DUSE_LEVELDB -DUSE_LMDB -I/usr/include/python2.7 -I/usr/lib/python2.7/dist-packages/numpy/core/include -I/usr/local/include -I.build_debug/src -I./src -I./include -I/usr/local/cuda-7.5/include -Wall -Wno-sign-compare -lcaffe -L/home/sindyz/anaconda/lib -L/usr/local/lib -L/usr/lib -L/usr/local/cuda-7.5/lib64 -L/usr/local/cuda-7.5/lib -L.build_debug/lib
-lcudart -lcublas -lcurand -lglog -lgflags -lprotobuf -lboost_system -lboost_filesystem -lm -lhdf5_hl -lhdf5 -lleveldb -lsnappy -llmdb -lopencv_core -lopencv_highgui -lopencv_imgproc -lboost_thread -lstdc++ -lcblas -latlas \
-Wl,-rpath,\$ORIGIN/../../lib
按照上面的配置,
i. 右键项目,点击:properties...菜单--&build target标签--&build options按钮 --&Linker Settings标签,在右侧的空白处,把上面文档中的链接库帖进去。分别是:
-pthread -lcaffe -lcudart -lcublas -lcurand -lglog -lgflags -lprotobuf -lboost_system -lboost_filesystem -lm -lhdf5_hl -lhdf5 -lleveldb -lsnappy -llmdb -lopencv_core -lopencv_highgui -lopencv_imgproc -lboost_thread -lstdc++ -lcblas -latlas另外,还有最后一句:-Wl,-rpath,\$ORIGIN/../../lib,将$CAFFE/build/lib的相对路径也添加进来。
ii, 在Search dictioneries--&Compile中添加搜索路径,就是上面-I后的路径,主要由三个:
$CAFFE/build/src
$CAFFE/include
如果使用gpu,需要添加:$CUDA/include, ($CUDA是cuda的安装路径,通常是(usr/local/cuda/include).
将这几个路径点击Add添加,其他的配置不用手动添加
iii. 在旁边的Linker标签下添加链接库的搜索路径:就是上面文本中-L开头的部分,也由三个:
$CAFFE/build/lib
$CUDA7.5/lib
$CUDA7.5/lib64
通过Add添加即可,其余也是不用手动添加的
iv. 在Compiler Settings标签下的#defines,把上面-D的部分贴进来:
USE_OPENCV
USE_LEVELDB
v. 最后,需要在other options下加入-Wno-sign-compare这句,就不会在编译过程中打印警告信息了
vi 将convert_mnist_data.cpp添加到工程中,在工程目录下创建data目录,把mnist数据帖到这个目录下,就可以编译了,如果没有报错,保存工程(右键工程名--&save project)
vii. 编译完成后,还需要向convert_mnist_data.cpp的主函数中输入参数。在$CAFFE/examples/mnist下的create_mnist.sh中有如下语句:
$BUILD/convert_mnist_data.bin $DATA/train-images-idx3-ubyte \
$DATA/train-labels-idx1-ubyte $EXAMPLE/mnist_train_${BACKEND} --backend=${BACKEND}将后面三个输入写入:Project--&Set programs` argument..--&program argument里面,路径要该成自己的路径,因为之前在工程下创建了data目录,因此,我添加的参数如下:data/mnist/train-images-idx3-ubyte
data/mnist/train-labels-idx1-ubyte
mnist_train_lmdb
--backend=lmdb
运行文件,在工程目录下就会生成mnist_train_lmdb文件夹,并生成lmdb格式的数据文件。
这样,我们就可以用codeblocks调试caffe的代码了。其他代码的添加过程也是类似的。
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:46466次
积分:1930
积分:1930
排名:第14356名
原创:143篇
转载:49篇
评论:41条
(4)(5)(1)(8)(2)(9)(2)(10)(2)(2)(41)(12)(25)(19)(32)(19)(2)

我要回帖

更多关于 vc6.0怎么单步调试 的文章

 

随机推荐