200813_tensorflow2---3、iris分类简单神经网络
200813_tensorflow2---3、iris分类简单神经网络
一、总结
一句话总结:
(A)、具体相乘就是 每个batch(这里是32)的数据来整体和w1相乘,然后加上b1,b1维度不够,肯定是用了广播
(B)、y = tf.matmul(x_train, w1) + b1 # 神经网络乘加运算
(C)、shape=(32, 4) * shape=(4, 3) + shape=(3,)
# 训练部分 for epoch in range(epoch): #数据集级别的循环,每个epoch循环一次数据集 for step, (x_train, y_train) in enumerate(train_db): #batch级别的循环 ,每个step循环一个batch with tf.GradientTape() as tape: # with结构记录梯度信息 y = tf.matmul(x_train, w1) + b1 # 神经网络乘加运算 y = tf.nn.softmax(y) # 使输出y符合概率分布(此操作后与独热码同量级,可相减求loss) y_ = tf.one_hot(y_train, depth=3) # 将标签值转换为独热码格式,方便计算loss和accuracy loss = tf.reduce_mean(tf.square(y_ - y)) # 采用均方误差损失函数mse = mean(sum(y-out)^2) loss_all += loss.numpy() # 将每个step计算出的loss累加,为后续求loss平均值提供数据,这样计算的loss更准确 # 计算loss对各个参数的梯度 grads = tape.gradient(loss, [w1, b1]) # 实现梯度更新 w1 = w1 - lr * w1_grad b = b - lr * b_grad w1.assign_sub(lr * grads[0]) # 参数w1自更新 b1.assign_sub(lr * grads[1]) # 参数b自更新 # 每个epoch,打印loss信息 print("Epoch {}, loss: {}".format(epoch, loss_all/4)) train_loss_results.append(loss_all / 4) # 将4个step的loss求平均记录在此变量中 loss_all = 0 # loss_all归零,为记录下一个epoch的loss做准备
1、将打乱后的数据集分割为训练集和测试集,训练集为前120行,测试集为后30行?
x_train = x_data[:-30]
x_test = x_data[-30:]
2、打乱数据的时候,如果保证x和y一一对应?
使用相同的seed,保证输入特征和标签一一对应
np.random.seed(116) # 使用相同的seed,保证输入特征和标签一一对应 np.random.shuffle(x_data) np.random.seed(116) np.random.shuffle(y_data)
3、from_tensor_slices函数使输入特征和标签值一一对应。(把数据集分批次,每个批次batch组数据)?
train_db = tf.data.Dataset.from_tensor_slices((x_train, y_train)).batch(32)
4、生成神经网络的参数,4个输入特征故,输入层为4个输入节点;因为3分类,故输出层为3个神经元?
w1 = tf.Variable(tf.random.truncated_normal([4, 3], stddev=0.1, seed=1))
5、用tf.Variable()标记参数可训练?
w1 = tf.Variable(tf.random.truncated_normal([4, 3], stddev=0.1, seed=1))
6、使用seed使每次生成的随机数相同(方便教学,使大家结果都一致,在现实使用时不写seed)?
(I)、 w1 = tf.Variable(tf.random.truncated_normal([4, 3], stddev=0.1, seed=1))
(II)、 b1 = tf.Variable(tf.random.truncated_normal([3], stddev=0.1, seed=1))
7、参数w1自更新?
w1.assign_sub(lr * grads[0])
8、y = tf.matmul(x_train, w1) + b1,b1的维度是不够的,会怎么办?
进行y = tf.matmul(x_train, w1) + b1 的时候,b1的维度是不够的,b1是会自动广播的
print([[1,2],[3,4]]+[5,6]) v1=tf.constant([[1,2],[3,4]]) v2=tf.constant([5,6]) print(v1) print(v2) print(v1+v2) 结果 [[1, 2], [3, 4], 5, 6] tf.Tensor( [[1 2] [3 4]], shape=(2, 2), dtype=int32) tf.Tensor([5 6], shape=(2,), dtype=int32) tf.Tensor( [[ 6 8] [ 8 10]], shape=(2, 2), dtype=int32)
9、对每个batch中y进行softmax操作的时候,到底是怎么做的?
softmax的时候,自然是每一个测试数据的哪些分类的概率的和为1,也就是三种分类的和为1
结果 y = tf.nn.softmax(y) tf.Tensor( [[0.28231245 0.13475922 0.58292836] [0.30029225 0.13068524 0.5690225 ] [0.5755953 0.04495765 0.37944704]], shape=(3, 3), dtype=float32) y_ = tf.one_hot(y_train, depth=3) tf.Tensor( [[1. 0. 0.] [1. 0. 0.] [0. 0. 1.]], shape=(3, 3), dtype=float32)
10、无论是softmax还是one_hot编码,本身都是概率形式,自然可以计算?
(①)、y = tf.matmul(x_train, w1) + b1 # 神经网络乘加运算
(②)、y = tf.nn.softmax(y) # 使输出y符合概率分布(此操作后与独热码同量级,可相减求loss)
(③)、y_ = tf.one_hot(y_train, depth=3) # 将标签值转换为独热码格式,方便计算loss和accuracy
(④)、loss = tf.reduce_mean(tf.square(y_ - y)) # 采用均方误差损失函数mse = mean(sum(y-out)^2)
计算均方误差的时候,预测值y是softmax操作之后的概率,y_是one_hot编码之后的样子, 所以计算出的的基础就是-1到1之间有正有负的形式,其实也好理解,无论是softmax还是one_hot编码,本身都是概率形式,自然可以计算 结果 y = tf.nn.softmax(y) tf.Tensor( [[0.28231245 0.13475922 0.58292836] [0.30029225 0.13068524 0.5690225 ] [0.5755953 0.04495765 0.37944704]], shape=(3, 3), dtype=float32) y_ = tf.one_hot(y_train, depth=3) tf.Tensor( [[1. 0. 0.] [1. 0. 0.] [0. 0. 1.]], shape=(3, 3), dtype=float32) y_ - y tf.Tensor( [[ 0.71768755 -0.13475922 -0.58292836] [ 0.69970775 -0.13068524 -0.5690225 ] [-0.5755953 -0.04495765 0.62055296]], shape=(3, 3), dtype=float32) tf.square(y_ - y) tf.Tensor( [[0.51507545 0.01816005 0.33980548] [0.48959094 0.01707863 0.3237866 ] [0.33130997 0.00202119 0.38508597]], shape=(3, 3), dtype=float32) loss = tf.reduce_mean(tf.square(y_ - y)) tf.Tensor(0.2691016, shape=(), dtype=float32)
11、求均方差的时候,是每个batch里面的[batch,type]里面的每个元素平方,然后求均值?
loss = tf.reduce_mean(tf.square(y_ - y)) # 采用均方误差损失函数mse = mean(sum(y-out)^2)
y = tf.nn.softmax(y) tf.Tensor( [[0.28231245 0.13475922 0.58292836] [0.30029225 0.13068524 0.5690225 ] [0.5755953 0.04495765 0.37944704]], shape=(3, 3), dtype=float32) y_ = tf.one_hot(y_train, depth=3) tf.Tensor( [[1. 0. 0.] [1. 0. 0.] [0. 0. 1.]], shape=(3, 3), dtype=float32) y_ - y tf.Tensor( [[ 0.71768755 -0.13475922 -0.58292836] [ 0.69970775 -0.13068524 -0.5690225 ] [-0.5755953 -0.04495765 0.62055296]], shape=(3, 3), dtype=float32) tf.square(y_ - y) tf.Tensor( [[0.51507545 0.01816005 0.33980548] [0.48959094 0.01707863 0.3237866 ] [0.33130997 0.00202119 0.38508597]], shape=(3, 3), dtype=float32) loss = tf.reduce_mean(tf.square(y_ - y)) tf.Tensor(0.2691016, shape=(), dtype=float32)
二、iris分类简单神经网络
博客对应课程的视频位置:
# -*- coding: UTF-8 -*-
# 利用鸢尾花数据集,实现前向传播、反向传播,可视化loss曲线
# 导入所需模块
import tensorflow as tf
from sklearn import datasets
from matplotlib import pyplot as plt
import numpy as np
# 导入数据,分别为输入特征和标签
x_data = datasets.load_iris().data
y_data = datasets.load_iris().target
# 随机打乱数据(因为原始数据是顺序的,顺序不打乱会影响准确率)
# seed: 随机数种子,是一个整数,当设置之后,每次生成的随机数都一样(为方便教学,以保每位同学结果一致)
np.random.seed(116) # 使用相同的seed,保证输入特征和标签一一对应
np.random.shuffle(x_data)
np.random.seed(116)
np.random.shuffle(y_data)
tf.random.set_seed(116)
# 将打乱后的数据集分割为训练集和测试集,训练集为前120行,测试集为后30行
x_train = x_data[:-30]
y_train = y_data[:-30]
x_test = x_data[-30:]
y_test = y_data[-30:]
# 转换x的数据类型,否则后面矩阵相乘时会因数据类型不一致报错
x_train = tf.cast(x_train, tf.float32)
x_test = tf.cast(x_test, tf.float32)
# from_tensor_slices函数使输入特征和标签值一一对应。(把数据集分批次,每个批次batch组数据)
train_db = tf.data.Dataset.from_tensor_slices((x_train, y_train)).batch(32)
test_db = tf.data.Dataset.from_tensor_slices((x_test, y_test)).batch(32)
# 生成神经网络的参数,4个输入特征故,输入层为4个输入节点;因为3分类,故输出层为3个神经元
# 用tf.Variable()标记参数可训练
# 使用seed使每次生成的随机数相同(方便教学,使大家结果都一致,在现实使用时不写seed)
w1 = tf.Variable(tf.random.truncated_normal([4, 3], stddev=0.1, seed=1))
b1 = tf.Variable(tf.random.truncated_normal([3], stddev=0.1, seed=1))
lr = 0.1 # 学习率为0.1
train_loss_results = [] # 将每轮的loss记录在此列表中,为后续画loss曲线提供数据
test_acc = [] # 将每轮的acc记录在此列表中,为后续画acc曲线提供数据
epoch = 500 # 循环500轮
loss_all