pytorch 学习笔记6 —— 一步步解析nn模块

AI权益加码!Claude Code、Cursor等20+工具免费用! 购周边限时加赠Coding Plan Lite,畅享主流AI工具!学习进阶更高效! 阅读详情

一步步解析nn模块

来源:https://pytorch.org/tutorials/beginner/nn_tutorial.html#refactor-using-optim

数据集

使用的数据集是MNIST,有多种方式可以获取,包括教程中的requests方式。这里不在详细说明,但是说明将数据转化为图片的方式。(MNIST的数据是手写数字)

使用matplotlib显示图片
pyplot.imshow(x_train[0].reshape((28, 28)), cmap="gray")
print(x_train.shape)
将数据转化为torch.tensor
x_train, y_train, x_valid, y_valid = map(
    torch.tensor, (x_train, y_train, x_valid, y_valid)
)
使用自动计算梯度
import math

weights = torch.randn(784, 10) / math.sqrt(784)
weights.requires_grad_()
bias = torch.zeros(10, requires_grad=True)
自定义自己的损失函数

虽然pytorch提供了很多写好的loss function,activation function给我们,但我们可以自己实现自己的版本。pytorch会自动将代码优化为更快的CPU或者向量化CPU的计算方式。

def log_softmax(x):
    return x - x.exp().sum(-1).log().unsqueeze(-1)

def model(xb):
    return log_softmax(xb @ weights + bias)

其中@代表点乘

批处理
bs = 64  # batch size

xb = x_train[0:bs]  # a mini-batch from x
preds = model(xb)  # predictions
preds[0], preds.shape
print(preds[0], preds.shape)

Out:
tensor([-2.9153, -2.6091, -2.9060, -2.2049, -2.4748, -2.4453, -2.1476, -2.1597,
        -2.7930, -1.4146], grad_fn=<SelectBackward>) torch.Size([64, 10])
定义negative log-likelihood loss_func
def nll(input, target):
    return -input[range(target.shape[0]), target].mean()

loss_func = nll
测试
yb = y_train[0:bs]
print(loss_func(preds, yb))

Out:
tensor(2.3504, grad_fn=<NegBackward>)
定义计算准确率函数
def accuracy(out, yb):
    preds = torch.argmax(out, dim=1)
    return (preds == yb).float().mean()

print(accuracy(preds, yb))

Out:
tensor(0.1562)
使用torch.no_grad()更新权重和偏置

使用weights.grad.zero_() bias.grad.zero_()是为了准备好进行下一次梯度计算。避免梯度累加。因为每次计算不是覆盖,而是累加上去。

set_trace() 可以追踪每一步的变量的值。

from IPython.core.debugger import set_trace

lr = 0.5  # learning rate
epochs = 2  # how many epochs to train for

for epoch in range(epochs):
    for i in range((n - 1) // bs + 1):
        # set_trace()
        start_i = i * bs
        end_i = start_i + bs
        xb = x_train[start_i:end_i]
        yb = y_train[start_i:end_i]
        pred = model(xb)
        loss = loss_func(pred, yb)

        loss.backward()
        with torch.no_grad():
            weights -= weights.grad * lr
            bias -= bias.grad * lr
            weights.grad.zero_()
            bias.grad.zero_()

# 再次测试
print(loss_func(model(xb), yb), accuracy(model(xb), yb))

Out:
tensor(0.0829, grad_fn=<NegBackward>) tensor(1.)
使用torch.nn.funcional进行改进
import torch.nn.functional as F

loss_func = F.cross_entropy

def model(xb):
    return xb @ weights + bias
	
print(loss_func(model(xb), yb), accuracy(model(xb), yb))

Out:
tensor(0.0829, grad_fn=<NllLossBackward>) tensor(1.)
使用nn.Module 进行改进

注意这里的Module是大写的M,小写的module是另一完全不同的库。

from torch import nn

class Mnist_Logistic(nn.Module):
    def __init__(self):
        super().__init__()
        self.weights = nn.Parameter(torch.randn(784, 10) / math.sqrt(784))
        self.bias = nn.Parameter(torch.zeros(10))

    def forward(self, xb):
        return xb @ self.weights + self.bias
		
model = Mnist_Logistic()

print(loss_func(model(xb), yb))

Out:
tensor(2.3437, grad_fn=<NllLossBackward>)
使用model.parameters() and model.zero_grad()进行改进

原来的版本:

with torch.no_grad():
    weights -= weights.grad * lr
    bias -= bias.grad * lr
    weights.grad.zero_()
    bias.grad.zero_()

改进之后的版本:

with torch.no_grad():
    for p in model.parameters(): p -= p.grad * lr
    model.zero_grad()

写进fit():

def fit():
    for epoch in range(epochs):
        for i in range((n - 1) // bs + 1):
            start_i = i * bs
            end_i = start_i + bs
            xb = x_train[start_i:end_i]
            yb = y_train[start_i:end_i]
            pred = model(xb)
            loss = loss_func(pred, yb)

            loss.backward()
            with torch.no_grad():
                for p in model.parameters():
                    p -= p.grad * lr
                model.zero_grad()

fit()

print(loss_func(model(xb), yb))

Out:
tensor(0.0812, grad_fn=<NllLossBackward>)
使用nn.Linear 进行改进

使用Linear帮助我们初始化和进行前向操作。

原来的版本:

class Mnist_Logistic(nn.Module):
    def __init__(self):
        super().__init__()
        self.weights = nn.Parameter(torch.randn(784, 10) / math.sqrt(784))
        self.bias = nn.Parameter(torch.zeros(10))

    def forward(self, xb):
        return xb @ self.weights + self.bias

改进之后的版本:

class Mnist_Logistic(nn.Module):
    def __init__(self):
        super().__init__()
        self.lin = nn.Linear(784, 10)

    def forward(self, xb):
        return self.lin(xb)

model = Mnist_Logistic()
print(loss_func(model(xb), yb))

Out:
tensor(2.3360, grad_fn=<NllLossBackward>)

fit()
print(loss_func(model(xb), yb))

Out:
tensor(0.0798, grad_fn=<NllLossBackward>)
使用optim 进行改进

原来的版本:

with torch.no_grad():
    for p in model.parameters(): p -= p.grad * lr
    model.zero_grad()

改进之后的版本:

from torch import optim

# opt.step()
# opt.zero_grad()


def get_model():
    model = Mnist_Logistic()
    return model, optim.SGD(model.parameters(), lr=lr)

model, opt = get_model()
print(loss_func(model(xb), yb))

for epoch in range(epochs):
    for i in range((n - 1) // bs + 1):
        start_i = i * bs
        end_i = start_i + bs
        xb = x_train[start_i:end_i]
        yb = y_train[start_i:end_i]
        pred = model(xb)
        loss = loss_func(pred, yb)

        loss.backward()
        opt.step()
        opt.zero_grad()

print(loss_func(model(xb), yb))

Out:
tensor(2.3593, grad_fn=<NllLossBackward>)
tensor(0.0821, grad_fn=<NllLossBackward>)
使用fit()进行改进

如果没有传入opt,那么将不会进行反向传播。

def loss_batch(model, loss_func, xb, yb, opt=None):
    loss = loss_func(model(xb), yb)

    if opt is not None:
        loss.backward()
        opt.step()
        opt.zero_grad()

    return loss.item(), len(xb)
	
import numpy as np

def fit(epochs, model, loss_func, opt, train_dl, valid_dl):
    for epoch in range(epochs):
        model.train()
        for xb, yb in train_dl:
            loss_batch(model, loss_func, xb, yb, opt)

        model.eval()
        with torch.no_grad():
            losses, nums = zip(
                *[loss_batch(model, loss_func, xb, yb) for xb, yb in valid_dl]
            )
        val_loss = np.sum(np.multiply(losses, nums)) / np.sum(nums)

        print(epoch, val_loss)
自己定义一个CNN网络
class Mnist_CNN(nn.Module):
    def __init__(self):
        super().__init__()
        self.conv1 = nn.Conv2d(1, 16, kernel_size=3, stride=2, padding=1)
        self.conv2 = nn.Conv2d(16, 16, kernel_size=3, stride=2, padding=1)
        self.conv3 = nn.Conv2d(16, 10, kernel_size=3, stride=2, padding=1)

    def forward(self, xb):
        xb = xb.view(-1, 1, 28, 28)
        xb = F.relu(self.conv1(xb))
        xb = F.relu(self.conv2(xb))
        xb = F.relu(self.conv3(xb))
        xb = F.avg_pool2d(xb, 4)
        return xb.view(-1, xb.size(1))

lr = 0.1

model = Mnist_CNN()
opt = optim.SGD(model.parameters(), lr=lr, momentum=0.9)

fit(epochs, model, loss_func, opt, train_dl, valid_dl)

Out:
0 0.346197331571579
1 0.26924657912254335
使用nn.Sequential

其实这是一种简化的定义神经网络的方式。

搭配Lambda:lambda可以在我们定义的模型的时候创建层。其定义如下:

Lambda will create a layer that we can then use when defining a network with Sequential.
class Lambda(nn.Module):
    def __init__(self, func):
        super().__init__()
        self.func = func

    def forward(self, x):
        return self.func(x)


def preprocess(x):
    return x.view(-1, 1, 28, 28)

model = nn.Sequential(
    Lambda(preprocess),
    nn.Conv2d(1, 16, kernel_size=3, stride=2, padding=1),
    nn.ReLU(),
    nn.Conv2d(16, 16, kernel_size=3, stride=2, padding=1),
    nn.ReLU(),
    nn.Conv2d(16, 10, kernel_size=3, stride=2, padding=1),
    nn.ReLU(),
    nn.AvgPool2d(4),
    Lambda(lambda x: x.view(x.size(0), -1)),
)

opt = optim.SGD(model.parameters(), lr=lr, momentum=0.9)

fit(epochs, model, loss_func, opt, train_dl, valid_dl)

Out:
0 0.38947487244606016
1 0.279226434135437
使用GPU

如果可以使用CUDA-capable GPU,将会对代码进行加速。

  • 判断是否可以用:
print(torch.cuda.is_available())

Out:
True
  • 接着创建设备:
dev = torch.device(
    "cuda") if torch.cuda.is_available() else torch.device("cpu")

  • 将数据移动到“设备”上
	
def preprocess(x, y):
    return x.view(-1, 1, 28, 28).to(dev), y.to(dev)

train_dl, valid_dl = get_data(train_ds, valid_ds, bs)
train_dl = WrappedDataLoader(train_dl, preprocess)
valid_dl = WrappedDataLoader(valid_dl, preprocess)
  • 将模型移动到GPU上
model.to(dev)
opt = optim.SGD(model.parameters(), lr=lr, momentum=0.9)

fit(epochs, model, loss_func, opt, train_dl, valid_dl)
Pytorch nn.Module模块详解 torcn.nn是专门为神经网络设计的模块化接口. nn构建于autograd之上,可以用来定义和运行神经网络。 nn.Module是nn中十分重要的类,包含网络各层的定义及forward方法。 如何定义自己的网络: 需要继承nn.Module类,并实现forward方法。 一般把网络中具有可学习参数的层放在构造函数__init__()中。 不具有可学习参数的层(如ReLU)可放在构造函数中,也... 阅读详情

相关推荐

PyTorch学习笔记(1)nn.Sequential、nn.Conv2d、nn.BatchNorm2d、nn.ReLU和nn.MaxPool2d

这里写目录标题一、nn.Sequential二、nn.Conv2d 一、nn.Sequential torch.nn.Sequential是一个Sequential容器,模块将按照构造函数中传递的顺序添加到模块中。另外,也可以传入一个有序模块。 为了更容易理解,官方给出了一些案例: # Sequential使用实例 model = nn.Sequential( nn.Conv2d(1,20,5), nn.ReLU(), nn.Conv2d(20,

weixin_42495721的博客 1万+

pytorch学习第二章——神经网络分类任务

Mnist分类任务: 网络基本构建与训练方法,常用函数解析 torch.nn.functional模块 nn.Module模块 import torch x_train, y_train, x_valid, y_valid = map( torch.tensor, (x_train, y_train, x_valid, y_valid) )#将数据转化为tensor类型 import torch.nn.functional as F loss_func = F.cross_ent

csdn_ggboy的博客 632

pytorch小记:nn.ModuleList和nn.Sequential的用法以及区别

参考链接: 官方文档containers 知乎:PyTorch 中的 ModuleList 和 Sequential: 区别和使用场景 知乎:详解PyTorch中的ModuleList和Sequential

sunnygirl's house 2万+

神经网络分类任务(手写数字识别)

网络基本构建与训练方法,常用函数解析torch.nn.functional模块nn.Module模块

qq_60498436的博客 534

Pytorch实战1—— 神经网络对MNIST 数据集分类

Pytorch实战1—— MNIST 数据集分类

Evan_qin_yi_quan的博客 1171

神经网络分类任务

数据大小x_train.shape=(x,y)x=数据集中样本个数y=每个样本的横*纵**像素若分类结果为n分类,每个像素点分类为1*n的概率矩阵将数据转换为tensor模式 由上,数据分为训练集输入x_train,训练集输出y_train,验证集输入x_valid,验证集输出y_valid。可以看见,训练集大小为50000784,而测试集大小为10000×784。每784个像素点为一个单独的数据,即说明当前训练集有50000个数据,而验证集有10000个数据。设置batch大小为bs=64,取得单个bat

chenweiguofff的博客 960

pytorch基础知识

搭建神经网络 定义神经网络,得到一个model 定义损失函数:torch.nn.xxLoss 定义优化器,构造一个optimizer对象:torch.optim.xx 训练神经网络 正向传播 根据损失函数计算loss 反向传播:loss.backward() 梯度下降:optimizer.step() 梯度归零:optimizer.zero_grad() 张量 生成张量 torch.tensor(data) torch.from_numpy(np_array) torch.x..

博观约取,厚积薄发 2033

Pytorch笔记 之 torch.nn 模块简介

参考翻译 [What is torch.nn really?](https://pytorch.org/tutorials/beginner/nn_tutorial.html) 主要是对 PyTorch 框架的各模块进行简要介绍 一定程度上是 PyTorch 的入门笔记 假设已经对神经网络相关基础知识有了一定了解 (或实现过机器学习梯度下降相关代码)

子耶 6万+

pytorchnn.Sequential详解

nn.Sequential是一个序列容器,用于搭建神经网络的模块被按照被传入构造器的顺序添加到容器中。除此之外,一个包含神经网络模块的OrderedDict也可以被传入nn.Sequential()容器中。利用nn.Sequential()搭建好模型架构,模型前向传播时调用forward()方法,模型接收的输入首先被传入nn.Sequential()包含的第一个网络模块中。然后,第一个网络模块的输出传入第二个网络模块作为输入,按照顺序依次计算并传播,直到nn.Sequential()里的最后一个模块输出结果

十年以上架构设计经验,专注于软件架构和人工智能领域,对机器视觉、NLP、音视频等领域都有涉猎 1万+

PyTorchnn.Module类的详细介绍

PyTorch中,nn.Module类是构建神经网络模型的基础类,所有自定义的层、模块或整个神经网络架构都需要继承自这个类。nn.Module类提供了一系列属性和方法用于管理网络的结构和训练过程中的计算。

xw555666的博客 7696

Pytorchnn.ModuleList和nn.Sequential的用法和区别

最近在定义一个多任务网络的时候对nn.ModuleList和nn.Sequential的用法产生了疑惑,这里让我们一起来探究一下二者的用法和区别。 nn.ModuleList的作用 先来探究一下nn.ModuleList的作用,定义一个简单的只含有全连接的网络来看一下。当不使用ModuleList只用list来定义网络中的层的时候: import torch import torch.nn...

watermelon1123的博客 7979

PyTorch学习笔记】23:nn.LSTM和nn.LSTMCell的使用

1 nn.LSTM 该模块一次构造完若干层的LSTM。 1.1 构造方法 使用nn.LSTM可以直接构建若干层的LSTM,构造时传入的三个参数和nn.RNN一样,依次是: [feature_len,hidden_len,num_layers] [feature\_len,hidden\_len,num\_layers] [feature_len,hidden_len,num_layers] 其中h...

大桔骑士的学习笔记 2万+

PyTorch 中神经网络库torch.nn的详细介绍

torch.nnPyTorch 深度学习框架中的一个核心模块,它为构建和训练神经网络提供了丰富的类库。通过torch.nn,开发者能够快速构建复杂的深度学习模型,并利用 PyTorch 动态计算图特性进行高效训练和推理。此外,该模块还与torch.optim配合,方便地进行权重优化;以及与DataLoader结合以组织和迭代训练数据。

xw555666的博客 6931

Pytorch中的nn.Embedding()

首先,我们先理解一下什么是Embedding。 Word Embedding 翻译过来的意思就是词嵌入,通俗来讲就是将文字转换为一串数字。因为数字是计算机更容易识别的一种表达形式。 我们词嵌入的过程,就相当于是我们在给计算机制造出一本字典的过程。计算机可以通过这个字典来间接地识别文字。 所以,接下来看看Pytorch里面的Embedding是什么样子的叭: torch.nn.Embedding 介...

qq_38883844的博客 5万+

PyTorch基础模块nn.Sequential

nn.Sequential模块学习

weixin_45653897的博客 6721

PyTorchnn.Module、nn.Sequential、nn.ModuleList使用详解

nn.functional 中的函数没有可学习的参数,与nn.Module 中的层不同。其实这两种方法都是使用relu激活,只是使用的场景不一样,F.relu()是函数调用,一般使用在foreward函数里。在上述示例中,我们首先导入nn.functional 模块,然后在网络的forward 方法中使用F.relu 函数作为激活函数。的主要优势是它的计算效率和灵活性,因为它允许你以函数的方式直接调用这些操作,而不需要创建额外的层。是PyTorch中一个重要的模块,它包含了许多用于构建神经网络的函数。

酒酿小圆子呀~ 6061

Pytorch学习(二)—— nn模块

torch.nnnn.Module常用的神经网络相关层优化器nn.functional初始化策略nn.Module深入分析nn和autograd借助nn搭建ResNet50 Pytorch nn模块提供了创建和训练神经网络的各种工具,其专门为深度学习设计,核心的数据结构是Module。Module是一个抽象的概念,既可以表示神经网络中的某个层,也可以表示一个包含很多层的神经网络。 nn.Module nn.Module基类构造函数: def __init__(self): self.tra

qq_38816432的博客 7412

PyTorch学习笔记】21:nn.RNNnn.RNNCell的使用

这节学习PyTorch的循环神经网络层nn.RNN,以及循环神经网络单元nn.RNNCell的一些细节。 1 nn.RNN涉及的Tensor PyTorch中的nn.RNN的数据处理如下图所示。每次向网络中输入batch个样本,每个时刻处理的是该时刻的batch个样本,因此xtx_txt​是shape为[batch,feature_len][batch, feature\_len][batch,f...

大桔骑士的学习笔记 1万+

PyTorchnn.ReLU与F.ReLU的区别

import torch.nn as nn import torch.nn.functional as F import torch.nn as nn class AlexNet_1(nn.Module): def __init__(self, num_classes=n): super(AlexNet, self).__init__() self.f...

鹊踏枝-码农的专栏 7万+
上一篇: pytorch 学习笔记5 —— 实例学习
下一篇: python 读取大文件
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值