《边做边学深度强化学习:PyTorch程序设计实践》——4使用pytorch进行深度学习

4.1神经网络和深度学习的历史

神经网络是一种机器学习算法,模仿人类神经元的活动。神经网络的原始模型是发表于1943年的麦卡洛克-皮茨(McCulloch-Pitts),也成为形式神经元,一种以数学上简单的方式模拟神经元活动的模型。麦卡洛克是一名外科医生和神经科学家,皮茨是一名数学家。
表示为
z = H ( ∑ i = 1 N w i x i + x 0 ) z=H(\sum_{i=1}^N w_ix_i+x_0) z=H(i=1Nwixi+x0)
其中, z z z表示目标神经元的输出, x i x_i xi表示连接到目标神经元的第 i i i个神经元的输出,神经元输出值为0或1。 w i w_i wi是目标神经元与它相连的第 i i i个神经元之间的连接参数(连接强度), x 0 x_0 x0是一个常数(偏差), H ( ) H() H()成为阶跃函数,也成为激活函数。

该模型是一种在数学上遵循“全或无定律”的模型,当没有一定强度或更多的输入时,神经元根本不输出,当输入强度超过某个阈值时,它突然将输出传送到下一个神经元。传递的输出超过一定范围时会发生被称为“激发”的现象。“全或无定律”在生物学上的发现表示两种状态,“激发”或“非激发”。

从1943年McCulloch-Pitts模型的发表到感知器的发表,中间过去15年,如何根据任务的输入-输出关系来学习这个连接参数,即建立学习规则。这个模型可以理解为神经元和神经元在称为突触的部分功能性连接,“高尔基理论”认为神经元在突触处时物理上直接连接的,二“卡哈尔理论”认为两者在突触上没有物理连接,是间接连接的,比如乙酰胆碱、多巴胺和GABA的神经递质,神经递质的传递时称为“激发”的信息传递。1952年生物学家霍奇金和赫胥黎建立了一个详细的神经数学模型,20世纪60年代,引发了第一次神经网络的繁荣和AI热潮,“如果能够制造与人脑一样机制的物体,使用它,就应该能制造出与人类大脑相同的智力”。但明斯基表示,单层感知器不能表示如XOR这样的非线性输入-输出关系,人们失去了对感知器的期望。

事实上,如果感知器时多层的,则可以表示XOR关系:
z = H ( x 1 + x 2 − 2 H ( x 1 + x 2 − 1.5 ) − 0.5 ) z=H(x_1+x_2-2H(x_1+x_2-1.5)-0.5) z=H(x1+x22H(x1+x21.5)0.5)
x 1 = 1 , x 2 = 1 , z = 0 x_1=1,x_2=1,z=0 x1=1,x2=1,z=0。问题的关键是,罗森布莱特的“感知器学习规则”无法学习这种多层感知学习规则的连接参数。“学习规则遵循大脑的发现,用算法来模拟神经元的突触连接强度的变化”

1986年,Rumelhart等人提出的反向传播(误差反向传播方法)再次激发神经网络的热潮。阶跃函数在数学上难以处理,因为当输入值为0时,输出值从0快速变为1,所以Rumelhart等人停止使用阶跃函数并决定使用Logistic函数(sigmoid函数)。用公式表示为 z = 1 1 + exp ⁡ ( − u ) z=\frac{1}{1+\exp(-u)} z=1+exp(u)1
除了0、1之外的输出点将偏离“全或无定律”这一神经元激发的生理学知识。但当神经元时群体而不是单个神经或单个细胞时,假设神经的概率行为时,可以认为Logistic函数也是符合生理学的),Logistic函数比阶跃函数在数学上容易处理太多,能够微分,使用实际输出和预期输出的误差以及sigmoid函数的导数,则可以计算如何更好地学习(调整)连接参数,该学习方法称为反向传播方法。通过引入Logistic函数和反向传播,实现了感知器有局限的非线性问题的学习,意味着第二次神经网络热潮来临。

然而繁荣再次结束。要学习复杂的输入-输出关系,需要增加一层中神经元的数量或采用更多的神经网络层。连接更多层神经网络称为“使层数变得更深(deep)”。增加每层中神经元的数量时低效的,因此,“使层数变得更深时必要的,在更深的神经网络中,Rumelhart等人提出的方法(logistic函数+反向传播)未能很好地学习连接参数。原因时发生了梯度消失/爆炸的现象。最终神经网络无法实现复杂的输入-输出关系……”第二次神经网络热潮就这样结束了。

Hinton在2016年使用一种叫做深度学习的想法来实现一个深度神经网络。他的想法不是从随机初始值开始学习深度神经网络的连接参数,而是提前给每层提供一定程度上更好的初始值。为了求得每层连接参数的初始值,他认为“将神经网络各层分隔开,给定连接参数值会使得对于各层的输入信息和输出信息能很好地进行信息压缩”。使用连接参数矩阵 W \textbf{W} W和N维输入 x x x,获得二维输出 a 1 a_1 a1 a 2 a_2 a2,将 a 1 a_1 a1 a 2 a_2 a2作为输入提供给具有 W T \textbf{W}^T WT的连接强度网络,求得N维输出y。通常,x和y将具有不同的值,训练连接参数,使其尽可能相似,这个思路称为自编码器。在2012年图像识别大赛“ILSVRC”中,Hinton等人提出了一种深度学习图像识别系统,大大提高了识别率。

4.2深度学习的计算方法

4.2.1推理阶段

下图展示一个用于深度学习的神经网络的简化版本。每个箭头附带的数字是连接参数。而h表示隐藏层(中间层)。在h中,来自x的输入之和由激活函数转换并输出到y。假设激活函数是在前一节中介绍的ReLU。当输入为负时,ReLU输出0;当输入为正时,输出与输入相同的值。
在这里插入图片描述

现在假设输入x是(3,2,1)。那么h1的输入之和就是3×1+2×3+1×(-5)=4类似地,h2的输入之和为3×2+2×(-4)+1×(-6)=-8在隐藏层中,此输入的总和由ReLU转换,因此h1的输出为4,h2的输出为0。随后,在求输出层中y的值时,y1为:4×(-1)+0×(-5)=-4 y2是:4×3+0×7=12换句话说,给定输入(3,2,1),图中的神经网络的输出是(-4,12)。这是推理过程中深度学习计算的基础。即使神经网络越来越深,它也只是重复本例中所给出的计算过程。基本上,像这样的推理计算非常简单。

4.2.2 学习阶段

学习阶段复杂一些,假设输入时(1,2,1),预期输出是(-1,8)。训练数据具有已知输出。当此输入被提供给神经网络时,h1的输入之和为1×1+2×3+1×(-5)=2h2的输入之和是1×2+2×(-4)+1×(-6)=-12则h1的输出为2,h2的输出为0。y1的输出是:2×(-1)+0×(-5)=-2。y2的输出是:2×3+0×7=6所以输出y是(-2,6)。预期输出为(-1,8),但实际输出为(-2,6)。

为此需要确定实际输出和预期输出之间的误差函数(损失函数)(监督学习回归通常会用平方误差函数,想求得某个标签值而不是特定值,使用交叉熵误差函数)。计算误差微分到每个连接参数,也就是如果连接参数稍微增加,输出层误差将增加多少。通过反向传播求得微分值,将使误差函数更小,较大幅度地调整那些对误差贡献大的连接参数,小幅度调整对误差贡献小的参数。使用这些微分值计算当前连接参数值的调整量的计算方法称为梯度下降法,具体包括Adam和RMSprop等。

使用所有输入数据来更新连接参数的方法称为批量学习,一个一个地使用输入数据更新连接参数的方法称为在线学习

使用pytorch实现MNIST手写数字分类任务

深度学习有名的包有Caffe、Tensorflow、Keras和Chainer。Pytorch是2017年2月基于Torch7写的,优点是一个名为“defined by run”(动态计算图)的特征。根据输入数据的大小和维数改变神经网络的形状和计算方法。Tensorflow是“defined and run”(静态计算图),首先确定神经网络的计算方法,难以应对输入数据的维度因数据而已的情况。

MNIST(Modified National Institute of Standards and Technology)手写数字识别,是美国统计局工作人员和高中生写的手写数字的图像数据集,提供60000个训练数据和10000个测试数据

pytorch进行深度学习六大步骤:

  1. 预处理数据
  2. 创建DataLoader
  3. 构建神经网络
  4. 设置误差函数和优化方法
  5. 设置学习和推理
  6. 执行学习和推理
import os
from sklearn.datasets import fetch_openml

# 设置数据集的存储路径
data_home = './data'
mnist_path = os.path.join(data_home, 'mnist_784')

# 检查数据是否已经下载
if not os.path.exists(mnist_path):
    print("Downloading MNIST data...")
    mnist = fetch_openml('mnist_784', version=1, as_frame=False, data_home=data_home)
    print("Download complete.")
else:
    print("MNIST data already downloaded.")


Downloading MNIST data...


d:\Anaconda3\envs\tensorflow2\lib\site-packages\sklearn\datasets\_openml.py:1022: FutureWarning: The default value of `parser` will change from `'liac-arff'` to `'auto'` in 1.4. You can set `parser='auto'` to silence this warning. Therefore, an `ImportError` will be raised from 1.4 if the dataset is dense and pandas is not installed. Note that the pandas parser may return different data types. See the Notes Section in fetch_openml's API doc for details.
  warn(


Download complete.
#1.预处理数据,拆分为图像数据和标签并标准化

X = mnist.data / 255 #0~255归一化为0~1
y = mnist.target
# 可视化第一个MNIST数据
import pylab as plt
plt.imshow(X[0].reshape(28,28),cmap='gray')
print(f'这一图像数据的标签是{y[0]}')
这一图像数据的标签是5

在这里插入图片描述

创建DataLoader
  1. 分离训练数据和测试数据
  2. 将Numpy数据转换为Tensor
  3. 创建Dataset
  4. 将Dataset转换为DataLoader
#2.创建DataLoader
import torch
import numpy as np
from torch.utils.data import TensorDataset,DataLoader
from sklearn.model_selection import train_test_split

#2.1将数据分为训练和测试(6:1)
X_train,X_test,y_train,y_test = train_test_split(
    X,y,test_size=1/7,random_state=0
)

#2.2将数据转换为pytorch tensor
#numpy数据转换为可以被pytorch处理的类型变量Tensor
#一个数是标量,一个维度是向量,二维是矩阵,多维叫Tensor,一阶二阶也是Tensor张量
X_train = torch.Tensor(X_train.astype(np.int64))
X_test = torch.Tensor(X_test.astype(np.int64))
y_train = torch.Tensor(y_train.astype(np.int64))
y_test = torch.Tensor(y_test.astype(np.int64))

y_train = torch.tensor(y_train, dtype=torch.long)  # 或者 y_train = torch.tensor(y_train).long()
y_test = torch.tensor(y_test, dtype=torch.long)    # 或者 y_test = torch.tensor(y_test).long()

#2.3使用一组数据和标签创建Dataset
ds_train = TensorDataset(X_train,y_train)
ds_test = TensorDataset(X_test,y_test)

#2.4使用小批量数据集创建DataLoader
#批量大小是用于训练神经网络连接参数的数据块大小,以及设置是否随机投放数据
#Dataset当前以0~9升序整齐的储存
loader_train = DataLoader(ds_train,batch_size=64,shuffle=True)
loader_test = DataLoader(ds_test,batch_size=64,shuffle=False)
#3.构建神经网络
#以keras风格构建网络
from torch import nn

model = nn.Sequential()
model.add_module('fc1',nn.Linear(28*28*1,100))
#fc1是一个28*28*1=784的输入层,输出到100个神经元
#784和100神经元都被连接,称为全连接层
model.add_module('relu1',nn.ReLU())
model.add_module('fc2',nn.Linear(100,100))
model.add_module('relu2',nn.ReLU())
model.add_module('fc3',nn.Linear(100,10))

print(model)
Sequential(
  (fc1): Linear(in_features=784, out_features=100, bias=True)
  (relu1): ReLU()
  (fc2): Linear(in_features=100, out_features=100, bias=True)
  (relu2): ReLU()
  (fc3): Linear(in_features=100, out_features=10, bias=True)
)
#4.设置误差函数和优化方法

from torch import optim

#设置误差函数
loss_fn = nn.CrossEntropyLoss() #很多时候用criterion作为变量名

#选择学习权重参数时的优化方法
optimizer = optim.Adam(model.parameters(),lr = 0.01)

#5.设置学习和推理
#5.1 定义学习1轮所做的事情

def train(epoch):
    model.train()  #网络切换到训练模式,model.eval()切换到推理模式
    #还有一些方法dropout(随即失活)batch normalization(批标准化)

    #从数据加载器中取小批量数据进行计算
    for data, targets in loader_train:

        optimizer.zero_grad() #初始梯度设置为0
        outputs = model(data)  #输入数据并计算输出
        loss = loss_fn(outputs,targets) #计算输出和训练数据之间的误差
        loss.backward()   #对误差进行反向传播
        optimizer.step()  #更新权重

    print(f'epoch{epoch}:结束\n')

def test():
    model.eval()
    correct = 0

    with torch.no_grad(): #输入数据并计算输出
        for data,targets in loader_test:

            outputs = model(data) #找到概率最高的标签

            #推论
            _,predicted = torch.max(outputs.data,1)
            correct += predicted.eq(targets.data.view_as(predicted)).sum()
            #如果计算结果和标签一致,则计数加一

    data_num = len(loader_test.dataset) #总数
    print(f'\n测试数据的准确率:{correct}/{data_num}=({100.*correct/data_num})')
#6.执行学习和推理
for epoch in range(5):
    train(epoch)
test()
epoch0:结束

epoch1:结束

epoch2:结束

epoch3:结束

epoch4:结束


测试数据的准确率:4040/10000=(40.400001525878906)
index = 6

model.eval()
data = X_test[index]
output = model(data)
_,predicted = torch.max(output.data,0)

print(f'预测结果时{predicted}')

X_test_show = (X_test[index]).numpy()
plt.imshow(X_test_show.reshape(28,28),cmap='gray')
print(f'正确标签时{y_test[index]}')
预测结果时7
正确标签时7
  • 14
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
《边边学深度强化学习PyTorch程序设计实践》是一本关于深度强化学习PyTorch实践的书籍,它提供了在PyTorch环境下进行深度强化学习的详细指南和实例代码。 本书以边边学的方式引导读者理解深度强化学习的基本概念和原理,并通过实践项目的方式加深对所学知识的理解和掌握。书中的案例覆盖了强化学习的主要应用领域,包括游戏、机器人控制和金融等,读者可以根据自己的兴趣和需求选择相应的案例进行学习。 在学习过程中,读者将使用PyTorch这一流行的深度学习框架来实现深度强化学习算法。书中给出了详细的代码示例和解释,以及实验结果的展示和讨论,读者可以通过自己动手编写代码来加深对算法原理的理解,并通过实验调优来提升算法的性能。 《边边学深度强化学习PyTorch程序设计实践》在设计上注重了实践和理论的结合,旨在帮助读者从零开始学习和实践深度强化学习,并具备独立设计、实现和优化应用模型的能力。书中还介绍了一些实用的工具和技巧,如数据预处理、模型评估和调参等,读者可以借鉴和应用到自己的项目中。 总之,《边边学深度强化学习PyTorch程序设计实践》是一本适合初学者和有一定基础的读者学习深度强化学习PyTorch实践的书籍,通过阅读这本书,读者将能够系统地学习和掌握深度强化学习算法,并能够利用PyTorch实现自己的深度强化学习应用模型。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

じょりゅう

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值