神经网络来袭!划重点:60分钟入门,这是最深入浅出的一次

简介: 现在对PyTorch的自动求导机制(autograd)有所了解,nn 依赖autograd来定义模型和区分它们。一个nn.Module包括layers和返回输出值的forword(input)方法。

神经网络


神经网络可以使用torch.nn包构建。

现在对PyTorch的自动求导机制(autograd)有所了解,nn 依赖autograd来定义模型和区分它们。一个nn.Module包括layers和返回输出值的forword(input)方法。

例如:下面的这个图片分类的神经网络。

image.png

这是一个简单的前馈神经网络。

它接收输入,一个接一个地通过几个层馈送,然后最后给出输出。

一个神经网络的典型训练程序如下:

定义具有可学习参数(或权重)的神经网络

迭代输入数据集

通过网络进行过程输入

计算损失(输出的正确程度有多远)

向神经网络参数回传梯度

更新网络中的参数权重,通常使用简单的更新规则:weight = weight - learning_rate* gradient

1.定义网络

我们开始定义网络:

import torch
import torch.nn as nn
import torch.nn.functional as F


class Net(nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        #卷积层, '1'表示输入图片的为单通道,'6'表示输出通道数,'5'表示卷积核 5*5
        #核心
        self.conv1 = nn.Conv2d(1, 6, 5)
        # '6'表示输入数据通道,16个输出,'5'表示卷积核 5*5 
        self.conv2 = nn.Conv2d(6, 16, 5)
    
        #映射层/全连接层:y = Wx+b
        # 为什么是16*5*5呢? 这是全连接层的第一个函数。
        # 经过卷积、池化后最后输出的结果是16个大小为5*5的图像.
        #第一次卷积:图片大小 = (32-5+1)/1 = 28
        #第一次池化:图片大小 = 28/2 = 14
        #第二次卷积:图片大小 = (14-5+1)/1 =10
        #第二次池化:图片大小 = 10/2 = 5
        self.fc1 = nn.Linear(16 * 5 * 5,120) 
        self.fc2 = nn.Linear(120,84)
        self.fc3 = nn.Linear(84,10)
        
    def forward(self,x):
        #在由多个输入平面组成哦输入信号上应用2D最大池化。
        #(2,2)表示的是池化操作的步幅
        x = F.max_pool2d(F.relu(self.conv1(x)),(2,2))
        #如果大小是正方形,则只能指定一个数字
        x = F.max_pool2d(F.relu(self.conv2(x)),2)
        #将一个多维数据转成N行一列的数据。
        x = x.view(-1,self.num_flat_features(x))
        x = F.relu(self.fc1(x))
        x = F.relu(self.fc2(x))
        x =self.fc3(x)
        return x
            
        
    def num_flat_features(self,x):
        size = x.size()[1:]
        num_features = 1
        for s in size:
            num_features *= s
        return num_features

net = Net()
print(net)

image.png

只定义了forward函数,backward函数(计算梯度的位置)通过使用autograd被自动定义了。你可以在forward函数中使用任何Tensor的运算操作。

模型中可学习的变量通过net.parameters()返回。

params = list(net.parameters())
print(len(params))
print(params[0].size())   # conv1's.weight

image.png

随机生成一个32 32的输入。注意: 这个网络(LeNet)的预期输入大小是 32 32。为了在个网络使用MNIST数据,请将数据集中的图像调整到32 * 32。

input = torch.randn(1, 1, 32, 32)
out = net(input)
print(out)

先将参数(parameters)的梯度缓存设置0,再随机生成一个梯度。

net.zero_grad()
out.backward(torch.randn(1,10))

注意:

torch.nn 只支持小批量数据。所有的torch.nn包都只支持输入样本为总样本的一小批,不支持单个样本。

例如:nn.Conv2d的输入必须是4维的张量,形如:nSamples x nChannels x Height x Width。

如果只有一个样本,必须使用input.unsqueeze(0)将batchsize设置为1

在继续之前,让我们来回顾一下之前见过的类

回顾:

torch.Tensor 多维数组支持自动求导操作与backward()类似。

nn.Module 神经网络模块。方便的方式封装参数, 帮助将其移动到GPU, 导出, 加载等.

nn.Parameter Tensor的一种,在被指定为 Module 的属性时,会自动被注册为一个参数。

autograd.Function 实现 autograd 操作的向前和向后定义..每个 Tensor 操作, 至少创建一个 Function 节点, 连接到创建 Tensor的函数, 并编码它的历史

到这里, 我们已完成:

定义一个神经网络

处理输入并反向传播

还剩下:

计算损失函数

更新网络的权重

2.损失函数

损失函数采用 (output,target) 输入对, 并计算预测输出结果与实际目标的距离。

在 nn 包下有几种不同的损失函数. 一个简单的损失函数是: nn.MSELoss 计算输出和目标之间的均方误差。

如下例:

output = net(input)
target = torch.randn(10)  # a dummy target, for example
target = target.view(1, -1)  # make it the same shape as output
criterion = nn.MSELoss()

loss = criterion(output, target)
print(loss)

image.png

现在, 如果你沿着 loss 反向传播的方向使用 .grad_fn 属性, 你将会看到一个如下所示的计算图:

input -> conv2d -> relu -> maxpool2d -> conv2d -> relu -> maxpool2d -> view -> linear -> relu -> linear -> relu -> linear -> MSELoss -> loss

所以, 当我们调用 loss.backward(), 整个图与损失是有区别的, 图中的所有变量都将用 .grad 梯度累加它们的变量.

为了说明, 让我们向后走几步:

print(loss.grad_fn)  # MSELoss
print(loss.grad_fn.next_functions[0][0])  # Linear
print(loss.grad_fn.next_functions[0][0].next_functions[0][0])  # ReLU

image.png

3.反向传播

为了反向传播误差, 我们所要做的就是 loss.backward(). 你需要清除现有的梯度, 否则梯度会累加之前的梯度。

现在我们使用 loss.backward(), 看看反向传播之前和之后 conv1 的梯度。

net.zero_grad()     # zeroes the gradient buffers of all parameters

print('conv1.bias.grad before backward')
print(net.conv1.bias.grad)

loss.backward()

print('conv1.bias.grad after backward')
print(net.conv1.bias.grad)

image.png

现在,我们已经知道怎么使用损失函数了。

稍后阅读:

神经网络类库中包含很多模块和损失函数,形成深度神经网络模块。完整的文件列表在http://t.cn/EIPR3z1

接下来唯一要学习的是:

更新网络的权重。

4.更新权重

时间中使用的最简单的更新规则是随机梯度下降(SGD):

weight = weight - learning_rate * gradient

我们可以使用简单的python代码实现:

learning_rate = 0.01
for f in net.parameters():
    f.data.sub_(f.grad.data * learning_rate)

但是,当你使用神经网络时,你可能想使用SGD,Nesterov-SGD,Adam,RMSProp等不同的更新规则。为了实现这些,我们建立了一个包: torch.optim ,实现了以上所有的方法。使用非常的简单:

import torch.optim as optim

#构建优化器
optimizer = optim.SGD(net.parameters(), lr=0.01)

#训练时循环的语句:
optimizer.zero_grad()   # 将梯度缓存清零。
output = net(input)
loss = criterion(output, target)
loss.backward()
optimizer.step()    # 更新权重

注意:

观察如何使用手动设置梯度清零 optimizer.zero_grad() . 需要手动清零的原因在 Backprop_ 中已经说明了(梯度会累加之前的梯度)。

Type Markdown and LaTeX: α2

目录
相关文章
|
19天前
|
机器学习/深度学习 人工智能 算法
深度学习入门:理解神经网络与反向传播算法
【9月更文挑战第20天】本文将深入浅出地介绍深度学习中的基石—神经网络,以及背后的魔法—反向传播算法。我们将通过直观的例子和简单的数学公式,带你领略这一技术的魅力。无论你是编程新手,还是有一定基础的开发者,这篇文章都将为你打开深度学习的大门,让你对神经网络的工作原理有一个清晰的认识。
|
1月前
|
监控 安全 数据安全/隐私保护
智能家居安全入门:保护你的网络家园
本文旨在为初学者提供一份简明扼要的指南,介绍如何保护自己的智能家居设备免受网络攻击。通过分析智能家居系统常见的安全漏洞,并提供实用的防御策略,帮助读者建立起一道坚固的数字防线。
|
14天前
|
域名解析 网络协议 应用服务中间件
网络编程入门如此简单(四):一文搞懂localhost和127.0.0.1
本文将以网络编程入门者视角,言简意赅地为你请清楚localhost和127.0.0.1的关系及区别等。
19 2
网络编程入门如此简单(四):一文搞懂localhost和127.0.0.1
|
9天前
|
机器学习/深度学习 人工智能 自然语言处理
深度学习中的卷积神经网络(CNN)入门与实践
【8月更文挑战第62天】本文以浅显易懂的方式介绍了深度学习领域中的核心技术之一——卷积神经网络(CNN)。文章通过生动的比喻和直观的图示,逐步揭示了CNN的工作原理和应用场景。同时,结合具体的代码示例,引导读者从零开始构建一个简单的CNN模型,实现对图像数据的分类任务。无论你是深度学习的初学者还是希望巩固理解的开发者,这篇文章都将为你打开一扇通往深度学习世界的大门。
|
20天前
|
机器学习/深度学习 人工智能 算法
深度学习中的卷积神经网络(CNN)入门与实践
【9月更文挑战第19天】在这篇文章中,我们将探索深度学习的一个重要分支——卷积神经网络(CNN)。从基础概念出发,逐步深入到CNN的工作原理和实际应用。文章旨在为初学者提供一个清晰的学习路径,并分享一些实用的编程技巧,帮助读者快速上手实践CNN项目。
|
25天前
|
机器学习/深度学习 人工智能 TensorFlow
深度学习入门:理解卷积神经网络(CNN)
【9月更文挑战第14天】本文旨在为初学者提供一个关于卷积神经网络(CNN)的直观理解,通过简单的语言和比喻来揭示这一深度学习模型如何识别图像。我们将一起探索CNN的基本组成,包括卷积层、激活函数、池化层和全连接层,并了解它们如何协同工作以实现图像分类任务。文章末尾将给出一个简单的代码示例,帮助读者更好地理解CNN的工作原理。
42 7
|
2月前
|
图形学 C#
超实用!深度解析Unity引擎,手把手教你从零开始构建精美的2D平面冒险游戏,涵盖资源导入、角色控制与动画、碰撞检测等核心技巧,打造沉浸式游戏体验完全指南
【8月更文挑战第31天】本文是 Unity 2D 游戏开发的全面指南,手把手教你从零开始构建精美的平面冒险游戏。首先,通过 Unity Hub 创建 2D 项目并导入游戏资源。接着,编写 `PlayerController` 脚本来实现角色移动,并添加动画以增强视觉效果。最后,通过 Collider 2D 组件实现碰撞检测等游戏机制。每一步均展示 Unity 在 2D 游戏开发中的强大功能。
99 6
|
1月前
|
机器学习/深度学习 人工智能 TensorFlow
神经网络入门到精通:Python带你搭建AI思维,解锁机器学习的无限可能
【9月更文挑战第10天】神经网络是开启人工智能大门的钥匙,不仅是一种技术,更是模仿人脑思考的奇迹。本文从基础概念入手,通过Python和TensorFlow搭建手写数字识别的神经网络,逐步解析数据加载、模型定义、训练及评估的全过程。随着学习深入,我们将探索深度神经网络、卷积神经网络等高级话题,并掌握优化模型性能的方法。通过不断实践,你将能构建自己的AI系统,解锁机器学习的无限潜能。
30 0
|
2月前
|
机器学习/深度学习 人工智能 自然语言处理
深度学习中的卷积神经网络(CNN)入门
【8月更文挑战第31天】在人工智能的浪潮中,深度学习以其强大的数据处理能力成为时代的宠儿。本文将引导你走进深度学习的核心组件之一——卷积神经网络(CNN),并带你一探其背后的奥秘。通过简明的语言和直观的代码示例,我们将一起构建一个简易的CNN模型,理解它在图像处理领域的应用,并探索如何利用Python和TensorFlow实现它。无论你是初学者还是有一定基础的开发者,这篇文章都将为你打开一扇通往深度学习世界的大门。
|
2月前
|
Java 前端开发 Apache
Apache Wicket与Spring MVC等Java Web框架大PK,究竟谁才是你的最佳拍档?点击揭秘!
【8月更文挑战第31天】在Java Web开发领域,众多框架各具特色。Apache Wicket以组件化开发和易用性脱颖而出,提高了代码的可维护性和可读性。相比之下,Spring MVC拥有强大的生态系统,但学习曲线较陡;JSF与Java EE紧密集成,但在性能和灵活性上略逊一筹;Struts2虽成熟,但在RESTful API支持上不足。选择框架时还需考虑社区支持和文档完善程度。希望本文能帮助开发者找到最适合自己的框架。
32 0