tensorflow2.0实现简易iris分类

此文章为跟着B站的课程学习时写的,感兴趣的可以去看看
北京大学tensorflow2.0教程
北大的老师讲的贼细致,不是调API那种,而是从最基础的操作讲起。

要实现iris数据集的分类,首先要实现以下几步:

  1. 导入数据集,分成训练集和测试集(因为是简易实现,所以就没加验证集了)
  2. 定义神经网络中所有可训练参数。
  3. 按照批次进行训练,向前传播预测标签,向后传播调整参数

以下是包含代码的详细步骤:

  1. 导入数据集,分成测试和训练集,并且匹配成[特征, 标签]对再整合成batch
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
  1. 训练部分就是嵌套循环,总的来说就是先正向传播求预测标签和loss,然后反向传播更新参数:
# 训练部分,嵌套循环,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)
  1. 最后再画个图来展示训练效果即可:
# 绘制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()

最后画出的曲线图如下所示:
tensorflow2.0实现简易iris分类_第1张图片
tensorflow2.0实现简易iris分类_第2张图片
各位发现什么错误烦请纠正喔

你可能感兴趣的:(深度学习入门,深度学习,tensorflow,机器学习,python,神经网络)