此文章为跟着B站的课程学习时写的,感兴趣的可以去看看
北京大学tensorflow2.0教程
北大的老师讲的贼细致,不是调API那种,而是从最基础的操作讲起。
要实现iris数据集的分类,首先要实现以下几步:
以下是包含代码的详细步骤:
from sklearn.datasets import load_iris
import tensorflow as tf
import matplotlib.pyplot as plt
import numpy as np
x_data = load_iris().data # 获得iris所有输入特征
y_data = load_iris().target # 获得所有标签
# 数据集乱序
np.random.seed(116) # 使用相同的seed,使输入的特征和标签一一对应
np.random.shuffle(x_data)
np.random.seed(116)
np.random.shuffle(y_data)
np.random.seed(116)
# 分出训练集和测试集
x_train = x_data[:-30]
y_train = y_data[:-30]
x_test = x_data[-30:]
y_test = y_data[-30:]
# 数据类型转换,后面数据类型不一样会报错
x_train = tf.cast(x_train, dtype=tf.float32)
x_test = tf.cast(x_test, dtype=tf.float32)
# 配成[特征, 标签]对,每次输入一个batch,batch大小一般为2的幂次方,因为gpu训练2的幂次方的数据更快
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)
需要尤其注意以上代码中数据类型转换的部分。
2. 初始化训练参数
此次的网络结构仅由四个输入结点和三个输出结点构成,且结点间没有使用激活函数:
# 定义神经网络中所有可训练参数
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_result = [] # 每轮的loss记录,为画图提供数据
test_acc = [] # 同上
epoch = 500
loss_all = 0
# 训练部分,嵌套循环,with结构更新参数,显示当前loss
for epoch in range(epoch): # 数据集级别迭代
for step, (x_train, y_train) in enumerate(train_db): # batch级别迭代
with tf.GradientTape() as tape: # 记录梯度信息
# 前向传播计算y
y = tf.matmul(x_train, w1) + b1
y = tf.nn.softmax(y) # 与独热编码同维, 可以相减求loss
y_ = tf.one_hot(y_train, depth=3) # 将概率转化为独热编码
# 计算总loss
loss = tf.reduce_mean(tf.square(y_ - y))
loss_all += loss.numpy()
# 计算loss对各个参数的梯度,向后传播更新参数
grads = tape.gradient(loss, [w1, b1])
# w1 = w1-lr*w1_grad, b1=b1-lr*b1_grad
w1.assign_sub(lr * grads[0]) # 参数自更新
b1.assign_sub(lr * grads[1])
# 每个epoch打印一次loss
print('Epoch {}, loss:{}'.format(epoch, loss_all / 4))
train_loss_result.append(loss_all / 4)
loss_all = 0
# 计算当前参数向前传播后的准确率,显示当先在test上的acc
total_correct = 0
total_number = 0
for x_test, y_test in test_db:
y = tf.matmul(x_test, w1) + b1 # y为预测结果
y = tf.nn.softmax(y) # 符合概率分布
pred = tf.argmax(y, axis=1) # y中最大值的索引,即预测的分类
pred = tf.cast(pred, dtype=y_test.dtype) # 调整数据类型与标签一致
correct = tf.cast(tf.equal(pred, y_test), dtype=tf.int32)
correct = tf.reduce_sum(correct) # 每个batch中正确的数量
total_correct += int(correct)
total_number += x_test.shape[0]
acc = total_correct / total_number
test_acc.append(acc)
print('test acc:{}'.format(acc))
print('-' * 50)
# 绘制loss曲线
plt.title('Loss Function Curve')
plt.xlabel('Epoch')
plt.ylabel('Loss')
plt.plot(train_loss_result, label='$Loss$')
plt.legend() # 画出坐标
plt.show()
# 绘制acc曲线
plt.title('Acc Curve')
plt.xlabel('Epoch')
plt.ylabel('Acc')
plt.plot(test_acc, label='$Acc$')
plt.legend() # 画出坐标
plt.show()