tensorflow2.0(4)-前向传播计算

  在网络的前向计算中,我们都可以用y = x*w + b 的形式去描述,此文介绍如何用tensorflow2.0计算网络中的前向计算和参数更新

前向计算

tf.constant() and tf.Variable()

  tf2中有两种创建张量的方式,分别为tf.constant()tf.Variable()

tf.constant(): 是创建一个常量数值/列表tensor,当然创建后值是不可变的,一般定义网络中不需要更新的参数。
tf.Variable(): 类型在普通的张量类型基础上添加了 nametrainable 等属性来支持计算图的构建,对于需要计算梯度并优化的张量,要通过此函数封装

简单的试验即可窥探两者的关系

x = tf.constant(1.)
<tf.Tensor: id=5732, shape=(), dtype=float32, numpy=1.0>

y = tf.Varible(1.)
<tf.Variable 'Variable:0' shape=() dtype=float32, numpy=1.0>
print(y.name, y.trainable)
Variable:0 True

在tf.Variable中,trainable参数默认是True,这里我们便可以根据情况手动设置True/False
constant也可以转换到Variable

x = tf.constant(1.)
<tf.Tensor: id=5732, shape=(), dtype=float32, numpy=1.0>

y = tf.Variable(x)
<tf.Variable 'Variable:0' shape=() dtype=float32, numpy=1.0>

对于wb,用tf.Variable定义,数据依然使用fashion_mnist

# 数据准备
x, y = keras.datasets.fashion_mnist.load_data()[0]  
x = tf.reshape(x, [-1, 28 * 28])   # 转换格式
x = tf.cast(x, tf.float32)
x = x / 255.
y = tf.one_hot(y, depth=10)  # 转换成独热编码

# 参数定义
w1 = tf.Variable(tf.random.truncated_normal([784, 128], stddev=0.1))
b1 = tf.Variable(tf.zeros([128]))

w2 = tf.Variable(tf.random.truncated_normal([128, 10], stddev=0.1))
b2 = tf.Variable(tf.zeros([10]))

tf.GradientTape()

  在使用 TensorFlow2自动求导功能计算梯度时,需要将前向计算过程放置在 tf.GradientTape()环境中,从而利用 GradientTape 对象的 gradient()方法自动求解参数的梯 度,并利用 optimizers 对象更新参数,形式如下

with tf.GradientTape() as tape:
    h1 = x@w1 + b1
    h1 = tf.nn.relu(h1)
    
    out = h1@w2 +b2
    
    loss = tf.square(y - out)
    loss = tf.reduce_mean(loss)

grads = tape.gradient(loss, [w1, b1, w2, b2])
print(grads)

[<tf.Tensor: id=5731, shape=(784, 128), dtype=float32, numpy=
 array([[-1.6100607e-03,  6.9914912e-03,  5.4573239e-04, ...,
          1.1394346e-02,  6.7010368e-03, -4.5570749e-04],
        [-4.6598859e-02,  8.9481764e-02,  1.0636392e-02, ...,
          8.8637583e-02,  6.8306737e-02,  3.1169101e-03],
        [-2.4604234e-01,  3.0288315e-01,  1.2252450e-02, ...,
          5.1393658e-01,  2.8754672e-01, -1.1293454e-02],
        ...,
        [-1.7132786e+01,  2.6959139e+01,  1.4552463e+00, ...,
          3.1937271e+01,  3.0912199e+01, -6.0341411e+00],
        [-5.6701980e+00,  7.6560483e+00,  5.6733060e-01, ...,
          8.5440788e+00,  9.5710907e+00, -1.1315466e+00],
        [-5.4063934e-01,  6.1388338e-01,  9.2204645e-02, ...,
          6.7820299e-01,  8.7314850e-01, -1.0959221e-01]], dtype=float32)>,
 <tf.Tensor: id=5730, shape=(128,), dtype=float32, numpy=
 array([-7.42730665e+00,  1.12210531e+01,  1.39284635e+00,  1.01494350e+01,
        -8.07421327e-01,  1.23828259e+01, -6.74541807e+00,  4.68487740e+00,
         2.48209095e+00,  6.72132134e-01,  1.45874703e+00,  3.87370616e-01,
         4.15165663e+00, -2.76716614e+00, -1.40455708e-01,  2.00560951e+00,
         2.68204361e-01, -9.28761959e+00, -8.48146820e+00,  4.43407488e+00,
         2.67940640e+00,  1.73321190e+01, -9.16018337e-02, -5.43434918e-01,
         2.07012024e+01,  2.75893402e+00,  1.56505895e+00,  2.19261336e+00,
         1.77217662e+00, -6.82915926e+00,  1.27866373e+01, -3.91614413e+00,
        -6.03287840e+00, -7.77332306e-01,  7.70938247e-02,  2.78442907e+00,
        -4.03842735e+00,  1.42863894e+00,  6.28497660e-01, -2.08575636e-01,
         1.29537325e+01,  1.57910907e+00,  6.15310764e+00, -1.28530553e-02,
        -5.76123714e-01,  8.60795438e-01,  1.76193161e+01,  7.69186687e+00,
         1.05096633e-02,  5.15164211e-02, -2.48046803e+00,  1.32270586e+00,
        -2.25072289e+00,  5.69219828e+00, -1.38959253e+00,  1.62736397e+01,
        -8.12963390e+00,  2.23423982e+00,  7.58430099e+00,  2.93936163e-01,
         4.16086674e+00,  9.06507683e+00,  7.49802440e-02,  9.94850695e-01,
        -5.30858874e-01,  2.83726931e+00,  6.86642528e-01,  1.60034144e+00,
         1.67230380e+00,  1.03161788e+00,  1.59616947e+01,  1.31335080e+00,
         4.84881115e+00,  6.14683032e-01, -8.90313816e+00, -2.12549075e-01,
        -2.11784393e-01, -1.48440564e+00,  4.82855380e-01, -9.86536026e-01,
        -3.39097095e+00, -6.08709872e-01,  6.58010149e+00, -1.88684082e+00,
        -1.24421378e-03,  1.05124637e-01,  5.68092060e+00, -5.80791092e+00,
         1.15198154e+01,  5.63493919e+00,  5.89573622e-01,  6.79265213e+00,
         6.17962408e+00, -8.74048519e+00,  5.99117374e+00,  1.38388929e+01,
        -3.47207069e-01,  4.13742256e+00,  9.31134319e+00,  7.82230973e-01,
         1.00510216e+01,  6.51883888e+00,  4.51659933e-02,  2.16893425e+01,
         1.84543401e-01, -3.50218683e-01,  9.49227095e-01,  4.19830494e-02,
        -8.80231977e-01,  1.04302864e+01,  1.07236528e+01, -3.01085401e+00,
         1.77256107e+00, -1.66283143e+00, -8.47181702e+00, -2.34353259e-01,
         1.53497944e+01,  7.91017103e+00,  1.79229784e+00,  5.81019521e-01,
         3.54849339e-01,  1.95794022e+00,  1.26474485e+01, -3.29144746e-01,
         1.15832796e+01,  1.18883247e+01,  8.93653870e+00, -8.44317555e-01],
       dtype=float32)>,
 <tf.Tensor: id=5721, shape=(128, 10), dtype=float32, numpy=
 array([[ 3.1336699e+03,  1.8366328e+03, -2.4875808e+03, ...,
         -4.4612781e+02, -2.6972102e+03,  4.0494846e+03],
        [ 1.2611420e+04,  9.4572920e+03, -8.0339561e+03, ...,
         -3.4947998e+02, -9.3134062e+03,  1.3998470e+04],
        [ 3.3486831e+03,  2.8550195e+03, -2.3804250e+03, ...,
         -3.6743832e+02, -3.3628354e+03,  4.0677268e+03],
        ...,
        [ 7.8448711e+03,  5.0678994e+03, -4.8276855e+03, ...,
         -1.4275117e+03, -7.3473486e+03,  1.0647826e+04],
        [ 1.6595094e+04,  1.1535066e+04, -1.0277844e+04, ...,
         -1.7369330e+03, -1.4152996e+04,  1.9956799e+04],
        [ 1.9223188e+03,  1.3224614e+03, -1.4478511e+03, ...,
         -5.4362202e+00, -1.2794425e+03,  2.1074729e+03]], dtype=float32)>,
 <tf.Tensor: id=5719, shape=(10,), dtype=float32, numpy=
 array([ 52.70592  ,  34.86287  , -35.887447 ,   2.6505039,  39.521217 ,
        -13.3063545,  46.65375  ,  -2.53192  , -39.36912  ,  62.809788 ],
       dtype=float32)>]

grads为一个列表, 分别记录了w1,b1,w2,b2的梯度

更新参数

熟悉深度学习里面,参数的更新形式如下:{w}' = w - lr*\frac{\vartheta l}{\vartheta w}
用assign_sub更新参数

w1.assign_sub(lr * grads[0]) 
b1.assign_sub(lr * grads[1]) 
w2.assign_sub(lr * grads[2]) 
b2.assign_sub(lr * grads[3])

当我们不断的循环更新参数,理论上loss的值是不断减少的

for i in range(50):
    with tf.GradientTape() as tape:
        h1 = x@w1 + b1
        h1 = tf.nn.relu(h1)

        out = h1@w2 +b2

        loss = tf.square(y - out)
        loss = tf.reduce_mean(loss)

    grads = tape.gradient(loss, [w1, b1, w2, b2])
    lr = 0.01
    w1.assign_sub(lr * grads[0]) 
    b1.assign_sub(lr * grads[1]) 
    w2.assign_sub(lr * grads[2]) 
    b2.assign_sub(lr * grads[3])
    print(loss.numpy())

loss:
0.41989234
0.35508955
0.31600225
0.29151577
0.27551207
0.26453122
0.25657973
0.25048772
0.24556401
0.24139453
0.23772821
0.2344122
0.2313513
0.22848529
0.22577567
0.2231966
0.22073068
...

实验证明也如此
当网络参数多的时候,不肯能再用assign_sub一个个地计算,这时候就要用到optimizer

optimizer = keras.optimizers.SGD()
for i in range(50):
    with tf.GradientTape() as tape:
        h1 = x@w1 + b1
        h1 = tf.nn.relu(h1)

        out = h1@w2 +b2

        loss = tf.square(y - out)
        loss = tf.reduce_mean(loss)

    grads = tape.gradient(loss, [w1, b1, w2, b2])
    optimizer.apply_gradients(zip(grads, [w1, b1, w2, b2]))

end

  此文写的东西比较简单基础,但也是非常重要的部分,操作再骚也离不开如此,熟练理解将很好帮助模型代码的构建

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 201,681评论 5 474
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,710评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 148,623评论 0 334
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,202评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,232评论 5 363
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,368评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,795评论 3 393
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,461评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,647评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,476评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,525评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,226评论 3 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,785评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,857评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,090评论 1 258
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,647评论 2 348
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,215评论 2 341

推荐阅读更多精彩内容

  • 这篇文章是针对有tensorflow基础但是记不住复杂变量函数的读者,文章列举了从输入变量到前向传播,反向优化,数...
    horsetif阅读 1,155评论 0 1
  • 原文链接:https://yq.aliyun.com/articles/178374 0. 简介 在过去,我写的主...
    dopami阅读 5,631评论 1 3
  • 第1章 未曾料到的命运 漫步在公园石子路,风带来的阵阵清香。嫩绿的枝桠,随性绽放的繁花,路边牵狗的老奶奶,弹弹珠...
    扔了一个香蕉皮阅读 533评论 0 0
  • 我辈皆是读书之人,立德,修身是非常重要的事情。 读完这本书,我想我明白了以下几点: 货币基金:比如余额宝,比银行定...
    秤心阅读 595评论 0 1
  • Vue函数使用的是ES5的语法而不是 Class,因为定义Vue之后,还会往Vue的原型上挂载一些方法,那么这些方...
    斜陽阅读 140评论 0 0