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)