Theano学习笔记(六)——载入与保存、条件

来源:互联网 发布:淘宝电子商务运营 编辑:程序博客网 时间:2024/05/29 07:58

载入与保存

Python标准的保存类别实体并重新载入它们的途径是pickle机制。许多Theano对象可以由此被序列化(或者反序列化),然而pickle的局限性在于,被序列化的类别实例的代码或者数据并没有被同时保存。因此重新载入先前版本的类可能会出问题。

因此,需要寻求基于预期保存和重新载入的耗时的不同机制。

对于短期(比如临时文件和网络转录),Theano的pickle是可行的。

对于长期(比如从实验中保存模型)不应当依赖于Theano的pickle对象。

推荐在任何其他Python项目的过程中的保存和载入底层共享对象。

 

Pickle基础

pickle和cPickle模块功能相似,但是cPickle用C编码,要更快一些

可以用cPickle.dump把对象序列化(或者保存或者pickle)为一个文件。

 

importcPicklef= file('obj.save', 'wb')cPickle.dump(my_obj,f, protocol=cPickle.HIGHEST_PROTOCOL)f.close()


使用了cPickle.HIGHEST_PROTOCOL,使得保存对象的过程大大加快。

使用了’b’二进制模式,是为了在Unix和Windows系统之间保持可移植性。

 

使用cPickle.load把文件反序列化(或载入,或unpickle)

f= file('obj.save', 'rb')loaded_obj= cPickle.load(f)f.close()


可以同时pickle多个对象到同一个文件:

f= file('objects.save', 'wb')forobj in [obj1, obj2, obj3]:    cPickle.dump(obj, f,protocol=cPickle.HIGHEST_PROTOCOL)f.close()


也可以按照同样的顺序载入:

f= file('objects.save', 'rb')loaded_objects= []fori in range(3):    loaded_objects.append(cPickle.load(f))f.close()


短期序列化

如果有信心,pickle整个模型是个好办法。

这种情况是指,你在项目中执行同样的保存和重载操作,或者这个类已经稳定运行很久了。

通过定义__getstate__ method和__setstate__可以控制从项目中保存何种pickle。

如果模型类包含了正在使用数据集的链接,而又不想pickle每个模型实例,上述控制方法会很实用。

def__getstate__(self):    state = dict(self.__dict__)    del state['training_set']    return state def__setstate__(self, d):    self.__dict__.update(d)self.training_set =cPickle.load(file(self.training_set_file, 'rb'))


长期序列化

如果想要保存的类运行不稳定,例如有函数创建或者删除、类成员重命名,应该只保存或载入类的不可变部分。

依然是使用定义__getstate__ method和__setstate__

例如只想要保存权重矩阵W和偏倚项b:

def__getstate__(self):    return (self.W, self.b) def__setstate__(self, state):    W, b = state    self.W = Wself.b = b

 

如果更新了下列函数来表现变量名称的改变,那么即使W和b被重命名为weights和bias,之前的pickle文件依然是可用的:

def__getstate__(self):    return (self.weights, self.bias) def__setstate__(self, state):    W, b = state    self.weights = Wself.bias = b

 

条件

-IfElse与Switch

-switch比ifelse更通用,因为switch是逐位操作。

-switch把2个输出变量都计算了,所以比ifelse要慢(只算1个)。

 

from theano import tensor as Tfrom theano.ifelse import ifelseimporttheano, time, numpy a,b= T.scalars('a', 'b')x,y= T.matrices('x', 'y') z_switch= T.switch(T.lt(a, b), T.mean(x), T.mean(y))z_lazy= ifelse(T.lt(a, b), T.mean(x), T.mean(y)) f_switch= theano.function([a, b, x, y], z_switch,                   mode=theano.Mode(linker='vm'))f_lazyifelse= theano.function([a, b, x, y], z_lazy,                   mode=theano.Mode(linker='vm')) val1= 0.val2= 1.big_mat1= numpy.ones((10000, 1000))big_mat2= numpy.ones((10000, 1000)) n_times= 10 tic= time.clock()fori in xrange(n_times):    f_switch(val1, val2, big_mat1, big_mat2)print'time spent evaluating both values %f sec' % (time.clock() - tic) tic= time.clock()fori in xrange(n_times):    f_lazyifelse(val1, val2, big_mat1,big_mat2)print'time spent evaluating one value %f sec' % (time.clock() - tic)


测试结果

time spent evaluating both values 0.200000 sectime spent evaluating one value 0.110000 sec

可见ifelse确实快了1倍,但是必须使用vm或者cvm作为Linker,而未来cvm会作为默认Linker出现。



0 0
原创粉丝点击