TensorFlow实现鸢尾花分类代码

TensorFlow实现鸢尾花分类代码

一:代码


from sklearn import datasets
from matplotlib import pyplot as plt
import tensorflow as tf
import numpy as np


# 获取鸢尾花数据和对应的标签
x_data = datasets.load_iris().data
y_data = datasets.load_iris().target

'''
因为原始数据是有序的,顺序不打乱就会影响准确率
seed:随机数种子,是一个整数,当设置之后,每次生成的随机数都一样
'''

np.random.seed(116)     # 使用相同的随机种子,使得输入特征与标签能够一一对应
np.random.shuffle(x_data)
np.random.seed(116)
np.random.shuffle(y_data)
tf.random.set_seed(116)

# 对数据集进行分类,分成训练集和测试集
x_train = x_data[:-30]      # 共150条数据,获取前120条数据
y_train = y_data[:-30]
x_test = x_data[-30:]       # 将后30条数据作为测试
y_test = y_data[-30:]

# 将x的数据进行类型转换,否则后面矩阵相乘时会因类型不一致而                                                                             报错
x_train = tf.cast(x_train,tf.float32)
x_test = tf.cast(x_test,tf.float32)

'''
将特征值与标签配对起来,并将每32组特征和标签对打包成一个batch,之后在喂入神经网络时会以batch为单位喂入
'''
train_db = tf.data.Dataset.from_tensor_slices((x_train,y_train)).batch(30)
test_db = tf.data.Dataset.from_tensor_slices((x_test,y_test)).batch(30)


'''
定义神经网络中所有可训练的参数
生成神经网络的参数:4个输入特征,因此输入层有四个输入节点;因为最终结果有三种结果,所以输出层是三个节点
使用seed使每次生成的随机数相同
'''
w1 = tf.Variable(tf.random.truncated_normal([4,3],stddev=0.1,seed=1))   # 生成权值随机数,此时表示的是4个输入单元,3个输出单元
b1 = tf.Variable(tf.random.truncated_normal([3],stddev=0.1,seed=1)) # 生成阈值

lr = 0.1    # 设置学习率
train_loss_result = []      # 将每轮产生的loss数据存放在此列表中,为后面画loss曲线提供数据
test_acc = []           # 将每轮的acc记录在此列表中,为后续画acc曲线提供数据
epoch = 500         # 训练500轮
loss_all = 0        # 每轮分4个step。loss_all记录四个step生成的4个loss的和

# 嵌套循环,在with结构中来更新参数,并显示当先的loss损失函数
for epoch in range(epoch):      # 数据集级别的循环,每个epoch循环一次数据集,训练500次
    for step,(x_train,y_train) in enumerate(train_db):
        with tf.GradientTape() as tape:     # with 结构记录梯度信息
            y = tf.matmul(x_train,w1) + b1      # 矩阵相乘并加上阈值,前向传播进行计算
            y = tf.nn.softmax(y)        # 使y的输出符合概率分布,此操作后就与独热码同量级

            y_ = tf.one_hot(y_train,depth=3)    # 将标签设置成独热码,方便计算loss和acc
            loss = tf.reduce_mean(tf.square(y_-y)) # 使用均方误差损失函数
            loss_all += loss.numpy()    # 将每个step计算出的loss累加,为后续求loss平均值提供数据

        # 前馈
        grads = tape.gradient(loss,[w1,b1])     # 计算loss函数的各个参数的梯度
        # 实现梯度的更新 w1 = w1 -lr*w1_grad    b   = b-lr*b_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


    # 测试部分,计算精度
    total_correct,total_number = 0,0
    for x_test,y_test in test_db:
        # 使用更新后的数据进行预测
        y = tf.matmul(x_test,w1)+b1
        y = tf.nn.softmax(y)
        pred = tf.argmax(y,axis=1)      # 返回y的最大值的索引,即为预测结果

        # 将pred转变成y_test()类型
        pred = tf.cast(pred,dtype=y_test.dtype)
        # 若分类正确,则correct=1,否则为0,将bool类型的结果转变成int类型
        correct = tf.cast(tf.equal(pred,y_test),dtype=tf.int32) # equal判断是否相同,如果相同就是True,否则为Flase
        # 将每个batch的correct数加在一起
        correct = tf.reduce_sum(correct)
        # 将所有batch中的correct数加在一起
        total_correct+=int(correct)
        # total_number为测试的总样本数,也就是x_test的行数,shape[0]返回变量的行数
        total_number += x_test.shape[0]
    # 总的准确率等于total_correct/total_number
    acc = total_correct/total_number
    test_acc.append(acc)
    print("Test_acc",acc)
    print("-------------------------------------------------------")

# 绘制loss曲线
plt.title('Loss Function Curve')
plt.xlabel('Epoch')     # x轴变量名
plt.ylabel('Loss')      # y轴变量名
plt.plot(train_loss_result,label="$Loss$") # 逐点画出值并连线
plt.legend()        # 画出曲线图标
plt.show()          # 画出图像


# 绘制Accuracy 曲线
plt.title('Acc Curve')
plt.xlabel("Epoch")
plt.ylabel("Acc")
plt.plot(test_acc,label="$Accuracy$")
plt.legend()
plt.show()


二:结果

损失函数:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QUbgQglq-1660274234619)(C:\Users\Zhaoyanyu\Desktop\loss.PNG)]

随着训练次数的增加,损失函数越来越趋向于0,即证明预测值与正确答案之间的差距越来越小

精确度:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FpQ96PqP-1660274234620)(C:\Users\Zhaoyanyu\Desktop\acc.PNG)]

随着训练次数的增加,精确度越来越趋向于1

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值