简单说分四步
01准备数据
02搭建网络
03优化训练参数————(训练部分 + 测试部分)循环
04作图——loss,acc
import tensorflow as tf
import numpy as np
from sklearn import datasets
from matplotlib import pyplot as plt
#01准备数据
x_data=datasets.load_iris().data
y_data=datasets.load_iris().target
#数据集乱序
np.random.seed(116)
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:]
#统一数据类型为float32,以免后面矩阵相乘时因为数据类型不一致而报错
x_train=tf.cast(x_train,tf.float32)
x_test=tf.cast(x_test,tf.float32)
#数据配对,使用tensorflow数据切片
#使得输入数据(特征)和标签一一配对,训练集120对数据,测试集30对数据
#并分组打包,每32对数据打包为一个batch,方便后面模型训练
#所以训练集包含4个batch,测试集包含1个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)
#02 搭建网络
#定义网络的初始参数
#随机生成符合[截断式正太分布]的初始参数 w1[4*3] 和 b1[3]
#参数标要记为可训练Variable,而不是常量constant
#标准差0.1,随机数种子seed=1
#(truncated——截断式,意思就是生成的参数,在均值的上下两个标准差范围内,是为了让生成的随机数不要相差太多)
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 #学习率
epoch=500
#迭代次数500轮,每轮都在更新参数,看能不能吧损失函数降到最低,不能的话可以再增加迭代次数
#可以看到结果,大概185次迭代后,acc就达到1了,但是loss还在降低。注意过拟合问题
#新建两个空列表
#一个记录每一轮训练后得到的损失函数值loss,一个记录每一轮测试后得到的精度acc
#两个列表后期用于作图
train_loss_results=[]
test_acc=[]
#上面说到120个训练样本组成的训练集,我们划分为4个batch来喂给模型
#所以每轮都会产生四个loss
#每轮记录的loss应该是四个loss的平均值
#设置一个变量来累加这四个loss
loss_all=0
#03 优化训练参数————(训练部分 + 测试部分)循环500次
#一:训练部分
#两层for循环,外层执行500次,内层是4个训练集的batch和1个测试集的batch
for epoch in range (epoch):
for step , (x_train,y_train) in enumerate(train_db):
#在with结构中记录梯度信息,计算每一轮batch的损失函数值
with tf.GradientTape() as tape:
y=tf.matmul(x_train,w1)+ b1 #计算训练集的预测值
y=tf.nn.softmax(y) #使y值符合概率分布——softmax激活函数就是归一化
y_=tf.one_hot(y_train,depth=3)#使训练集的标签转变为独热码
#定义损失函数为——均方误差损失函数
loss=tf.reduce_mean(tf.square(y_-y))
#累计四个batch的loss值,方便后面求每次迭代里,loss的平均值
loss_all=loss_all+loss.numpy()
tf.reduce_mean 函数
用于计算张量tensor沿着指定的数轴(tensor的某一维度)上的的平均值,主要用作降维或者计算tensor(图像)的平均值。tf.reduce_mean(input_tensor, axis=None, keep_dims=False, name=None )
第一个参数input_tensor: 输入的待降维的tensor;
第二个参数axis: 指定的轴,如果不指定,则计算所有元素的均值;
第三个参数keep_dims:是否降维度,
设置为True,输出的结果保持输入tensor的形状,设置为False,输出结果会降低维度;
#进行完一次batch后更新参数
#01求导(损失函数对各个参数),02更新
grads =tape.gradient(loss,[w1,b1])
w1.assign_sub(lr*grads[0])
b1.assign_sub(lr*grads[1])
# ---------- 至此,一个batch的训练结束,获得了一个损失函数值,两个参数各更新了1次
#每结束一次epoch,打印一次loss信息(也就是四个batch,获得了四次loss累计值loss_all)
print("Epoch{}\nloss:{}".format(epoch,loss_all/4))
#记录下这轮epoch的loss值 到 之前新建的空列表中,方便后面作图,同时清空loss_all
train_loss_results.append(loss_all/4)
loss_all=0
#二:测试部分
#注意是包含在外层循环里的 也就是训练500轮,每一轮都在更新参数获得loss,每一轮最后都会测试获得acc
#预测正确的样本个数,测试的总样本个数
total_correct,total_number=0,0
#遍历测试集中的所有数据,计算前想传播的预测结果
for x_test,y_test in test_db:
#使用更新后的参数进行预测,并计算分类准确度acc
y=tf.matmul(x_test,w1)+ b1
y=tf.nn.softmax(y)
#返回y中最大值的索引,即预测的类别号
pred=tf.argmax(y,axis=1) #axis=1,横向比较
#将pred转换为和y_test一致的数据类型,方便比较
pred=tf.cast(pred,dtype=y_test.dtype)
#将pred 与 y_test 相比较 ,若分类正确,则令correct=1,否则为0
#这里需要把equal的结果(bool类型)转换为int类型
correct=tf.cast(tf.equal(pred,y_test),dtype=tf.int32)
#将每个batch的correct值加起来
correct=tf.reduce_sum(correct)
#将所有batch的correct值加起来
total_correct=total_correct+int(correct)
#total_number为测试的总样本数,也就是x_test的行数,.shape[0]返回变量行数
total_number=total_number+x_test.shape[0] #————————说实话不是很懂这里啥意思,为什么要累加
#计算准确率acc,每一轮epoch计算一次
acc=total_correct/total_number
#将每一轮的acc丢到之前的空列表,方便后面作图
test_acc.append(acc)
print("Test_acc:",acc)
print("----------------------------------")
输出结果:
Epoch0
loss:0.282131090760231
Test_acc 0.16666666666666666
----------------------------------
Epoch1
loss:0.25459615513682365
Test_acc 0.16666666666666666
----------------------------------
Epoch2
loss:0.22570250555872917
Test_acc 0.16666666666666666
----------------------------------
Epoch3
loss:0.21028400212526321
Test_acc 0.16666666666666666
----------------------------------
Epoch4
loss:0.19942264258861542
Test_acc 0.16666666666666666
----------------------------------
Epoch5
loss:0.18873638287186623
Test_acc 0.5
----------------------------------
Epoch6
loss:0.17851299792528152
Test_acc 0.5333333333333333
----------------------------------
Epoch7
loss:0.16922874748706818
Test_acc 0.5333333333333333
----------------------------------
Epoch8
loss:0.16107673197984695
Test_acc 0.5333333333333333
----------------------------------
Epoch9
loss:0.15404684096574783
Test_acc 0.5333333333333333
----------------------------------
·
·
·
·
·
·
Epoch500
#04 作图————loss,acc
#loss曲线
plt.title("Loss Function Curve")
plt.xlabel("epoch")
plt.ylabel("loss")
plt.plot(train_loss_results,label="$loss$") #这里的label是指图片上的图例名称
plt.legend() #图片上的图例
plt.show()
#accuracy曲线
plt.title("Acc Curve")
plt.xlabel("epoch")
plt.ylabel("acc")
plt.plot(test_acc,label="$acc$") #这里的label是指图片上的图例名称
plt.legend() #图片上的图例
plt.show()