图 graph

73 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第六天,点击查看活动详情

总结:此文为12月更文计划第六天第十一篇。

图graph

图是使用tensorflow提供的接口,将python的函数变为图,用来提高程序的运行速度。

自己编写代码实现relu激活函数,如果scale不为1,那就是selu

# tf.function and auto-graph.
def scaled_elu(z, scale=1.0, alpha=1.0):
    # z >= 0 ? scale * z : scale * alpha * tf.nn.elu(z)
    is_positive = tf.greater_equal(z, 0.0)
#     return scale * tf.where(is_positive, z, alpha * tf.nn.elu(z))
    return scale * tf.where(is_positive, z, alpha * (tf.math.exp(z)-1))

可以先运行一下,此可是python函数:

print(scaled_elu(tf.constant(-3.)))
print('-'*50)
print(scaled_elu(tf.constant([-3., -2.5])))
print('-'*50)

然后将python函数转化为图,可以提高运速度:

通过tf.function可以把py的函数变为图实现的函数

scaled_elu_tf = tf.function(scaled_elu)
print(scaled_elu_tf(tf.constant(-3.)))
print('-'*50)
image.png

我们来测试一下性能,100万个数

%timeit scaled_elu(tf.random.normal((1000, 1000)))
%timeit scaled_elu_tf(tf.random.normal((1000, 1000)))

输出的结果如下:

image.png

通过装饰器把函数变为图

#加了@tf.function装饰后就变为图结果,但是输入类型上不会有变化
@tf.function
def converge_to_2(n_iters):
    total = tf.constant(0.)
    increment = tf.constant(1.)
    for _ in range(n_iters):
        total += increment
        increment /= 2.0
    return total
print(converge_to_2)
print('-'*50)
print(converge_to_2(20))

加了@tf.function装饰后就变为图结果,但是输入类型上不会有变化

@tf.function
def converge_to_2(n_iters):
    total = tf.constant(0.)
    increment = tf.constant(1.)
    for _ in range(n_iters):
        total += increment
        increment /= 2.0
    return total
print(converge_to_2)
print('-'*50)
print(converge_to_2(20))

输出的结果如下:

image.png

tf要把变量定义在函数外面,不能放里边

var = tf.Variable(0.)

@tf.function
def add_21():
    return var.assign_add(21) # += 

print(add_21())

输出的结果如下:

image.png

cube计算立方,py是泛型设计,我们通过input_signature加类型限制可以防止调错

# @tf.function(input_signature=[tf.TensorSpec([None], tf.int32, name='x')])
@tf.function
def cube(z):
    return tf.pow(z, 3)

try:
    print(cube(tf.constant([1., 2., 3.])))
except ValueError as ex:
    print(ex)

print('-'*50)
#这行没问题
print(cube(tf.constant([1, 2, 3])))

输出的结果如下:

image.png