• 深度学习入门——基于TensorFlow的鸢尾花分类实现(TensorFlow_GPU版本安装、实现)


    Author(作者): Nirvana Of Phoenixl
    Proverbs for you(送给你的哦):There is no doubt that good things will always come, and when it comes late, it can be a surprise.

    文章可以作为深度学习或者TensorFlow入门的了解学习。使用PyChram和Python实现,安装过程中最容易出现的问题是GPU版本的与显卡的问题。如果需要对应版本的TensorFlow,可以私信一下,呜呜我懒的放上来,可以发一份给你们!

    0 引言

      本文主要是基于TensorFlow和Keras框架实现的鸢尾花分类,主要包含关于深度学习TensorFlow-GPU环境的搭建,以及实现框架的实现,其实验目的是实现鸢尾花分类,本质是通过简单的实践理解深度学习基本流程,加深对于代码实现的理解,通过对框架中的参数修改和完善理解调参对于框架识别精度的影响。最终目标是熟悉包括软件安装在内的深度学习环境的搭建、框架的构建、参数的调整做一个系统的学习和理解。

    1 基本介绍和环境搭建

    1.1关于TensorFlow-GPU环境搭建

      深度学习的核心概念就是以张量(矩阵)运算模拟神经网络的。TensorFlow主要的设计就是让矩阵运算达到最高性能,并且能够在各种不同的平台下运行。TensorFlow最初由谷歌开发,深度学习的发展是由前景的,谷歌希望建立一个开源的社区,强大TensorFlow使其更加完善,最后开源。TensorFlow架构主要由处理器(cpu/gpu/tpu)、平台(win/linux/android/ios/raspi)、tensoflow引擎、前端语言(python/c++)、高级api(keras/TF-learn/TF-slim/TF-layer)组成。如下图所示,TensorFlow架构组成。
    TensorFlow架构组成
            图1 TensorFlow架构组成

      TensorFlow是比较低级深度学习API,所以在程序设计模型时必须自行设计:张量乘积、卷积等底层操作,好处是我们可以自行设计各种深度学习模型,但缺点是开发时需要编写更多的程序代码,并且需要花费很长的时间。所以网上的开发社区以TensorFlow为底层开发很多高级的深度学习API,例如Keras、TF-Learn等。这样可以使得开发者使用更简洁、更具可读性的程序代码就可以构建出各种复杂的深度学习模型。本文主要采用Keras,因为Keras功能最为完整。

      下面介绍如何在Windows上安装TensorFlow-GPU版本,因为其计算能力更强。因为之前本人已经安装过了TensorFlow-GPU版本,并搭建了环境,参考代码实现了一些经典数据集的学习训练,比如Keras MINIST、Keras-CIFAR-10等。下面将讲解如何安装和踩坑出现的问题。首先明确,对于GPU版本的TensorFlow主要通过NVIDIA提供的CUDA和cudnn存取GPU,CUDA是NVIDIA推出的整合技术,实质功能就是一种通过应用显卡处理数量较大的数据问题的架构,而cudnn是NVIDIA深度学习SDK的一部分,用于提供GPU深度学习库和加速深度学习的。

    具体的安装步骤

    第一步:安装Anaconda

      指的是一个开源的Python发行版本,其包含了conda、Python等180多个科学包及其依赖项。(按步骤安装即可)

    在这里插入图片描述
            图示上下分别为基本环境和新建的虚拟的GPU环境。

    第二步:安装GPU版本需要,明确显卡型号

      (目前绝大多数时NVIDIA的显卡),去官方的网址下载CUDA和cudnn(注意这里需要明确版本对应查找适合是显卡型号的CUDA然后根据CUDA确定cudnn)实际在我测试过程当中可以低版本安装,但是不能高于当前适用的版本安装。(实际显卡提示安装CUAD11.0,cudnn 8.0但是我安装的是CUDA10.0和cudnn7.4)
    在这里插入图片描述
          图示 为安装CUDA版本的版本,cudnn对应可以去配置文件里面查看。

    第三步:打开conda终端建立Tensorflow环境

    conda create –name tensorflow-gpu python=3.7

      建立名为tensorflow-gpu的python3.7的环境(或者在后面加上anaconda直接下载python所有包)如果需要单独安装缺少的包pip install 包名 -i 软件源

    第四步:激活虚拟环境:

    activate tensorflow-gpu
    在这里插入图片描述

      创建的虚拟环境会在anaconda安装路径下envs中出现新建的虚拟环境。

    在这里插入图片描述
    启用python环境导入tensorflow,显示安装成功。

    第五步:安装ensorflow gpu版本:

    pip install tensorflow-gpu -i 软件源
    
    • 1

    中科大软件源https://pypi.mirrors.ustc.edu.cn/simple/,在安装tensorflow gpu版本的时候可以限制具体版本号即pip install tensorflow-gpu=1.14.0 -i 软件源

    第六步:安装keras:pip install keras -i 软件源

    第七步:进入IDE(Pycharm或者VScode)切换环境为tensorflow-gpu调试

    在这里插入图片描述
    图示为Tensorflow-gpu虚拟环境。

    1.2关于鸢尾花数据集介绍

      Iris 鸢尾花数据集是一个经典数据集,在统计学习和机器学习领域都经常被用作示例。数据集内包含 3 类,共 150 条记录,每类各 50 个数据,每条记录都有 4 项特征:花萼长度Sepal.Length、花萼宽度Sepal.Width、花瓣长度Petal.Length、花瓣宽度Petal.Width,可以通过这4个特征预测鸢尾花卉属于狗尾草iris-setosa、杂色鸢尾花 iris-versicolour、弗吉尼亚鸢尾花 iris-virginica是属于什么类别,在数据集中也包括花萼花瓣长度对应的鸢尾花种类Species数据。
    在这里插入图片描述
    一般由两种格式.csv和.txt格式。

    2 实现过程及分析

      本文主要通过Pycharm开发环境实现,基于tensorflow-gpu完成深度学习框架搭建。

    2.1 数据集可视化化以及PCA降维:

    在这里插入图片描述

    2.2 实验结果如下:

    (1)学习率0.1,循环次数为500,当次数为185时,测试准确率刚好为1
    Epoch 185, loss: 0.05128058139234781,Test_acc: 1.0
    在这里插入图片描述

    (2)学习率为0.01,循环次数为500,当次数为500时,测试准确为0.66…
    Epoch 499, loss: 0.08802829124033451,Test_acc: 0.6666666666666666
    在这里插入图片描述

    (3)学习率为0.5,循环次数为500,当次数为500时,精度为1.0
    Epoch 499, loss: 0.024999298620969057,Test_acc: 1.0
    在这里插入图片描述

    (4)学习率为0.1,循环次数为3000,当次数为185时,精度为1
    Epoch 185, loss: 0.05128058139234781,Test_acc: 1.0
    在这里插入图片描述
    (5)学习率为0.1,循环次数186,当次数为185时,精度为1
    Epoch 185, loss: 0.05128058139234781,Test_acc: 1.0
    在这里插入图片描述

    2.3 分析结论

    实际上我们可以对比发现,(1)(2)每轮循环次数一样学习率不同导致的情况不同,当学习率过小的时候会影响模型的收敛时间,直观来看明显使得过程缓慢;(1)(3)可以得到学习率过大,会导致梯度会在最小值附近可能来回震荡,严重的可能导致无法收敛。从一定程度上来看,(4)(5)学习率一定循环次数在达到一个固定的值后,再多次循环不影响精度值。
    具体实现代码见附录。

    附录(完整Python代码)

    
    ```python
    #导入所需模块:
    import tensorflow as tf                 # 导入模型框架
    from sklearn import datasets            # 从sklearn文件包中导入含有的数据集
    from matplotlib import pyplot as plt    # 从python中导入绘图库matplotlib
    import numpy as np                      # 导入开源计算包numpy
    from sklearn.decomposition import PCA
    from mpl_toolkits.mplot3d import Axes3D
    
    tf.enable_eager_execution(
                    config=None,
                    device_policy=None,
                    execution_mode=None
                )     # 在即将到来的TensorFlow2.0中将对部分机制做出重大调整,其中之一就是将原有的静态图机制调整为动态图机制,这将使得TensorFlow更加灵活和易用,2.0版本之前,可以通过 tf.enable_eager_execution() 方法来启用动态图机制
    
    #导入数据可视化数据集
    #————————————————————————————————
    iris = datasets.load_iris()
    X = iris.data[:, :2]  # 列切片索引:只取前两个特征.
    y = iris.target
    
    x_min, x_max = X[:, 0].min() - .5, X[:, 0].max() + .5
    y_min, y_max = X[:, 1].min() - .5, X[:, 1].max() + .5
    
    plt.figure(2, figsize=(8, 6))
    plt.clf()
    
     绘制训练数据点
    plt.scatter(X[:, 0], X[:, 1], c=y, cmap=plt.cm.Set1,
                edgecolor='k')
    plt.xlabel('Sepal length')
    plt.ylabel('Sepal width')
    
    plt.xlim(x_min, x_max)
    plt.ylim(y_min, y_max)
    plt.xticks(())
    plt.yticks(())
    
     为了对数据的各个维度之间的相互作用有一个更好地理解,
    #绘制前三个 PCA dimensions。
    fig = plt.figure(1, figsize=(8, 6))
    ax = Axes3D(fig, elev=-150, azim=110)
    X_reduced = PCA(n_components=3).fit_transform(iris.data)
    ax.scatter(X_reduced[:, 0], X_reduced[:, 1], X_reduced[:, 2], c=y,
               cmap=plt.cm.Set1, edgecolor='k', s=40)
    ax.set_title("First three PCA directions")
    ax.set_xlabel("1st eigenvector")
    ax.w_xaxis.set_ticklabels([])
    ax.set_ylabel("2nd eigenvector")
    ax.w_yaxis.set_ticklabels([])
    ax.set_zlabel("3rd eigenvector")
    ax.w_zaxis.set_ticklabels([])
    
    plt.show()
    #————————————————————————————————————
    #框架模型搭建以及实现
    #导入数据:共计数据150组,分别为输入特征(x)和标签(y)
    x_data = datasets.load_iris().data
    y_data = datasets.load_iris().target
    
     输入数据预处理:随机打乱数据(因为原始数据是顺序的,顺序不打乱会影响准确率)
    np.random.seed(116)  # 使用相同的seed,保证输入特征和标签一一对应(seed参数每一个数对应一个随机规则,数字一样随机规则一样产生的随机结果也一样)
    np.random.shuffle(x_data)   # 重新排序返回一个随机序列,在原数组上进行,改变自身序列,无返回值
    np.random.seed(116)
    np.random.shuffle(y_data)
    tf.compat.v1.random.set_random_seed(116)     # 版本原因导致的一些写法错误,tf.random.set_seed(116)修改内容
    
    #分割数据集:将打乱后的数据集(共有数据150行)分割为训练集和测试集,训练集为前120行,测试集为后30行
    x_train = x_data[:-30]         # x_data[:-30]=x_data[0:120]
    y_train = y_data[:-30]
    x_test = x_data[-30:]          # x_data[-30:]=x_data[120:150]
    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组数据)
    #batch(数据集大小/batch大小),两个数字可能不是整除,会导致一个batch大小可能小于等于batch size
    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 = 186 # 循环500轮
    loss_all = 0  # 每轮分4个step,loss_all记录四个step生成的4个loss的和
    
    #训练部分
    
    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做准备
    
        # 测试部分
        # total_correct为预测对的样本个数, total_number为测试的总样本数,将这两个变量都初始化为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)
            # 将每个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
    
        total_number= int(total_number)               #错误的原因在,一个是numpy对象,一个是Dimension对象,无法相除,                                               #用int函数,将Dimension对象对象转换为int
        acc = total_correct / total_number
        test_# 导入所需模块:
    import tensorflow as tf                 # 导入模型框架
    from sklearn import datasets            # 从sklearn文件包中导入含有的数据集
    from matplotlib import pyplot as plt    # 从python中导入绘图库matplotlib
    import numpy as np                      # 导入开源计算包numpy
    
    tf.enable_eager_execution(
                    config=None,
                    device_policy=None,
                    execution_mode=None
                )     # 在即将到来的TensorFlow2.0中将对部分机制做出重大调整,其中之一就是将原有的静态图机制调整为动态图机制,#
                      # 这将使得TensorFlow更加灵活和易用,2.0版本之前,可以通过 tf.enable_eager_execution() 方法来启用动态图机制
    
     导入数据:共计数据150组,分别为输入特征(x)和标签(y)
    x_data = datasets.load_iris().data
    y_data = datasets.load_iris().target
    
     输入数据预处理:随机打乱数据(因为原始数据是顺序的,顺序不打乱会影响准确率)
    np.random.seed(116)  # 使用相同的seed,保证输入特征和标签一一对应(seed参数每一个数对应一个随机规则,数字一样随机规则一样产生的随机结果也一样)
    np.random.shuffle(x_data)   # 重新排序返回一个随机序列,在原数组上进行,改变自身序列,无返回值
    np.random.seed(116)
    np.random.shuffle(y_data)
    tf.compat.v1.random.set_random_seed(116)     # 版本原因导致的一些写法错误,tf.random.set_seed(116)修改内容
    
    #分割数据集:将打乱后的数据集(共有数据150行)分割为训练集和测试集,训练集为前120行,测试集为后30行
    x_train = x_data[:-30]         # x_data[:-30]=x_data[0:120]
    y_train = y_data[:-30]
    x_test = x_data[-30:]          # x_data[-30:]=x_data[120:150]
    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组数据)
     batch(数据集大小/batch大小),两个数字可能不是整除,会导致一个batch大小可能小于等于batch size
    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 = 186 # 循环500轮
    loss_all = 0  # 每轮分4个step,loss_all记录四个step生成的4个loss的和
    
     训练部分
    
    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做准备
    
        # 测试部分
        # total_correct为预测对的样本个数, total_number为测试的总样本数,将这两个变量都初始化为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)
            # 将每个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
    
        total_number= int(total_number)               #错误的原因在,一个是numpy对象,一个是Dimension对象,无法相除,                                               #用int函数,将Dimension对象对象转换为int
        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_results, label="$Loss$")  # 逐点画出trian_loss_results值并连线,连线图标是Loss
    plt.legend()  # 画出曲线图标
    plt.show()  # 画出图像
    
     绘制 Accuracy 曲线
    plt.title('Acc Curve')  # 图片标题
    plt.xlabel('Epoch')  # x轴变量名称
    plt.ylabel('Acc')  # y轴变量名称
    plt.plot(test_acc, label="$Accuracy$")  # 逐点画出test_acc值并连线,连线图标是Accuracy
    plt.legend()
    plt.show()
    #导入所需模块:
    import tensorflow as tf                 # 导入模型框架
    from sklearn import datasets            # 从sklearn文件包中导入含有的数据集
    from matplotlib import pyplot as plt    # 从python中导入绘图库matplotlib
    import numpy as np                      # 导入开源计算包numpy
    
    tf.enable_eager_execution(
                    config=None,
                    device_policy=None,
                    execution_mode=None
                )     # 在即将到来的TensorFlow2.0中将对部分机制做出重大调整,其中之一就是将原有的静态图机制调整为动态图机制,#
                      # 这将使得TensorFlow更加灵活和易用,2.0版本之前,可以通过 tf.enable_eager_execution() 方法来启用动态图机制
    
    #导入数据:共计数据150组,分别为输入特征(x)和标签(y)
    x_data = datasets.load_iris().data
    y_data = datasets.load_iris().target
    
    #输入数据预处理:随机打乱数据(因为原始数据是顺序的,顺序不打乱会影响准确率)
    np.random.seed(116)  # 使用相同的seed,保证输入特征和标签一一对应(seed参数每一个数对应一个随机规则,数字一样随机规则一样产生的随机结果也一样)
    np.random.shuffle(x_data)   # 重新排序返回一个随机序列,在原数组上进行,改变自身序列,无返回值
    np.random.seed(116)
    np.random.shuffle(y_data)
    tf.compat.v1.random.set_random_seed(116)     # 版本原因导致的一些写法错误,tf.random.set_seed(116)修改内容
    
    #分割数据集:将打乱后的数据集(共有数据150行)分割为训练集和测试集,训练集为前120行,测试集为后30行
    x_train = x_data[:-30]         # x_data[:-30]=x_data[0:120]
    y_train = y_data[:-30]
    x_test = x_data[-30:]          # x_data[-30:]=x_data[120:150]
    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组数据)
    #batch(数据集大小/batch大小),两个数字可能不是整除,会导致一个batch大小可能小于等于batch size
    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 = 186 # 循环500轮
    loss_all = 0  # 每轮分4个step,loss_all记录四个step生成的4个loss的和
    
    #训练部分
    
    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做准备
    
        # 测试部分
        # total_correct为预测对的样本个数, total_number为测试的总样本数,将这两个变量都初始化为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)
            # 将每个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
    
        total_number= int(total_number)               #错误的原因在,一个是numpy对象,一个是Dimension对象,无法相除,                                               #用int函数,将Dimension对象对象转换为int
        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_results, label="$Loss$")  # 逐点画出trian_loss_results值并连线,连线图标是Loss
    plt.legend()  # 画出曲线图标
    plt.show()  # 画出图像
    #绘制 Accuracy 曲线
    plt.title('Acc Curve')  # 图片标题
    plt.xlabel('Epoch')  # x轴变量名称
    plt.ylabel('Acc')  # y轴变量名称
    plt.plot(test_acc, label="$Accuracy$")  # 逐点画出test_acc值并连线,连线图标是Accuracy
    plt.legend()
    plt.show()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216
    • 217
    • 218
    • 219
    • 220
    • 221
    • 222
    • 223
    • 224
    • 225
    • 226
    • 227
    • 228
    • 229
    • 230
    • 231
    • 232
    • 233
    • 234
    • 235
    • 236
    • 237
    • 238
    • 239
    • 240
    • 241
    • 242
    • 243
    • 244
    • 245
    • 246
    • 247
    • 248
    • 249
    • 250
    • 251
    • 252
    • 253
    • 254
    • 255
    • 256
    • 257
    • 258
    • 259
    • 260
    • 261
    • 262
    • 263
    • 264
    • 265
    • 266
    • 267
    • 268
    • 269
    • 270
    • 271
    • 272
    • 273
    • 274
    • 275
    • 276
    • 277
    • 278
    • 279
    • 280
    • 281
    • 282
    • 283
    • 284
    • 285
    • 286
    • 287
    • 288
    • 289
    • 290
    • 291
    • 292
    • 293
    • 294
    • 295
    • 296
    • 297
    • 298
    • 299
    • 300
    • 301
    • 302
    • 303
    • 304
    • 305
    • 306
    • 307
    • 308
    • 309
    • 310
    • 311
    • 312
    • 313
    • 314
    • 315
    • 316
    • 317
    • 318
    • 319
    • 320
    • 321
    • 322
    • 323
    • 324
    • 325
    • 326
    • 327
    • 328
    • 329
    • 330
    • 331
    • 332
    • 333
    • 334
    • 335
    • 336
    • 337
    • 338
    • 339
    • 340
    • 341
    • 342
    • 343
    • 344
    • 345
    • 346
    • 347
    • 348
    • 349
    • 350
    • 351
    • 352
    • 353
    • 354
    • 355
    • 356
    • 357
    • 358
    • 359
    • 360
    • 361
    • 362
    • 363
    • 364
    • 365
    • 366
    • 367
    • 368
    • 369
    • 370
  • 相关阅读:
    Spring——@Transactional事务注解原理及失效场景
    Amazon云计算AWS之[1]基础存储架构Dynamo
    Hive分区表和分桶表
    【655. 输出二叉树】
    【虹科新品】HK-MR340系列传感器产品介绍合集
    MT4选网页版还是桌面版?anzo capital昂首资本分析优劣
    查看目录和文件大小: du -sh
    WEB网页设计期末作业个人主页——基于HTML+CSS制作个人简介网站
    有意思的水平横向溢出滚动
    电机学 基础概念 野火电机第四章 电机分类
  • 原文地址:https://blog.csdn.net/weixin_42491720/article/details/127983707