Tensorflow2学习--002(快速入手,向前传播神经网络搭建)

由tensorflow搭建一个简单的神经网络

既然上一篇讲了一些tensorflow的基本操作,那就直接拿来用一下吧,搭建一个简单前馈神经网络

Forward propagation

在我理解中,所谓的神经网络 无非是 累加的多层函数,通过数以千万的参数组成的一个参数矩阵,通过不断地叠加函数和参数,来达到拟合的目的。所有的神经网络 基本的流程是一样的,通过大量的数据集,来对函数的参数进行不停地迭代,达到最好的拟合效果。

本文将 使用tensorflow搭建一个简单的前馈神经网络

image

导入所需要的包

import tensorflow as tf
import cv2 as cv
from tensorflow import keras
from tensorflow.keras import datasets

导入数据集

本次实验使用 mnist 的手写数据集 来进行训练和测试
拿到一个shape为[60k,28,28]的图片集 shape为[60k]的标签集

返还两个元组 解压赋值 将元组1 解压赋值给x,y
这里的图片类型为ndarray

(x,y),_ = datasets.mnist.load_data()

将数据集转换为tensor类型

x = tf.convert_to_tensor(x,dtype=tf.float32)
y = tf.convert_to_tensor(y,dtype=tf.int32)

将数据切分成组 使用tf.data.Dataset.from_tensor_slices((x,y)).batch(n) 函数
将60k份数据分为 128份为一组

train_db = tf.data.Dataset.from_tensor_slices((x,y)).batch(128)
train_iter = iter(train_db)
# 转为迭代器 看一下返回的数据的样子
data = next(train_iter)
print(data[0].shape,data[1].shape)

image

可以看到 单份数据 现在是 (128,28,28) (128,)的shape

搭建神经网络

下面我们搭建一个简单的三层向前传播神经网络

人工神经网络的基本原理见下图:

image

解析:
第一层是一张图片的(28 * 28)个像素点所对应的灰度值
第二层是自定义层本层的个数由自己来确定;第二层点的值 由第一层来计算
下图为第二层某点的计算image
第三层同上
第四层同上
第五层为输出层,转为one-hot编码,及每个点对应的为一个结果 选取权最大的即为结果

本神经网络结构如下:
[b,784] --> [b,256] --> [b,128] --> [b,10]

由于一次性处理多张图片来进行向前传播,所以传入为[b,784]的一个矩阵。b代表一次性处理的图片数
所以由上述可知,我们需要设计w(权重矩阵)来进行计算 权重矩阵中的每一个都相当于一个参数

所以w矩阵的shape应该为下式

w [dim_in,dim_out] b[dim_out]

利用正态分布 生成初始w

w1 = tf.Variable(tf.random.truncated_normal([784,256],stddev=0.01))
b1 = tf.Variable(tf.random.truncated_normal([256]))

w2 = tf.Variable(tf.random.truncated_normal([256,128],stddev=0.01))
b2 = tf.Variable(tf.random.truncated_normal([128]))

w3 = tf.Variable(tf.random.truncated_normal([128,10],stddev=0.01))
b3 = tf.Variable(tf.random.truncated_normal([10]))

这是超参数 步长
lr = 1e-3

x 是 当前 batch 数

循环训练十次

for i in range(10):

对每个batch进行训练

for step,(x,y) in enumerate(train_db): #默认只会跟着 tf.Variable
		x = tf.reshape(x,(-1,28*28))

tf.GradientTape() 可以记录梯度值 为之后梯度下降使用
tf.nn.relu()是激活函数 就像神经必须要达到一定的值 才会有反应
在神经网络中对于每个神经元也是如此

image

with tf.GradientTape() as tape:
			h1 = x @ w1 + b1
			h1 = tf.nn.relu(h1)
			h2 = h1 @ w2 + b2
			h2 = tf.nn.relu(h2)
			out = h2 @ w3 + b3

向前传播后,得到一个误差loss 即正确结果和预测结果的偏差

# loss [b] -- > [b,10] 将标签 转为one_hot形式
			y_onehot = tf.one_hot(y,depth=10)

在这里将一个batch的误差进行中和

# loss = mean((正确结果 - 预处结果)^2 )

这里求得是每张图片的误差的平方

loss = tf.square(y_onehot - out)

这里是一个batch的误差值 即128张图片的误差均值

loss = tf.reduce_mean(loss)

求解 loss 关于 w1,b1,w2,b2,w3,b3的梯度 就是loss关于w1,...b3的偏导数
代表了 loss 在 w1 。。。 b3 方向上的最大变化率

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

利用梯度下降算法 得到新的参数(预备知识: 导数 梯度 梯度下降 方向导数 偏导数 矩阵运算)

# 相减运算后 返回的是一个tensor类型 不是一个 tf.Variable类型 所以使用原地操作
		w1.assign_sub(lr * grads[0])
		w2.assign_sub(lr * grads[2])
		w3.assign_sub(lr * grads[4])
		b1.assign_sub(lr * grads[1])
		b2.assign_sub(lr * grads[3])
		b3.assign_sub(lr * grads[5])
		if step % 100 == 0:
			print(step,'loss:',float(loss))

运行结果:image

网络应用

从数据集得到数据,并且带入网络进行求解 输出one-hot编码的结果

image

image

可以看到 效果还是挺不错的

完整代码

点击查看代码
import tensorflow as tf
import cv2 as cv
from tensorflow import keras
from tensorflow.keras import datasets

# 拿到一个[60k,28,28] [60k]的数据集   
# 返还两个元组 解压赋值  将元组1 解压赋值给x,y
(x,y),_ = datasets.mnist.load_data()
# 这里的数据集是 ndarray类型
x = tf.convert_to_tensor(x,dtype=tf.float32)
y = tf.convert_to_tensor(y,dtype=tf.int32)

train_db = tf.data.Dataset.from_tensor_slices((x,y)).batch(128)
train_iter = iter(train_db)
data = next(train_iter)
print(data[0].shape,data[1].shape)
# 迭代器 返还一个元组 0代表图片 1代表标签

# 神经网络 向前传播
# [b,784] --> [b,256] --> [b,128] --> [b,10]
# w [dim_in,dim_out],[dim_out]  因为 第二层中的值 由 第一层中的 每个值的权重和决定
# 正态分布 生成初始w
w1 = tf.Variable(tf.random.truncated_normal([784,256],stddev=0.01))
b1 = tf.Variable(tf.random.truncated_normal([256]))

w2 = tf.Variable(tf.random.truncated_normal([256,128],stddev=0.01))
b2 = tf.Variable(tf.random.truncated_normal([128]))

w3 = tf.Variable(tf.random.truncated_normal([128,10],stddev=0.01))
b3 = tf.Variable(tf.random.truncated_normal([10]))

lr = 1e-3
# 前向运算  x 是 batch  
for i in range(10):
    for step,(x,y) in enumerate(train_db): #默认只会跟着 tf.Variable
        # x[128,28,28]
        # y[128] 
        x = tf.reshape(x,(-1,28*28))
        with tf.GradientTape() as tape:
            # x[b,784] * [784,256]
            h1 = x @ w1 + b1
            h1 = tf.nn.relu(h1)
            h2 = h1 @ w2 + b2
            h2 = tf.nn.relu(h2)
            out = h2 @ w3 + b3

            # loss [b] -- > [b,10] 将标签 转为one_hot形式
            y_onehot = tf.one_hot(y,depth=10)

            # loss = mean((正确结果 - 预处结果)^2 ) 
            loss = tf.square(y_onehot - out)
            loss = tf.reduce_mean(loss)

        # 求解 loss 关于 w1,b1,w2,b2,w3,b3的梯度
            grads = tape.gradient(loss,[w1,b1,w2,b2,w3,b3])

        # 相减运算后 返回的是一个tensor类型 不是一个 tf.Variable类型
        w1.assign_sub(lr * grads[0])
        w2.assign_sub(lr * grads[2])
        w3.assign_sub(lr * grads[4])
        b1.assign_sub(lr * grads[1])
        b2.assign_sub(lr * grads[3])
        b3.assign_sub(lr * grads[5])
        if step % 100 == 0:
            print(step,'loss:',float(loss))



(x,y),_ = datasets.mnist.load_data()
img = x[0,:,:]
cv.imshow('img',img)
cv.waitKey(0)
cv.destroyAllWindows()

img = tf.convert_to_tensor(img,dtype=tf.float32)
img = tf.reshape(img,(-1,28*28))
h1 = img @ w1 + b1
h1 = tf.nn.relu(h1)
h2 = h1 @ w2 + b2
h2 = tf.nn.relu(h2)
out = h2 @ w3 + b3
print('one-hot:',out)
print('预测该数字结果为:',list(out.numpy().reshape(10)).index(max(list(out.numpy().reshape(10)))))
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值