从Fashion-Mnist开始,入门Tensorflow与深度
从今天开始,我们进行机器学习领域的最后一块拼图——深度学习的学习之旅,以及Tensorflow这个工具的使用。
深度学习即deep learning, 这种机器学习算法源于人们通过人类大脑的学习过程进行研究而受到启发进而通过人工神经网络模拟人类大脑学习过程。通过仔细的品味,可以发现它和我们常说的Data Mining(数据挖掘)还是有一些不同。
Deep Learning 通过构建多层次的神经网络进行学习,强调的是自适应感知和人工智能。通过构建多层次网络的来训练和学习数据集中的规律,这种设计灵感来自于人们研究大脑对认识事物的过程。我们的眼睛中的视觉神经捕捉事物的颜色、质地、轮廓等信息并抽象化在结合相应的标签形成记忆。
记忆是智能的基石。而基于多层级神经网络的深度学习算法也正是如此。所以,从这个方面来说,深度学习的发展和兴起很大程度上是源于人类对自身发展出的智能进行逆向开发的过程。既然人类拥有的我们所谓的智能,很自然的我们就会探索我们这种智能是如何产生的。如果这个过程可以量化并实体化成一套程序放入机器中运行,那么很自然的,这样的机器也会理论上和我们人类拥有同样的智能。从这个方面来说,深度学习是计算机科学与神经科学/认知科学的交叉;而Data Mining 强调的是通过大数据、统计数学分析来挖掘数据中的规律,是计算机和统计学的交叉。
在接下来的几周中,我们将带着大家学习深度学习中的常用网络结构,我们用到的工具是Tensorflow。TensorFlow 是一个开源的、基于 Python 的机器学习框架,它由 Google 开发,并在图形分类、音频处理、推荐系统和自然语言处理等场景下有着丰富的应用,是目前最热门的机器学习框架。
TensorFlow的名字中已经说明了它最重要的两个概念——Tensor和Flow。Tensor就是张量,在TensorFlow中,张量可以被简单地理解为多维数组,Flow翻译成中文就是“流”,它直观的表述计算的过程,即数据tensor流入一个节点,节点按照固定好的算法进行计算输出,流入到下一层或下一个节点。TensorFlow中的每一个计算都是计算图上的一个节点,而节点之间的边描述了计算之间的依赖关系。这种计算流图表达了数据从输入到输出的整个过程。这种计算图结构和Matlab中的Simulink计算图很像。下面展示一张计算流图给大家感受一下:
image.png
好了,本次我们就用一个小案例带着大家入门Tensorflow的使用。通过这个案例,大家可以初步感受到使用在Python中使用Tensorflow搭建神经算法的便利性。
我们直接使用tensorflow里面的keras模块中自带的Fashion-Mnist数据集来进行演示。在之前的sklearn学习中,我们接触过一个手写字体的数据集minist用来学习分类算法,这里的fashion-mnist可以当作手写字体minist数据集的升级版本。该数据集中包含了60000张28*28的图片,同样是分成了10个类别:0 T恤(T-shirt)、1 裤子(Trouser)、 2 套头衫(Pullover)、 3 连衣裙(Dress)、 4 外套(Coat)、 5 凉鞋(Sandal) 、6 衬衫(Shirt)、 7 运动鞋(Sneaker)、 8 包(Bag)、 9 靴子(Ankle boot)
下面代码走起!
step1-导入tensorflow和其他库
import numpy as np
import pandas as pd
import os
import sys
import time
import sklearn
import tensorflow as tf
from tensorflow import keras
import matplotlib as mpl
import matplotlib.pyplot as plt
# 查看各个库的版本是否满足要求
print('keras version: ', keras.__version__)
for module in mpl,np,pd,sklearn,tf:
print(module.__name__, module.__version__)
>>>
keras version: 2.4.0
matplotlib 3.2.2
numpy 1.18.5
pandas 1.0.5
sklearn 0.23.1
tensorflow 2.3.1
可以看到tenflow为2.3.1版,我们以后的各项试验也是基于这个版本
小技巧: 可以通过一个for循环将各个库的版本统一输出,简洁高效!
step2-导入Fashion-Mnist数据集,并拆分
# 数据集共有60000张图片,前50000张用于训练,后10000张测试
# 训练集按照前55000张训练,后5000张验证
fashion_mnist = keras.datasets.fashion_mnist
(x_train_all, y_train_all), (x_test, y_test) = fashion_mnist.load_data()
x_valid, x_train = x_train_all[:5000], x_train_all[5000:]
y_valid, y_train = y_train_all[:5000], y_train_all[5000:]
print(x_train_all.shape, y_train_all.shape)
print(x_valid.shape, y_valid.shape)
print(x_train.shape, y_train.shape)
>>>
(60000, 28, 28) (60000,)
(5000, 28, 28) (5000,)
(55000, 28, 28) (55000,)
可以看到每一张图片为一个28*28的二维数组。我们可以用matplot中的image show功能直接打印出来看看。下面打印前30个数据看看到底是啥东东。
for i in range(3):
for j in range(10):
index = 10 * i + j
plt.subplot(3, 10, index+1)
plt.imshow(x_train[index], cmap = 'binary',
interpolation= 'nearest')
plt.axis('off')
结果如下:3行10列,都是些衣服包包之类的,果然很Fansion!
image.png
我们在把图片的标签作为图片标题加上:
def show_all_image(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.6, n_rows * 1.8))
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()
class_names = ['T-shirt','Trouser','Pullover','Dress','Coat','Sandal','Shirt',
'Sneaker','Bag','Ankle boot']
show_all_image(3, 5, x_train, y_train, class_names)
image.png
增加标签后看起来舒服多了!
step3-使用Tensorflow中的keras搭建网络并训练
model = tf.keras.Sequential() # 通过keras中的Sequential直接创建模型
model.add(keras.layers.Flatten(input_shape = [28,28])) # 输入层
model.add(keras.layers.Dense(400, activation = 'relu')) # 中间层
model.add(keras.layers.Dense(100, activation = 'relu')) # 中间层
# 输出层:
model.add(keras.layers.Dense(10, activation = 'softmax'))
创建好之后,可以通过model.summary查看一下模型:
model.summary()
>>>
Model: "sequential_1"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
flatten_1 (Flatten) (None, 784) 0
_________________________________________________________________
dense_3 (Dense) (None, 400) 314000
_________________________________________________________________
dense_4 (Dense) (None, 100) 40100
_________________________________________________________________
dense_5 (Dense) (None, 10) 1010
=================================================================
Total params: 355,110
Trainable params: 355,110
Non-trainable params: 0
_________________________________________________________________
可以看到网络有4层结构,问题来了,为什么第二层的参数个数是314000?
我们是通过layers.Dense来添加层的,这样的网络为全连接网络。即:网络中的每一个神经元会和下一层的每个神经元连接。
- 输入: 28*28 = 784,一维向量
- 第二层: 400个神经元
- 这两层之间的连接是通过来建立全连接
所以个数为784*400 + 400 = 314000个
这个网络结构看起来不够过瘾,我们直接用计算流图更加直观。
计算流图:
image.png
可以看到我们的网络结构还是非常简单的。
step4-训练网络并输出网络结果
model.compile(loss = 'sparse_categorical_crossentropy',
optimizer = 'adam',
metrics = ['accuracy'])
history = model.fit(x_train, y_train, epochs = 10,
validation_data = (x_valid, y_valid))
>>>
Epoch 1/10
1719/1719 [==============================] - 2s 1ms/step - loss: 2.2141 - accuracy: 0.6792 - val_loss: 0.7868 - val_accuracy: 0.7108
Epoch 2/10
1719/1719 [==============================] - 2s 1ms/step - loss: 0.7171 - accuracy: 0.7144 - val_loss: 0.6604 - val_accuracy: 0.7844
Epoch 3/10
1719/1719 [==============================] - 2s 1ms/step - loss: 0.6610 - accuracy: 0.7390 - val_loss: 0.6477 - val_accuracy: 0.7650
Epoch 4/10
1719/1719 [==============================] - 2s 1ms/step - loss: 0.5852 - accuracy: 0.7846 - val_loss: 0.5470 - val_accuracy: 0.8218
Epoch 5/10
1719/1719 [==============================] - 2s 1ms/step - loss: 0.4912 - accuracy: 0.8312 - val_loss: 0.4387 - val_accuracy: 0.8562
Epoch 6/10
1719/1719 [==============================] - 2s 1ms/step - loss: 0.4497 - accuracy: 0.8424 - val_loss: 0.4150 - val_accuracy: 0.8630
Epoch 7/10
1719/1719 [==============================] - 2s 1ms/step - loss: 0.4235 - accuracy: 0.8536 - val_loss: 0.4470 - val_accuracy: 0.8630
Epoch 8/10
1719/1719 [==============================] - 2s 1ms/step - loss: 0.4117 - accuracy: 0.8564 - val_loss: 0.4472 - val_accuracy: 0.8570
Epoch 9/10
1719/1719 [==============================] - 2s 1ms/step - loss: 0.3866 - accuracy: 0.8641 - val_loss: 0.4242 - val_accuracy: 0.8572
Epoch 10/10
1719/1719 [==============================] - 2s 1ms/step - loss: 0.3708 - accuracy: 0.8690 - val_loss: 0.4032 - val_accuracy: 0.8606
上面的代码中,我们使用adam作为优化器,用history记录训练的结果。
在model.fit中,我们定义了epochs=10,即迭代10次。从结果可以看到,短短10次之后,模型在验证集上即达到了0.86的精度!
我们输出训练过程的图形更加直观
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)
image.png
至此,通过不超过10行的代码我们就完成了一个简单的神经网络的搭建和训练。下一期我们来谈谈归一化和Tensorflow中的其他好用的功能。
本期结束!