资讯专栏INFORMATION COLUMN

Theano - 更多的例子

brianway / 3229人阅读

摘要:函数同时执行多种计算任务支持多种输出的函数。例如多次调用将会返回相同的随机数和相同。第一个元素是共享变量它表示和特定变量相关的随机数生成器的状态。第二个元素表示和随机数生成过程相对应的。

Logistic函数
import theano
import theano.tensor as T
x = T.dmatrix("x")
s = 1 / (1 + T.exp(-x))
logistic = theano.function([x], s)
logistic([[0, 1], [-1, -2]])
# s(x) = 1/(1+exp(-x)) = (1+tanh(x/2))/2
s2 = (1 + T.tanh(x / 2)) / 2
logistic2 = theano.function([x], s2)
logistic2([[0, 1], [-1, -2]])
同时执行多种计算任务

Theano支持多种输出的函数。例如,我们可以同时计算两个矩阵a,b相应元素之间的差、绝对差、平方差。当我们调用函数f是,返回三个变量:

import theano
import theano.tensor as T
a, b = T.dmatrices("a", "b")
diff = a - b
abs_diff = abs(diff)
diff_squared = diff ** 2
f = theano.function([a, b], [diff, abs_diff, diff_squared])
f([[1, 1], [1, 1]], [[0, 1], [2, 3]])
为参数设置默认值

假设我们要定义一个实现两个数字加法的函数。如果你仅仅提供一个数字,另一个数字假设(默认)为1,就可以这么做:

from theano import In, function
import theano.tensor as T
x, y = T.dscalars("x", "y")
z = x + y
f = function([x, In(y, value=1)], z)
f(33)
f(33, 2)

含有默认值的输入必须位于不含默认值的输入之后(和python的函数类似)。允许多个输入含有默认值,这些参数可以通过位置设定,也可以通过名字进行设定。

x, y, w = T.dscalars("x", "y", "w")
z = (x + y) * w
f = function([x, In(y, value=1), In(w, value=2, name="w_by_name")], z)
f(33)
f(33, 2)
f(33, 0, 1)
f(33, w_by_name=1)
f(33, w_by_name=1, y=0)

In 不知道通过参数传递的局部变量x,y的名字。符号变量对象拥有名字(name)属性(在上本例中通过dscalars进行设置),这也是我们构建函数function关键字参数的名字。通过In(y, value=1)这一机制实现。在In(w, value=2, name="w_by_name")中,我们重写了符号变量的名字属性。所有当我们通过f(x=33, y=0, w=1)的形式调用函数时,就会出错。w应该改为w_by_name.

使用共享变量

我们也可以构建一个含有内状态(internal state)的函数。例如,假设我们要构造一个累加函数(accumulator):初始状态设置为0。接着,每次调用函数,状态就会通过函数的参数自动增加。

# 首先,我们定义一个累加函数。它将自己的内状态加上它的参数,然后返回旧状态的值。
import theano
import theano.tensor as T
from theano import shared
state = shared(0)
inc = T.iscalar("inc")
accumulator = function([inc], state, updates=[(state, state+inc)])

# state的值可以通过.get_value()和.set_value()惊行获取和修改
state.get_value()
accumulator(1)
state.get_value()
accumulator(300)
state.get_value()

state.set_value(-1)
accumulator(3)
state.get_value()

# 我们可以构造多个函数,使用相同共享变量,这些函数都可以更新状态的值
decrementor = function([inc], state, updates=[(state, state-inc)])
decrementor(2)
state.get_value()

# 可能你会使用一个共享变量表达多个公式,但是你并不想使用共享变量的值。
# 这种情况下,你可以使用function中的givens参数。
fn_of_state = state * 2 + inc
foo = T.scalar(dtype=state.dtype)   # foo的类型必须和将要通过givens取代的共享变量的类型保持一致
skip_shared = function([inc, foo], fn_of_state, givens=[(state, foo)])
skip_shared(1, 3)   # 我们正在使用3作为state,并非state.value
state.get_value()   # 旧的状态(state)一直存在,但是我们使用它。
复制函数(copying functions)

Theano中的函数可以被复制,被用于构造相似的函数(拥有不同的共享变量和更新),这可以通过function中的copy()实现。让我们从以上定义的累加函数(accumulator)开始:

import theano
import theano.tensor as T
state = theano.shared(0)
inc = T.iscalar("inc")
accumulator = function([inc], state, updates=[(state, state+inc)])
# 我们可以像平常一样增加它的状态(state)
accumulator(10)
state.get_value()
# 我们可以用copy()创建一个相似的累加器(accumulator),但是可以通过swap参数拥有自己的内状态,
# swap参数是将要交换的共享参数字典
new_state = theano.shared(0)
new_accumulator = accumulator.copy(swap={state:new_state})
new_accumulator(100)
new_state.get_value()
state.get_value()

# 现在我们创建一个复制,但是使用delete_updates参数移除更新,此时,默认为False
# 此时,共享状态将不会再更新。
null_accumulator = accumulator.copy(delete_updates=True)
null_accumulator(9000)
state.get_value()
使用随机数(Using Random Numbers) 简洁的例子
from theano.tensor.shared_randomstreams import RandomStreams
from theano import function
srng = RandomStreams(seed=324)
rv_u = srng.uniform((2,2))
rv_n = srng.normal((2,2))
f = function([], rv_u)
g = function([], rv_n, no_default_updates=True) # 不更新rv_n.rng
nearly_zeros = function([], rv_u + rv_u - 2 * rv_u)

# rv_u表示服从均匀分布的2*2随机数矩阵
# rv_n表示服从正太分布的2*2随机数矩阵
# 现在我们来调用这些对象。如果调用f(),我们将会得到随机均匀分布数。
# 随机数产生器的内状态将会自动更新,所以我们每次调用f()时将会得到不同的随机数
f_val0 = f()
f_val1 = f()

# 当我们添加额外的参数no_default_updates=True(在函数g中)后,随机数产生器的状态将不会受调用函数的影响。
# 例如:多次调用g()将会返回相同的随机数,g_val0和g_val1相同。
g_val0 = g()
g_val1 = g()

# 一个重要的观点是:一个随机变量在一次调用函数期中最多只能构建一次。
# 所以nearly_zeros函数保证了输出近似为0,尽管rv_u随机变量在输出表达式中出现了3次。
nearly_zeros()
种子流(Seeding Streams)

随机变量可以多带带也可以共同产生,你可以通过对.rng属性进行seeding或者使用.rng.set_value()对.rng进行赋值产生一个随机变量。

rng_val = rv_u.rng.get_value(borrow=True)   # 获取rv_u的rng(随机数生成器)
rng_val.seed(89234)                         # 对generator(生成器)进行seeds(播种)
rv_u.rng.set_value(rng_val, borrow=True)    # 对rng进行赋值

# 你可以seed由RandomStreams对象分配的所有随机变量。
srng.seed(902340)
函数之间共享流(Sharing Streams Between Functions)

像共享变量一样,随机变量使用的随机数生成器在不同函数之间是相同的。所以我们的nearly_zeros函数将会更新f函数使用的生成器的状态。例如:

state_after_v0 = rv_u.rng.get_value().get_state()
nearly_zeros()  # 这将会影响rv_u的生成器
v1 = f()
rng = rv_u.rng.get_value(borrow=True)
rng.set_state(state_after_v0)
rv_u.rng.set_value(rng, borrow=True)
v2 = f()    # v2 != v1
v3 = f()    # v3 == v1
在Theano Graphs之间复制随机状态

在很多应用场景中,使用者可能想把一个theano graph(图:g1,内置函数:f1)中的所有随机数生成器的状态传递给第二个theano graph(图:g2,内置函数:f2)。

例如:如果你试图从之前储存模型的参数中,初始化一个模型的状态,将会出现上述需要。theano.tensor.shared_randomstreams.RandomStreams和theano.sandbox.rng_mrg.MRG_RandomStreams这些在state_updates参数的复制元素可以实现。

每一次从RandomStreams对象中生成一个随机变量,将会有一个元组添加到state_update列表中。 第一个元素是共享变量:它表示和特定变量相关的随机数生成器的状态。第二个元素表示和随机数生成过程相对应的theano graph。

下面的例子展示了:随机状态(random states)如何从一个theano function 传递给另一个theano function中的。

import theano
import numpy
import theano.tensor as T
from theano.sandbox.rng_mrg import MRG_RandomStreams
from theano.tensor.shared_randomstreams import RandomStreams


class Graph:
    def __init__(self, seed=123):
        self.rng = RandomStreams(seed)
        self.y = self.rng.uniform(size=(1,))


g1 = Graph(seed=123)
f1 = theano.function([], g1.y)

g2 = Graph(seed=987)
f2 = theano.function([], g2.y)

# 默认情况下,两个函数f1,f2不同步
f1()
f2()


def copy_random_state(g1, g2):
    if isinstance(g1.rng, MRG_RandomStreams):
        g2.rng.rstate = g1.rng.rstate
    for (su1, su2) in zip(g1.rng.state_updates, g2.rng.state_updates):
        su2[0].set_value(su1[0].get_value())


# 现在我们赋值theano随机数生成器的状态
copy_random_state(g1, g2)
f1()
f2()
一个真实的例子:逻辑回归
import numpy
import theano
import theano.tensor as T
rng = numpy.random

N = 400                         # training sample size
feats = 784                     # number of input variables

# generate a data set: D = (input_values, target_class)
D = (rng.rand(N, feats), rng.randint(size=N, low=0, high=2))
training_steps = 10000

# Declare Theano symbolic variables
x = T.dmatrix("x")
y = T.dvector("y")

# initialize the weight vector w randomly
#
# this and the following bias variable b
# are shared so they keep their values
# between training iterations (updates)
w = theano.shared(rng.randn(feats), name="w")

# initialize the bias term
b = theano.shared(0., name="b")

print("Initial model:")
print(w.get_value())
print(b.get_value())

# Construct Theano expression graph
p_1 = 1 / (1 + T.exp(-T.dot(x, w) - b))         # Probability that target = 1
prediction = p_1 > 0.5                          # The prediction thresholded
xent = -y * T.log(p_1) - (1-y) * T.log(1-p_1)   # Cross-entropy loss function
cost = xent.mean() + 0.01 * (w ** 2).sum()      # The cost to minimize
gw, gb = T.grad(cost, [w, b])                   # Compute the gradient of the cost


# Compile
train = theano.function(
    inputs=[x,y],
    outputs=[prediction, xent],
    updates=((w, w - 0.1 * gw), (b, b - 0.1 * gb))
)

predict = theano.function(inputs=[x], outputs=prediction)

# Train
for i in range(training_steps):
    pred, err = train(D[0], D[1])

print("Final model:")
print(w.get_value())
print(b.get_value())
print("target values for D:")
print(D[1])
print("prediction on D:")
print(predict(D[0]))

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/38634.html

相关文章

  • Theano - theano如何处理形状信息

    摘要:是怎么处理形状信息在构建图的时候,不可能严格执行变量的形状。形状推断问题在图中,将会传播形状的信息。以下情形是目前我们可以做到的当调用时,你可以直接把形状信息传递给。例如你可以在图的任何位置使用添加位置信息。 Theano是怎么处理形状信息(Shape Information) 在构建图的时候,不可能严格执行Theano变量的形状。因为在运行的时候,传递给Theano函数的某一参数的值...

    muddyway 评论0 收藏0
  • Yoshua Bengio等大神传授:26条深度学习经验

    摘要:另外,当损失函数接近全局最小时,概率会增加。降低训练过程中的学习率。对抗样本的训练据最近信息显示,神经网络很容易被对抗样本戏弄。使用高度正则化会有所帮助,但会影响判断不含噪声图像的准确性。 由 Yoshua Bengio、 Leon Bottou 等大神组成的讲师团奉献了 10 天精彩的讲座,剑桥大学自然语言处理与信息检索研究组副研究员 Marek Rei 参加了本次课程,在本文中,他精炼地...

    Lowky 评论0 收藏0
  • Yoshua Bengio等大神传授:26条深度学习经验

    摘要:八月初,我有幸有机会参加了蒙特利尔深度学习暑期学校的课程,由最知名的神经网络研究人员组成的为期天的讲座。另外,当损失函数接近全局最小时,概率会增加。降低训练过程中的学习率。对抗样本的训练据最近信息显示,神经网络很容易被对抗样本戏弄。 8月初的蒙特利尔深度学习暑期班,由Yoshua Bengio、 Leon Bottou等大神组成的讲师团奉献了10天精彩的讲座,剑桥大学自然语言处理与信息检索研...

    Salamander 评论0 收藏0
  • Theano - 循环

    摘要:复发的一种常用形式,可以用于循环和是的特例可以根据一些输出序列一个函数,每一步都会生成一个输出可以查看之前步的输出给定一个初始状态可以通过函数计算一个列表的和通常一个循环可以用操作符进行实现使用的优点迭代次数为符号图的一部分最大限度地减少传 Scan 复发(Recurrence)的一种常用形式,可以用于循环(looping) Reduction和map是scan的特例 可以根据一些输...

    import. 评论0 收藏0
  • PyTorch和TensorFlow到底哪个更好?看看一线开发者怎么说

    摘要:我认为对机器学习开发者来说,是一个了不起的工具集。这个帖子发出后得到了很多机器学习研究者和开发者的关注,他们纷纷跟贴谈论自己的想法和经验不只是关于和,讨论中还涉及到更多工具。 Theano、TensorFlow、Torch、MXNet 再到近日比较热门的 PyTorch 等等,深度学习框架之间的比较一直以来都是非常受人关注的热点话题。机器之心也曾发表过多篇相关的介绍和对比文章,如《主流深度学...

    coordinate35 评论0 收藏0

发表评论

0条评论

brianway

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<