5.4.1 不带参数的层

import torchimport torch.nn.functional as Ffrom torch import nnclass 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]))# 可以正常运行
tensor([-2., -1.,0.,1.,2.])
net = nn.Sequential(nn.Linear(8, 128), CenteredLayer())# 可以将其组合进更复杂的模型中Y = net(torch.rand(4, 8))Y.mean()# 均值为0,可以说明正常(由于浮点数特性,无法严格为0)
tensor(2.3283e-09, grad_fn=)

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))# 测试正常
(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]]))
net = nn.Sequential(MyLinear(64, 8), MyLinear(8, 1))# 可正常组合使用net(torch.rand(2, 64))
tensor([[0.0000],[2.0065]])

练习

(1)设计一个接收输入并计算张量降维的层,它返回 yk= ∑ i , jW i j kxixj y_k=\sum_{i,j}W_{ijk}x_ix_jyk=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 ylayer = DimensionalityReductionTensors(3)layer.weight, layer(torch.rand(3, 1))# 测试正常
(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=))

(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))# 测试正常
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]])