TensorFlow2_200729系列---8、前向传播(张量)实战

TensorFlow2_200729系列---8、前向传播(张量)实战

一、总结

一句话总结:

A、就是手动(模拟原理)实现多层多节点的神经网络计算,784(输入)->256->128->10(输出)
B、多节点的神经网络,用矩阵计算很方便,比代数计算方便多了
for epoch in range(10): # iterate db for 10
    for step, (x, y) in enumerate(train_db): # for every batch
        # x:[128, 28, 28]
        # y: [128]

        # 维度变换,-1自动计算
        # [b, 28, 28] => [b, 28*28]
        x = tf.reshape(x, [-1, 28*28])

        # 自动梯度计算
        with tf.GradientTape() as tape: # tf.Variable
            # x: [b, 28*28]
            # h1 = x@w1 + b1
            # [b, 784]@[784, 256] + [256] => [b, 256] + [256] => [b, 256] + [b, 256]
            # 这里矩阵运算真方便,如果是代数,就要多写几层循环,太麻烦
            h1 = x@w1 + tf.broadcast_to(b1, [x.shape[0], 256])
            h1 = tf.nn.relu(h1)
            # [b, 256] => [b, 128]
            h2 = h1@w2 + b2
            h2 = tf.nn.relu(h2)
            # [b, 128] => [b, 10]
            out = h2@w3 + b3

            # compute loss
            # 转换成one_hot编码
            # out: [b, 10]
            # y: [b] => [b, 10]
            y_onehot = tf.one_hot(y, depth=10)

            # mse = mean(sum(y-out)^2)
            # [b, 10]
            loss = tf.square(y_onehot - out)
            # mean: scalar
            loss = tf.reduce_mean(loss)

        # compute gradients
        grads = tape.gradient(loss, [w1, b1, w2, b2, w3, b3])
        # print(grads)
        # w1 = w1 - lr * w1_grad
        # 数据原地更新,只是值改变,类型不变
        w1.assign_sub(lr * grads[0])
        b1.assign_sub(lr * grads[1])
        w2.assign_sub(lr * grads[2])
        b2.assign_sub(lr * grads[3])
        w3.assign_sub(lr * grads[4])
        b3.assign_sub(lr * grads[5])


        if step % 100 == 0:
            print(epoch, step, 'loss:', float(loss))

1、手写数字识别的时候,[784]->[512]->[128]->[10]不断降维,表示的神经网络是怎样的?

输入是图片,也就是相当于784节点,然后是512节点,所以参数w的话,是[784, 256]个,也就是784*256个

2、tf.random.truncated_normal()?

截断正态分布:sigmoid激活函数,用截断的正态分布更好,因为这样就不会有两侧的梯度消失的情况

3、神经网络参数初始化实例(第一层的784*256个w,以及256个b)?

A、w1 = tf.Variable(tf.random.truncated_normal([784, 256], stddev=0.1))
B、b1 = tf.Variable(tf.zeros([256]))

4、初始化数据的时候,为什么转换成tf.Variable,比如 w1 = tf.Variable(tf.random.truncated_normal([784, 256], stddev=0.1))?

tf.Variable类型的数据才能自动跟踪梯度

5、第一层神经网络的计算(y=relu(w@x+b))?

h1 = x@w1 + tf.broadcast_to(b1, [x.shape[0], 256])
h1 = tf.nn.relu(h1)

6、tensorflow转成one_hot编码的代码?

y_onehot = tf.one_hot(y, depth=10)

7、w1 = w1 - lr * w1_grad 过程代码?

w1.assign_sub(lr * grads[0]) # 数据原地更新,只是值改变,类型不变

二、前向传播(张量)实战

博客对应课程的视频位置:

import  tensorflow as tf
from    tensorflow import keras
from    tensorflow.keras import datasets
import  os

os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'

# x: [60k, 28, 28],
# y: [60k]
(x, y), _ = datasets.mnist.load_data()

# 图像数据归一化
# x: [0~255] => [0~1.]
x = tf.convert_to_tensor(x, dtype=tf.float32) / 255.
y = tf.convert_to_tensor(y, dtype=tf.int32)

print(x.shape, y.shape, x.dtype, y.dtype)
print("----------------x的最小值和最大值----------------")
print(tf.reduce_min(x), tf.reduce_max(x))
print("----------------y的最小值和最大值----------------")
print(tf.reduce_min(y), tf.reduce_max(y))
(60000, 28, 28) (60000,) <dtype: 'float32'> <dtype: 'int32'>
----------------x的最小值和最大值----------------
tf.Tensor(0.0, shape=(), dtype=float32) tf.Tensor(1.0, shape=(), dtype=float32)
----------------y的最小值和最大值----------------
tf.Tensor(0, shape=(), dtype=int32) tf.Tensor(9, shape=(), dtype=int32)
In [2]:
# print(x[0])
In [3]:
# 每次取128张图片
train_db = tf.data.Dataset.from_tensor_slices((x,y)).batch(128)
train_iter = iter(train_db)
sample = next(train_iter)
print('batch:', sample[0].shape, sample[1].shape)
batch: (128, 28, 28) (128,)

初始化w和b

In [5]:
# [b, 784] => [b, 256] => [b, 128] => [b, 10]
# [dim_in, dim_out], [dim_out]
# 创建三对tensor

# tf.random.truncated_normal()
# 截断正态分布
# sigmoid激活函数,用截断的正态分布更好,因为这样就不会有两侧的梯度消失的情况
# w给随机数,b给0
w1 = tf.Variable(tf.random.truncated_normal([784, 256], stddev=0.1))
# 方差为0.1
b1 = tf.Variable(tf.zeros([256]))
w2 = tf.Variable(tf.random.truncated_normal([256, 128], stddev=0.1))
b2 = tf.Variable(tf.zeros([128]))
w3 = tf.Variable(tf.random.truncated_normal([128, 10], stddev=0.1))
b3 = tf.Variable(tf.zeros([10]))
# tf.Variable类型的数据才能自动跟踪梯度
print(w1)
print(b1)

# 手写数字识别的时候,[784]->[512]->[128]->[10]不断降维,表示的神经网络是怎样的
# 输入是图片,也就是相当于784节点,然后是512节点,
# 所以参数w的话,是[784, 256]个,也就是784*256个

# 这里这个例子是模拟神经节点个数比较多的例子,也就是原理
<tf.Variable 'Variable:0' shape=(784, 256) dtype=float32, numpy=
array([[-0.01459773,  0.04212301, -0.13790604, ...,  0.08872523,
         0.0180968 , -0.05272236],
       [-0.05939614, -0.07033015,  0.11356516, ..., -0.07142108,
        -0.05276656, -0.11897977],
       [-0.13474506,  0.0867815 , -0.02494188, ...,  0.07558486,
        -0.09416623, -0.10133455],
       ...,
       [ 0.02961926,  0.00650147,  0.0724051 , ...,  0.00143908,
         0.06767387,  0.07980036],
       [-0.08844294, -0.08748388,  0.04978892, ..., -0.04194697,
        -0.19967984,  0.09004744],
       [-0.00167311, -0.00427087, -0.03273085, ..., -0.03299765,
        -0.13217148,  0.0366438 ]], dtype=float32)>
<tf.Variable 'Variable:0' shape=(256,) dtype=float32, numpy=
array([0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
       0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
       0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
       0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
       0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
       0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
       0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
       0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
       0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
       0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
       0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
       0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
       0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
       0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
       0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
       0.], dtype=float32)>
In [6]:
# 学习率
lr = 1e-3
In [7]:
for epoch in range(10): # iterate db for 10
    for step, (x, y) in enumerate(train_db): # for every batch
        # x:[128, 28, 28]
        # y: [128]

        # 维度变换,-1自动计算
        # [b, 28, 28] => [b, 28*28]
        x = tf.reshape(x, [-1, 28*28])

        # 自动梯度计算
        with tf.GradientTape() as tape: # tf.Variable
            # x: [b, 28*28]
            # h1 = x@w1 + b1
            # [b, 784]@[784, 256] + [256] => [b, 256] + [256] => [b, 256] + [b, 256]
            # 这里矩阵运算真方便,如果是代数,就要多写几层循环,太麻烦
            h1 = x@w1 + tf.broadcast_to(b1, [x.shape[0], 256])
            h1 = tf.nn.relu(h1)
            # [b, 256] => [b, 128]
            h2 = h1@w2 + b2
            h2 = tf.nn.relu(h2)
            # [b, 128] => [b, 10]
            out = h2@w3 + b3

            # compute loss
            # 转换成one_hot编码
            # out: [b, 10]
            # y: [b] => [b, 10]
            y_onehot = tf.one_hot(y, depth=10)

            # mse = mean(sum(y-out)^2)
            # [b, 10]
            loss = tf.square(y_onehot - out)
            # mean: scalar
            loss = tf.reduce_mean(loss)

        # compute gradients
        grads = tape.gradient(loss, [w1, b1, w2, b2, w3, b3])
        # print(grads)
        # w1 = w1 - lr * w1_grad
        # 数据原地更新,只是值改变,类型不变
        w1.assign_sub(lr * grads[0])
        b1.assign_sub(lr * grads[1])
        w2.assign_sub(lr * grads[2])
        b2.assign_sub(lr * grads[3])
        w3.assign_sub(lr * grads[4])
        b3.assign_sub(lr * grads[5])


        if step % 100 == 0:
            print(epoch, step, 'loss:', float(loss))
0 0 loss: 0.44212737679481506
0 100 loss: 0.19576606154441833
0 200 loss: 0.1763547956943512
0 300 loss: 0.14690229296684265
0 400 loss: 0.16461005806922913
1 0 loss: 0.1481630802154541
1 100 loss: 0.13947637379169464
1 200 loss: 0.14118121564388275
1 300 loss: 0.125637024641037
1 400 loss: 0.1387656033039093
2 0 loss: 0.1261889487504959
2 100 loss: 0.12272664159536362
2 200 loss: 0.12352275848388672
2 300 loss: 0.11308278143405914
2 400 loss: 0.123313769698143
3 0 loss: 0.11250965297222137
3 100 loss: 0.11181002855300903
3 200 loss: 0.11165700107812881
3 300 loss: 0.10446763038635254
3 400 loss: 0.1128990426659584
4 0 loss: 0.10315148532390594
4 100 loss: 0.10395848751068115
4 200 loss: 0.10311208665370941
4 300 loss: 0.09810370206832886
4 400 loss: 0.10533001273870468
5 0 loss: 0.09622949361801147
5 100 loss: 0.09795238822698593
5 200 loss: 0.09663848578929901
5 300 loss: 0.09307707101106644
5 400 loss: 0.09949030727148056
6 0 loss: 0.09085840731859207
6 100 loss: 0.0931745320558548
6 200 loss: 0.09150215238332748
6 300 loss: 0.08896996080875397
6 400 loss: 0.09488751739263535
7 0 loss: 0.08653409779071808
7 100 loss: 0.08927203714847565
7 200 loss: 0.08729908615350723
7 300 loss: 0.08555082231760025
7 400 loss: 0.09112046658992767
8 0 loss: 0.0829336866736412
8 100 loss: 0.08598417043685913
8 200 loss: 0.08376041799783707
8 300 loss: 0.0826173797249794
8 400 loss: 0.087943896651268
9 0 loss: 0.07984770834445953
9 100 loss: 0.08314327895641327
9 200 loss: 0.08072730898857117
9 300 loss: 0.08008376508951187
9 400 loss: 0.08518940210342407
In [ ]:
 
 
我的旨在学过的东西不再忘记(主要使用艾宾浩斯遗忘曲线算法及其它智能学习复习算法)的偏公益性质的完全免费的编程视频学习网站: fanrenyi.com;有各种前端、后端、算法、大数据、人工智能等课程。
博主25岁,前端后端算法大数据人工智能都有兴趣。
大家有啥都可以加博主联系方式(qq404006308,微信fan404006308)互相交流。工作、生活、心境,可以互相启迪。
聊技术,交朋友,修心境,qq404006308,微信fan404006308
26岁,真心找女朋友,非诚勿扰,微信fan404006308,qq404006308
人工智能群:939687837

作者相关推荐

原文地址:https://www.cnblogs.com/Renyi-Fan/p/13418110.html