深度学习 —— 个人学习笔记8(层和块、参数管理、自定义层及读写文件)

news2024/9/21 22:35:38

声明

  本文章为个人学习使用,版面观感若有不适请谅解,文中知识仅代表个人观点,若出现错误,欢迎各位批评指正。

十五、层和块

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

device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")

# 单层神经网络,线性层 + RelU + 线性层
net = nn.Sequential(nn.Linear(20, 256), nn.ReLU(), nn.Linear(256, 10)).to(device)

X = torch.rand(2, 20).to(device)
print(f'net(X) : {net(X)}')
print(net, "\n")

""" 自定义块 """
class MLP(nn.Module):
    # 用模型参数声明层。这里,我们声明两个全连接的层
    def __init__(self):
        # 调用 MLP 的父类 Module 的构造函数来执行必要的初始化。
        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)))


net = MLP().to(device)
print(f'自定义块 : {net(X)}')
print(net, "\n")

""" 顺序块 """
class MySequential(nn.Module):
    def __init__(self, *args):
        super().__init__()
        for idx, module in enumerate(args):
            # 这里,module 是 Module 子类的一个实例。我们把它保存在'Module'类的成员
            # 变量_modules 中。_module 的类型是 OrderedDict
            self._modules[str(idx)] = module

    def forward(self, X):
        # OrderedDict 保证了按照成员添加的顺序遍历它们
        for block in self._modules.values():
            X = block(X)
        return X


net = MySequential(nn.Linear(20, 256), nn.ReLU(), nn.Linear(256, 10)).to(device)
print(f'顺序块 : {net(X)}')
print(net, "\n")

""" 在前向传播函数中执行代码 """
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.to(device)) + 1)
        # 复用全连接层。这相当于两个全连接层共享参数
        X = self.linear(X).to(device)
        # 控制流
        while X.abs().sum() > 1:
            X /= 2
        return X.sum()


net = FixedHiddenMLP().to(device)
print(f'将自定义功能集成到神经网络计算的流程中 : {net(X)}')
print(net, "\n")

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()).to(device)
print(f'混合搭配各种组合块 : {chimera(X)}')
print(chimera, "\n")

十六、参数管理

import torch
from torch import nn

device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")

""" 参数管理 """
net = nn.Sequential(nn.Linear(4, 8), nn.ReLU(), nn.Linear(8, 1)).to(device)
X = torch.rand(size=(2, 4)).to(device)
print(f'net(X) : {net(X)}')
""" 访问目标参数 """
print(f'访问第 2 个全连接层的参数 : {net[2].state_dict()}')
print(f'查看第 2 个全连接层偏置的类型 : {type(net[2].bias)}')
print(f'查看第 2 个全连接层的偏置 : {net[2].bias}')
print(f'查看第 2 个全连接层偏置的值 : {net[2].bias.data}')

print(f'查看第 2 个全连接层参数的梯度是否处于初始状态 : {net[2].weight.grad == None}')

""" 一次性访问所有参数 """
print("访问第一个全连接层的参数 : ", *[(name, param.shape) for name, param in net[0].named_parameters()])
print("访问所有全连接层的参数 : ", *[(name, param.shape) for name, param in net.named_parameters()])

print("查看第 2 个全连接层偏置的值 : ", net.state_dict()['2.bias'].data)

""" 从嵌套块收集参数 """
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):
        # 在这里嵌套,循环套入 4 次 block1
        net.add_module(f'block {i}', block1())
    return net


rgnet = nn.Sequential(block2(), nn.Linear(4, 1)).to(device)
print("rgnet(X) : ", rgnet(X))

print(f'rgnet 中包含哪些层和块 : {rgnet}')

print("访问第一个主要的块中、第二个子块的第一层的偏置项 : ", rgnet[0][1][0].bias.data)

""" 内参初始化 """
def init_normal(m):
    if type(m) == nn.Linear:
        # 初始化为均值为 0,标准差为 0.01 的高斯随机变量,且将偏置参数设置为 0
        nn.init.normal_(m.weight, mean=0, std=0.01)
        nn.init.zeros_(m.bias)


net.apply(init_normal)
print("查看初始化后的权重值及偏置值 : ", net[0].weight.data[0], net[0].bias.data[0])

def init_constant(m):
    if type(m) == nn.Linear:
        nn.init.constant_(m.weight, 1)
        nn.init.zeros_(m.bias)


net.apply(init_constant)
print("查看初始化后的权重值及偏置值 : ", net[0].weight.data[0], net[0].bias.data[0])

def init_xavier(m):
    if type(m) == nn.Linear:
        nn.init.xavier_uniform_(m.weight)
def init_15(m):
    if type(m) == nn.Linear:
        nn.init.constant_(m.weight, 15)


net[0].apply(init_xavier)
net[2].apply(init_15)
print("查看初始化后的权重值及偏置值 : ", net[0].weight.data[0], net[2].weight.data)

""" 自定义初始化 """
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               # 保留绝对值大于 5 的数,其余变为 0


net.apply(my_init)
print("查看初始化后的权重值 : ", net[0].weight[:2])

net[0].weight.data[:] += 5
net[0].weight.data[0, 0] = 15
print("查看修改后的权重值 : ", net[0].weight.data[0])

""" 参数绑定 """
# 需要给共享层一个名称,以便可以引用它的参数
shared = nn.Linear(8, 8)
net = nn.Sequential(nn.Linear(4, 8), nn.ReLU(),
                    shared, nn.ReLU(),
                    shared, nn.ReLU(),
                    nn.Linear(8, 1)).to(device)
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])

print("查看 net 中的层和块 : ", net)

十七、自定义层

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

device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")

""" 自定义层 """
class CenteredLayer(nn.Module):
    def __init__(self):
        super().__init__()

    def forward(self, X):
        return X - X.mean()               # X - X 的均值


layer = CenteredLayer()
print("查看构建的层 : ", layer(torch.FloatTensor([1, 2, 3, 4, 5]).to(device)))

net = nn.Sequential(nn.Linear(8, 128), CenteredLayer()).to(device)

Y = net(torch.rand(4, 8).to(device))
print("将层作为组件合并到其它的模型 : ", format(Y.mean(), '.2f'))         # 验证 Y 的均值

""" 带参数的层 """
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)


linear = MyLinear(5, 3).to(device)
print("访问模型参数 : ", linear.weight)

print("使用自定义层直接执行前向传播计算 : ", linear(torch.rand(2, 5).to(device)))

net = nn.Sequential(MyLinear(64, 8), MyLinear(8, 1)).to(device)
print("使用自定义层构建模型 : ", net(torch.rand(2, 64).to(device)))

十八、读写文件

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

""" 读写文件 """
x = torch.arange(4)
# 将数据存入指定位置
torch.save(x, 'E:\\DeeplearningStudyDoc\\x-file')

x2 = torch.load('E:\\DeeplearningStudyDoc\\x-file')
print("将存储在文件中的数据读回内存 : ", x2)

y = torch.zeros(4)
torch.save([x, y],'E:\\DeeplearningStudyDoc\\x-file')
x2, y2 = torch.load('E:\\DeeplearningStudyDoc\\x-file')
print("存储一个张量列表,然后把它们读回内存 : ", (x2, y2))

mydict = {'x': x, 'y': y}
torch.save(mydict, 'E:\\DeeplearningStudyDoc\\mydict')
mydict2 = torch.load('E:\\DeeplearningStudyDoc\\mydict')
print("存储成字典并读取 : ", mydict2)

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)

torch.save(net.state_dict(), 'E:\\DeeplearningStudyDoc\\mlp.params')

clone = MLP()
clone.load_state_dict(torch.load('E:\\DeeplearningStudyDoc\\mlp.params'))
print("直接读取文件中存储的参数以创建备份 : ", clone.eval())

Y_clone = clone(X)
print("验证备份模型与原模型是否相同 : ", Y_clone == Y)


  文中部分知识参考:B 站 —— 跟李沐学AI;百度百科

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

6-1 从全连接层到卷积

我们之前讨论的多层感知机十分适合处理表格数据,其中行对应样本,列对应特征。 对于表格数据,我们寻找的模式可能涉及特征之间的交互,但是我们不能预先假设任何与特征交互相关的先验结构。 此时,多层感知机可能是最好的…

程序员面试题------N皇后问题算法实现

N皇后问题是一个著名的计算机科学问题,它要求在NN的棋盘上放置N个皇后,使得它们之间不能相互攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上。这个问题可以看作是一个回溯算法问题,通过逐步尝试不同的放置位置&#xf…

手持气象设备:掌握天气的便捷伙伴

在这个快速变化的时代,手持气象设备成为了我们日常生活中重要的小帮手。它小巧轻便,易于携带,让我们随时随地都能掌握天气变化,为出行、户外活动提供准确参考。 手持气象设备内置了高精度传感器,能够迅速感知并显示当前…

PCB学习

教你怎么检查电路原理图_原理图检视主要内容-CSDN博客https://blog.csdn.net/chenhuanqiangnihao/article/details/113664734

继全球蓝屏后,微软 Azure 云服务因安全错误导致全球宕机

7月30日,微软Azure云服务全球宕机约8小时。该事件由一次DDoS攻击引起,成功触发系统保护机制,但这些防御机制中的实施错误反而进一步放大了影响,最终造成一次大宕机事件。据英国广播公司报道,此次中断持续了大约 10 个小…

5步教你学会古诗词生成AI绘画

本文由 ChatMoney团队出品 首先,打开时下最热门的两个AI工具,mj和chatgpt这两个都是我们在创作AI古诗词绘画中一定要用到的,这里我用的是chatmoneyAI系统 第一步:我们要先使用ChatGPT来生成我们所想要展示古诗的关键词。那么我们…

代码随想录算法训练营第二十一天| 39. 组合总和, 40.组合总和II, 131.分割回文串

今天是回溯算法学习的第二天,主要的学习内容包括:1.组合问题的重复使用 2.组合问题的去重 3.分割问题的处理方法。 39. 组合总和 题目链接:39. 组合总和 - 力扣(LeetCode) 这个组合问题的特点是,集合内的…

Java:基于TextRank算法的自动摘要(自动生成事件摘要)

TextRank 是一种用于文本摘要的自然语言处理算法。它的工作原理类似于 Google 搜索引擎的 PageRank 算法,即根据文本中每个单词出现的频率和被引用的次数来评估它的重要性。 所谓自动摘要,就是从文章中自动抽取关键句。何谓关键句?人类的理解…

最好用的复制粘贴软件pastemate功能简介

这应当是windows下最好用的复制粘贴软件,遥遥领先的复制粘贴软件。 效增PasteMate - 下载页面 windows下界面最优美,操作最方便的复制粘贴神器,学生党论文必备,效率神器 pastemate 1.搜索功能,能够按文本、图片、文件…

C# 构建观测者模式(或者为订阅者模型)

前言: 观测者模型的基本理念,就是,我有一个公共的事件,定义好他的事件的触发、数据接口。然后,通过增加订阅者(实例)来订阅这个事件的,或者说观察这个事件。如果事件发生&#xff0…

软件测试的挑战和压力

软件测试过程中可能会遇到很多挑战,比如: 1. 需求不明确或不稳定。如果需求文档不完整、不清晰或不一致,或者需求在开发过程中频繁变更,那么测试人员就很难设计和执行有效的测试用例,也很难判断测试结果是否符合预期。…

5年经验的软件测试人员,碰到这样的面试题居然会心虚......

我们这边最近的面试机会比较多,但是根据他们的反馈,结束后大部分都没音信了,因为现在企业面试问的非常多,范围非常广,而且开放性的问题很多,很多人即便面试前刷了成百上千道面试题,也很难碰到一…

C语言——指针数组

文章目录 🍊自我介绍🍊前言🍊含义🍊输出指针数组中的值🍊指针数组工程的用法(模拟linux的内核代码) 你的点赞评论就是对博主最大的鼓励 当然喜欢的小伙伴可以:点赞关注评论收藏&…

实习中学到的一点计算机知识(MP4在企业微信打不开?)

我在实习中,常有同事向我反馈说我在微信发的视频格式打不开。这就导致我还要一帧帧的盯着某一个时刻来截图,今天查了一下资料尝试修改视频后缀来解决视频的播放问题。 在网上下载mp4的格式,在本地都能播放,怎么可能发上企业微信就…

使用CLI脚手架搭建Vue2项目

一、配置前端的环境 1、下载安装Node.js 网址:Node.js 中文网 (nodejs.com.cn) 参考:【简明图文教程】Node.js的下载、安装、环境配置及测试_node下载安装-CSDN博客 推荐安装路径C盘改为D盘 2、配置nodejs及环境变量【安装的时候勾选Add to PATH就不…

[算法]归并排序(C语言实现)

一、归并排序的定义 归并排序(Merge sort)是建立在归并操作上的一种有效的排序算法。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。 二、归并排序的算法原理 归并排序的算法可以用递归法和非递归法来实现…

2024新版python安装教程【附图片】

Python的安装步骤因操作系统而异,但大致可以分为下载、安装和验证三个主要步骤。以下是Windows系统中Python的详细安装步骤: Windows系统 下载Python安装包 访问Python官网(https://www.python.org/)。点击页面头部的“Download…

【优秀python django系统案例】基于python的医院挂号管理系统,角色包括医生、患者、管理员三种

随着信息技术的迅猛发展,传统的医院挂号管理方式面临着效率低下、排队时间长、信息不对称等诸多问题。这些问题不仅影响患者的就医体验,也加重了医院工作人员的负担。在此背景下,基于Python的医院挂号管理系统应运而生。该系统旨在通过信息化…

OZON饰品产品什么好卖,OZON热销饰品有哪些

在OZON平台上,饰品产品的销售情况受多种因素影响,包括市场需求、季节变化、消费者偏好以及流行趋势等。以下是一些可能热销的OZON饰品产品类别及具体推荐: OZON热销饰品地址:D。DDqbt。COm/74rDTop1 发带套装 Утика Ком…

Idea常用快捷键:设置自动导包、格式化、抽取方法

Idea设置自动导包 【File】→【Setting】(或使用快捷键【Crlt Shift S】)打开Setting设置。点击【Editor】→【General】→【Auto Import】。勾选自定导包的选项,并确定,如下: Addunambiguousimportsonthefly:添加明确的导入 …