唉。好不容易折腾完毕caffe,突然发现caffe比较适合搭建卷积神经网络,而对于DBN和LSTM的搭建好像比较麻烦,相关教程没有找到,手头上又有一个theano的代码想调试看看,所以入坑了。
准备工具:
VS2013:链接:http://pan.baidu.com/s/1coNs7c 密码:r2s4
Anaconda2-4.0.0:链接:http://pan.baidu.com/s/1o7Nu4Qm 密码:qiil
关于anaconda可以到官网下载:https://www.continuum.io/downloads#_windows
【注】本教程只是瞎折腾最新版的theano 0.9,目前网上的教程基本都是theano 0.82版本的配置方法好像
第一步
安装anaconda
【PS】尽量使用3.5版本一下的,因为我注意要PTVS竟然不支持python3.5,如果你使用pycharm的话,可以自己尝试一下python3.x的配置
双击安装
第二步
win+r输入cmd命令,打开命令窗口,输入
pip install theano
可能你们运行的和我不一样,因为我已经安装过了,如果为安装过的话,这个界面会弹出一堆横条条附带百分号,显示安装了多少
下面那个python -m pip install --upgrade pip 是更新命令,敲上去再说。。。。。。。
归结起来步骤就是:下载anaconda->安装之->cmd安装theano->pip命令的更新(这个随便)
第三步
配置一下python的环境变量,这个anaconda安装完毕以后好像会有python.exe,只需要把这个环境变量加进去就行啦(记得与后面的环境变量用英文分号隔开)
测试一下python是否安装成功
cmd输入python就行了
但是当我们输入import theano.tensor as T的时候提示g++未检测到,这个时候使用anaconda下载一个mingw,(不要轻易自己去下载mingw安装,可能会遇到坑)
直接cmd里面输入
conda install mingw libpython
下载完毕以后添加环境变量:
path中添加:C:\Anaconda2\MinGW\bin;C:\Anaconda2\MinGW\x86_64-w64-mingw32\lib;【根据你自己的路径定哦】
新建一个PYTHONPATH:C:\Anaconda2\Lib\site-packages\theano;【同样根据自己的路径添加】
好了,测试一下怎么样:
看到这里就放心了,成功~~~
第四步
【注】使用pycharm的童鞋可以跳过此步骤,反正都是python的IDE嘛,没啥区别。
VS安装PTVS,这个可以在https://pytools.codeplex.com/这里找到,相关视频教程在https://www.youtube.com/watch?v=JNNAOypc6Ek,我记得需要下载两个东西, 这个就不解释了
傻瓜式安装就是,直接文件->新建->python,然后他会提示缺少什么,而且相关安装信息也会给你,就点它安装就行,视频教程很清楚,只看前三分钟就行,后面介绍的是PTVS的特性。
第五步
更新VS的环境变量
第六步
测试一下theano是否安装成功
在此处能找到测试代码:http://deeplearning.net/software/theano/install_windows.html#installation-of-theano-on-windows
我贴出来我的测试代码:
import numpy as np
import time
import theano
A=np.random.rand(1000,10000).astype(theano.config.floatX)
B=np.random.rand(10000,1000).astype(theano.config.floatX)
np_start=time.time()
AB=A.dot(B)
np_end=time.time()
X,Y=theano.tensor.matrices('XY')
mf=theano.function([X,Y],X.dot(Y))
t_start=time.time()
tAB=mf(A,B)
t_end=time.time()
print("NP time %f[s],theano time :%f(s)(times should be close when run on CPU!)"%(np_end-np_start,t_end-t_start))
print("Result difference:%f "%(np.abs(AB-tAB).max(), ))
我的测试结果
第七步
【废话】网上有很多theano 0.8.2的配置方法,虽然可以运行出结果,但是我跑代码的时候就是出错,无奈啊,瞎折腾了许久,最后瞎配了,也不知道成功了没,但是运行我目前的代码是达到了CPU一样的效果,之前按照网上配置的theano 0.8.2,虽然测试没问题,也能算东西,但是就是结果明显不对,尴尬,说了堆废话。
前提条件:安装CUDA8.0+CUDNN5.1的方法看我前面caffe的gpu安装方法就行啦,最好是找个方法自己测试一下你的cuda和cudnn是否正确安装,因为我的GPU版caffe能跑起来,说明环境一起准备妥当,如果后续出现问题,肯定可以排除CUDA和cudnn安装错误这个选项。
因为前面使用pip安装过CPU版本的theano,我也不知道这个会不会影响conda安装同样的东西,不过保险起见,卸载之,win10管理员powershell,运行
pip uninstall theano
接下来的方法很简单:
首先,其实也就是比网上theano 0.8.2的配置方法多出来的一步骤
conda install theano pygpu
然后找到依据cmd运行所提示的home目录,一般都是类似于C:\Users\Administrator这个文件夹(慢慢找,学计算机的基本都知道这个文件夹,非计算机的没找到建议寻求计算机专业学生帮助)。在此文件夹下添加空白的.theanorc.txt文档,然后添加以下内容:
[global]
openmp = False
device = gpu
floatX = float32
allow_input_downcast=True[blas]
ldflags =[gcc]
cxxflags = -IC:\ProgramData\Anaconda2\MinGW\x86_64-w64-mingw32\include[nvcc]
flags = -LC:\ProgramData\Anaconda2\libs
compiler_bindir = C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\bin
fastmath = True[cuda]
root=C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v8.0[dnn]
include_path=C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v8.0\include
library_path=C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v8.0\lib\x64[lib]
cnmem=0.8
路径自己对着改改。
第八步
为了保险,进行了两次测试。
使用cmd中的python命令行测试如下代码:
新建一个test.py
from theano import function, config, shared, sandbox
import theano.tensor as T
import numpy
import timevlen = 10 * 30 * 768 # 10 x #cores x # threads per core
iters = 1000rng = numpy.random.RandomState(22)
x = shared(numpy.asarray(rng.rand(vlen), config.floatX))
f = function([], T.exp(x))
print (f.maker.fgraph.toposort())
t0 = time.time()
for i in range(iters):r = f()
t1 = time.time()
print ('Looping %d times took' % iters, t1 - t0, 'seconds')
print ('Result is', r)
if numpy.any([isinstance(x.op, T.Elemwise) for x in f.maker.fgraph.toposort()]):print ('Used the cpu')
else:print ('Used the gpu')
运行结果:
PS E:\code_test\theano> python .\test.py
WARNING (theano.sandbox.cuda): The cuda backend is deprecated and will be removed in the next release (v0.10). Please switch to the gpuarray backend. You can get more information about how to switch at this URL:https://github.com/Theano/Theano/wiki/Converting-to-the-new-gpu-back-end%28gpuarray%29Using gpu device 0: GeForce GTX 1060 6GB (CNMeM is disabled, cuDNN 5005)
[GpuElemwise{exp,no_inplace}(<CudaNdarrayType(float32, vector)>), HostFromGpu(GpuElemwise{exp,no_inplace}.0)]
('Looping 1000 times took', 0.32000017166137695, 'seconds')
('Result is', array([ 1.23178029, 1.61879349, 1.52278066, ..., 2.20771813,2.29967761, 1.62323296], dtype=float32))
Used the gpu
---------------------可爱的分割线----------------------------------
使用jupyter notebook测试另一个关于图像的代码:
import theano
import numpy
import pylab
from theano import tensor as T
from theano.tensor.nnet import conv
from PIL import Image # 生成一个随机数生成类rng,其seed为23455(随机数种子)。
rng = numpy.random.RandomState(23455) # 实例化一个4D的输入tensor,是一个象征性的输入,相当于形参,需要调用时传入一个实参
input = T.tensor4(name='input') # 权值数组的shape(可以理解为权值的数组大小),用来确定需要产生的随机数个数,
#(该大小可以理解为是一个 2行3列 的矩阵,其中每个矩阵元素又是一个 9行9列的 矩阵)
w_shp = (2, 3, 9, 9) # 每个权值的边界,用来确定需要产生的每个随机数的范围。
w_bound = numpy.sqrt(3 * 9 * 9) # rng.uniform(low,hign,size)的作用是产生一个shape为size的均匀分布数组,每个数的范围为(low,high)
# numpy.asarray(a)的作用是将 类数组a 转化为array类型
# theano.shared()实例化一个权值变量(只是为了进行GPU加速时用),可以调用W.get_value()查看其value
W = theano.shared( numpy.asarray( rng.uniform( low=-1.0 / w_bound, high=1.0 / w_bound, size=w_shp), dtype=input.dtype), name ='W') # 下面是用同样的方法初始化一个偏置值b,b通常被初始化为0,因为它在算法中会有一个被学习的过程;
# 但是此处是需要直接用它来计算,所以用随机值给它初始化,就当做是已经经过学习后的值了。
b_shp = (2,)
b = theano.shared(numpy.asarray( rng.uniform(low=-.5, high=.5, size=b_shp), dtype=input.dtype), name ='b') # conv.conv2d(input,filter) 需要2个输入,一个是input,一个是filter。
# input就是上文中的4D张量,每个张量分别代表[mini-batch size,特征图的数量,图像高度,图像宽度]。
# filter就是上文中的W。也是一个4D张量,分别代表[m层特征图数量,m-1层特征图数量,过滤器高度,过滤器宽度]。
#
# 当其他函数需要用到变量conv_out时,会先把实参input传入conv2d()中,再计算出conv_out
#
conv_out = conv.conv2d(input, W) # dimshuffle是一个很强大的能轻松改变一个张量结构的工具。b.dimshuffle('x', 0, 'x', 'x')
# 就是把b的原始的第0列向量的左侧添加一个维度,在其右侧添加两个维度。
# b原来是个一维数据(2),经过dimshuffle之后,则变成了一个四维数据(1*2*1*1)。
# dimshuffle具体的操作,参见文章一开始。
output = T.nnet.sigmoid(conv_out + b.dimshuffle('x', 0, 'x', 'x')) # 创建一个用来过滤图像的theano.function(可以把f编译为c,然后就可以随时拿来用了。)
#
# 当其他函数需要调用f时(调用形式为f(input)),需要传入实参input,然后将计算结果存入output中。
#
f = theano.function([input], output) # 下面开始处理几幅图片来看一下效果
# 打开一幅图片,源代码中有2个"open",应该是在linux中的语法,我是在windows上运行的,所以改成1个open
img = Image.open('F:\\Photo\\1.jpg')# 得到图片的宽度和高度(注意,顺序一定不要弄反)
img_w, img_h = img.size # 将图片像素按照(高度,宽度,通道数量)格式化为array数组
# 其实就是将图片数据格式化为一个数组,因为每个像素点包括3个字节,B,G,R,且其范围为0-255,
# 这个地方最后将其除以256是为了归一化,归一化后的数据是float64类型
img = numpy.asarray(img, dtype='float32') / 256. # 图片的原始数据是一个3D数据【高,宽,通道数量】,
# 经过数据置换(transpose(2,0,1))之后,变成了【通道数量,高,宽】,
# 因为f中传入参数需要4D,因此需要将图片数据reshape成为一个【1, 通道数量, 高, 宽】这样的4D张量,
# reshape的参数一定要注意,1就是最外的那一维度,3就是通道数量,然后是【高】和【宽】,
# 这样结果的 img_.shape =【1, 3, 宽, 高】
#
# 为什么reshape为这样的size呢?因为调用f时需要传入一个input,而这个input就是4D,最终的这个input是传入到
# conv2d中的第一个参数,而那个参数的格式是什么呢?[mini-batch size,特征图的数量,图像高度,图像宽度]
# 这样就串起来了吧,第一个参数是batch size,据我所知应该是指卷积核的数量吧,但是不知道为什么这里是1?
# 第二个参数代表输入层的特征图数量,这个地方是3,其实就是把一张彩色图片按照3个通道作为3个特征图进行输入;
# 最后两个是图像的高度和宽度,正好一一对应。
#
img_ = img.transpose(2, 0, 1).reshape(1, 3, img_h, img_w) # 将img_作为f的参数,经过计算得到输出
filtered_img = f(img_) # 将原始图片显示出来
pylab.subplot(1, 3, 1); pylab.axis('off'); pylab.imshow(img)
# 图片灰度化
pylab.gray(); # 分别显示不同处理后的图片
pylab.subplot(1, 3, 2); pylab.axis('off'); pylab.imshow(filtered_img[0, 0, :, :])
pylab.subplot(1, 3, 3); pylab.axis('off'); pylab.imshow(filtered_img[0, 1, :, :])
pylab.show()
结果
【注】第二个测试代码一定要测试,因为我当时配置theano 0.8.2的GPU模式以后,死活运行不了这第二个代码,第一个代码的结果倒是和网上说的一模一样。