第二章 神经网络的数学基础
一、初识神经网络
keras的手写数字识别:
#载入数据
from keras.datasets import mnist
(train_images, train_labels), (test_images, test_labels) = mnist.load_data()
#网络架构
from keras import models
from keras import layers
network = models.Sequential()
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
#标签分类编码(??第三章会讲。。。)
from keras.utils import to_categorical
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)
- 网络包含两个Dense层,第二个Dense是输出10路的softmax层。(Dense==FC层)
- 编译compile需要指定3个参数:
分别是:loss/optimizer/metrics===损失函数/优化器/监控的指标
- 拟合fit:需要指定epochs、batch_size、train_X、train_Y
- 测试evaluate:需要指定test_X、test_Y
二、神经网络中的数据表示
mnist中的tensor存储在Numpy数组中。
tensor是矩阵向任意维度的推广,tensor的维度叫做轴(axis)
- 标量(scalar)—>0D张量
-
Numpy可以通过x.ndim查看x的Tensor维度,轴的个数
-
import numpy as np
x = np.array(12) #生成了一个常数12
print(x.ndim)
- 向量(1D张量)
import numpy as np
x = np.array([12, 10, 8])
#生成了一个1Dtensor[12, 10, 8],但是,是个3D向量vector
print(x.ndim)
- 矩阵(2D张量)
x = np.array([[5, 78, 2, 34, 0],
[6, 79, 3, 35, 1],
[7, 80, 4, 36, 2]])
print(x.ndim)
- 3D张量
x = np.array([[[
......
......
- 关键属性
- 轴的个数(axis)---->阶数---->张量的ndim
- 形状---->shape是某个轴方向上面的维度大小–>vector只有一个,常数为空
- 数据类型---->dtype—>float32、float64、uint8…
- Numpy操作张量
#张量切片
my_slice = train_images[10:100]
#包含10、11、12....99(不包含100,一共90个)
my_slice = train_image[10:100, 0:28, 0:28]
#后面两个是另外两个轴上面的切片
- 数据批量
深度学习中所有数据张量的第一个轴(0轴)都是“样本轴”,维度代表样本个数。
分成批量时,第一个轴叫做“批量轴”,代表一个batch的样本个数。
- 常用的数据张量
- 向量数据—>2D张量(samples,features)
- 时间或序列数据—>3D张量(samples,timesteps,features)
- 图像—>4D张量(samples,channels,heght,width)
- 视频数据—>5D张量(samples,frames,channels,height,width)
样本数—0轴();时间步长—1轴(width);特征数—2轴(height)
视频数据稍微特殊:
三、张量运算
keras.layers.Dense(512, activation='relu')
===> o u t p u t = r e l u ( d o t ( W , i n p u t ) + b ) output = relu(dot(W, input)+b) output=relu(dot(W,input)+b)
- 逐元素计算
Python逐元素计算:
Numpy逐元素计算:
- 广播
当一个2D张量和一个1D向量相加,阶数低的一个张量会被“广播”
广播分两步:1.添加轴 2.新轴上重复
- 张量点积
两个向量点积得到一个标量
z = np.dot(x,y)
点积不要交换顺序,对于两个矩阵,只有x.shape[1]==y.shape[0]
才可以dot(x,y)
- 张量变形
Tesor Reshaping
张量变形是改变张量的行和列,得到想要的形状
++np.reshape()
和np.transpose(x)
一个变形,一个转置++
- 张量运算的几何解释
- 深度学习的几何解释
DL将复杂变换转化为最基本的一系列简单变换
四、基于梯度的优化
随机初始化:W,b选择随机的小值来进行初始化
步骤:
- 抽取batch数据
- 前向传播,得到y_pred
- 计算这个batch上面的损失函数值
- 计算损失相对于网络参数的梯度 “反向传播”
- 更新权重,沿着梯度反方向移动一点,降低损失函数值
小批量随机梯度下降:mini-SGD,++随机,指的是每批数据都是随机抽取的++。(相对的,每次只取一个样本计算loss的,称为++真SDG++,而每次在所有数据上迭代,称为批量SDG,虽然准确但是计算消耗太大)
SGD变种:
带动量的SGD,Adagrad,RMSProp等…这些都称为优化器
其中,带**++动量的SGD解决了两个问题:收敛速度和局部极小值。++**
指的是在更新参数W时候,不仅要考研当前的梯度值,也要考虑上一次的**++参数更新++**。
past_velocity = 0.
momentum = 0.1 #不变的动量因子
while loss > 0.01: #优化循环
w, loss, gradient = get_current_parameters()
velocity = past_velocity * momentum - learning_rate * gradient
w = w + momentum * velocity - learning_rate * gradient
past_velocity = velocity
update_parameter(w)
五、回顾第一个例子
# 输入数据
(train_images, train_labels), (test_images, test_labels) = mnist.load_data()
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
# 构建网络
network = models.Sequential()
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'])
# 训练
network.fit(train_images, train_labels, epochs=5, batch_size=128)