《深度学习实战》第3章前馈神经网络(代码片段)

醉一心 醉一心     2023-01-25     527

关键词:

实现深层神经网络

本章我们将编码完成全连接神经网络,并使用CIFAR-10数据集进行测试,在本章练习中我们将完成:

  • 1.仿射层传播
  • 2.ReLU层传播
  • 3.组合单层神经元
  • 4.实现浅层全连接神经网络
  • 5.实现深层全连接神经网络
# -*- coding: utf-8 -*-
import time
import numpy as np
import matplotlib.pyplot as plt
from classifiers.chapter3 import *
from utils import *

%matplotlib inline
plt.rcParams['figure.figsize'] =(10.0, 8.0) # 设置默认绘图尺寸
plt.rcParams['image.interpolation'] = 'nearest'
plt.rcParams['image.cmap'] = 'gray'

%load_ext autoreload
%autoreload 2

def rel_error(x, y):
  #计算相对错误
  return np.max(np.abs(x - y) /(np.maximum(1e-8, np.abs(x) + np.abs(y))))
# 将CIFAR10数据集的导入,切片,预处理操作进行封装
data = get_CIFAR10_data()  #获取数据
# 训练数据
X_train =data['X_train']
y_train =data['y_train']
# 验证数据
X_val = data['X_val']
y_val = data['y_val']
# 测试数据
X_test = data['X_test']
y_test = data['y_test']
for k, v in data.items():
    print('%s: ' % k, v.shape)
X_train:  (49000, 3, 32, 32)
y_train:  (49000,)
X_val:  (1000, 3, 32, 32)
y_val:  (1000,)
X_test:  (1000, 3, 32, 32)
y_test:  (1000,)

仿射层前向传播

仿射(affine)传播就是将各个输入特征进行加权求和,如果下一层有m个神经元,那就相当于线性代数中的m组线性方程式。

进行测试:

# 测试affine_forward 函数
# np.linspaces,规定起点、终点(包含)、返回array的长度,返回一个两端点间数值平均分布的array。
num_inputs = 2
input_shape =(4, 5, 6)
output_dim = 3 #输出维度

# 2*4*5*6
input_size = num_inputs * np.prod(input_shape)
# 3*4*5*6
weight_size = output_dim * np.prod(input_shape)

# 初始化输入参数
x = np.linspace(-0.1, 0.5, num=input_size).reshape(num_inputs, *input_shape)
w = np.linspace(-0.2, 0.3, num=weight_size).reshape(np.prod(input_shape), output_dim)
b = np.linspace(-0.3, 0.1, num=output_dim)

# 测试affine_forward函数
out, _ = affine_forward(x, w, b)
correct_out = np.array([[ 1.49834967,  1.70660132,  1.91485297],
                        [ 3.25553199,  3.5141327,   3.77273342]])

# 比较你的实现结果和正确结果。该误差应该小于1e-9。
print('测试 affine_forward 函数:')
print('误差: ', rel_error(out, correct_out))
测试 affine_forward 函数:
误差:  9.769847728806635e-10

仿射层反向传播

在前向传播中,实现的启示就是out=x1w1+x2w2+b这个函数,那仿射层的反向传播,其实就是将x,w,b各自对应的梯度求出即可。需要注意的是,在缓存中我们存储的是原始数据的四维图像数据。因此,同前向传播一样,首先将数据转换为二维数据后,再进行求解。

# 测试 affine_backward 函数
from utils.gradient_check import *

x = np.random.randn(10, 2, 3)
w = np.random.randn(6, 5)
b = np.random.randn(5)
dout = np.random.randn(10, 5)

dx_num = eval_numerical_gradient_array(lambda x: affine_forward(x, w, b)[0], x, dout)
dw_num = eval_numerical_gradient_array(lambda w: affine_forward(x, w, b)[0], w, dout)
db_num = eval_numerical_gradient_array(lambda b: affine_forward(x, w, b)[0], b, dout)

_, cache = affine_forward(x, w, b)
dx, dw, db = affine_backward(dout, cache)

# 相对误差应该小于1e-10
print('测试 affine_backward 函数:')
print('dx 误差: ', rel_error(dx_num, dx))
print('dw 误差: ', rel_error(dw_num, dw))
print('db 误差: ', rel_error(db_num, db))
测试 affine_backward 函数:
dx 误差:  2.6581417320273106e-08
dw 误差:  2.2266239834308258e-11
db 误差:  3.035949501360111e-11

ReLU层前向传播

ReLU激活函数的公式为max(0, x),我们直接使用NumPy提供的内置公式即可。实现 relu_forward 激活函数的前向传播,并使用下列代码进行测试:

# 测试relu_forward 函数

x = np.linspace(-0.5, 0.5, num=12).reshape(3, 4)

out, _ = relu_forward(x)
correct_out = np.array([[ 0.,          0.,          0.,          0.,        ],
                        [ 0.,          0.,          0.04545455,  0.13636364,],
                        [ 0.22727273,  0.31818182,  0.40909091,  0.5,       ]])

# 比较输出结果. 其误差大约为 1e-8
print('测试 relu_forward 函数:')
print('误差: ', rel_error(out, correct_out))
测试 relu_forward 函数:
误差:  4.999999798022158e-08

ReLU层反向传播

实现 relu_backward函数并使用数值梯度进行检验:

x = np.random.randn(10, 10)
dout = np.random.randn(*x.shape)

dx_num = eval_numerical_gradient_array(lambda x: relu_forward(x)[0], x, dout)

_, cache = relu_forward(x)
dx = relu_backward(dout, cache)

# 其相对误差大约为1e-12
print('测试 relu_backward 函数:')
print('dx 误差: ', rel_error(dx_num, dx))
测试 relu_backward 函数:
dx 误差:  3.2756356627391068e-12

完整的神经元层

接下来我们将上述的affine传播,和ReLU传播组合在一起,形成一层完整的神经元层。

在你实现affine_relu_forward和affine_relu_backward函数之后,运行下面的代码进行梯度检验:

#初始化。
x = np.random.randn(2, 3, 4)
w = np.random.randn(12, 10)
b = np.random.randn(10)
dout = np.random.randn(2, 10)

#执行ReLU,获取分析梯度。
out, cache = affine_relu_forward(x, w, b)
dx, dw, db = affine_relu_backward(dout, cache)

#获取数值梯度。
dx_num = eval_numerical_gradient_array(lambda x: affine_relu_forward(x, w, b)[0], x, dout)
dw_num = eval_numerical_gradient_array(lambda w: affine_relu_forward(x, w, b)[0], w, dout)
db_num = eval_numerical_gradient_array(lambda b: affine_relu_forward(x, w, b)[0], b, dout)

#比较相对误差。
print('测试 ReLU神经元相对误差:')
print('dx 误差: ', rel_error(dx_num, dx))
print('dw 误差: ', rel_error(dw_num, dw))
print('db 误差: ', rel_error(db_num, db))
测试 ReLU神经元相对误差:
dx 误差:  6.029307341263184e-11
dw 误差:  4.873523095375596e-10
db 误差:  4.284094461510698e-11

输出层:Softmax

运行下列代码以确认我们的实现是正确的:

num_classes, num_inputs = 10, 50
x = 0.001 * np.random.randn(num_inputs, num_classes)

y = np.random.randint(num_classes, size=num_inputs)
dx_num = eval_numerical_gradient(lambda x: softmax_loss(x, y)[0], x, verbose=False)
loss, dx = softmax_loss(x, y)

# 测试 softmax_loss 函数. 损失值大约为 2.3 dx 误差大约为 1e-8
print('\\n测试 softmax_loss:')
print('loss: ', loss)
print('dx error: ', rel_error(dx_num, dx))
测试 softmax_loss:
loss:  2.3026391824439414
dx error:  9.528882883490555e-09

浅层神经网络

现在我们将实现浅层全连接神经网络,打开chapter3\\shallow_layer_net.py文件,阅读内容完成相应任务后,执行下面代码进行验证。

N, D, H, C = 3, 5, 50, 7
X = np.random.randn(N, D)
y = np.random.randint(C, size=N)

std = 1e-2
model = ShallowLayerNet(input_dim=D, hidden_dim=H, num_classes=C, weight_scale=std)

print('测试初始化 ... ')
W1_std = abs(model.params['W1'].std() - std)
b1 = model.params['b1']
W2_std = abs(model.params['W2'].std() - std)
b2 = model.params['b2']
# assert(W1_std < std / 10, '第一层权重初始化有问题')
# assert(np.all(b1 == 0), '第一层偏置初始化有问题')
# assert(W2_std < std / 10, '第二层权重初始化有问题')
# assert(np.all(b2 == 0), '第二层偏置初始化有问题')

print('测试前向传播过程 ... ')
model.params['W1'] = np.linspace(-0.7, 0.3, num=D*H).reshape(D, H)
model.params['b1'] = np.linspace(-0.1, 0.9, num=H)
model.params['W2'] = np.linspace(-0.3, 0.4, num=H*C).reshape(H, C)
model.params['b2'] = np.linspace(-0.9, 0.1, num=C)
X = np.linspace(-5.5, 4.5, num=N*D).reshape(D, N).T
scores = model.loss(X)
correct_scores = np.asarray(
    [[11.53165108,    12.2917344,     13.05181771,    13.81190102,    14.57198434, 15.33206765,    16.09215096],
     [12.05769098,    12.74614105,    13.43459113,    14.1230412,     14.81149128, 15.49994135,    16.18839143],
     [12.58373087,    13.20054771,    13.81736455,    14.43418138,    15.05099822, 15.66781506,    16.2846319 ]])
scores_diff = np.abs(scores - correct_scores).sum()
# assert(scores_diff < 1e-6, '前向传播有问题')

# print('测试训练损失(无正则化)')
y = np.asarray([0, 5, 1])
loss, grads = model.loss(X, y)
correct_loss = 3.4702243556
# assert(abs(loss - correct_loss) < 1e-10, '训练阶段的损失值(无正则化)有问题')

print('测试训练损失(正则化0.1)')
model.reg = 1.0
loss, grads = model.loss(X, y)
correct_loss = 26.5948426952
# assert(abs(loss - correct_loss) < 1e-10, '训练阶段的损失值(有正则化)有问题')

for reg in [0.0, 0.7]:
    print('梯度检验,正则化系数 = ', reg)
    model.reg = reg
    loss, grads = model.loss(X, y)

    for name in sorted(grads):
        f = lambda _: model.loss(X, y)[0]
        grad_num = eval_numerical_gradient(f, model.params[name], verbose=False)
        print('%s 相对误差: %.2e' %(name, rel_error(grad_num, grads[name])) )
测试初始化 ... 
测试前向传播过程 ... 
测试训练损失(正则化0.1)
梯度检验,正则化系数 =  0.0
W1 相对误差: 1.52e-08
W2 相对误差: 3.48e-10
b1 相对误差: 6.55e-09
b2 相对误差: 4.33e-10
梯度检验,正则化系数 =  0.7
W1 相对误差: 8.18e-07
W2 相对误差: 2.85e-08
b1 相对误差: 1.09e-09
b2 相对误差: 9.09e-10

训练浅层全连接网络

阅读 ShallowLayerNet.train()以及predict()函数,确保自己了解整个流程

input_size = 32 * 32 * 3
hidden_size = 100
num_classes = 10
net = ShallowLayerNet(input_size, hidden_size, num_classes)

# 训练网络
stats = net.train(X_train, y_train, X_val, y_val,
            num_iters=2000, batch_size=500,
            learning_rate=1e-3, learning_rate_decay=0.95,
            reg=0.6, verbose=True)

# 验证结果
val_acc =(net.predict(X_val) == y_val).mean()
print('最终验证正确率: ', val_acc)
print('历史最佳验证正确率: ', stats['best_val_acc'])
迭代次数 0 / 2000: 损失值 2.394240
迭代次数 100 / 2000: 损失值 1.933027
迭代次数 200 / 2000: 损失值 1.765465
迭代次数 300 / 2000: 损失值 1.647589
迭代次数 400 / 2000: 损失值 1.582696
迭代次数 500 / 2000: 损失值 1.606909
迭代次数 600 / 2000: 损失值 1.512944
迭代次数 700 / 2000: 损失值 1.545821
迭代次数 800 / 2000: 损失值 1.487011
迭代次数 900 / 2000: 损失值 1.611031
迭代次数 1000 / 2000: 损失值 1.502333
迭代次数 1100 / 2000: 损失值 1.413480
迭代次数 1200 / 2000: 损失值 1.604284
迭代次数 1300 / 2000: 损失值 1.431850
迭代次数 1400 / 2000: 损失值 1.334827
迭代次数 1500 / 2000: 损失值 1.464982
迭代次数 1600 / 2000: 损失值 1.335481
迭代次数 1700 / 2000: 损失值 1.418904
迭代次数 1800 / 2000: 损失值 1.367120
迭代次数 1900 / 2000: 损失值 1.418279
最终验证正确率:  0.512
历史最佳验证正确率:  0.512
# 绘制损失函数变化曲线
plt.subplot(2, 1, 1)
plt.plot(stats['loss_history'])
plt.title('Loss history')
plt.xlabel('Iteration')
plt.ylabel('Loss')

plt.subplot(2, 1, 2)
plt.plot(stats['train_acc_history'], label='train')
plt.plot(stats['val_acc_history'], label='val')
plt.plot([0.5] * len(stats['val_acc_history']), 'k--')
plt.title('Classification accuracy history')
plt.xlabel('Epoch')
plt.ylabel('Clasification accuracy')
# 添加图标
plt.legend()
# 控制布局
plt.tight_layout()
plt.show()



深层全连接网络

接下来我们将实现深层的全连接网络,由于我们以及实现了浅层网络,深层网络的实现将变得很简单。

深层神经网络相比于浅层神经网络,虽然仅仅是隐藏层数量变多而已,但它却具有了浅层网络没有的强大能力。由于我们已经实现了浅层网络,深层网络的实现将变得非常简单。现在要做的仅仅是将浅层网络中固定的单隐藏层变成任意多层即可。在深层全连接神经网络,隐藏层使用ReLU作为激活函数,输出层使用Softmax作为分类器。

N, D, H1, H2,H3, C = 2, 15, 20, 30, 20, 10
X = np.random.randn(N, D)
y = np.random.randint(C, size=(N,))

for reg in [0, 0.11, 3.14]:
    print('权重衰减系数= ', reg)
    model = FullyConnectedNet(input_dim=D,hidden_dims=[H1, H2,H3],num_classes=C,reg=reg, weight_scale=5e-2)

    loss, grads = model.loss(X, y)
    print('初始化化损失值: ', loss)

    for name in sorted(grads):
        f = lambda _: model.loss(X, y)[0]
        grad_num = eval_numerical_gradient(f, model.params[name], verbose=False, h=1e-5)
        print('%s 相对误差: %.2e' %(name, rel_error(grad_num, grads[name])))
权重衰减系数=  0
初始化化损失值:  2.302395002878659
W1 相对误差: 7.33e-06
W2 相对误差: 2.52e-07
W3 相对误差: 1.21e-06
W4 相对误差: 3.73e-07
b1 相对误差: 5.57e-07
b2 相对误差: 1.47e-08
b3 相对误差: 1.74e-06
b4 相对误差: 1.38e-10
权重衰减系数=  0.11
初始化化损失值:  2.5387725473271425
W1 相对误差: 1.22e-07
W2 相对误差: 8.56e-07
W3 相对误差: 1.27e-07
W4 相对误差: 7.80e-08
b1 相对误差: 7.76e-08
b2 相对误差: 4.06e-07
b3 相对误差: 3.10e-09
b4 相对误差: 9.36e-11
权重衰减系数=  3.14
初始化化损失值:  8.877932640499402
W1 相对误差: 1.11e-08
W2 相对误差: 9.18e-08
W3 相对误差: 5.11e-08
W4 相对误差: 4.26e-08
b1 相对误差: 3.60e-07
b2 相对误差: 9.61e-08
b3 相对误差: 2.56e-08
b4 相对误差: 3.55e-10
# 在小数据集上测试训练效果,正常情况下应该出现严重过拟合现象
input_size = 32 * 32 * 3
num_classes = 10
num_train = 50

X_train_small= X_train[:num_train]
y_train_small= y_train[:num_train]
w= 1e-1
l = 1e-3
net = FullyConnectedNet(input_size ,[100,查看详情  

tensorflow实战-tensorflow和其他深度学习框架的对比-第2章

...wTensorFlow是相对高阶的机器学习库,用户?方便地用它设计神经网络结构,而不必为了追求高效率的实现亲自写C++或者CUDA代码。TensorFlow另外一个特点是灵活的移植性。TensorFlow还提供了TensorBoard,TensorBoard是TensorF 查看详情

神经网络与深度学习摘要第1章绪论

【神经网络与深度学习摘要】第1章绪论文章目录【神经网络与深度学习摘要】第1章绪论1.人工智能1.1图灵测试1.2人工智能的主要领域1.3人工智能的发展历史1.4人工智能的流派2.机器学习2.1机器学习定义2.2使用机器学习模型步骤3.... 查看详情

tensorflow实战google深度学习框架(代码片段)

第3章TensorFlow入门3.1TensorFlow计算模型-计算图3.1.1计算图的概念Tensorflow中所有计算都会被转化成计算图的一个节点,计算图上的边表示了他们之间的相互依赖关系。3.1.2计算图的使用Tensorflow的程序可以分成两个阶段:定义计算、... 查看详情

第3章神经网络《深度学习入门基于python的理论与实现》

第3章神经网络《深度学习入门基于Python的理论与实现》3.1从感知机到神经网络3.2激活函数3.1从感知机到神经网络 查看详情

深度学习:基于python:第7章卷积神经网络(代码片段)

第7章卷积神经网络第7章卷积神经网络7.1整体结构7.2卷积层7.2.1 全连接层存在的问题7.2.2 卷积运算7.2.3 填充7.2.4 步幅7.2.5 3维数据的卷积运算7.2.6 结合方块思考7.2.7 批处理7.3池化层7.4卷积层和池化层的实现7.4.1 4维数组7... 查看详情

2023.5.7《动手学深度学习》第78章(代码片段)

今天继续学习《动手学习深度学习》第7章:现代卷积神经网络、第8章:循环神经网络,今天学到的内容主要有这两章的概念。一、理论部分:1、LeNet和AlexNet的网络结构LeNet的激活函数是Sigmoid,AlexNet的激活函数是ReLU。2、AlexNet... 查看详情

[人工智能-深度学习-59]:生成对抗网络gnn-基本原理(图解详解通俗易懂)(代码片段)

作者主页(文火冰糖的硅基工坊):文火冰糖(王文兵)的博客_文火冰糖的硅基工坊_CSDN博客本文网址:https://blog.csdn.net/HiWangWenBing/article/details/121878299目录第1章生成对抗网络GAN概述与主要应用第2章生成对抗网络GAN... 查看详情

keras深度学习实战——卷积神经网络详解与实现(代码片段)

Keras深度学习实战(7)——卷积神经网络详解与实现0.前言1.传统神经网络的缺陷1.1构建传统神经网络1.2传统神经网络的缺陷2.使用Python从零开始构建CNN2.1卷积神经网络的基本概念2.2卷积和池化相比全连接网络的优势3.使用... 查看详情

深度学习100例|第43天:文本卷积神经网络(textcnn)新闻文本分类实战(代码片段)

🚩本文作者:微学AI、K同学啊🥇精选专栏:《深度学习100例》🔥推荐专栏:《新手入门深度学习》📚选自专栏:《Matplotlib教程》🧿优秀专栏:《Python入门100题》大家好,我是K同学啊&... 查看详情

keras深度学习实战——卷积神经网络的局限性(代码片段)

Keras深度学习实战(9)——卷积神经网络的局限性0.前言1.卷积神经网络的局限性2.情景1——训练数据集图像尺寸较大3.情景2——训练数据集图像尺寸较小4.情景3——在训练尺寸较大的图像时使用更大池化小结系列链接0.... 查看详情

tensorflow实战-tensorflow实现卷积神经网络cnn-第5章

第5章-TensorFlow实现卷积神经网络CNN5.1卷积神经网络简介卷积神经网络CNN最初是为了解决图像识别等问题设计的,当然现在的应用已经不限于图像和视频,也可以用于时间序列信号,比如音频信号、文本数据等。在深度学习出现之... 查看详情

2023.5.6《动手学深度学习》第34章(代码片段)

...动手学习深度学习》第5章:深度学习计算、第6章:卷积神经网络,今天学到的内容主要有这两章的概念。以及实现LeNet对FashionMNIST进行分类。一、理论部分:1、概念解释:1×1卷积的作用:卷积通常用于识别相邻元素间相互作用... 查看详情

keras深度学习实战(20)——神经风格迁移详解(代码片段)

...m图像生成算法的学习中,我们通过修改像素值试图使神经网络中卷积核的激活最大化。但是,这并不具备灵活生成指定风格图像的功能,因此,本节我们继续学习神经风格迁 查看详情

keras深度学习实战(29)——长短时记忆网络详解与实现(代码片段)

...TermMemory,LSTM),顾名思义是具有记忆长短期信息能力的神经网络 查看详情

keras深度学习实战(29)——长短时记忆网络详解与实现(代码片段)

...TermMemory,LSTM),顾名思义是具有记忆长短期信息能力的神经网络 查看详情

keras深度学习实战(26)——文档向量详解(代码片段)

...实战(26)——文档向量详解0.前言1.文档向量基本概念2.神经网络模型与数据集分析2.1模型分析2.2数据集介绍3.利用Keras构建神经网络模型生成文档向量小结系列链接0.前言在《从零开始构建单词向量》一节中,我们学习了单词向... 查看详情

keras深度学习实战(22)——生成对抗网络详解与实现(代码片段)

...链接0.前言生成对抗网络(GenerativeAdversarialNetworks,GAN)使用神经网络生成与原始图像集非常相似的新图像,它在图像生成中应用广泛,且GAN的相关研究正在迅速发展ÿ 查看详情