Caffe训练源码基本流程

【活动】2017 CSDN博客专栏评选    【评论送书】SQL优化、深度学习、数据科学家    CSDN日报20170524 ——《2017 软件精英挑战赛总结》    Python创意编程活动结果公布

Caffe训练源码基本流程

标签: BloblayerNetSolvercaffe
1362人阅读 评论(1) 收藏 举报
本文章已收录于:
人工智能开发框架知识库
分类:
作者同类文章X

    目录(?)[+]

    1. Caffe简介
    2. 训练LeNet
    3. 网络初始化
    4. 训练过程
      1. loss net_-ForwardBackward
      2. UpdateSmoothedLoss
      3. ApplyUpdate

    Caffe简介

    一般在介绍Caffe代码结构的时候,大家都会说Caffe主要由Blob Layer Net 和 Solver这几个部分组成。

    Blob:::
    主要用来表示网络中的数据,包括训练数据,网络各层自身的参数(包括权值、偏置以及它们的梯度),网络之间传递的数据都是通过 Blob 来实现的,同时 Blob 数据也支持在 CPU 与 GPU 上存储,能够在两者之间做同步。

    Layer:::
    是对神经网络中各种层的一个抽象,包括我们熟知的卷积层和下采样层,还有全连接层和各种激活函数层等等。同时每种 Layer 都实现了前向传播和反向传播,并通过 Blob 来传递数据。

    Net::: 是对整个网络的表示,由各种 Layer 前后连接组合而成,也是我们所构建的网络模型。

    Solver :::定义了针对 Net 网络模型的求解方法,记录网络的训练过程,保存网络模型参数,中断并恢复网络的训练过程。自定义 Solver 能够实现不同的网络求解方式。

    不过在刚开始准备阅读Caffe代码的时候,就算知道了代码是由上面四部分组成还是感觉会无从下手,下面我们准备通过一个Caffe训练LeNet的实例并结合代码来解释Caffe是如何初始化网络,然后正向传播、反向传播开始训练,最终得到训练好的模型这一过程。

    训练LeNet

    在Caffe提供的例子里,训练LeNet网络的命令为:

    cd $CAFFE_ROOT
    ./build/tools/caffe train --solver=examples/mnist/lenet_solver.prototxt
    • 1
    • 2
    • 1
    • 2

    其中第一个参数build/tools/caffe是Caffe框架的主要框架,由tools/caffe.cpp文件编译而来,第二个参数train表示是要训练网络,第三个参数是 solver的protobuf描述文件。在Caffe中,网络模型的描述及其求解都是通过 protobuf 定义的,并不需要通过敲代码来实现。同时,模型的参数也是通过 protobuf 实现加载和存储,包括 CPU 与 GPU 之间的无缝切换,都是通过配置来实现的,不需要通过硬编码的方式实现,有关
    protobuf的具体内容可参考这篇博文:http://alanse7en.github.io/caffedai-ma-jie-xi-2/。

    网络初始化

    下面我们从caffe.cpp的main函数入口开始观察Caffe是怎么一步一步训练网络的。在caffe.cpp中main函数之外通过RegisterBrewFunction这个宏在每一个实现主要功能的函数之后将这个函数的名字和其对应的函数指针添加到了g_brew_map中,具体分别为train(),test(),device_query(),time()这四个函数。

    在运行的时候,根据传入的参数在main函数中,通过GetBrewFunction得到了我们需要调用的那个函数的函数指针,并完成了调用。

    // caffe.cpp
    return GetBrewFunction(caffe::string(argv[1])) ();
    • 1
    • 2
    • 1
    • 2

    在我们上面所说的训练LeNet的例子中,传入的第二个参数为train,所以调用的函数为caffe.cpp中的int train()函数,接下来主要看这个函数的内容。在train函数中有下面两行代码,下面的代码定义了一个指向Solver的shared_ptr。其中主要是通过调用SolverRegistry这个类的静态成员函数CreateSolver得到一个指向Solver的指针来构造shared_ptr类型的solver。而且由于C++多态的特性,尽管solver是一个指向基类Solver类型的指针,通过solver这个智能指针来调用各个成员函数会调用到各个子类(SGDSolver等)的函数。

    // caffe.cpp
    // 其中输入参数solver_param就是上面所说的第三个参数:网络的模型及求解文件
    shared_ptr<caffe::Solver<float> >solver(caffe::SolverRegistry<float>::CreateSolver(solver_param);
    • 1
    • 2
    • 3
    • 4
    • 1
    • 2
    • 3
    • 4

    因为在caffe.proto文件中默认的优化type为SGD,所以上面的代码会实例化一个SGDSolver的对象,’SGDSolver’类继承于Solver类,在新建SGDSolver对象时会调用其构造函数如下所示:

    //sgd_solvers.hpp
    explicit SGDSolver(const SolverParameter& param): Solver<Dtype>(param) { PreSolve(); }
    • 1
    • 2
    • 3
    • 1
    • 2
    • 3

    从上面代码可以看出,会先调用父类Solver的构造函数,如下所示。Solver类的构造函数通过Init(param)函数来初始化网络。

    //solver.cpp
    template <typename Dtype>
    Solver<Dtype>::Solver(const SolverParameter& param, const Solver* root_solver): net_(), callbacks_(), root_solver_(root_solver),requested_early_exit_(false)
    {Init(param);
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    而在Init(paran)函数中,又主要是通过InitTrainNet()和InitTestNets()函数分别来搭建训练网络结构和测试网络结构。

    训练网络只能有一个,在InitTrainNet()函数中首先会设置一些基本参数,包括设置网络的状态为TRAIN,确定训练网络只有一个等,然会会通过下面这条语句新建了一个Net对象。InitTestNets()函数和InitTrainNet()函数基本类似,不再赘述。

    //solver.cpp
    net_.reset(new Net<Dtype>(net_param));
    • 1
    • 2
    • 1
    • 2

    上面语句新建了Net对象之后会调用Net类的构造函数,如下所示。可以看出构造函数是通过Init(param)函数来初始化网络结构的。

    //net.cpp
    template <typename Dtype>
    Net<Dtype>::Net(const NetParameter& param, const Net* root_net): root_net_(root_net) {Init(param);
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    下面是net.cpp文件里Init()函数的主要内容(忽略具体细节),其中LayerRegistry::CreateLayer(layer_param)主要是通过调用LayerRegistry这个类的静态成员函数CreateLayer得到一个指向Layer类的shared_ptr类型指针。并把每一层的指针存放在vector

    //net.cpp Init()
    for (int layer_id = 0; layer_id < param.layer_size(); ++layer_id) {//param是网络参数,layer_size()返回网络拥有的层数const LayerParameter& layer_param = param.layer(layer_id);//获取当前layer的参数layers_.push_back(LayerRegistry<Dtype>::CreateLayer(layer_param));//根据参数实例化layer//下面的两个for循环将此layer的bottom blob的指针和top blob的指针放入bottom_vecs_和top_vecs_,bottom blob和top blob的实例全都存放在blobs_中。相邻的两层,前一层的top blob是后一层的bottom blob,所以blobs_的同一个blob既可能是bottom blob,也可能使top blob。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);}for (int top_id = 0; top_id < num_top; ++top_id) {AppendTop(param, layer_id, top_id, &available_blobs, &blob_name_to_idx);}// 调用layer类的Setup函数进行初始化,输入参数:每个layer的输入blobs以及输出blobs,为每个blob设置大小
    layers_[layer_id]->SetUp(bottom_vecs_[layer_id], top_vecs_[layer_id]);//接下来的工作是将每层的parameter的指针塞进params_,尤其是learnable_params_。const int num_param_blobs = layers_[layer_id]->blobs().size();for (int param_id = 0; param_id < num_param_blobs; ++param_id) {AppendParam(param, layer_id, param_id);//AppendParam负责具体的dirtywork}}
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    经过上面的过程,Net类的初始化工作基本就完成了,接着我们具体来看看上面所说的layers_[layer_id]->SetUp对每一具体的层结构进行设置,我们来看看Layer类的Setup()函数,对每一层的设置主要由下面三个函数组成:
    LayerSetUp(bottom, top):由Layer类派生出的特定类都需要重写这个函数,主要功能是设置权值参数(包括偏置)的空间以及对权值参数经行随机初始化。
    Reshape(bottom, top):根据输出blob和权值参数计算输出blob的维数,并申请空间。

    //layer.hpp
    // layer 初始化设置
    void SetUp(const vector<Blob<Dtype>*>& bottom,   const vector<Blob<Dtype>*>& top) {InitMutex();CheckBlobCounts(bottom, top);LayerSetUp(bottom, top);Reshape(bottom, top);SetLossWeights(top);
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    经过上述过程基本上就完成了初始化的工作,总体的流程大概就是新建一个Solver对象,然后调用Solver类的构造函数,然后在Solver的构造函数中又会新建Net类实例,在Net类的构造函数中又会新建各个Layer的实例,一直具体到设置每个Blob,大概就介绍完了网络初始化的工作,当然里面还有很多具体的细节,但大概的流程就是这样。

    训练过程

    上面介绍了网络初始化的大概流程,如上面所说的网络的初始化就是从下面一行代码新建一个solver指针开始一步一步的调用Solver,Net,Layer,Blob类的构造函数,完成整个网络的初始化。

    //caffe.cpp
    shared_ptr<caffe::Solver<float> > //初始化solver(caffe::SolverRegistry<float>::CreateSolver(solver_param));
    • 1
    • 2
    • 3
    • 1
    • 2
    • 3

    完成初始化之后,就可以开始对网络经行训练了,开始训练的代码如下所示,指向Solver类的指针solver开始调用Solver类的成员函数Solve(),名称比较绕啊。

    // 开始优化
    solver->Solve();
    • 1
    • 2
    • 1
    • 2

    接下来我们来看看Solver类的成员函数Solve(),Solve函数其实主要就是调用了Solver的另一个成员函数Step()来完成实际的迭代训练过程。

    //solver.cpp
    template <typename Dtype>
    void Solver<Dtype>::Solve(const char* resume_file) {...int start_iter = iter_;...// 然后调用了'Step'函数,这个函数执行了实际的逐步的迭代过程Step(param_.max_iter() - iter_);...LOG(INFO) << "Optimization Done.";
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    顺着来看看这个Step()函数的主要代码,首先是一个大循环设置了总的迭代次数,在每次迭代中训练iter_size x batch_size个样本,这个设置是为了在GPU的显存不够的时候使用,比如我本来想把batch_size设置为128,iter_size是默认为1的,但是会out_of_memory,借助这个方法,可以设置batch_size=32,iter_size=4,那实际上每次迭代还是处理了128个数据。

    //solver.cpp
    template <typename Dtype>
    void Solver<Dtype>::Step(int iters) {...//迭代while (iter_ < stop_iter) {...// iter_size也是在solver.prototxt里设置,实际上的batch_size=iter_size*网络定义里的batch_size,// 因此每一次迭代的loss是iter_size次迭代的和,再除以iter_size,这个loss是通过调用`Net::ForwardBackward`函数得到的// accumulate gradients over `iter_size` x `batch_size` instancesfor (int i = 0; i < param_.iter_size(); ++i) {/** 调用了Net中的代码,主要完成了前向后向的计算,* 前向用于计算模型的最终输出和Loss,后向用于* 计算每一层网络和参数的梯度。*/loss += net_->ForwardBackward();}.../** 这个函数主要做Loss的平滑。由于Caffe的训练方式是SGD,我们无法把所有的数据同时* 放入模型进行训练,那么部分数据产生的Loss就可能会和全样本的平均Loss不同,在必要* 时候将Loss和历史过程中更新的Loss求平均就可以减少Loss的震荡问题。*/UpdateSmoothedLoss(loss, start_iter, average_loss);...// 执行梯度的更新,这个函数在基类`Solver`中没有实现,会调用每个子类自己的实现//,后面具体分析`SGDSolver`的实现ApplyUpdate();// 迭代次数加1++iter_;...}
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40

    上面Step()函数主要分为三部分:

    loss += net_->ForwardBackward();

    这行代码通过Net类的net_指针调用其成员函数ForwardBackward(),其代码如下所示,分别调用了成员函数Forward(&loss)和成员函数Backward()来进行前向传播和反向传播。

    // net.hpp
    // 进行一次正向传播,一次反向传播
    Dtype ForwardBackward() {Dtype loss;Forward(&loss);Backward();return loss;
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    前面的Forward(&loss)函数最终会执行到下面一段代码,Net类的Forward()函数会对网络中的每一层执行Layer类的成员函数Forward(),而具体的每一层Layer的派生类会重写Forward()函数来实现不同层的前向计算功能。上面的Backward()反向求导函数也和Forward()类似,调用不同层的Backward()函数来计算每层的梯度。

    //net.cpp
    for (int i = start; i <= end; ++i) {
    // 对每一层进行前向计算,返回每层的loss,其实只有最后一层loss不为0Dtype layer_loss = layers_[i]->Forward(bottom_vecs_[i], top_vecs_[i]);loss += layer_loss;if (debug_info_) { ForwardDebugInfo(i); }
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    UpdateSmoothedLoss();

    这个函数主要做Loss的平滑。由于Caffe的训练方式是SGD,我们无法把所有的数据同时放入模型进行训练,那么部分数据产生的Loss就可能会和全样本的平均Loss不同,在必要时候将Loss和历史过程中更新的Loss求平均就可以减少Loss的震荡问题

    ApplyUpdate();

    这个函数是Solver类的纯虚函数,需要派生类来实现,比如SGDSolver类实现的ApplyUpdate();函数如下,主要内容包括:设置参数的学习率;对梯度进行Normalize;对反向求导得到的梯度添加正则项的梯度;最后根据SGD算法计算最终的梯度;最后的最后把计算得到的最终梯度对权值进行更新。

    template <typename Dtype>
    void SGDSolver<Dtype>::ApplyUpdate() {CHECK(Caffe::root_solver());// GetLearningRate根据设置的lr_policy来计算当前迭代的learning rate的值Dtype rate = GetLearningRate();// 判断是否需要输出当前的learning rateif (this->param_.display() && this->iter_ % this->param_.display() == 0) {LOG(INFO) << "Iteration " << this->iter_ << ", lr = " << rate;}// 避免梯度爆炸,如果梯度的二范数超过了某个数值则进行scale操作,将梯度减小ClipGradients();// 对所有可更新的网络参数进行操作for (int param_id = 0; param_id < this->net_->learnable_params().size();++param_id) {// 将第param_id个参数的梯度除以iter_size,// 这一步的作用是保证实际的batch_size=iter_size*设置的batch_sizeNormalize(param_id);// 将正则化部分的梯度降入到每个参数的梯度中Regularize(param_id);// 计算SGD算法的梯度(momentum等)ComputeUpdateValue(param_id, rate);}// 调用`Net::Update`更新所有的参数this->net_->Update();
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    等进行了所有的循环,网络的训练也算是完成了。上面大概说了下使用Caffe进行网络训练时网络初始化以及前向传播、反向传播、梯度更新的过程,其中省略了大量的细节。上面还有很多东西都没提到,比如说Caffe中Layer派生类的注册及各个具体层前向反向的实现、Solver派生类的注册、网络结构的读取、模型的保存等等大量内容。

    转自:::http://buptldy.github.io/2016/10/09/2016-10-09-Caffe_Code/

    0
    0

    相关文章推荐
    • win版本caffe源码libcaffe研究
    • 机器学习(Machine Learning)&深度学习(Deep Learning)资料集合
    • 码农周刊分类整理
    • 机器学习(Machine Learning)&深度学习(Deep Learning)资料(Chapter 1)
    • 【机器学习Machine Learning】资料大全
    • 机器学习&深度学习
    • 机器学习(Machine Learning)&深度学习(Deep Learning)资料(Chapter 1)
    • 机器学习(Machine Learning)&深度学习(Deep Learning)资料
    • 深度学习如何入门?
    • 深度学习和机器学习的相关资料

    参考知识库

    img

    人工智能规划与决策知识库

    img

    软件测试知识库

    img

    算法与数据结构知识库

    更多资料请参考:
    猜你在找
    Android核心技术——Android数据存储
    Android之数据存储
    Android中的数据存储
    360度解析亚马逊AWS数据存储服务
    iOS开发高级专题—数据存储
    顾荣:开源大数据存储系统Alluxio(原Tachyon)的原理分析与案例简介
    云端存储的基本技巧和上云实践——清宵教你玩转云存储一:数据上云的基本实践
    Ceph—分布式存储系统的另一个选择
    Windows Server 2012 R2 存储和文件服务管理
    Windows Server 2012 存储和文件管理
    Android核心技术——Android数据存储
    Android之数据存储
    Android中的数据存储
    360度解析亚马逊AWS数据存储服务
    iOS开发高级专题—数据存储
    顾荣:开源大数据存储系统Alluxio(原Tachyon)的原理分析与案例简介
    云端存储的基本技巧和上云实践——清宵教你玩转云存储一:数据上云的基本实践
    Ceph—分布式存储系统的另一个选择
    Windows Server 2012 R2 存储和文件服务管理
    Windows Server 2012 存储和文件管理
    关闭
    查看评论
    1楼 李木木乃伊 2017-03-21 18:24发表 [回复] [引用] [举报]
    讲的好透彻,赞一个
    * 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    快速回复 TOP
    核心技术类目
    全部主题HadoopAWS移动游戏JavaAndroidiOSSwift智能硬件DockerOpenStackVPNSparkERPIE10EclipseCRMJavaScript数据库UbuntuNFCWAPjQueryBIHTML5SpringApache.NETAPIHTMLSDKIISFedoraXMLLBSUnitySplashtopUMLcomponentsWindows MobileRailsQEMUKDECassandraCloudStackFTCcoremailOPhone CouchBase云计算iOS6Rackspace Web AppSpringSideMaemoCompuware大数据aptechPerlTornadoRubyHibernateThinkPHPHBasePureSolrAngularCloud FoundryRedisScalaDjangoBootstrap
    • 个人资料

    • _苏_
      3
      • 访问:62214次
      • 积分:1210
      • 等级:
        积分:1210
      • 排名:千里之外
      • 原创:57篇
      • 转载:5篇
      • 译文:0篇
      • 评论:79条
    • 文章分类
    • C语言学习(3)
    • Linux学习(12)
    • 数学算法(1)
    • 图像处理(2)
    • 模式识别(3)
    • 机器学习(12)
    • 其他(3)
    • 深度学习(23)
    • Python语言学习(3)
    • 文章存档
      • 2017年01月(7)
      • 2016年12月(8)
      • 2016年11月(14)
      • 2016年10月(8)
      • 2016年09月(7)
      • 2016年08月(3)
      • 2016年07月(6)
      • 2016年06月(1)
      • 2015年11月(2)
      • 2015年02月(1)
      • 2015年01月(4)
        展开
    • 阅读排行
    • caffe生成lenet-5的deploy.prototxt文件(6485)
    • 用caffe训练好的lenet_iter_10000.caffemodel测试单张mnist图片(5571)
    • Caffe编译 Mnist训练测试(4094)
    • 用caffe训练测试自己的图片(3906)
    • adaboost训练 之 弱分类器训练原理(2496)
    • 运动目标检测 之 Vibe背景模型算法(2373)
    • adaboost训练 之 参数详解(2350)
    • caffe测试单张图片(1947)
    • ubuntu安装nvidia显卡驱动(双显卡)(1447)
    • Caffe训练源码基本流程(1344)
    • 评论排行
    • 用caffe训练好的lenet_iter_10000.caffemodel测试单张mnist图片(39)
    • caffe生成lenet-5的deploy.prototxt文件(14)
    • Caffe图片分类(8)
    • adaboost训练 之 参数详解(6)
    • BP神经网络(3)
    • 编译cuda-7.5 samples文件报错(2)
    • caffe源码 之 dropout层(2)
    • 机器学习 之 Haar特征(2)
    • Caffe编译 Mnist训练测试(2)
    • Caffe训练源码基本流程(1)
    • 推荐文章
      • * 5月书讯:流畅的Python,终于等到你!
      • *【新收录】CSDN日报 —— Kotlin 专场
      • * Android中带你开发一款自动爆破签名校验工具kstools
      • * Android图片加载框架最全解析——深入探究Glide的缓存机制
      • * Android 热修复 Tinker Gradle Plugin解析
      • * Unity Shader-死亡溶解效果
    • 最新评论
    • Caffe图片分类

      qingdeng8127:imgsave = imgsave.erase(61,2);哥哥 这句话里的61和2是怎么确定的 我...

    • Caffe图片分类

      qingdeng8127:---------- Prediction for examples/mymnist2/test_d...

    • 用caffe训练好的lenet_iter_10000.caffemodel测试单张mnist图片

      God_bless_us:作者你好,我硬件有限,仅仅支持cpu。所以此处应该同你有些差异,我尝试过在classifymnist...

    • BP神经网络

      qq_33178422:感谢

    • 用caffe训练好的lenet_iter_10000.caffemodel测试单张mnist图片

      God_bless_us:楼主您好,我想请教您的是sysnset_words.txt文件的具体生成办法是什么,我参考过imag...

    • caffe生成lenet-5的deploy.prototxt文件

      zzz321year:楼主你好,我为什么输出的top5正确率都是0,但是label貌似正确;而且train、test正确率...

    • 用caffe训练好的lenet_iter_10000.caffemodel测试单张mnist图片

      _苏_:@qq_35173755:这个文件是自己创建的

    • 用caffe训练好的lenet_iter_10000.caffemodel测试单张mnist图片

      qq_35173755:请教一下,您的源代码在哪里下载,我从官网下载的代码训练后没有sysnset_words.txt文件

    • caffe源码 之 dropout层

      _苏_:@qq_24693721:这里是我写错了,是处于训练阶段。训练时的传入参数中有个是train,如果是...

    • caffe源码 之 dropout层

      qq_24693721:博主你好,有个问题想问你,就是网络所处的阶段是怎么判别的?另外“if (this->phase_ =...

    本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/510295.shtml

    如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

    相关文章

    ubuntu16.04下安装opencv3.2版本

    1、下载OpenCV的源码 OpenCV官网上有linux版本的源码包可以下载&#xff0c;不过最好是从git上下载&#xff0c;这样可以保证下载得到的是最新的代码&#xff1a;1 wget -O opencv.zip https://github.com/Itseez/opencv/archive/3.2.0.zip 2 unzip opencv.zip 2、编译安装…

    windows 静态IP设置

    1.打开cmd&#xff0c;输入ipconfig 记录 IP address 子网掩码 网关 打开 wlan 属性 选中一个网络右键 “属性” 设置 ipv4&#xff0c;选择“使用下面的IP地址” 对应填写 ip地址 子网掩码 网关 tips&#xff1a;DNS建议和网关一样

    window 远程linux

    1.我们需要在Linux安装ssh服务 sudo apt-get install openssh-server 2.然后开启ssh服务 sudo /etc/init.d/ssh start 3.在window上安装PUTTY 下载网址 4.填写Linux ip 查看ip: 在Linux输入&#xff1a;ifconfig 5.然后填写登陆Linux的账户名和密码 大功告成。。。。。…

    赫夫曼编码长度计算问题?

    例题&#xff1a;一组字符(a,b,c,d)在文中出现的次数分别为(7,6,3,5),字符&#xff07;d&#xff07;的哈夫曼编码的长度为&#xff1f; 题解&#xff1a; 首先构造huffman树 每一步都将所有数字排序 方法如下: 1: 3 5 6 7 2: 6 7 8 / \ 3 5 3: 8 13 / \ / \ 3 5 6 7 4: 21 /…

    windows + cmake + vs2019 编程

    1.安装minGW64 2.安装cmake 3.安装vs2019 4.组建代码文件结构&#xff1a; 5.在build 文件下打开git bash&#xff0c;执行一下指令 cmake .. -G"Visual Studio 16 2019" tips( vs2017 对应 cmake .. -G"Visual Studio 15 2017" ) cmake 模板…

    所感

    记住别太善良了&#xff0c;别太大方了&#xff0c;也别太能干了&#xff0c;时间久了人家会觉得&#xff0c;你做的一切都是应该的。即使有一天你撑不住&#xff0c;哭了累了&#xff0c;也没人心疼你。 因为在他们眼里这都是你愿意的。有时候心眼也别太好了不要什么事都为别人…

    享受孤独

    今天看见网易云音乐一个 有趣的活动。。。突发其感参与了评论“孤独”这个话题&#xff1a;

    使自己的注意力集中方法

    英国Kent大学最近有一篇文章对注意力做出了详尽的分析&#xff0c;关于如何保持专心养成好习惯的&#xff0c;其中包括了如下几点建议&#xff1a; 养成好习惯&#xff1a;养成在固定时间、固定地点专心学习工作的好习惯。如果可能&#xff0c;在进入学习或者工作状态前做一些小…

    PCL “(”:“::”右边的非法标记 和 E2512 功能测试宏的参数必须是简单标识符

    PCL “(”:“::”右边的非法标记 解决方法&#xff1a; 项目属性 ——> C/C ——> 预处理器 ——> 预处理器定义 (此处添加预定义编译开关 NOMINMAX&#xff09; E2512 功能测试宏的参数必须是简单标识符 解决方法&#xff1a; 将SDL 设置为否。

    普通本科生应该坚持ACM吗?知乎

    这是本人当初学ACM有疑惑从知乎看见这一篇文章&#xff0c;从中解决了自己的疑惑&#xff0c;虽然是粘贴复制&#xff0c;但是我觉得我们可以从里面找出自己想要的答案&#xff01; 非211一本学校&#xff0c;软件工程专业。学校搞ACM的水平不高&#xff0c;最好的大概就是区域…

    解决虚拟机打开不了?提示VMware Workstation cannot connect to the virtual machine的问题

    解决方法&#xff1a; 从提示消息我们可以看到&#xff0c;问题在于VMware授权服务没有开启&#xff0c;具体处理方法如下&#xff1a; No1. "This PC&#xff08;我的电脑&#xff09;"---右键"manage&#xff08;管理&#xff09;"---"Service and…

    Redis-3.2.4服务搭建

    1.下载安装包并解压 全部版本地址&#xff1a;http://download.redis.io/releases 安装包下载&#xff1a; http://download.redis.io/releases/redis-3.2.4.tar.gz 我们这里使用3.2.4 2.编译安装 cd redis-3.2.4 make && make install 可能异常&#xff1a;&…

    Android Fragment 真正的完全解析(上)

    转载请标明出处&#xff1a;http://blog.csdn.net/lmj623565791/article/details/37970961 自从Fragment出现&#xff0c;曾经有段时间&#xff0c;感觉大家谈什么都能跟Fragment谈上关系&#xff0c;做什么都要问下Fragment能实现不~~~哈哈&#xff0c;是不是有点过~~~ 本篇博…

    Hbase Import导入数据异常处理-RetriesExhaustedWithDetailsException

    CDH显示 问题导致原因&#xff1a; hbase org.apache.hadoop.hbase.mapreduce.Import -Dmapred.job.queue.nameetl crawl:wechat_biz /hbase/test4 执行import时&#xff0c;短时间内写入数据量过大导致写入异常。 18/09/11 09:44:27 INFO mapreduce.Job: Task Id : attempt_…

    Android RecyclerView 使用完全解析 体验艺术般的控件

    转载请标明出处&#xff1a; http://blog.csdn.net/lmj623565791/article/details/45059587&#xff1b; 本文出自:【张鸿洋的博客】 概述 RecyclerView出现已经有一段时间了&#xff0c;相信大家肯定不陌生了&#xff0c;大家可以通过导入support-v7对其进行使用。 据官方的…

    三维刚体变换

    1.旋转向量&#xff1a; 满足以下关系 (E单位阵) 进一步得到&#xff1a; p经过旋转和平移得到,公式表达如下&#xff1a; ;(t平移矩阵) 我们可以将上面的式子写成齐次&#xff1a; T也成为变换举证&#xff08;transform Matrix&#xff09; 它的反变换可以表示如下&am…

    远程桌面管理工具

    链接&#xff1a;https://pan.baidu.com/s/1K_AMitnmpYQkRWSBq9HhVA 提取码&#xff1a;d9eo

    Impala-shell 查询异常 - ERROR: AnalysisException: Failed to evaluate expr: 1

    直接使用impala-shell 进行最近本查询&#xff0c;异常 [test:21000] default> select * from tbName limit 1; Query: select * from vt_article limit 1 Query submitted at: 2018-09-14 13:43:10 (Coordinator: http://fwqzx002:25000) ERROR: AnalysisException: Fail…

    手把手教你写平衡二叉树

    因为上BST课的时候睡觉睡过了结果。。。&#xff0c;后者折腾了一个下午才写了出来&#xff0c;感谢http://blog.chinaunix.net/uid-24948645-id-3913917.html博客的详细解析&#xff0c;但是上面的不足之处在于代码是伪代码&#xff0c;基本实现不了&#xff0c;然后自己做了修…

    cuda编程性能 分析工具 nvprof的使用

    ubuntu环境上&#xff0c;安装cuda,会自动安装一些工具nvcc ,nvprof nvcc-gdb.... 1.编译生成可执行文件 2.nvprof ./test 可以把性能分析数据输出到文件中 nvprof ./test -o test.nvvp 可以把在nvidia visual profiler现实更加直观 一些常用的配置参数&#xff1a; achie…