要说明的是此篇文章的最终结果参照的是用Google搜索出来的()教程, 在这之前图省事没去(也是觉得就百度搜索的结果应该Ok), 结果百度出来的教程都没能在我的电脑中安装好Caffe(无GPU版本, 电脑用的是Intel Iris的显卡, 不能用NVIDIA的CUDA并行库).
更要吐槽的是, 虽然是Google搜索出来的此篇博文(wordpress), 但最终参考的是上述博文中的一篇知乎专栏文章(ref)的参考, 你这百度, 搜索国内的文章都这么费劲吗? (百度的结果全是Csdn等网站的(相似)文章)
首先, Caffe的安装大致是沿着官网的思路(link): 1.Caffe的C++依赖安装, 2.Caffe的Python接口的依赖安装, 3.Caffe源码编译.
1.依赖环境安装(Prerequisite): 包含Caffe的系统环境依赖(C++库, Mac中使用
brew
命令安装);2.Caffe Python的环境依赖(Python接口的一些依赖库), Caffe也有Matlab接口, 但我不熟也用不来, 故不安装;
3.源码编译(Compilation, Caffe Source Code): 从Github上下载然后
make install
(用C++编译器编译出需要的二进制程序).
但是, 官网上的安装教程, 也不是完全一对一的(每个人的电脑总会不同), 针对我的情况来说, 有些细节, 官网多讲了, 有些细节, 官网没讲.
环境这事情, 具体情况具体分析吧, 这么说, 也都是血与泪的教训啊, 故将此次安装的总结成众多Caffe安装方法的其中一个版本.
import caffe
无报错):由于我电脑上已经有了Xcode和brew
了, 故没有在此安装, 然后进行Caffe官方的环境依赖安装:
解释
brew
: Mac上管理系统库的一种工具接口/体系, 类似于Python中的pip
包管理工具.
以下, 通过brew
安装如下库, 由于不同库之间有版本依赖关系, 今天的某库A(旧版本)到一年后变成了新版本的库A, 但别的对此库有依赖的库B(依赖A的旧版本), 却是不能使用新版本的A, 故在brew
安装时, 要特别指定某个版本.
Caffe安装中通过
brew
安装的一些系统库:
snappy, leveldb, gflags, glog, szip, lmdb, openblas, hdf5, opencv, boost, boost-python
,以及
protobuf
,其中,
protobuf
库有点特殊, 较新的版本(如3.6.1
)还不是很稳定(不能正确编译), 故在此手动安装其它版本(使用make install
编译安装3.5.1
版本).
# 1.如果出现"Updating Homebrew.."且很慢的话(brew的自动更新, 可设置不自动更新), 可直接Ctrl+C中止更新;
brew install -vd snappy leveldb gflags glog szip lmdb
# 2.安装openblas;
brew install openblas
# 3.安装hdf5和opencv, 由于时间点的关系, 以下命令会安装最新opencv的4版本, 可以将'Makefile.configure'中的'OPENCV_VERSION'改成4, 或者使用'brew install opencv@3'命令(不保证, 没尝试);
brew install hdf5 opencv
# 4.安装指定版本的boost和boost-python, 因为这两个库的新版本可能与Python 2.7有兼容性问题:
# https://www.boost.org/doc/libs/1_67_0/libs/python/doc/html/rn.html;
brew install [email protected] [email protected]
brew link [email protected] --force
brew link [email protected] --force
# 5.手动编译protobuf库;
cd ~/Desktop
wget https://github.com/protocolbuffers/protobuf/archive/v3.5.1.zip
unzip v3.5.1.zip
cd protobuf-3.5.1/
./autogen.sh
./configure
make
make install
在此处执行make install
命令时, 可能会遇到如下报错(我遇到了, 没有则更好了):
..(省略一些上下文(Context))
# 以下是报错信息:
/usr/local/bin/ginstall -c -m 644 google/protobuf/compiler/javanano/javanano_generator.h '/usr/local/include/google/protobuf/compiler/javanano' # ginstall命令输入;
ginstall: cannot remove '/usr/local/include/google/protobuf/compiler/javanano/javanano_generator.h': Permission denied # ginstall命令错误提示输出;
make[3]: *** [install-nobase_includeHEADERS] Error 1
make[2]: *** [install-am] Error 2
make[1]: *** [install] Error 2
make: *** [install-recursive] Error 1
简单说来, 上述错误是由于ginstall
命令没有删除javanano_generator.h
文件的权限, 只要将该文件的权限改成可读/可写
(可以没有执行权限, 无论手动修改还是命令行修改都可以), 修改文件后再次执行命令, 没有报错. (额外分析见"附录-讲解A")
至此, Caffe的"C++/系统依赖"安装完了, 可以开始安装(编译)Caffe源码了(附带Python环境/依赖安装).
由于安装的是Python接口的Caffe, 则要选择某一版本的Python进行安装, 这里我选了2.7版本的Python(据说Python3和Caffe的匹配容易出问题和bug), 首先, 在anaconda中新建一个python2.7的envs
:
# 6.Python 2.7环境安装(此环境在我电脑的"~/miniconda3"中).
conda create --name py27 python=2.7
source activate py27
pip install numpy scipy scikit-image
以上安装无报错后, 真正开始安装/编译Caffe:
# 7.下载并修改Caffe的一些编译选项;
cd ~/Desktop
git clone https://github.com/BVLC/caffe.git
cd caffe
cp Makefile.config.example Makefile.config
根据官方的建议, 在进行build
时, 需要对make
的"配方"(recipe, 即Makefile.config
文件)进行修改, 具体的, 此次安装的修改如下:
# 8.修改'Makefile.configure'配置文件, 共8个修改点;
1.取消CPU_ONLY前面的注释
2.取消USE_OPENCV前面的注释
3.取消USE_HDF5前面的注释,并改成1
4.取消OPENCV_VERSION前面的注释, 并改成4 # 在brew install opencv时, 由于时间点的关系会安装最新的版本4;
5.注释掉CUDA_DIR那一行 # 解释: 无GPU版本并没有安装CUDA;
6.将BLAS改成open # 使用的的是openblas库: brew install openblas;
7.设置blas的路径,取消下面这两行的注释('>'处):
# Homebrew puts openblas in a directory that is not on the standard search path
> BLAS_INCLUDE := $(shell brew --prefix openblas)/include
> BLAS_LIB := $(shell brew --prefix openblas)/lib
8.设置python的路径, 因为我使用的是miniconda3并创建了一个名叫py27的python=2.7的子环境, 然后设置如下:
# Anaconda Python distribution is quite popular. Include path:
# Verify anaconda location, sometimes it's in root.
> ANACONDA_HOME := $(HOME)/miniconda3/envs/py27
> PYTHON_INCLUDE := $(ANACONDA_HOME)/include \
> $(ANACONDA_HOME)/include/python2.7 \
> $(ANACONDA_HOME)/lib/python2.7/site-packages/numpy/core/include
# Uncomment to use Python 3 (default is Python 2)
# PYTHON_LIBRARIES := boost_python3 python3.5m
# PYTHON_INCLUDE := /usr/include/python3.5m \
# /usr/lib/python3.5/dist-packages/numpy/core/include
# We need to be able to find libpythonX.X.so or .dylib.
# PYTHON_LIB := /usr/lib
> PYTHON_LIB := $(ANACONDA_HOME)/lib
# Uncomment to support layers written in Python (will link against Python libs)
> WITH_PYTHON_LAYER := 1
修改好Makefile.configure
之后, 可以进行源码编译了, make
命令会从Makefile
的第3行(CONFIG_FILE := Makefile.config
)读取配置(即: 我们的修改):
# 9.Caffe编译, part 1;
make all
make test
make runtest
make pycaffe
# source activate py27
上述几个步骤(part 1
)如果没有报错, 则可以继续part 2
的步骤, 但由于到现在我们没有安装caffe源码文件夹中python/requirements.txt
的Python依赖, 在执行python -c "import caffe"
时应该会有如下报错: ImportError: No module named google.protobuf.internal
.
刚看到这个报错时也是一脸懵逼(不知所措): **1.**之前没用过这个依赖(不知道其为何物), **2.**因不知其为何物而产生的一种"恐惧", **3.**不熟悉Caffe的内部引用结构(就不主动将
google.protobuf.internal
与import caffe
关联起来), 4.因第3点的原因而没有意识到少安装了一些依赖(python/requirements.txt
).
发觉是没有安装依赖后, 开始安装依赖(使用如下命令), 但需将requirements.txt
做如下修改(状况迭出):
# 修改: 第12行, 去掉行末的',<2';
python-dateutil>=1.4,<2 修改成 python-dateutil>=1.4
# 分析: 如果不修改, 会有版本报错:
> ERROR: pandas 0.24.2 has requirement python-dateutil>=2.5.0, but you'll have python-dateutil 1.5 which is incompatible.
> ERROR: matplotlib 2.2.4 has requirement python-dateutil>=2.1, but you'll have python-dateutil 1.5 which is incompatible.
# 原因: 上述包中(pandas和matplotlib)依赖的'dateutil'版本不能是<2的, 而该文件明确将dateutil的版本规定到'<2'的版本, 这肯定要报错了; 然而, 我只是将',<2'去掉, 它实际安装的是'1.5'版本(因为满足要求'>=1.4'), 却不报错了, 这很是费解:
# "~/miniconda3/envs/py27/lib/python2.7/site-packages/dateutil/__init__.py" => __version__="1.5"
# 既然不报错, 那就先这样吧: 只要bug不出现, 就是没bug..;
修改requirements.txt
完成后, 执行import caffe
所需的Python依赖的安装:
# 10.如果'py27'环境中缺少'import caffe'所需的依赖, 则执行以下依赖安装:
pip install -r python/requirements.txt
安装无误后, 检查是否可以使用caffe:
# 11.Caffe编译, part 2;
python -c "import caffe"
此时, 没有报错.
至此, 我的Mac无GPU版本的caffe算是安装完成了, 弄了几天, 之前试了几种方法, 走了几遍安装流程, 换来了这一次的成功, 不过更大的意义在于: 1.之前几天的过程, 2.这篇思路梳理和总结的文章.
(如果有写的不对的地方, 欢迎指正, 亦欢迎交流)
讲解A: 错误详解
其实对于这种提示, 若不是要安装Caffe, 则可能是不会遇到的.
看一下ginstall
命令(g
代表是Google的命令, 避免与系统命令名重合)的命令输入, 发现其是.../ginstall -c -m 644 .../javanano_generator.h
这样的命令格式,
而之后的报错提示则是ginstall: cannot remove '.../javanano_generator.h': permission denied
, 合理推测应该是ginstall
在寻求删除上述文件时(程序内部有申请删除文件这种系统调用), 遇到了权限不够的问题: 此时并没有用sudo
命令执行make install
, 故ginstall
并不属于该文件644
权限中的6(可读与可写不可执行, owner权限)
, 而是4(可读不可写不可执行, group权限)
, 而remove(删除)
是属于写权限范围的, 系统内核拒绝了ginstall
的删除文件这个请求, 于是make
命令出现了install Error
的状态.
在手动(鼠标右键-显示简介-共享与权限)将上述文件的权限修改成664
之后, 再次make install
, 则不再出现Permission denied
的错误了.
上面这个错误产生的系统原因:
关于权限/Permission: 虽然每次打开电脑登陆操作系统都是用某个用户名登录的(即owner/group/guest
中的owner
), 但在终端中如果没有在命令前加上sudo
或su
, 则命令的默认执行权限应该是group
这一档次的(如执行make install
这样的命令拥有的是group
这一档上的权限).
举例: 如果
group
档上的权限是4(只读)
, 则在进行rm(删除)
操作时, 就会出现Permission denied
报错.
讲解B: 关于编译/Compile:
make
根据Makefile
中的一系列shell命令, 执行相应的编译工作(诸如g++
这样的二进制文件承担了此类功能).
引申开去, 由于可执行的二进制文件的根基是C语言和UNIX这个体系的, 此类二进制文件中也包含了对应于C/C++语言的main()
函数的入口.
从宏观上理解, 整个make install
命令做的就是通过Makefile
规定好的编译规则, 将Caffe的C++源码编译成系统中各种可使用的各种二进制(可执行)文件及相应的动态/静态库(在相应的目录中).
编译期间遇到的各种Warning
和Error
, 则是C/C++编译器的一种"规则违反提示", 如缺源码文件/缺引用库/变量未定义(引用版本不对)/删除权限不足(系统环境问题), 这些"异常", 在C/C++编译器的设计时就设定好了.
[1] Install Caffe and MatCaffe CPU-Only on MacOS 10.14.3: link (Accessed on 2019-10-05).
[2] 在Mac OS Mojave(10.14)上安装 caffe: link (Accessed on: 2019-10-06).
[3] Caffe官方: link (Accessed on: 2019-10-03).