import theano import theano.tensor as T from theano import function from theano import shared state = shared(200) # 使用shared定义共享变量,初始化为200 inc = T.iscalar('inc') # 定义累加器 accumulator = function([inc], state, updates=[(state, state+inc)]) # function(局部变量列表,共享变量,update参数), 其中update的形式为'(共享变量,新表达式)' accumulator(2) # 返回200, 即返回共享变量更新前的值'state=200' state.get_value() # 返回202, 即更新后的共享变量,'state+inc = 202' # 定义'累减器' decrementor = function([inc], state, updates=[(state, state-inc)]) decrementor(2) # 返回202 state.get_value() # 返回200 # theano.shared(value, name=None, strict=False, allow_downcast=None, **kwargs) # 注意:有时候需要使用共享变量和做一些表达式,但是不想改变共享变来那个的值,此时可以在函数中使用‘givens’参数 fn_of_state = state * 2 + inc foo = T.scalar(dtype=state.dtype) # foo的数据类型必须与state一样,用于取代state skip_shared = function([inc, foo], fn_of_state, givens = [(state, foo)]) skip_shared(1,3) # 返回7, inc + 2 * foo
2. AutoEncoder-Theano实现与测试
只需要更改参数,既可以使用最基本的autoencoder算法了,看考deeplearning.net网站
未优化版本如下:
import time import numpy import numpy.random as RandomState from numpy import * import theano import theano.tensor as T from theano.tensor.shared_randomstreams import RandomStreams # theano中的随机数生成器工具 from operateFile import writeDataToFile """ 其中参数input, W, bhid, bvis都是张量类型: theano.tensor.TensorType 设定随机数:numpy.random.RandomState; theano.tensor.shared_randomstreams.RandomStreams 如果最初没给权重W,则初始化为[-a, a]之间的均匀分布,numpy.random.RandomState.uniform(low, high, size) """ class AutoEncoder(object): def __init__(self, numpy_rng, input=None, n_visible=784, n_hidden=500, W=None, bhid=None, bvis=None): self.n_visible = n_visible self.n_hidden = n_hidden if not W: initial_W = numpy.asarray(numpy_rng.uniform( low = -4 * numpy.sqrt(6. / (n_hidden + n_visible)), high = 4 * numpy.sqrt(6. / (n_hidden + n_visible)), size = (n_visible, n_hidden)), dtype = 'float64' ) W = theano.shared(value = initial_W, name = 'W') # 设置为共享变量 if not bvis: bvis = theano.shared(value = numpy.zeros(n_visible, dtype = 'float64'), name='bvis') if not bhid: bhid = theano.shared(value = numpy.zeros(n_hidden, dtype = 'float64'), name='bhid') self.W = W self.b = bhid # b corresponds to the bias of the hidden (最后希望获得W和bhid) self.b_prime = bvis # b_prime 对应‘输入’层的偏置向量 self.W_prime = self.W.T # tied weights, therefore W_prime is W transpose if input == None: self.x = T.dmatrix(name = 'input') # TensorType variable: 2-dim matrix type else: self.x = input self.params = [self.W, self.b, self.b_prime] def get_hidden_values(self, input): return T.nnet.sigmoid(T.dot(input, self.W) + self.b) # 返回隐层值 def get_reconstructed_input(self, hidden): return T.nnet.sigmoid(T.dot(hidden, self.W_prime) + self.b_prime) # 将所有数据点(data point,样本),得到的损失函数是一个向量, axis=1 表示按照列计算 # 上式得到的所有样本的重构误差之和,下面计算平均重构误差,实际的损失函数 # 计算目标函数的梯度 def get_cost_updates(self, learning_rate): y = self.get_hidden_values(self.x) z = self.get_reconstructed_input(y) L = - T.sum(self.x * T.log(z) + (1- self.x) * T.log(1-z), axis = 1) cost = T.mean(L) gparams = T.grad(cost, self.params) # 张量数据类型,可以很方便的求梯度T.grad() ''' 生成参数的更新列表, 实际中,可能没必要保存所有更新参数,只要最后一组即可,可改写 return_param for param, gparam in zip(self.param, gparams): return_param = param - learning_rate * gparam del param, gparam gc.collect() ''' # generate the list of updates updates = [] for param, gparam in zip(self.params, gparams): updates.append((param, param - learning_rate * gparam)) return (cost, updates) # 返回的是(损失代价,参数更新) # 构造类AutoEncoder的实例 x = T.dmatrix('x') M = 10000 N = 2000 K = 1200 train_x = numpy.random.randn(M, N) # 构建模型 autoencoder = AutoEncoder(numpy_rng = numpy.random.RandomState(1234), input = x, n_visible=N, n_hidden=K) cost, updates = autoencoder.get_cost_updates(learning_rate = 0.1) hidden = autoencoder.get_hidden_values(x) # 输出隐层值 construction = autoencoder.get_reconstructed_input(hidden) # 训练模型 startTime = time.time() train_autoencoder = theano.function(inputs = [x], outputs = [cost, hidden, construction], updates = updates) cost_value, hidden_value, construction_value = train_autoencoder(train_x) endTime = time.time() print 'shape(autoencoder.W):%s,\ttype(autoencoder.W):%s' % (shape(autoencoder.W.get_value()), type(autoencoder.W.get_value())) print 'autoencoder.W.get_value():\n', autoencoder.W.get_value()[range(5), range(5)] print 'type(train_autoencoder):', type(train_autoencoder) print 'cost_value:', cost_value print 'type(cost_value):', type(cost_value) print 'shape(autoencoder.get_hidden_value(train_x)):', shape(hidden_value) print 'shape(autoencoder.get_hidden_value(train_x)):', shape(construction_value) writeDataToFile('E:/test_ctr/hidden.value.txt', hidden_value) writeDataToFile('E:/test_ctr/construction_value.txt', construction_value) print '程序运行时间:', (endTime - startTime)