• 由浅入深,走进深度学习(补充篇:神经网络基础)


    在编程实战中,基础是最重要的,所以为了巩固基础,哈哈哈~

    不说废话了,大家喜欢就往下看看,也是我自己的一些总结,方便以后自己看~

    我觉得还是动手敲一遍,会有不一样的感受~

    相关内容:

    由浅入深,走进深度学习(2)_卷积层-CSDN博客

    由浅入深,走进深度学习(补充篇:神经网络结构层基础)-CSDN博客

    目录

    一、层和块

    二、参数管理

    三、自定义层

    四、模型保存和读取


    正片开始!!!

    一、层和块

    这下面的代码中分别包括几个重要部分:

    自定义块

    对块进行实例化

    顺序块

    正向传播

    混合块

    代码和相关内容的解释,给大家放在下面了:

    1. import torch
    2. from torch import nn
    3. from torch.nn import functional as F
    4. net = nn.Sequential(nn.Linear(20, 256),
    5. nn.ReLU(),
    6. nn.Linear(256, 10))
    7. x = torch.rand(4, 20) # 这里必须是20 对应第一个 Linear 的20
    8. print('x:', x)
    9. print('x.shape:', x.shape)
    10. output = net(x)
    11. print('output:', output)
    12. # 自定义块
    13. print('--------------------------------------')
    14. class MLP(nn.Module):
    15. def __init__(self):
    16. super(MLP, self).__init__() # 调用父类的__init__函数
    17. self.hidden = nn.Linear(20, 256)
    18. self.output = nn.Linear(256, 10)
    19. self.relu = nn.ReLU()
    20. def forward(self, x):
    21. x = self.hidden(x)
    22. x = self.relu(x)
    23. x = self.output(x)
    24. return x
    25. # 实例化多层感知机的层 然后在每次调用正向传播函数调用这些层
    26. net = MLP()
    27. x = torch.rand(2, 20)
    28. output = net(x)
    29. print('output:', output)
    30. # 顺序块
    31. print('- - - - - - - - - - - - - - - - - - - - - -')
    32. class MySequential(nn.Module):
    33. def __init__(self, *args):
    34. super(MySequential, self).__init__()
    35. for block in args:
    36. self._modules[block] = block # block 本身作为它的key 存在_modules里面的为层,以字典的形式
    37. def forward(self, x):
    38. for block in self._modules.values():
    39. print('block:', block)
    40. x = block(x)
    41. return x
    42. net = MySequential(nn.Linear(20, 256),
    43. nn.ReLU(),
    44. nn.Linear(256, 10))
    45. x = torch.rand(2, 20)
    46. output = net(x)
    47. print('output:', output)
    48. # 正向传播
    49. # 在正向传播中执行代码
    50. print('-----------------------------------------')
    51. class FixeHidden(nn.Module):
    52. def __init__(self):
    53. super(FixeHidden, self).__init__()
    54. self.rand_weight = torch.rand((20, 20), requires_grad = True)
    55. self.linear = nn.Linear(20, 20)
    56. def forward(self, x):
    57. x = self.linear(x)
    58. x = F.relu(torch.mm(x, self.rand_weight + 1))
    59. x = self.linear(x)
    60. while x.abs().sum() > 1:
    61. x /= 2
    62. return x.sum()
    63. net = FixeHidden()
    64. a = torch.rand(2, 20)
    65. y = net(a)
    66. print('y:', y)
    67. # 混合组合块
    68. print('------------------------------------------------------------------')
    69. class Mixmodel(nn.Module):
    70. def __init__(self):
    71. super(Mixmodel, self).__init__()
    72. self.net = nn.Sequential(nn.Linear(20, 64),
    73. nn.ReLU(),
    74. nn.Linear(64, 16),
    75. nn.ReLU())
    76. self.linear = nn.Linear(16, 32)
    77. def forward(self, xx):
    78. xx = self.net(xx)
    79. xx = self.linear(xx)
    80. return xx
    81. mixnet = nn.Sequential(Mixmodel(),
    82. nn.Linear(32, 20),
    83. MySequential())
    84. aa = torch.rand(3, 20)
    85. out1 = mixnet(aa)
    86. print('out1:', out1)

    二、参数管理

    在这个部分涉及到:参数管理、参数替换和参数绑定三部分内容

    具体代码和相关解释如下:

    1. # 参数管理
    2. # 首先关注具有单隐藏层的多层感知机
    3. import torch
    4. from torch import nn
    5. from torch.nn import functional as F
    6. net = nn.Sequential(nn.Linear(4, 8),
    7. nn.ReLU(),
    8. nn.Linear(8, 1))
    9. x = torch.rand(size = (2, 4))
    10. print('net(x):', net(x))
    11. print('net[2].stat_dict:', net[2].state_dict()) # 访问参数 net[2]就是最后一个输出层
    12. print('net[2].bias:', type(net[2].bias)) # 目标参数
    13. print(net[2].bias)
    14. print(net[2].bias.data)
    15. print(net[2].weight.grad == None) # 还没进行反向计算 所以grad为None
    16. print('------------', *[(name, param.shape) for name, param in net[0].named_parameters()]) # 一次性访问所有参数
    17. print('- - - - - - - -', *[(name, param.shape) for name, param in net.named_parameters()]) # 0是第一层名字 1是ReLU 它没有参数
    18. print('*************', net.state_dict()['2.bias'].data) # 通过名字获取参数
    19. # 嵌套块
    20. # 从嵌套块收集参数
    21. def block1():
    22. return nn.Sequential(nn.Linear(4, 8),
    23. nn.ReLU(),
    24. nn.Linear(8, 4),
    25. nn.ReLU())
    26. def block2():
    27. net = nn.Sequential()
    28. for i in range(4):
    29. net.add_module(f'block{i}', block1()) # f'block{i}' 可以传一个字符串名字过来 block2可以嵌套四个block1
    30. return net
    31. regnet = nn.Sequential(block2(),
    32. nn.Linear(4, 1))
    33. xx = torch.rand(size = (2, 4))
    34. yy = torch.rand(2, 4)
    35. print('xx:', xx)
    36. print('yy:', yy)
    37. print('regnet(xx):', regnet(xx))
    38. print('regnet(yy):', regnet(yy))
    39. print('regnet:', regnet)
    40. # 内置初始化
    41. print('**********************************************************')
    42. net1 = nn.Sequential(nn.Linear(4, 8),
    43. nn.ReLU(),
    44. nn.Linear(8, 4),
    45. nn.ReLU())
    46. def init_normal(m):
    47. if type(m) == nn.Linear:
    48. nn.init.normal_(m.weight, mean = 0, std = 0.01) # 下划线表示把m.weight的值替换掉
    49. nn.init.zeros_(m.bias)
    50. net1.apply(init_normal) # 会递归调用 直到所有层都初始化
    51. print('net1[0].weight.data[0]:', net1[0].weight.data[0])
    52. print('net1[0].bias.data[0]:', net1[0].bias.data[0])
    53. net2 = nn.Sequential(nn.Linear(4,8),
    54. nn.ReLU(),
    55. nn.Linear(8,1))
    56. def init_constant(m):
    57. if type(m) == nn.Linear:
    58. nn.init.constant_(m.weight, 1)
    59. nn.init.zeros_(m.bias)
    60. net2.apply(init_constant)
    61. print('net2[0].weight.data[0]:', net2[0].weight.data[0])
    62. print('net2[0].bias.data[0]:', net2[0].bias.data[0])
    63. # 对某些块应用不同的初始化
    64. def xavier(m):
    65. if type(m) == nn.Linear:
    66. nn.init.xavier_uniform_(m.weight)
    67. def init_42(m):
    68. if type(m) == nn.Linear:
    69. nn.init.constant_(m.weight, 42)
    70. net1[0].apply(xavier)
    71. net1[2].apply(init_42)
    72. print('net1[0].weight.data[0]:', net1[0].weight.data[0])
    73. print('net1[2].weight.data:', net1[2].weight.data)
    74. # 参数替换
    75. # 自定义初始化
    76. def my_init(m):
    77. if type(m) == nn.Linear:
    78. print("Init",*[(name, param.shape) for name, param in m.named_parameters()][0]) # 打印名字是啥,形状是啥
    79. nn.init.uniform_(m.weight, -10, 10)
    80. m.weight.data *= m.weight.data.abs() >= 5
    81. # 这里*=的代码相当于先计算一个布尔矩阵(先判断>=) 然后再用布尔矩阵的对应元素去乘以原始矩阵的每个元素 保留绝对值大于5的权重 不是的话就设为0
    82. net2.apply(my_init)
    83. print('net2[0].weight[:2]:', net2[0].weight[:2])
    84. net2[0].weight.data[:] += 1 # 参数替换
    85. net2[0].weight.data[0, 0] = 42
    86. print('net2[0].weight.data[0]:', net2[0].weight.data[0])
    87. # 参数绑定
    88. shared = nn.Linear(8,8)
    89. net3 = nn.Sequential(nn.Linear(4,8),
    90. nn.ReLU(), shared,
    91. nn.ReLU(), shared,
    92. nn.ReLU(),
    93. nn.Linear(8,1)) # 第2个隐藏层和第3个隐藏层是share权重的 第一个和第四个是自己的
    94. print(net3)
    95. net3(torch.rand(2, 4))
    96. print(net3[2].weight.data[0] == net3[4].weight.data[0])
    97. net3[2].weight.data[0,0] = 100
    98. print(net3[2].weight.data[0] == net3[4].weight.data[0])

    三、自定义层

    在这部分,构造的时候:由非参数层和参数层

    1. # 自定义层
    2. # 构造一个没有任何参数的自定义层
    3. import torch
    4. import torch.nn.functional as F
    5. from torch import nn
    6. class MyLayer(nn.Module):
    7. def __init__(self):
    8. super(MyLayer, self).__init__()
    9. def forward(self, x):
    10. return x - x.mean()
    11. net = MyLayer()
    12. z = torch.tensor([1, 2, 3, 4, 5], dtype = torch.float32)
    13. print('net(z):', net(z))
    14. # 将层作为组件合并到构建更复杂的模型中
    15. net1 = nn.Sequential(nn.Linear(8, 128),
    16. MyLayer())
    17. zz = torch.rand(4, 8)
    18. print('net1(zz):', net1(zz))
    19. print('net1(zz).mean:', net1(zz).mean())
    20. # 带参数的图层
    21. class MyLinear(nn.Module):
    22. def __init__(self, in_units, units):
    23. super().__init__()
    24. self.weight = nn.Parameter(torch.randn(in_units,units)) # nn.Parameter使得这些参数加上了梯度
    25. self.bias = nn.Parameter(torch.randn(units,))
    26. def forward(self, X):
    27. linear = torch.matmul(X, self.weight.data) + self.bias.data
    28. return F.relu(linear)
    29. dense = MyLinear(5,3)
    30. print('dense.weight', dense.weight)
    31. # 使用自定义层直接执行正向传播计算
    32. print('dense(torch.rand(2,5))', dense(torch.rand(2,5)))
    33. # 使用自定义层构建模型
    34. net = nn.Sequential(MyLinear(64,8),
    35. MyLinear(8,1))
    36. print('net(torch.rand(2,64))', net(torch.rand(2,64)))

    四、模型保存和读取

    这里涉及使用torch保存和读取文件,然后就是在以后我们设计模型,训练的时候,我们可以通过这种方式,保存我们的模型,然后再最后测试的时候在调用模型!!!

    代码如下:

    1. # 读写文件
    2. # 加载和保存张量
    3. import torch
    4. from torch import nn
    5. from torch.nn import functional as F
    6. x = torch.arange(4)
    7. torch.save(x, 'x_file')
    8. x1 = torch.load('x_file')
    9. print('x1:', x1)
    10. #存储一个张量列表 然后把它们读回内存
    11. y = torch.zeros(4)
    12. torch.save([x, y], 'x-file')
    13. x2, y2 = torch.load('x-file')
    14. print('x2:', x2)
    15. print('y2:', y2)
    16. # 写入或读取从字符串映射到张量的字典
    17. mydict = {'x':x, 'y':y}
    18. torch.save(mydict, 'mydict')
    19. mydict1 = torch.load('mydict')
    20. print('mydict1:', mydict1)

    加载和保存模型参数

    1. # 加载和保存模型参数
    2. import torch
    3. from torch import nn
    4. from torch.nn import functional as F
    5. class MLP(nn.Module):
    6. def __init__(self):
    7. super(MLP, self).__init__() # 调用父类的__init__函数
    8. self.hidden = nn.Linear(20, 256)
    9. self.output = nn.Linear(256, 10)
    10. self.relu = nn.ReLU()
    11. def forward(self, x):
    12. x = self.hidden(x)
    13. x = self.relu(x)
    14. x = self.output(x)
    15. return x
    16. # 实例化多层感知机的层 然后在每次调用正向传播函数调用这些层
    17. net = MLP()
    18. x = torch.rand(2, 20)
    19. output = net(x)
    20. print('output:', output)
    21. # 将模型的参数存储为一个叫做"mlp.params"的文件
    22. torch.save(net.state_dict(), 'MLP.params')
    23. # 实例化了原始多层感知机模型的一个备份。直接读取文件中存储的参数
    24. clone = MLP() # 必须要先声明一下,才能导入参数
    25. clone.load_state_dict(torch.load('MLP.params'))
    26. print('MLP eval', clone.eval()) # eval()是进入测试模式
    27. output_clone = clone(x)
    28. print(output_clone == output)

    注:上述内容参考b站up主“我是土堆”的视频,参考吴恩达深度学习,机器学习内容,参考李沐动手学深度学习!!!

  • 相关阅读:
    【无标题】Open Verification Library Assertion检查
    SpringMVC的整合完成CRUD
    java基于ssm网上超市购物商城-计算机毕业设计
    antd 表格getCheckboxProps禁用
    Ansible--playbook 剧本
    C语言每日一题(21)删除排序数组中的重复项
    华为OD机试 - 判断一组不等式是否满足约束并输出最大差(Java 2023 B卷 100分)
    【LeetCode每日一题】——37.解数独
    讲座记录|1024学科周讲座分享
    阿里P8大能倾力编撰的“Java 进阶面试手册”,助力跳槽外包毕业生秋招收获大厂offer
  • 原文地址:https://blog.csdn.net/weixin_45325693/article/details/139946949