深度学习(基于Tensorflow2.0)学习笔记——实战Tensorflow分类器

引言

经过一番折腾,我们终于配置好了Tensorflow2.0的环境,接下来通过Tensorflow来一起揭开深度学习的神秘面纱吧。

实战Tensorflow分类器

首先我们打开我们昨天的Hello TF工程,进入编辑界面之后,依次点击Kernel -> Restart & Clear Output,这样就可以把上一次的编译结果清除了。为了避免产生一些不必要的错误,我们尽量在每次重新打开一个工程的都要执行此操作,然后再重新运行。在这里插入图片描述
完成之后,我们在这里首先把今天以及以后需要用到的python库添加一下。

import matplotlib as mpl
import matplotlib.pyplot as plt
%matplotlib inline
import numpy as np
import sklearn
import pandas as pd
import tensorflow as tf
import tensorflow.keras as keras

我分别简单地介绍一下这些库的作用。首先是matplotlib,它的作用是就相当于一个绘图工具,有了它,我们可以很方便的来绘制各种函数图像或者展示其他图像。同时下面的是matplotlib.pyplot是它的一个子类,为了方便我们直接将他添加进来。接下来为了配合Jupyter Notebook使用,我们需要添加%matplotlib inline这行代码。其次numpy以及pandas我们就不再说了,二者都是常用的python包。作为sklearn来说,其本身可以理解为一个数据库,我们接下来会用到其中的一些数据。最后是tensorflow,然后我们添加了keras这个库。这里要注意,keras是Tensorflow里面有关深度学习的一个库,我们要用到的深度学习的一些高阶API几乎全部来自于这个库,我们接下来搭建的深度学习框架就是依靠keras来完成的。

然后点击运行。如果这时出现报错就说明你的某些库没有成功安装,这时你就需要回到你的环境里面,像之前安装tensorflow一样来用pip安装你所缺少的这些库。具体步骤都在这里了。

数据的读取与展示

作为一个分类问题,我们就需要导入待分类的数据集,这里我们选择官方提供的Fashion-MNIST数据集。之前对深度学习感兴趣的小伙伴应该都知道MNIST手写数字集,该数据集包含了大量的手写数字。在很长一段时间内来自机器学习、机器视觉、人工智能、深度学习领域的研究员们把这个数据集作为衡量算法的基准之一。在Tensorflow官方教程中甚至将其比作深度学习的Hello Word!(众所周知,在学习一个新的编程语言的时候我们总是倾向于让其打印Hello World!作为开始)。实际上,MNIST数据集已经成为算法作者的必测的数据集之一。有人曾调侃道:"如果一个算法在MNIST不work, 那么它就根本没法用;而如果它在MNIST上work, 它在其他数据上也可能不work!"但随着深度学习的发展,用于训练的模型越来越复杂,更多的人认为MINST已经不适合用来做深度学习了。

Fashion-MNIST是一个替代MNIST手写数字集的图像数据集。 它是由Zalando(一家德国的时尚科技公司)旗下的研究部门提供。其涵盖了来自10种类别的共7万个不同商品的正面图片。Fashion-MNIST的大小、格式和训练集/测试集划分与原始的MNIST完全一致。60000/10000的训练测试数据划分,28x28的灰度图片。你可以直接用它来测试你的机器学习和深度学习算法性能,且不需要改动任何的代码。

导入这个数据集的方法也很简单。

fashion_mnist = keras.datasets.fashion_mnist
(x_train_all, y_train_all), (x_test, y_test) = fashion_mnist.load_data()

这样就成功导入了该数据集,在这里我们将这个数据集做了一下分类,分别进行训练和测试。然后点击运行,程序将自动帮你下载这个数据集。但是在这里我之前一直遇到网络连接导致下载失败的问题,这里我给出手动下载的方法。(如果你下载成功了请忽略此内容)

首先我们应该清楚,我们这里需要下载的其实四个包含数据的.gz文件,在下面我给出了这四个文件的下载方式。

名称 描述 样本数量 文件大小 链接
train-images-idx3-ubyte.gz 训练集的图像 60,000 26 MBytes 下载
train-labels-idx1-ubyte.gz 训练集的类别标签 60,000 29 KBytes 下载
t10k-images-idx3-ubyte.gz 测试集的图像 10,000 4.3 MBytes 下载
t10k-labels-idx1-ubyte.gz 测试集的类别标签 10,000 5.1 KBytes 下载

或者可以直接下载整个库git clone [email protected]:zalandoresearch/fashion-mnist.git

下载完成之后将这四个文件放到同一个文件夹下,然后在程序中我们需要定义一个读取这些数据的函数,如下:

def load_data(path,files):
    import gzip
    import numpy as np
    paths = [path + each for each in files]
    with gzip.open(paths[0],'rb') as lbpath:
        y_train_all = np.frombuffer(lbpath.read(),np.uint8,offset=8)
    with gzip.open(paths[1],'rb') as imgpath:
        x_train_all = np.frombuffer(imgpath.read(),np.uint8,offset = 16).reshape(len(y_train_all),28,28)
    with gzip.open(paths[2],'rb') as lbpath:
        y_test = np.frombuffer(lbpath.read(),np.uint8,offset=8)
    with gzip.open(paths[3],'rb') as imgpath:
        x_test = np.frombuffer(imgpath.read(),np.uint8,offset=16).reshape(len(y_test),28,28)
    return (x_train_all,y_train_all),(x_test,y_test)

然后将我们的数据集导入:

path ='/home/patrick/fashion-mnist-master/data/fashion/' #your file path 
file = ['train-labels-idx1-ubyte.gz','train-images-idx3-ubyte.gz','t10k-labels-idx1-ubyte.gz','t10k-images-idx3-ubyte.gz']
(x_train_all, y_train_all), (x_test, y_test) =load_data(path,file)

注意一下,这里的path是我们刚才存放数据集的文件夹的路径。然后点击运行,数据集就可以成功导入了,我这里导入的结果和上面是一致的。

然后们开始将数据集进行分类:

x_valid, x_train = x_train_all[:5000], x_train_all[5000:]
y_valid, y_train = y_train_all[:5000], y_train_all[5000:]

我们从全部的训练数据中拿出来前5000张作为验证集,其余的作为训练集。然后我们打印一下各个各个集合的大小:

print(x_valid.shape,y_valid.shape)
print(x_train.shape,y_train.shape)
print(x_test.shape,y_test.shape)

如果你的上述操作都正确的话,输出应该为:

(5000, 28, 28) (5000,)
(55000, 28, 28) (55000,)
(10000, 28, 28) (10000,)

我们可以看到,我们的验证集有5000张图片,训练集有55000张图片,测试集有10000张图片,它们的大小分别都是28*28(这和MNIST手写数字的数据集是一样的)。

我们另外还知道,在我们所有的这些数据一共分为了十个类,也就是有十个标签,这里我们需要把这几个标签的名字添加一下:

class_names = ['T-shirt/top', 'Trouser', 'Pullover', 'Dress', 'Coat',
               'Sandal', 'Shirt', 'Sneaker', 'Bag', 'Ankle boot']

它们之间的对应关系如下:

标签
0 T-shirt/top
1 Trouser
2 Pullover
3 Dress
4 Coat
5 Sandal
6 Shirt
7 Sneaker
8 Bag
9 Ankle boot

从这里我们可以初步看出来这些数据集都包括那些东西。然后我们需要进一步了解一下我们的数据集,看一下我们的数据集具体都包含什么内容。这里就需要用到我们刚才引入的matplotlib库中的pyplot类,我们先来定义一个函数实现一张图片的读取:

def show_single_image(img_arr):
	plt.imshow(img_arr, camp="binary")
	plt.show()
show_single_image(x_train[0])

具体的参数我就不再详细叙述了,我们这里目的是来展示一张二值图片,效果如下:
在这里插入图片描述
在这里我们也可以来展示多张图片,具体代码如下:

def show_images(n_rows, n_cols, x_data, y_data, class_names):
	assert len(x_data) == len(y_data)
	assert n_rows*n_cols < len(x_data)
	plt.figure(figsize = (n_cols*1.4, n_rows*1.6))
	for row in range(n_rows):
		for col in range(n_cols):
			index = n_cols*row + col
			plt.subplot(n_rows, n_cols, index+1)
			plt.imshow(x_data[index], cmap ="binary", interpolation = 'nearest')
			plt.axis('off')
			plt.title(class_names[y_data[index]])
	plt.show()

这里的输入参数分别为数据的行和列,以及数据和标签,最后一个参数是我们上面定义的类名,也添加进去一起显示出来。

show_images(3, 5, x_train, y_train, class_names)

这里我们要展示的就是前三行前五列的15张图片以及他们的标签,效果如下:
在这里插入图片描述

模型搭建

建立图层

接下来我们就要步入正题,利用Tensorflow的keras库来搭建一个模型进行分类。
这里我们用到的是tf.keras.models.Sequential这个API,关于这个API的说明详见Tensorflow官方文档。这里我们简单理解为它的作用就是将几个我们训练需要的层进行堆叠,从而形成一个网络。代码如下:

model = keras.models.Sequential()

作为一个神经网络首先需要一个输入层,在这个输入层里我们需要将28*28的二维矩阵展平为一个一维的向量(格式化参数),添加方法是利用tf.keras.layers.Flatten来完成。在展平之后我们需要继续创建隐藏层(在这里由于这些层次都是紧密连接或完全连接的,我们称其为全连接层),每个全连接层都需要有一个激活函数,这里用到的激活函数是一个ReLU函数,表示形式为y=max(0, x),然后我们需要添加一个具有128个节点(神经元)的全连接层,添加方法是利用tf.keras.layers.Dense实现。最后是我们的输出层,我们已经知道最终输出的结果必须是十个分数,即分别为该图片属于每种类型的概率。这里我们就要用到softmax模型,softmax是一个典型的回归模型,我们在这里可以将他理解为一个激活函数,表示形式为 x = [x1, x2, x3], y = [e^x1/sum, e^x2/sum, e^x3/sum], sum = e^x1 + e^x2 + e^x3.它可以将向量变成概率分布。关于这些函数和模型我计划接下来单独写一篇文章来详细介绍,这里我们只要知道它是用来正则化我们的数据并得到相应的概率即可。完整的代码如下:

model.add(keras.layers.Flatten(input_shape=[28, 28]))
model.add(keras.layers.Dense(128, activation='relu')
model.add(keras.layers.Dense(10, activation='softmax'))

点击运行完成模型的搭建。

编译模型

在开始准备训练模型之前,我们需要将模型进行编译。编译过程经常用的参数有三个,分别是

  1. 损失函数
  2. 优化器
  3. 观测指标

我们直接看代码:

model.compile(optimizer ='adam',
             loss = 'sparse_categorical_crossentropy',
             metrics=['accuracy'])

这里我们可以看出,我们的优化器选择的是adam,损失函数选择的是sparse_categorical_crossentropy,另外添加了观测指标accuracy即模型的准确性。这里我们要清楚,这些字符串在函数里分别映射到一个具体的函数,这些函数也可以自己定义。然后点击运行,我们的模型就编译完成了。

现在我们来看一下我们的模型究竟是什么样的:

model.summary()

运行后输出:

Model: "sequential"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
flatten (Flatten)            (None, 784)               0         
_________________________________________________________________
dense (Dense)                (None, 128)               100480    
_________________________________________________________________
dense_1 (Dense)              (None, 10)                1290      
=================================================================
Total params: 101,770
Trainable params: 101,770
Non-trainable params: 0

这里我们大概能看出整个网络的结构了。首先是输入层,这里要注意,每一层的大小中None不是表示不存在,也不是表示为0,这里的None表示的是样本数。第二层表示一个全连接层,由来自输入层的数据乘一个矩阵w之后,加上相应的偏置b所得到的,这里我们能看出w应该是一个大小为784*128的矩阵,而b应该是一个长度为128的向量。之后经过softmax变成相应的概率分布到输出层。

训练模型

模型的训练非常简单,只需要调用model.fit方法就可以了:

history = model.fit(x_train, y_train, epochs=10, validation_data=(x_valid,y_valid))

我们可以看到需要输入的参数主要有训练集,训练集标签,迭代次数(epochs)以及相应的验证集和验证集标签。这里的history里面储存的是在模型训练过程中一些参数变化的情况。由于我们的数据集的规模比较小,所以我们的迭代次数比较少。点击运行模型就开始训练了。
在这里插入图片描述
在这里模型每一次训练之后都会进行验证,从而确实每一次的准确度。在训练的过程中,我们会发现随着训练次数的增多,准确率在不断提高。我们来绘制一下训练过程中各个参数的变化情况。

def plot_learning_curves(history):
    pd.DataFrame(history.history).plot(figsize=(8,5))
    plt.grid(True)
    plt.gca().set_ylim(0 ,1)
    plt.show()
    
plot_learning_curves(history)

输出图像大致如下:
在这里插入图片描述
从图中可以直观的看出在训练过程中,模型的准确率在不断提高,相应的损失也在不断下降。
然后需要对利用测试集对我们训练出来的模型进行评估:

model.evaluate(x_test, y_test)

运行后我们就能看到模型最终的准确率,一般应该在80%以上我们说这个模型可用。

用模型进行预测

最后一步就应该来看一下我们的训练出来的模型是否可以进行分类。为了进行预测,我们需要在建立一个预测模型,将我们刚才训练好的模型作为输入,然借助softmax激活函数得到相应的概率。

probability_model = tf.keras.Sequential([model, 
                                         tf.keras.layers.Softmax()])

我们将全部的测试集全部进行预测:

predictions = probability_model.predict(test_images)

这样我们就得到了对于测试集所有的预测标签,我们来看一下第一个预测的结果:

predictions[0]

运行后输出:

array([0.08593271, 0.08593269, 0.08593269, 0.08593272, 0.0859327 ,
       0.08604191, 0.08593274, 0.09021804, 0.08593276, 0.22221103],
      dtype=float32)

我们可以看到这里有十组数据,他们对应的分别是对这十个标签的概率(置信度),我们用numpy取出其中的最大值:

np.argmax(predictions[0])

发现结果输出为:

这意味着我们的模型对测试集中第一个标签的预测值为9,我们看一下测试集的第一个标签的值:

y_test[0]

运行:

这样我们就完成了对一个样本的正确预测。

发布了5 篇原创文章 · 获赞 7 · 访问量 433

猜你喜欢

转载自blog.csdn.net/qq_43632917/article/details/104355785
今日推荐