动手学深度学习—深度学习计算(层和块、参数管理、自定义层和读写文件)

目录

  • 1. 层和块
    • 1.1 自定义块
    • 1.2 顺序块
    • 1.3 在前向传播函数中执行代码
  • 2. 参数管理
    • 2.1 参数访问
      • 2.1.1 目标参数
      • 2.1.2 一次性访问所有参数
      • 2.1.3 从嵌套块收集参数
    • 2.2 参数初始化
      • 2.2.1 内置初始化
      • 2.2.2 自定义初始化
    • 2.3 参数绑定
  • 3. 自定义层
    • 3.1 不带参数的层
    • 3.2 带参数的层
  • 4. 读写文件
    • 4.1 加载和保存张量
    • 4.2 加载和保存模型参数
  • 5. GPU

1. 层和块

块可以描述单个层、由多个层组成的组件或整个模型本身。

# 生成一个网络,其中包含一个具有256个单元和ReLU激活函数的全连接隐藏层
# 然后是一个具有10个隐藏单元且不带激活函数的全连接输出层
import torch
from torch import nn
from torch.nn import functional as F

net = nn.Sequential(nn.Linear(20,256), nn.ReLU(), nn.Linear(256,10))

X = torch.rand(2, 20)
net(X)

在这里插入图片描述

1.1 自定义块

"""
    自定义块:
    1、将输入数据作为其前向传播函数的参数。
    2、通过前向传播函数来生成输出(输出的形状可能与输入的形状不同)。
    3、计算其输出关于输入的梯度,可通过其反向传播函数进行访问。
    4、存储和访问前向传播计算所需的参数。
    5、根据需要初始化模型参数。
"""
"""
    多层感知机:
    1、输入是一个20维的输入。
    2、具有256个隐藏单元的隐藏层和一个10维输出层。
"""
class MLP(nn.Module):
    # 用模型参数声明层。这里,我们声明两个全连接层
    def __init__(self):
        # 调用MLP父类Module的构造函数来执行必要的初始化
        # 这样,在类实例化中也可以指定其他函数的参数,例如模型参数params
        super().__init__()
        self.hidden = nn.Linear(20, 256) # 隐藏层
        self.out = nn.Linear(256, 10) # 输出层
        
    # 定义模型的前向传播,即如何根据输入X返回所需的模型输出
    def forward(self, X):
        # 注意,这里我们使用ReLU的函数版本,其在nn.functional模块定义
        return self.out(F.relu(self.hidden(X)))

在这里插入图片描述

1.2 顺序块

"""
    顺序块(相当于Sequential类):
    1、一种将块逐个追加到列表中的函数;
    2、一种前向传播函数,用于将输入按追加块的顺序传递给块组成的“链条”。
"""
class MySequential(nn.Module):
    def __init__(self, *args):
        # __init__函数将每个模块逐个添加到有序字典_modules中
        super().__init__()
        for idx, module in enumerate(args):
            # 这里,module是Module子类的一个实例。我们把它保存在'Module'类的成员
            # _module的类型是OrderedDict,在模块的参数初始化过程中, 系统知道在_modules字典中查找需要初始化参数的子块。
            self._modules[str(idx)] = module
            
    def forward(self, X):
        # OrderedDict保证了按照成员添加的顺序遍历它们
        for block in self._modules.values():
            X = block(X)
        return X

在这里插入图片描述

1.3 在前向传播函数中执行代码

"""
   实现FixedHiddenMLP模型类:
   1、实现一个隐藏层, 其权重(self.rand_weight)在实例化时被随机初始化,之后为常量。
   2、这个权重不是一个模型参数,因此它永远不会被反向传播更新。
   3、神经网络将这个固定层的输出通过一个全连接层。
   4、返回输出时做一个循环操作,输出需小于1
"""
class FixedHiddenMLP(nn.Module):
    def __init__(self):
        super().__init__()
        # 不计算梯度的随机权重参数。因此其在训练期间保持不变
        self.rand_weight = torch.rand((20, 20), requires_grad=False)
        self.linear = nn.Linear(20 ,20)
        
    def forward(self, X):
        X = self.linear(X)
        # 使用创建的常量参数以及relu和mm函数
        X = F.relu(torch.mm(X, self.rand_weight) + 1)
        # 复用全连接层。这相当于两个全连接层共享参数
        X = self.linear(X)
        # 控制流
        while X.abs().sum() > 1:
            X /= 2
        return X.sum()

在这里插入图片描述

# 混合搭配各种组合块
class NestMLP(nn.Module):
    def __init__(self):
        super().__init__()
        self.net = nn.Sequential(nn.Linear(20, 64), nn.ReLU(),
                                 nn.Linear(64, 32), nn.ReLU())
        self.linear = nn.Linear(32, 16)
    
    def forward(self, X):
        return self.linear(self.net(X))

chimera = nn.Sequential(NestMLP(), nn.Linear(16, 20), FixedHiddenMLP())
chimera(X)

在这里插入图片描述

2. 参数管理

  1. 访问参数,用于调试、诊断和可视化;
  2. 参数初始化;
  3. 在不同模型组件间共享参数。
import torch 
from torch import nn

net = nn.Sequential(nn.Linear(4, 8), nn.ReLU(), nn.Linear(8, 1))
X = torch.rand(size=(2, 4))
net(X)

在这里插入图片描述

2.1 参数访问

"""
    检查第二个全连接层的参数:
    1、这个全连接层包含两个参数,分别是该层的权重和偏置。
    2、两者都存储为单精度浮点数(float32)。
"""
print(net[2].state_dict())

在这里插入图片描述

2.1.1 目标参数

# 访问目标参数
print(type(net[2].bias))
print(net[2].bias)
print(net[2].bias.data)

在这里插入图片描述

2.1.2 一次性访问所有参数

# 一次性访问所有参数
print(*[(name, param.shape) for name, param in net[0].named_parameters()])
print(*[(name, param.shape) for name, param in net.named_parameters()])

在这里插入图片描述

2.1.3 从嵌套块收集参数

# 从嵌套块收集参数
def block1():
    return nn.Sequential(nn.Linear(4, 8), nn.ReLU(),
                         nn.Linear(8, 4), nn.ReLU())

def block2():
    net = nn.Sequential()
    for i in range(4):
        # 在这里嵌套
        net.add_module(f'block {i}', block1())
    return net

rgnet = nn.S

在这里插入图片描述

2.2 参数初始化

"""
    参数初始化:
    1、内置初始化
    2、自定义初始化
"""
# 将所有权重参数初始化为标准差为0.01的高斯随机变量, 且将偏置参数设置为0
def init_normal(m):
    if type(m) == nn.Linear:
        nn.init.normal_(m.weight, mean=0, std=0.01)
        nn.init.zeros_(m.bias)

# model.apply(fn)会递归地将函数fn应用到父模块的每个子模块submodule,也包括model这个父模块自身
net.apply(init_normal)
net[0].weight.data[0], net[0].bias.data[0]

在这里插入图片描述

2.2.1 内置初始化

# 将所有参数初始化为给定的常数,比如初始化为1
def init_constant(m):
    if type(m) == nn.Linear:
        nn.init.constant_(m.weight, 1)
        nn.init.zeros_(m.bias)
        
net.apply(init_constant)
net[0].weight.data[0], net[0].bias.data[0]

在这里插入图片描述

# 使用Xavier初始化方法初始化第一个神经网络层, 然后将第三个神经网络层初始化为常量值42。
def init_xavier(m):
    if type(m) == nn.Linear:
        nn.init.xavier_uniform_(m.weight)
def init_42(m):
    if type(m) == nn.Linear:
        nn.init.constant_(m.weight, 42)

net[0].apply(init_xavier)
net[2].apply(init_42)
print(net[0].weight.data[0])
print(net[2].weight.data)

在这里插入图片描述

2.2.2 自定义初始化

# 自定义初始化
def my_init(m):
    if type(m) == nn.Linear:
        print("Init", *[(name, param.shape)
                        for name, param in m.named_parameters()][0])
        nn.init.uniform_(m.weight, -10, 10)
        m.weight.data *= m.weight.data.abs() >= 5

net.apply(my_init)
net[0].weight[:2]
# net[0].weight[0:]

在这里插入图片描述

2.3 参数绑定

# 在多个层间共享参数: 我们可以定义一个稠密层,然后使用它的参数来设置另一个层的参数。
# 我们需要给共享层一个名称,以便可以引用它的参数
"""
    参数绑定:
    1、第三个和第五个神经网络层的参数是绑定的。 它们不仅值相等,而且由相同的张量表示。
    2、如果我们改变其中一个参数,另一个参数也会改变。
    3、由于模型参数包含梯度,因此在反向传播期间第二个隐藏层 (即第三个神经网络层)和第三个隐藏层(即第五个神经网络层)的梯度会加在一起。
"""
shared = nn.Linear(8, 8)
net = nn.Sequential(nn.Linear(4, 8), nn.ReLU(),
                    shared, nn.ReLU(),
                    shared, nn.ReLU(),
                    nn.Linear(8 ,1))
net(X)
# 检查参数是否相同
print(net[2].weight.data[0] == net[4].weight.data[0])
net[2].weight.data[0, 0] = 100
# 确保它们实际上是同一个对象,而不是只有相同的值
print(net[2].weight.data[0] == net[4].weight.data[0])

在这里插入图片描述

3. 自定义层

我们可以用创造性的方式组合不同的层,从而设计出适用于各种任务的架构。

3.1 不带参数的层

"""
    自定义CenteredLayer类:
    1、要从其输入中减去均值;
    2、要构建它,我们只需继承基础层类并实现前向传播功能。
"""
import torch
import torch.nn.functional as F
from torch import nn

class CenteredLayer(nn.Module):
    def __init__(self):
        super().__init__()
        
    def forward(self, X):
        return X - X.mean()

在这里插入图片描述

3.2 带参数的层

"""
    自定义带参数的全连接层:
    1、该层需要两个参数,一个用于表示权重,另一个用于表示偏置项;
    2、使用修正线性单元作为激活函;
    3、in_units和units,分别表示输入数和输出数。
"""
class MyLinear(nn.Module):
    def __init__(self, in_units, units):
        super().__init__()
        self.weight = nn.Parameter(torch.randn(in_units, units))
        self.bias = nn.Parameter(torch.randn(units,))
    def forward(self, X):
        linear = torch.matmul(X, self.weight.data) + self.bias.data
        return F.relu(linear)

在这里插入图片描述

4. 读写文件

有时我们希望保存训练的模型, 以备将来在各种环境中使用(比如在部署中进行预测)。

4.1 加载和保存张量

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

x = torch.arange(4)
torch.save(x, 'x-file')

在这里插入图片描述

# 存储一个张量列表,然后把它们读回内存。
y = torch.zeros(4)
torch.save([x, y], 'x-files')
x2, y2 = torch.load('x-files')
(x2, y2)

在这里插入图片描述

# 写入或读取从字符串映射到张量的字典
mydict = {'x': x, 'y': y}
torch.save(mydict, 'mydict')
mydict2 = torch.load('mydict')
mydict2

在这里插入图片描述

4.2 加载和保存模型参数

"""
    加载和保存模型参数:
    1、深度学习框架提供了内置函数来保存和加载整个网络;
    2、保存模型的参数而不是保存整个模型。
"""
class MLP(nn.Module):
    def __init__(self):
        super().__init__()
        self.hidden = nn.Linear(20, 256)
        self.output = nn.Linear(256, 10)
        
    def forward(self, x):
        return self.output(F.relu(self.hidden(x)))
    
net = MLP()
X = torch.randn(size=(2, 20))
Y = net(X)

在这里插入图片描述

# 为了恢复模型,我们实例化了原始多层感知机模型的一个备份
clone = MLP()
clone.load_state_dict(torch.load('mlp.params'))
clone.eval()

在这里插入图片描述

5. GPU

GPU能够帮助我们更好地进行计算,使用nvidia-smi命令来查看显卡信息。

!nvidia-smi
# 定义了两个方便的函数, 这两个函数允许我们在不存在所需所有GPU的情况下运行代码
def try_gpu(i=0): #@save
    """如果存在,则返回gpu(i),否则返回cpu()"""
    if torch.cuda.device_count() >= i + 1:
        return torch.device(f'cuda:{i}')
    return torch.device('cpu')

def try_all_gpus(): #@save
    """返回所有可用的GPU,如果没有GPU,则返回[cpu(),]"""
    devices = [torch.device(f'cuda{i}')
              for i in range(torch.cuda.device_count())]
    return devices if devices else [torch.device('cpu')]

try_gpu(), try_gpu(10), try_all_gpus()

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/61297.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

数据安全治理实施办法

随着《数据安全法》和《个人信息保护法》陆续出台,各行业数据安全监管力度持续增强,数据安全合规成为企业数据安全治理体系建设的第一推动力。同时,企业普遍面临数据安全治理成本过高,对业务影响过大,实施路径不清晰等…

【雕爷学编程】Arduino动手做(186)---WeMos ESP32开发板14

37款传感器与模块的提法,在网络上广泛流传,其实Arduino能够兼容的传感器模块肯定是不止37种的。鉴于本人手头积累了一些传感器和执行器模块,依照实践出真知(一定要动手做)的理念,以学习和交流为目的&#x…

SQL从三个表中根据时间分别查询并汇总数量一行展示

需求:如果您要从三个表中根据时间分别查询并汇总数量,然后将结果以时间和数量一行展示,可以使用子查询和条件聚合。 入库主表 入库明细表 出库主表 出库明细表 退货主表 退货明细表 SQL代码 SELECT time,sum(a.inQty) as inQty,sum(a.outQty…

FFmpeg中硬解码后深度学习模型的图像处理dnn_processing(一)

ffmpeg 硬件解码 ffmpeg硬件解码可以使用最新的vulkan来做,基本上来说,不挑操作系统是比较重要的,如果直接使用cuda也是非常好的选择。 AVPixelFormat sourcepf AV_PIX_FMT_NV12;// AV_PIX_FMT_NV12;// AV_PIX_FMT_YUV420P;AVPixelFormat d…

O3DE的Pass

Pass介绍 Pass是具有输入和输出的渲染过程。 在最终渲染帧中看到的每个细节都是通过一系列Pass(前一个Pass的输出是下一个Pass的输入)计算出来的。Pass可以生成图像(作为纹理、缓冲区或渲染目标)。每个图像都包含关于场景的特定…

云曦暑期学习第四周——流量、日志分析

1 日志分析 1.1 What is 日志 日志,是作为记录系统与服务最直接有效的方法。在日志中,可以发现访问记录以及发现攻击线索。日志分析也是最常用的分析安全 事件所采用的途径。系统日志和 web 日志分别记录了不同内容,为分析攻击提供了有效证…

【敏捷开发】测试驱动开发(TDD)

测试驱动开发(Test-Driven Development,简称TDD)是敏捷开发模式中的一项核心实践和技术,也是一种设计方法论。TDD有别于以往的“先编码,后测试”的开发模式,要求在设计与编码之前,先编写测试脚本…

java+python企业会议在线办公微信小程序 ia505

一、小程序端功能 该部分内容提供员工注册、员工资料修改、通知公告、部门信息、会议记录等等功能。 二、管理员管理功能 该部分内容包含了首页、个人中心、通知公告管理、员工管理、部门信息管理、职位信息管理、会议记录管理、待办事项管理、工资信息管理、留言板管理、系统管…

Spring Boot 单元测试

目录 1.什么是单元测试? 2.单元测试的优点 3.Spring Boot 单元测试使用 3.1 生成单元测试的类 3.2 添加 Spring Boot 框架测试注解:SpringBootTest 3.3 添加单元测试业务逻辑 3.4 注解 Transactional 4. 断言 1.什么是单元测试? 单元…

Flink开发环境准备: centos-jdk8

linux-jdk8 - Flink开发环境准备 一、基本介绍二、环境准备1.1 JDK环境1.2 开发工具1.3 Maven环境 三、flink下载安装配置3.1 Flink下载3.2 flink本地模式安装 - linux3.3 常用配置3.4 日志的查看和配置 四、单机 Standalone 的方式运行 Flink 一、基本介绍 Flink底层源码是基于…

Open3D (C++) 计算矩阵的广义逆

目录 一、算法原理1、广义逆2、计算过程二、代码实现三、结果展示四、参考链接本文由CSDN点云侠原创,原文链接。爬虫网站自重,把自己当个人,爬些不完整的误导别人有意思吗???? 一、算法原理 1、广义逆 非方阵不存在逆,但是存在广义逆(伪逆)。对于一个矩阵

【大数据】-- docker 启动 mysql 5.7,开启 binlog

1.说明 mysql binlog:二进制日志文件。它有两个作用,一是增量备份,即只备份新增的内容,可以用于恢复数据;二是用于主从复制等,即主节点维护了一个binlog日志文件,从节点从binlog中同步数据。 …

ChatGPT下架官方检测工具,承认无法鉴别AI内容

去年底,OpenAI 推出的 ChatGPT ,带来了生成式人工智能涌现的热潮。它不仅能够协助完成撰写邮件、视频脚本、文案、翻译、代码等任务,还能通过学习和理解人类的语言来进行对话,并根据聊天的上下文进行互动。 但随之而来的争议也让人…

【雕爷学编程】Arduino动手做(186)---WeMos ESP32开发板15

37款传感器与模块的提法,在网络上广泛流传,其实Arduino能够兼容的传感器模块肯定是不止37种的。鉴于本人手头积累了一些传感器和执行器模块,依照实践出真知(一定要动手做)的理念,以学习和交流为目的&#x…

Java 8 中使用 Stream 遍历树形结构

在实际开发中,我们经常会开发菜单,树形结构,数据库一般就使用父id来表示,为了降低数据库的查询压力,我们可以使用Java8中的Stream流一次性把数据查出来,然后通过流式处理,我们一起来看看&#x…

找不到org.apache.http.annotation.NotThreadSafe的类文件

问题现象 最近在做一个调用包含请求体的GET请求功能的时候,引用了 httpclient-4.5.2.jar 和 httpcore-4.4.5.jar。 在工程编译环节报错如下: 原因分析 httpcore 和 httpclient 的版本不匹配。 解决方案 将 httpcore 的版本由 4.4.5 改为 4.4.4&am…

Unity学习参考文档和开发工具

☺ unity的官网文档:脚本 - Unity 手册 ■ 学习方式: 首先了解unity相关概述,快速认识unity编辑器,然后抓住重点的学:游戏对象、组件|C#脚本、预制体、UI ☺ 学习过程你会发现,其实Unity中主要是用c#进行开…

大麦订单生成器 大麦一键生成订单

后台一键生成链接,独立后台管理 教程:修改数据库config/Conn.php 不会可以看源码里有教程 下载源码程序:https://pan.baidu.com/s/16lN3gvRIZm7pqhvVMYYecQ?pwd6zw3

基于C#的应用程序单例唯一运行的完美解决方案 - 开源研究系列文章

今次介绍一个应用程序单例唯一运行方案的代码。 我们知道,有些应用程序在操作系统中需要单例唯一运行,因为程序多开的话会对程序运行效果有影响,最基本的例子就是打印机,只能运行一个实例。这里将笔者单例运行的代码共享出来&…

安防监控视频融合EasyCVR平台接入RTSP流后设备显示离线是什么原因?

安防监控视频EasyCVR视频汇聚融合平台基于云边端智能协同架构,具有强大的数据接入、处理及分发能力,平台支持海量视频汇聚管理、全网分发、按需调阅、鉴权播放、智能分析等视频能力与服务。平台开放度高、兼容性强、可支持灵活拓展与第三方集成&#xff…