Caffe for Windows: Microsoft Caffe的安装、修改和使用(Windows 10 + GPU)

目录

0  环境准备

1  Caffe编译(生成)

2  Caffe再编译

实验原理

实验过程

        一、添加ChangeLossLayer损失层

        二、添加一个新的卷积层

3  使用

训练

预测


0  环境准备

由于BVLC Caffe不支持Cuda 8.0,以下实验均在Microsoft Caffe基础上完成。本节将完整列出编译安装深度学习框架Caffe必需的组件。

需要严格按照说明书安装,否则将导致安装失败。

  • 安装VS2013,提取码umnu

       Visual Studio 2013是之后用于编译Caffe工程的IDE。

  • 安装Anaconda2,提取码fn2s;或Miniconda3,提取码m02a

Caffe编译需要的是python2.7,所以一般做法是安装Anaconda2。注意安装过程中不要多余勾选它没勾的框。安好后手动添加环境变量%CONDA_HOME%(实际python2.7安装根目录)%CONDA_HOME%\Scripts%CONDA_HOME%\Library\bin。实际python2.7安装根目录是什么意思呢?就是实际的python2.7解释器——python.exe所在的目录喽。

注意,我编译时,是先用Anaconda3创建了python2.7虚拟环境“python27”,然后添加的第一个环境变量就要相应地变为%CONDA_HOME%\envs\python27,即%CONDA_HOME% := %CONDA_HOME%\envs\python27。创建好虚拟环境后记得要安装numpy。

或者有些人的虚拟环境默认是创建在其他地方的比如C盘的.conda文件夹等等,总之这一步的目的就是为了声明python2.7的位置,和配置PyCharm的环境变量的过程可以说是非常相似的。所以具体的环境变量根据你的python2.7的实际位置来定就好。

  • 安装cuda8.0.61,提取码lecj

       步骤略。

  • 安装cudnn5.1,提取码r1a1

       步骤略。


1  Caffe编译(生成)

Caffe,全称Convolution Architecture For Feature Extraction,是一个清晰且快速的深度学习框架。下面介绍一下如何在Windows 10下配置Caffe框架。

  • 下载微软caffe源码并解压到适当的路径。下面统一用%CAFFE_MASTER%指代解压后所在的目录。
  • 下载NugetPackages并解压到任意的路径,提取码7uev。

        这一步可以省略。这样的话在生成libcaffe这一步中,VS2013会自动帮我们下载NugetPachages,是不是很贴心呢?但是,为了避免某些校园网网络存在不稳定等的复杂情况而导致失败,我们先下载好了,这样就不用等着VS2013缓慢地下载啦。

  • 复制%CAFFE_MASTER%\windows\CommonSettings.props.example 为%CAFFE_MASTER%\windows\CommonSettings.props
  • 用记事本打开CommonSetting.props,修改如下:将默认的7.5修改为 8.0默认  为 false,修改为 true修改这一行下面的  路径为当前python 2.7的安装路径%CONDA_HOME%\默认  为 false,修改为true修改这一行下面的为当前Matlab安装路径%MATLAB_HOME%

       再提醒一下上面的%CONDA_HOME%和%MATLAB_HOME%取决于你的python2.7和Matlab的实际安装路径。

  • 打开%CAFFE_MASTER%\windows下的Caffe.sln调试器模式设为Release X64所有项目的属性中“将警告是为错误”设为“否”。
  • 打开VS2013菜单栏的工具->NuGet程序包管理器->程序包管理器设置,选择程序包源,点右上方的加号,然后右下方名称任意(就叫默认的Package Source 1就好),点击旁边的“..."浏览并选择之前下载解压的NugetPackages文件夹,再点更新,再点右上方的上箭头将该源移到顶部,最后确定保存。

        结合第2步,这一步就能确保编译过程中使用我们之前下载好的NugetPackages。

  • 打开VS2013菜单栏的工具->选项,选择项目和解决方案->生成并运行,最大并行项目生成数设为3(或更小),确定保存。
  • 生成libcaffe。
  • 生成caffe。
  • 依次生成剩余的14个项目。

如果在生成matcaffe时出现问题..\..\matlab\+caffe\private\caffe_.cpp(16): fatal error C1083: 无法打开包括文件: “gpu/mxGPUArray.h”: No such file or directory,则把%MATLAB_HOME%\toolbox\distcomp\gpu\extern\include下的gpu文件夹复制到%MATLAB_HOME%\extern\include下,然后继续从matcaffe开始生成。

如果在生成pycaffe时出现问题..\..\python\caffe\_caffe.cpp(10): fatal error C1083: 无法打开包括文件: “numpy/arrayobject.h”: No such file or directory,说明未安装numpy,给当前python2.7装上numpy即可。然后继续从pycaffe开始生成。

  • 16个项目都生成成功后关闭vs2013。最后,在%CAFFE_MASTER%下出现Build文件夹,即%CAFFE_HOME% := %CAFFE_MASTER%\Build\x64\Release。可以选择将%CAFFE_HOME%添加到系统环境变量。

至此Windows 10下的caffe就安装成功了,是不是非常的简单呢?这里也提供一下我编译好的caffe作为参考(4uvj)。但是,这个版本并没有把matcaffe编译进去,而且如果以后想要做进一步更改,编译Caffe是必须步骤,所以建议完整地按照说明亲自安装。另外,%CAFFE_HOME%\pycaffe中的caffe文件夹是用于import caffe的caffe包。在

import caffe

前,需要将%CAFFE_HOME%\pycaffe加入python工程路径或将%CAFFE_HOME%\pycaffe下的caffe文件夹拷贝到相应python工程所在虚拟环境下的包引用目录中。caffe只支持python2.7的虚拟环境。


2  Caffe再编译

针对caffe添加新的层,网上有许多教程。但是,大部分教程关注的是Caffe for Linux,缺乏Caffe for Windows下的完整、快速和通用的实现方法。有一些贴出了Caffe for Windows下的实验流程,但是都集中于新层的hpp、cpp和cu代码的编写方面。虽然新层的hpp、cpp和cu代码的编写也很重要,但有些时候,往往我们得到了已编写好的新层代码,却不知如何将其再编译进Caffe for Windows中。因此,本节将以向Caffe for Windows中添加新损失函数(层)“ChangeLossLayer"为例,详细描述相应的完整实验步骤。

实验原理

假设我想添加一个叫ChangeLossLayer的损失层,损失函数是L=l0+l1+l2,其中l1、l2和l3都具有Contrastive Loss的形式,且具有同一个阈值参数margin。除此之外,这个损失层还有额外3个参数alpha、beta和gamma用于调整l1、l2和l3的大小。类似于SmoothL1Loss具有的参数sigma可以在prototxt中定义,我们所添加的层具有的4个参数margin、alpha、beta和gamma也应该能够在prototxt中定义。所以这些参数都是需要后面在一个叫caffe.proto的文件里注册的。

怎么看出来一个新损失层需要哪些参数?只需要看它的cpp文件即可。以SmoothL1Loss为例,打开它的cpp文件,可以看到第5行表明需要用到的自定义参数就是sigma。同理,只需要看其他损失层的cpp相同位置,即可知道后面我们需要注册哪些参数。

template 
void SmoothL1LossLayer::LayerSetUp(
  const vector*>& bottom, const vector*>& top) {
  SmoothL1LossParameter loss_param = this->layer_param_.smooth_l1_loss_param();
  sigma2_ = loss_param.sigma() * loss_param.sigma();  //
  has_weights_ = (bottom.size() >= 3);
  if (has_weights_) {
    CHECK_EQ(bottom.size(), 4) << "If weights are used, must specify both "
      "inside and outside weights";
  }
}

要添加ChangeLossLayer光有源代码是不够的,还需要在caffe.proto中定义新的结构化数据。关于caffe.proto的原理可以参考这里。caffe.proto的位置见下表。修改caffe.proto时务必注意格式和大小写。

caffe.proto中都是描述性语言,Caffe for Windows需要的是由caffe.proto编译而来的C代码(caffe.pb.h和caffe.pb.cc)。所以改完caffe.proto后会用到一个proto文件的编译器protoc。这个是需要额外下载的。

最后会用到原生工程自带的ProtoCompile.cmd。ProtoCompile.cmd在再编译Caffe工程的过程中由Caffe工程自动调用。ProtoCompile.cmd的位置见下表。ProtoCompile.cmd负责调用protoc编译caffe.proto并自动替换老caffe.pb.h和caffe.pb.cc。

目前全部的材料总结如下,下面将把新损失层集成到Caffe for Windows中。

Caffe for Windows: Microsoft Caffe的安装、修改和使用(Windows 10 + GPU)_第1张图片

实验过程

一、添加ChangeLossLayer损失层

1、用记事本打开caffe.proto,做如下修改,具体的名字根据实际添加的层决定,但是修改时务必注意格式和大小写。

  • 找到message LayerParameter块,根据上方显示的下一个可用ID(我的是151),在块内最下方添加
optional ChangeLossParameter change_loss_param = 151;
  • 在块外任意空白位置添加
message ChangeLossParameter {
  optional float margin = 1 [default = 1.0];
  optional float alpha = 2 [default = 3.0];
  optional float beta = 3 [default = 5.0];
  optional float gamma = 4 [default = 50.0];
}
  • 保存并关闭。不需要改动V1LayerParameter中的内容。

2、下载proto文件的编译器protoc。打开该网址选择protoc-2.6.1-win32.zip。假设将下载后的压缩包解压到了%PROTOC_HOME%,则将%PROTOC_HOME%添加到系统环境变量。之所以链接中的版本是2.6.1,是因为caffe不支持别的版本。

3、用记事本打开ProtoCompile.cmd,做一点小修改:删掉第二行的set PROTO_DIR=%~2%;将第12行"%PROTO_DIR%protoc"改为"protoc"(删掉了引号中的%PROTO_DIR%)。最后保存。这样做是因为我们已经添加了%PROTOC_HOME%至系统环境变量。

4、将新层的hpp文件拖到%CAFFE_MASTER%\include\caffe\layers下,将新层的cpp和cu文件拖到%CAFFE_MASTER%\src\caffe\layers下。

5、用VS2013打开%CAFFE_MASTER%\windows\Caffe.sln展开libcaffe\cu,右键layers->添加现有项->选择刚才拖动后的cu文件;展开libcaffe\src,右键layers->添加现有项->选择刚才拖动后的cpp文件;展开libcaffe\include,右键layers->添加现有项->选择刚才拖动后的hpp文件。

6、检查调试器模式是否设为Release X64所有项目的属性中“将警告是为错误”是否设为了“否”,是否启用了已下载好的NugetPackages,最大并行项目生成数是否设为了3(或更小)。matcaffe和pycaffe是否根据第一节已设置正确。

7、先右键libcaffe选“重新生成”,再右键caffe选“重新生成”,最后依次重新生成剩余的14个项目。

二、添加一个新的卷积层

这样,Windows 10下的Caffe框架就重新编译成功了,我们就可以像使用其他层一样随意使用新添加的层了,是不是非常的简单方便呢?相比Caffe for Linux,不得不说Caffe for Windows的安装和修改稍微复杂了一些,但是Microsoft Caffe已经尽可能地适配了Windows系统,而且安装成功后,后者的工作效率丝毫不比前者差,甚至能获得更完善的GPU支持。考虑到Windows 10的工作链比Linux完善得多,Caffe for Windows仍具有足够吸引人的性价比。


3  使用

以回归任务为例,样本是N×N×3的图片,首先按照7/1/2或8/2分成训练、测试预测集,这样就有了3个内容是图片的文件夹。当然可以直接读取纯图片,但是读取慢。第二种方法是分别生成训练和测试的lmdb格式数据集,这种格式是Caffe数据层支持的格式,但是需要预先将图片和标签存入相应的数据库,例如

import os
import lmdb
from PIL import Image 
import numpy as np 
import sys
import caffe

file_input = open('./test.txt', 'r')  # file info
img_list = []
label_list = []
num = 1
for line in file_input:
    content = line.strip()
    content = content.split(' ')
    img_list.append(content[0]) # Name of the sample
    label = []
    for i in range(37):  # Number of my tags of a label
        label.append(float(content[i+1]))
    label_list.append(label)
    del content
    print(num)
    num = num + 1
file_input.close() 
# Saving the samples to the database
in_db = lmdb.open('./img/', map_size=int(1e10))
with in_db.begin(write=True) as in_txn:
    for in_idx, in_ in enumerate(img_list):
        _in_ = in_.split('_')[0]
        in__ = _in_ + '/' + in_ + '.bmp'
        im_file = './' + in__
        im = Image.open(im_file)
        im = np.array(im)
        im = im[:, :, ::-1]
        im = im.transpose((2, 0, 1))
        im_dat = caffe.io.array_to_datum(im)
        in_txn.put('{:0>10d}'.format(in_idx), im_dat.SerializeToString())
        print('image carried through: {} [{}/{}]'.format(in__, in_idx+1, len(img_list)))
        del im_file, im, im_dat
in_db.close()
# Saving the corresponding labels to the database
in_db = lmdb.open('./label/', map_size=int(1e10))
with in_db.begin(write=True) as in_txn:
    for in_idx, in_ in enumerate(img_list):
        target_label = np.zeros((37, 1, 1))
        for i in range(37):
            target_label[i, 0, 0] = label_list[in_idx][i]
        label_data = caffe.io.array_to_datum(target_label)
        in_txn.put('{:0>10d}'.format(in_idx), label_data.SerializeToString())
        print('labels carried through: {} [{}/{}]'.format(in_, in_idx+1, len(img_list)))
        del target_label, label_data    
in_db.close()
print('Preparation accomplished.')

这样就制作好了用于训练的数据集,其中每张图片对应一个37维的标签。网络模型就能直接从数据库里读取图片了。

使用caffe一般需要以下几个文件:

train_val.prototxt:设定训练的具体网络结构,即定义具体的数据层、卷积层、全连接层、损失函数等等。网站Netscope用于可视化train_val.prototxt中的网络。

solver.prototxt:设定超参数,如:

# The train/test net protocol buffer definition
net: "./train_val.prototxt"

test_iter:1313
test_interval: 10000
base_lr: 0.001
lr_policy: "step"
gamma:0.1
stepsize: 55000
display: 100
max_iter: 200000
momentum: 0.9
weight_decay: 0.00001
snapshot: 5000
snapshot_prefix: "./snapshot"
solver_mode: GPU

test_iter和test_interval一定要设,否则在训练时每迭代一次就进行一次测试,导致训练极慢。

deploy.prototxt:设定用模型进行预测时的网络结构,基本与 train_val.prototxt相同。但它应该是不含loss layer的。

训练

设置好solver.prototxt和train_val.prototxt后,使用如下命令启动训练(已添加环境变量)

caffe.exe train --solver=./solver.prototxt --gpu=all
pause

Caffe for Windows: Microsoft Caffe的安装、修改和使用(Windows 10 + GPU)_第2张图片

一般来说,一个epoch所含的iteration=样本数量÷batch_size。



预测

直接执行测试脚本(已添加环境变量),但不便于获取结果

caffe test --weights=./snapshot_iter_200000.caffemodel --model=./deploy.prototxt --iterations=99402 --gpu=all
pause

也可以利用caffe的python接口进行预测,能够根据需要看到中间结果或保存结果

# -*- coding: utf-8 -*-

import caffe

net = caffe.Net('./deploy.prototxt', 1, weights='./snapshot_iter_200000.caffemodel')

with open('./test.txt') as image_list:
    with open('./pd.txt', 'w') as r:
        while 1:
            list_name = image_list.readline()
            if not list_name:
                break
            img_name = list_name.split(' ')[0]
            img_y = list_name.split(' ')[1]    # 真实值
            out = net.forward()
            score = (out['fc3'])[0, 0]  # 获取预测值;fc3是我的最后一个全连接层名
            r.write(img_name + " " + img_y + " " + repr(score) + '\n')

你可能感兴趣的:(#,图像质量评价,深度学习,caffe,windows,神经网络,visual,studio)