• 《动手学深度学习 Pytorch版》 5.4 自定义层


    5.4.1 不带参数的层

    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()  # 仅作减去均值的操作
        
    layer = CenteredLayer()
    layer(torch.FloatTensor([1, 2, 3, 4, 5]))  # 可以正常运行
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    tensor([-2., -1.,  0.,  1.,  2.])
    
    • 1
    net = nn.Sequential(nn.Linear(8, 128), CenteredLayer())  # 可以将其组合进更复杂的模型中
    
    Y = net(torch.rand(4, 8))
    Y.mean()  # 均值为0,可以说明正常(由于浮点数特性,无法严格为0)
    
    • 1
    • 2
    • 3
    • 4
    tensor(2.3283e-09, grad_fn=)
    
    • 1

    5.4.2 带参数的层

    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)
    linear.weight, linear(torch.rand(2, 5))  # 测试正常
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    (Parameter containing:
     tensor([[ 0.1349, -1.0820, -0.8273],
             [-0.2127, -1.0748, -0.5577],
             [-0.9080,  0.5133, -0.4401],
             [-0.4881, -0.8850, -0.0289],
             [-0.0330, -1.4289, -0.6820]], requires_grad=True),
     tensor([[2.6406, 0.0000, 0.0000],
             [1.7090, 0.0000, 0.0000]]))
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    net = nn.Sequential(MyLinear(64, 8), MyLinear(8, 1))  # 可正常组合使用
    net(torch.rand(2, 64))
    
    • 1
    • 2
    tensor([[0.0000],
            [2.0065]])
    
    • 1
    • 2

    练习

    (1)设计一个接收输入并计算张量降维的层,它返回 y k = ∑ i , j W i j k x i x j y_k=\sum_{i,j}W_{ijk}x_ix_j yk=i,jWijkxixj

    class DimensionalityReductionTensors(nn.Module):
        def __init__(self, in_units):
            super().__init__()
            self.weight = nn.Parameter(torch.randn(in_units, in_units, in_units))  # 初始化权重
        def forward(self, X):
            y = torch.zeros_like(X)
            for k in range(0, X.shape[0]):
                for i in range(0, X.shape[0]):
                    for j in range(0, X.shape[0]):
                        y[k] += self.weight[i][j][k] * X[i] * X[j]
            return y
        
    layer = DimensionalityReductionTensors(3)
    layer.weight, layer(torch.rand(3, 1))  # 测试正常
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    (Parameter containing:
     tensor([[[-0.3133,  0.6214,  0.6835],
              [-0.0720,  0.8630,  1.1317],
              [-0.5848, -0.9351, -0.5103]],
     
             [[ 0.2724,  0.3710, -0.6909],
              [ 1.1569,  0.8924, -0.2694],
              [-0.2803, -1.0708,  0.5445]],
     
             [[-0.4135,  1.2961, -0.2054],
              [-0.5572,  1.0026,  0.7997],
              [ 0.3076,  0.4108,  0.4654]]], requires_grad=True),
     tensor([[0.3252],
             [0.6745],
             [0.1474]], grad_fn=))
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    (2)设计一个返回输入数据的傅里叶系数前半部分的层。

    class FirstHalfFouriercoefficient(nn.Module):
        def __init__(self):
            super().__init__()
        def forward(self, X):
            FFT = torch.fft.fft(X)
            return FFT[:, :round(X.shape[1]/2)]
        
    layer = FirstHalfFouriercoefficient()
    layer(torch.rand(3, 7))  # 测试正常
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    tensor([[ 3.9421+0.0000j, -0.2037+0.1165j, -0.6413-1.0152j, -0.4512-0.3608j],
            [ 3.5853+0.0000j, -0.4951-0.8863j, -0.0675+0.4883j,  0.6614+0.0268j],
            [ 4.0120+0.0000j,  0.9124+0.1392j, -0.5101+0.0387j,  0.9813+0.3515j]])
    
    • 1
    • 2
    • 3
  • 相关阅读:
    C#数据去重的这几种方式,你知道几种?
    java计算机毕业设计江智能股票推荐系统MyBatis+系统+LW文档+源码+调试部署
    Win10中安装多个MySQL8.0
    面试突击:输入URL之后会执行什么流程?
    MyBatis-Plus 字段为Null时不更新解决方案,MyBatis-Plus 更新空字段
    聊一聊 Valgrind 监视非托管内存泄露和崩溃
    Spring AOP+Redis实现接口访问限制
    分享一个基于Python的电子产品销售系统可视化销量统计java版本相同(源码+调试+开题+lw)
    开源项目ChatGPT-website再次更新,累计下载使用1600+
    2-Pytorch创建随机值张量
  • 原文地址:https://blog.csdn.net/qq_43941037/article/details/132914690