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

基于TensorFlow的鸢尾花分类实现

  • 0 引言
  • 1 基本介绍和环境搭建
    • 1.1关于TensorFlow-GPU环境搭建
      • 第一步:安装Anaconda:
      • 第二步:安装GPU版本需要,明确显卡型号
      • 第三步:打开conda终端建立Tensorflow环境
      • 第四步:激活虚拟环境:
      • 第五步:安装ensorflow gpu版本:
      • 第六步:安装keras:pip install keras -i 软件源
      • 第七步:进入IDE(Pycharm或者VScode)切换环境为tensorflow-gpu调试
    • 1.2关于鸢尾花数据集介绍
  • 2 实现过程及分析
    • 2.1 数据集可视化化以及PCA降维:
    • 2.2 实验结果如下:
    • 2.3 分析结论
  • 附录(完整Python代码)

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架构组成。

        图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多个科学包及其依赖项。(按步骤安装即可)

深度学习入门——基于TensorFlow的鸢尾花分类实现(TensorFlow_GPU版本安装、实现)_第1张图片
        图示上下分别为基本环境和新建的虚拟的GPU环境。

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

  (目前绝大多数时NVIDIA的显卡),去官方的网址下载CUDA和cudnn(注意这里需要明确版本对应查找适合是显卡型号的CUDA然后根据CUDA确定cudnn)实际在我测试过程当中可以低版本安装,但是不能高于当前适用的版本安装。(实际显卡提示安装CUAD11.0,cudnn 8.0但是我安装的是CUDA10.0和cudnn7.4)
深度学习入门——基于TensorFlow的鸢尾花分类实现(TensorFlow_GPU版本安装、实现)_第2张图片
      图示 为安装CUDA版本的版本,cudnn对应可以去配置文件里面查看。

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

conda create –name tensorflow-gpu python=3.7

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

第四步:激活虚拟环境:

activate tensorflow-gpu
深度学习入门——基于TensorFlow的鸢尾花分类实现(TensorFlow_GPU版本安装、实现)_第3张图片

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

深度学习入门——基于TensorFlow的鸢尾花分类实现(TensorFlow_GPU版本安装、实现)_第4张图片
启用python环境导入tensorflow,显示安装成功。

第五步:安装ensorflow gpu版本:

pip install tensorflow-gpu -i 软件源

中科大软件源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的鸢尾花分类实现(TensorFlow_GPU版本安装、实现)_第5张图片
图示为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数据。
深度学习入门——基于TensorFlow的鸢尾花分类实现(TensorFlow_GPU版本安装、实现)_第6张图片
一般由两种格式.csv和.txt格式。

2 实现过程及分析

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

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

深度学习入门——基于TensorFlow的鸢尾花分类实现(TensorFlow_GPU版本安装、实现)_第7张图片

2.2 实验结果如下:

(1)学习率0.1,循环次数为500,当次数为185时,测试准确率刚好为1
Epoch 185, loss: 0.05128058139234781,Test_acc: 1.0
深度学习入门——基于TensorFlow的鸢尾花分类实现(TensorFlow_GPU版本安装、实现)_第8张图片

(2)学习率为0.01,循环次数为500,当次数为500时,测试准确为0.66…
Epoch 499, loss: 0.08802829124033451,Test_acc: 0.6666666666666666
深度学习入门——基于TensorFlow的鸢尾花分类实现(TensorFlow_GPU版本安装、实现)_第9张图片

(3)学习率为0.5,循环次数为500,当次数为500时,精度为1.0
Epoch 499, loss: 0.024999298620969057,Test_acc: 1.0
深度学习入门——基于TensorFlow的鸢尾花分类实现(TensorFlow_GPU版本安装、实现)_第10张图片

(4)学习率为0.1,循环次数为3000,当次数为185时,精度为1
Epoch 185, loss: 0.05128058139234781,Test_acc: 1.0
深度学习入门——基于TensorFlow的鸢尾花分类实现(TensorFlow_GPU版本安装、实现)_第11张图片
(5)学习率为0.1,循环次数186,当次数为185时,精度为1
Epoch 185, loss: 0.05128058139234781,Test_acc: 1.0
深度学习入门——基于TensorFlow的鸢尾花分类实现(TensorFlow_GPU版本安装、实现)_第12张图片

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()

你可能感兴趣的:(深度学习,语义分割,tensorflow,深度学习,分类)