学了一个星期的Theano,写篇博客mark一下了。+-_-+
首先说下Theano是什么,Theano 是Python一个深度学习框架,主要功能有编译函数,对函数求导,这里面最nb的地方莫过于对函数求导,直接导致不用再手写各种梯度下降算法了,像什么BP,RNN,LSTM神经网络都能很easy的搞定呐。
回到实验,以前用HOG特征训练精度能到94%的酱紫,这次直接将整张图片直接输入到网络中,精度大概能到97%的样子,如果fine tune的话 到99%应该是没有问题的。
说一下网络的构成吧,一个输入层X就是图片像素构成的向量784维(图片是28*28),中间加一个隐藏层H1维度是784*1000,最后放一层输出层是1000*10,综合起来一共要训练的参数为W1(784*1000),W2(1000*10),每层之间分别加一个偏执向量b1(1000*1),b2(10*1),最终一共需要训练的参数为784*1000+1000*10+1000+10 = 786010个,训练数据一共有60000个,妥妥的没问题。数据采用的是标准的mnit的数据集。代码可能就200行的样子,刚开始写Python写得有点烂啊!!
#读取数据图片和标签
#readData.py
import numpy as np
import struct
import matplotlib.pyplot as plt
def readIm():
filename='data/train-images.idx3-ubyte'
binfile = open(filename , 'rb')
buf = binfile.read()
index = 0
magic, numImages , numRows , numColumns = struct.unpack_from('>IIII' , buf , index)
x =[]
index += struct.calcsize('>IIII')
for i in xrange(numImages):
im = struct.unpack_from('>784B' , buf, index)
index += struct.calcsize('>784B')
im=list(im)
x.append(im)
'''
#预览图片
io = im.reshape(28,28)
fig = plt.figure()
plt.imshow(io , cmap='gray')
plt.show()
'''
x=np.array(x)
return x
def read_labels():
filename = 'data/train-labels.idx1-ubyte'
binfi = open(filename , 'rb')
buf = binfi.read()
index = 0
[magic , numlabels] = struct.unpack_from('>II', buf, index)
index += struct.calcsize('>II')
y = np.array([])
while y.shape[0] < numlabels:
l = struct.unpack_from('>B', buf, index)
index += struct.calcsize('>B')
im = np.array(l)
if y.size==0:
y = im
else :
y=np.vstack((y,im))
ret = []
for i in y:
tmp = [0]*10
tmp[i]=1
ret.append(tmp)
ret = np.array(ret)
return ret
#网络构造,代码TM太简单,想想以前写的MATLAB,说多了都是泪啊!!!
#bp_net.py
import numpy as np
import theano
import theano.tensor as T
class BPnet:
def __init__(self,x_size=784,y_size=10,hide=1000):
self.INIT = 0.5
W1 = np.random.uniform(-self.INIT, self.INIT , (x_size, hide))
W2 = np.random.uniform(-self.INIT, self.INIT , (hide, y_size))
b1 = np.random.uniform(-self.INIT, self.INIT , hide)
b2 = np.random.uniform(-self.INIT, self.INIT , y_size)
self.W1 = theano.shared(name='W1', value=W1.astype(theano.config.floatX))
self.W2 = theano.shared(name='W2', value=W2.astype(theano.config.floatX))
self.b1 = theano.shared(name='b1',value=b1.astype(theano.config.floatX))
self.b2 = theano.shared(name='b2',value=b2.astype(theano.config.floatX))
self.__build_bp()
def __build_bp(self):
x = T.vector('x')
y = T.vector('y')
h1 = T.nnet.sigmoid(T.dot(x,self.W1)+self.b1)
o = T.nnet.sigmoid(T.dot(h1,self.W2)+self.b2)
error=T.sum(-y * T.log(o) - (1.-y) * T.log(1-o))
dw1,db1,dw2,db2 = T.grad(error,self.W1),T.grad(error,self.b1),T.grad(error,self.W2),T.grad(error,self.b2)
prediction = T.argmax(o, axis=0)
self.predict = theano.function([x],prediction)
self.get_grad = theano.function(inputs=[x,y],outputs=[o,error,dw1,db1,dw2,db2,prediction])
#保存数据和加载数据
#utils.py
import numpy as np
def save(outfile,value):
np.savez(outfile, name=value)
def load(path,name):
try:
npzfile=np.load(path)
value = npzfile[name]
return value
except:
return None
#训练我网络代码,这段代码写得很烂,Theano里面有scan循环的函数,然后还没有看明白,所以就写了个loop,看着有点恶心,训练也是用的经典的最速梯度下降法+SGD(最优化没有白学!哈哈哈)
#train_net.py
import numpy as np
from datetime import datetime
import bp_net as bp
import utils
import readData as rd
x_train= utils.load('data/x.npz','name')
x_train=x_train/255.0
y_train= utils.load('data/y.npz','name')
if x_train == None :
x_train = rd.readIm()
utils.save("data/x.npz",x_train)
if y_train == None:
y_train = rd.read_labels()
utils.save("data/y.npz",y_train)
EPOCH = 100
NUM = 60000
def train_sgd(model,rate,EPOCH,NUM):
i = 0
ep = 0
while True:
while i < NUM:
dw1 = np.zeros([784,1000])
dw2 = np.zeros([1000,10])
db1 = np.zeros(1000)
db2 = np.zeros(10)
cnt = 0
error = 0
j = i
ep+=1
while j < EPOCH+i:
ans = model.get_grad(x_train[j,:],y_train[j,:])
dw1 += ans[2]
db1 += ans[3]
dw2 += ans[4]
db2 += ans[5]
if y_train[j, :][ans[6]] == 1:
cnt += 1
j += 1
error += ans[1]
dw1 /= (1.00*EPOCH)
dw2 /= (1.00*EPOCH)
db1 /= (1.00*EPOCH)
db2 /= (1.00*EPOCH)
error /= (1.0*EPOCH)
model.W1.set_value( model.W1.get_value()-dw1*rate)
model.W2.set_value( model.W2.get_value()-dw2*rate)
model.b1.set_value( model.b1.get_value()-db1*rate)
model.b2.set_value( model.b2.get_value()-db2*rate)
i += EPOCH
now = datetime.now().strftime('%Y-%m-%d-%H-%M-%S')
print("Epoch : %d .Cross error is %f .Accuracy is %f . at %s ." % (ep,error, cnt*1.00/(1.00*EPOCH),now))
i = 0
model = bp.BPnet()
time_start = datetime.now().strftime('%Y-%m-%d-%H-%M-%S')
print("start training %s ." %(time_start))
train_sgd(model,0.2,EPOCH,NUM)
最后贴一下最终的实验结果吧:
一个batch 大概20s的样子,速度还是很快的。
想想快回家了,想想还是有点小激动的!!!