要理解深度学习,需要熟悉很多简单的数学概念:张量,张量运算,微分,梯度下降等。
首先给出一个神经网络的示例,引出张量和梯度下降的概念。
该示例神经网络的问题是,将手写数据的灰度图像划分到10个类别中,使用MNIST数据集。
from keras.datasets import mnist
from keras import models
from keras import layers
from keras.utils import to_categorical
# train_images, train_labels组成测试集,模型在这些数据中进行学习。test_images, test_labels测试集中对模型进行测试。
#图像被编码为Numpy数组,而标签是数字数组,取值范围为0-9,图像和标签一一对应
(train_images, train_labels), (test_images, test_labels) = mnist.load_data()
network = models.Sequential()
# 层(layer)是一种数据处理模块,进去一些数据,出来的数据变得更加有用。层从输入数据中提取表示
# 要想训练网络,我们需要选择编译步骤的三个参数1:损失函数(loss function);2:优化器(optimizer);3:在训练和测试过程中需要监控的指标(metric)
network.add(layers.Dense(512, activation='relu', input_shape=(28 * 28,)))
network.add(layers.Dense(10, activation='softmax'))
network.compile(optimizer='rmsprop', loss='categorical_crossentropy', metrics=['accuracy'])
# 分类之前对数据进行的预处理
train_images = train_images.reshape((60000, 28 * 28))
train_images = train_images.astype('float32') / 255
test_images = test_images.reshape((10000, 28 * 28))
test_images = test_images.astype('float32') / 255
train_labels = to_categorical(train_labels)
test_labels = to_categorical(test_labels)
network.fit(train_images, train_labels, epochs=5, batch_size=128)
test_loss, test_acc = network.evaluate(test_images, test_labels)
print('test_acc:', test_acc)
数据存储在Numpy数组中,也叫张量(tensor),是数据容器。例:矩阵是二维张量。
标量
仅含一个数字的张量叫做标量,标量有0个轴(ndim == 0)。
向量
数字组成的数组叫做向量(vector)或一维张量(1D张量)
矩阵
向量组成的数组叫作矩阵(matrix)或二维张量
import numpy as np
x = np.array([[5, 4, 6, 8, 9],
[45, 87, 22, 5, 96],
[98, 12, 23, 56, 43]])
print(x.ndim)
# 得到 2
关键属性
张量由3个属性来定义
轴的个数:如3D张量有3个轴,2D张量有2个轴。
形状:如前面矩阵示例的形状为(3,5)。向量的形状值包含一个元素,比如(5,),而标量的形状为空,即为()。
数据类型(在Python库中通常叫做detype):张量类型可以是float32,uint8,float64等
from keras.datasets import mnist
(train_images, train_labels), (test_images, test_labels) = mnist.load_data()
print(train_images.ndim) # 轴的个数
print(train_images.shape) # 它的形状
print(train_images.dtype)
# 输出
# 3
# (60000, 28, 28)
# uint8
这里可以看出train_images是一个由8位整数组成的3D张量。更准确的说,它是60000个矩阵组成的数组,每个矩阵由28*28个整数组成。
使用Matplotlib库来显示这个3D张量中的第4个数字
from keras.datasets import mnist
(train_images, train_labels), (test_images, test_labels) = mnist.load_data()
print(train_images.ndim) # 轴的个数
print(train_images.shape) # 它的形状
print(train_images.dtype)
数据批量的概念
深度学习中所有数据张量的第一轴(0轴)都是样本轴,深度学习模型不会同时处理整个数据集,而是将数据拆分成小批量
下面代码是MNIST数据集对的一个批量,批量大小为128。
batch = train_image[:128] #第一个轴叫批量轴,常出现在keras和其他深度学习库中
batch = train_image[128*n:128 *(n+1)]
现实世界的张量
向量数据:2D张量,形状(samples,features)
时间序列数据或序列数据:3D张量,形状为(samples,timesteps,features)
图像:4D张量,形状为(samples,height,width,channels)
视频:5D张量,形状为(samples,frames,height,width,channels)
向量数据
第一个轴是样本轴,第二个轴是特征轴
例:每个人的信息包括姓名,电话和地址,每个人可以表示包含3个值的向量,整个数据集包含200个,所以可以存储在形状为(200,3)的2D张量中。
张量变形
张量变形是指改变张量的行和列,一得到想要的形状,变形后的张量元素总数个数与初始张量相同。以下代码了解张量变形。
import numpy as np
x = np.array([[0., 1.],
[2., 3.],
[4., 5.]])
print(x.shape)
a = x.reshape((6, 1))
print(a)
b = x.reshape((2, 3))
print(b)
矩阵转置也是张量变形
c = np.zeros((400, 30))
c = np.transpose(c)
print(c.shape)
根据上述给的示例,每个神经层都用下述方法对输入数据进行变换
output = relu(dot(w, input)+b)
w,b都是张量,均为该层的属性,他们被称为该层的权重,分别对应Kernel和bias属性。一开始,这些权重矩阵取较小的随机值。下一步根据反馈信号逐渐调节这些权重,这就是机器学习中的学习。
上述学习的过程一直重复,过程如下:
最终得到的网络在训练数据上的损失非常小,这里会导致过拟合,一般使用优化器来解决,以后的博客来详细介绍。
综上所诉:
train_images = train_images.reshape((60000, 28 * 28))
train_images = train_images.astype('float32') / 255
test_images = test_images.reshape((10000, 28 * 28))
test_images = test_images.astype('float32') / 255
输入图像保存在float32格式的Numpy张量中,形状分别为(60000,784)【训练数据】和(10000,784)【测试数据】
network = models.Sequential()
# 层(layer)是一种数据处理模块,进去一些数据,出来的数据变得更加有用。层从输入数据中提取表示
# 要想训练网络,我们需要选择编译步骤的三个参数1:损失函数(loss function);2:优化器(optimizer);3:在训练和测试过程中需要监控的指标(metric)
network.add(layers.Dense(512, activation='relu', input_shape=(28 * 28,)))
network.add(layers.Dense(10, activation='softmax'))
这个网络包含两个Dense层,每层对输入数据进行一些简单的张量运算,这些运算都包括张量权重
network.compile(optimizer='rmsprop', loss='categorical_crossentropy', metrics=['accuracy'])
上述是网络编译
network.fit(train_images, train_labels, epochs=5, batch_size=128)
fit过程中发生:网络在开始训练数据上进行迭代(每个小批量包含128个样本),共迭代5次【在所有训练数据上迭代一次叫做一个轮次】。在每次迭代过程中,网络会计算批量损失相对于权重的梯度,并相应的更新权重。