概述
先说要干嘛
如标题所示,本人是手动定义了神经网络的每一层的w和b,就是采用TF的随机正态分布初始化的数值,然后实现Mnist数据集与w,b参数之间的运算过程,以帮助自己加深印象理解神经网络
开始了
Step1:加载所需要的包
"""
导入所需的包,其中包括 TF的高层接口keras里面的数据集接口datasets
"""
import tensorflow as tf
from tensorflow.keras import datasets
import os # 因为本人用的TF是2.0-cpu版本,总是打印一些无关的信息,故调用os,使其不打印
# 设置一个环境变量,将TF打印的无关信息关掉
os.environ["TF_CPP_MIN_LOG_LEVEL"] = "2"
Step2:加载Mnist数据集,并做数据预处理
# 首先加载数据集,因为此代码只是实现mnist数据集的训练集的前向传播
# 就是利用梯度下降算法,完成训练集的真实y值与模型输出预测y值
# 之间的损失函数的下降
# 此句会返回两个数据集,一个训练集,一个测试集,因为此次代码用不到测试集数据,故用"_"表示
(x, y), _ = datasets.mnist.load_data()
print(x.shape, type(x), y.shape, type(y)) # (60000, 28, 28) <class 'numpy.ndarray'> (60000,) <class 'numpy.ndarray'>
# 如上所述,此时加载出的数据,类型是np.array,所以,要想在TF中进行运算
# 需要转换成Tensor形式
# 此外,mnist数据集中的图片像素大小范围是0-255,不利于深度学习的训练
# 所以将其数值再转换为0-1之间
x = tf.convert_to_tensor(x, dtype=tf.float32) / 255.0
# 对于y值,也需要同样处理,不过不同点在于,y值还要进行one_hot编码
# 目的是为了和模型的预测结果之间构造损失函数,计算误差
# 因为要保证一样的shape,才可以做运算
y = tf.one_hot(tf.convert_to_tensor(y, dtype=tf.int64), depth=10) # 有几分类,depth参数就设置为几
print(x.shape, type(x), y.shape, type(y))
"""
(60000, 28, 28) <class 'tensorflow.python.framework.ops.EagerTensor'> (60000, 10) <class 'tensorflow.python.framework.ops.EagerTensor'>
"""
# 为了每次取60k中的照片的部分,也就是一个batch,因为没必要一次将60k的照片全部加载到内存中
# 先设置每次取128张
# 用TF的Dataset命令,将(x,y)作为参数传入
# train-db会有两个返回值,一个是x:[128, 28, 28],一个是y:[128, 10]
# 形式是以tuple的格式返回
# y之所以会是这种shape,因为提前做了one-hot
train_db = tf.data.Dataset.from_tensor_slices((x, y)).batch(batch_size=128)
# 数据预处理,到此基本算是结束
Step3:定义3层网络所需要的w,b,并随机初始化数值
# 下面进行随机初始化w,b,手动模拟初始化神经网络中的w,b参数
# 这里将要简单初始化三层网络的参数
# 外面要包一个tf.Variable,因为后面测试时发现,只有这样
# TF才会识别这是需要自动求导的变量
w1 = tf.Variable(tf.random.normal([784, 256], stddev=0.1))
b1 = tf.Variable(tf.zeros([256])) # bias就可以直接初始化为0
w2 = tf.Variable(tf.random.normal([256, 128], stddev=0.1))
b2 = tf.Variable(tf.zeros([128]))
w3 = tf.Variable(tf.random.normal([128, 10], stddev=0.1))
b3 = tf.Variable(tf.zeros([10]))
# 下面再定义一个计算梯度时需要的变量,learning rate,学习率
learning_rate = 1e-3 # 一般设置为此值
Step4:开始循环迭代,且梯度下降,更新损失值
# 下面开始循环迭代,利用梯度下降不断优化定义的损失函数的值
# 使模型预测值不断接近真实值
# 最外层循环定义epoch,迭代次数,也就是将全部训练集迭代多少次
for epoch in range(10):
# 这层循环是在train-db上循环,因为前面已经设置了每次取128张图片
# 避免一次全部将所有图片加载进来,占用内存太多
# step可以记录遍历到的图片的数量的索引
for step, (x, y) in enumerate(train_db):
# 因为下面要开始模拟神经网络线性层的矩阵运算
# 故将图片的像素打平,使之满足矩阵运算的形式
x = tf.reshape(x, [-1, 784])
# 在TF中,所有需要计算梯度信息的变量与过程
# 都需要包在这个函数下面,TF才可以追踪得到
with tf.GradientTape() as tape:
h1 = x@w1 + b1 # 开始第一层的矩阵运算
h1 = tf.nn.relu(h1) # 用非线性激活函数Relu作非线性变换
# 第二层与第一层同理
h2 = h1@w2 + b2
h2 = tf.nn.relu(h2)
# 最后一层输出层,直接矩阵运算后即可
# 一般不再使用激活函数
out = h2@w3 +b3
# 定义预测值与真实值之间的损失函数是均方误差损失函数(MSE)
# 也就是二者做差,再求平均值
loss = tf.reduce_mean((y-out) ** 2)
# 第一次以随机化的初始值计算后
# 开始计算各个参数的梯度
# 用下列函数,传入需要的target,也就是loss值,因为你的目标是做到loss最小
# 再传入需要计算梯度的变量,也就是w和b
# 此函数会返回一个列表,里面装着w,b计算梯度后的值
grads = tape.gradient(loss, [w1, b1, w2, b2, w3, b3])
# 下面开始用学习率更新梯度
# 使其朝着下降方向减小
# assign-sub函数的使用,意为在原地更新数值
# 用它是因为实际测试时发现,如果将计算后的梯度赋值给原来的
# 这样之后下次就不会自动计算梯度
# 这里是一个目前本人也不太明白的点
w1.assign_sub(learning_rate * grads[0])
b1.assign_sub(learning_rate * grads[1])
w2.assign_sub(learning_rate * grads[2])
b2.assign_sub(learning_rate * grads[3])
w3.assign_sub(learning_rate * grads[4])
b3.assign_sub(learning_rate * grads[5])
# 在设置一下每次迭代了100次之后,就打印一下loss值,看看有没有下降
if step % 100 == 0:
print("epoch:", epoch, "step:", step, "loss:", loss)
Step5:查看结果,看看损失值有没有下降,模型有效否
"""
epoch: 0 step: 0 loss: tf.Tensor(1.0942584, shape=(), dtype=float32)
epoch: 0 step: 100 loss: tf.Tensor(0.3216721, shape=(), dtype=float32)
epoch: 0 step: 200 loss: tf.Tensor(0.2719552, shape=(), dtype=float32)
epoch: 0 step: 300 loss: tf.Tensor(0.2538827, shape=(), dtype=float32)
epoch: 0 step: 400 loss: tf.Tensor(0.26400667, shape=(), dtype=float32)
epoch: 1 step: 0 loss: tf.Tensor(0.2568364, shape=(), dtype=float32)
epoch: 1 step: 100 loss: tf.Tensor(0.2126673, shape=(), dtype=float32)
epoch: 1 step: 200 loss: tf.Tensor(0.18923984, shape=(), dtype=float32)
epoch: 1 step: 300 loss: tf.Tensor(0.18678169, shape=(), dtype=float32)
epoch: 1 step: 400 loss: tf.Tensor(0.19586797, shape=(), dtype=float32)
epoch: 2 step: 0 loss: tf.Tensor(0.19531345, shape=(), dtype=float32)
epoch: 2 step: 100 loss: tf.Tensor(0.17209809, shape=(), dtype=float32)
epoch: 2 step: 200 loss: tf.Tensor(0.1540105, shape=(), dtype=float32)
epoch: 2 step: 300 loss: tf.Tensor(0.15437967, shape=(), dtype=float32)
"""
持续下降,OK,有门
下面是全部代码:
"""
导入所需的包,其中包括 TF的高层接口keras里面的数据集接口datasets
"""
import tensorflow as tf
from tensorflow.keras import datasets
import os # 因为本人用的TF是2.0-cpu版本,总是打印一些无关的信息,故调用os,使其不打印
# 设置一个环境变量,将TF打印的无关信息关掉
os.environ["TF_CPP_MIN_LOG_LEVEL"] = "2"
# 首先加载数据集,因为此代码只是实现mnist数据集的训练集的前向传播
# 就是利用梯度下降算法,完成训练集的真实y值与模型输出预测y值
# 之间的损失函数的下降
# 此句会返回两个数据集,一个训练集,一个测试集,因为此次代码用不到测试集数据,故用"_"表示
(x, y), _ = datasets.mnist.load_data()
print(x.shape, type(x), y.shape, type(y)) # (60000, 28, 28) <class 'numpy.ndarray'> (60000,) <class 'numpy.ndarray'>
# 如上所述,此时加载出的数据,类型是np.array,所以,要想在TF中进行运算
# 需要转换成Tensor形式
# 此外,mnist数据集中的图片像素大小范围是0-255,不利于深度学习的训练
# 所以将其数值再转换为0-1之间
x = tf.convert_to_tensor(x, dtype=tf.float32) / 255.0
# 对于y值,也需要同样处理,不过不同点在于,y值还要进行one_hot编码
# 目的是为了和模型的预测结果之间构造损失函数,计算误差
# 因为要保证一样的shape,才可以做运算
y = tf.one_hot(tf.convert_to_tensor(y, dtype=tf.int64), depth=10) # 有几分类,depth参数就设置为几
print(x.shape, type(x), y.shape, type(y))
"""
(60000, 28, 28) <class 'tensorflow.python.framework.ops.EagerTensor'> (60000, 10) <class 'tensorflow.python.framework.ops.EagerTensor'>
"""
# 为了每次取60k中的照片的部分,也就是一个batch,因为没必要一次将60k的照片全部加载到内存中
# 先设置每次取128张
# 用TF的Dataset命令,将(x,y)作为参数传入
# train-db会有两个返回值,一个是x:[128, 28, 28],一个是y:[128, 10]
# 形式是以tuple的格式返回
# y之所以会是这种shape,因为提前做了one-hot
train_db = tf.data.Dataset.from_tensor_slices((x, y)).batch(batch_size=128)
# 数据预处理,到此基本算是结束
# 下面进行随机初始化w,b,手动模拟初始化神经网络中的w,b参数
# 这里将要简单初始化三层网络的参数
# 外面要包一个tf.Variable,因为后面测试时发现,只有这样
# TF才会识别这是需要自动求导的变量
w1 = tf.Variable(tf.random.normal([784, 256], stddev=0.1))
b1 = tf.Variable(tf.zeros([256])) # bias就可以直接初始化为0
w2 = tf.Variable(tf.random.normal([256, 128], stddev=0.1))
b2 = tf.Variable(tf.zeros([128]))
w3 = tf.Variable(tf.random.normal([128, 10], stddev=0.1))
b3 = tf.Variable(tf.zeros([10]))
# 下面再定义一个计算梯度时需要的变量,learning rate,学习率
learning_rate = 1e-3 # 一般设置为此值
# 下面开始循环迭代,利用梯度下降不断优化定义的损失函数的值
# 使模型预测值不断接近真实值
# 最外层循环定义epoch,迭代次数,也就是将全部训练集迭代多少次
for epoch in range(10):
# 这层循环是在train-db上循环,因为前面已经设置了每次取128张图片
# 避免一次全部将所有图片加载进来,占用内存太多
# step可以记录遍历到的图片的数量的索引
for step, (x, y) in enumerate(train_db):
# 因为下面要开始模拟神经网络线性层的矩阵运算
# 故将图片的像素打平,使之满足矩阵运算的形式
x = tf.reshape(x, [-1, 784])
# 在TF中,所有需要计算梯度信息的变量与过程
# 都需要包在这个函数下面,TF才可以追踪得到
with tf.GradientTape() as tape:
h1 = x@w1 + b1 # 开始第一层的矩阵运算
h1 = tf.nn.relu(h1) # 用非线性激活函数Relu作非线性变换
# 第二层与第一层同理
h2 = h1@w2 + b2
h2 = tf.nn.relu(h2)
# 最后一层输出层,直接矩阵运算后即可
# 一般不再使用激活函数
out = h2@w3 +b3
# 定义预测值与真实值之间的损失函数是均方误差损失函数(MSE)
# 也就是二者做差,再求平均值
loss = tf.reduce_mean((y-out) ** 2)
# 第一次以随机化的初始值计算后
# 开始计算各个参数的梯度
# 用下列函数,传入需要的target,也就是loss值,因为你的目标是做到loss最小
# 再传入需要计算梯度的变量,也就是w和b
# 此函数会返回一个列表,里面装着w,b计算梯度后的值
grads = tape.gradient(loss, [w1, b1, w2, b2, w3, b3])
# 下面开始用学习率更新梯度
# 使其朝着下降方向减小
# assign-sub函数的使用,意为在原地更新数值
# 用它是因为实际测试时发现,如果将计算后的梯度赋值给原来的
# 这样之后下次就不会自动计算梯度
# 这里是一个目前本人也不太明白的点
w1.assign_sub(learning_rate * grads[0])
b1.assign_sub(learning_rate * grads[1])
w2.assign_sub(learning_rate * grads[2])
b2.assign_sub(learning_rate * grads[3])
w3.assign_sub(learning_rate * grads[4])
b3.assign_sub(learning_rate * grads[5])
# 在设置一下每次迭代了100次之后,就打印一下loss值,看看有没有下降
if step % 100 == 0:
print("epoch:", epoch, "step:", step, "loss:", loss)
最后
以上就是彪壮发箍为你收集整理的手动初始化w,b参数,实现3层神经网络前向传播过程【基于TensorFlow2.0】的全部内容,希望文章能够帮你解决手动初始化w,b参数,实现3层神经网络前向传播过程【基于TensorFlow2.0】所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复