自定义层

https://zh-v2.d2l.ai/chapter_deep-learning-computation/custom-layer.html

你好。我发现 named_parameters() 方法会自动捕捉到 MyLinear 类中定义的 weight 和 bias 参数, 请问 PyTorch 是如何发现这些参数的呢?

因为你使用了 pytorch的接口函数,比如 nn.Parameter nn.Linera nn.conv2d …

猜测是Module的相关方法,会分析类中类型为Parameter类型的参数,把这些成员标记为该module的参数,key值就是成员名。

1 Like

记得应该是在nn.Module里面的__setattr__里面有,会对这些东西自动分类并放到模型的OrderedDict里

第一问,不知道对不对,请大家指正。
class sumyk(nn.Module):
def init(self,xi,xj):
super().init()
self.weight = nn.Parameter(torch.randn(xi.shape[1],xj.shape[0]))
def forward(self,xi,xj):
return torch.matmul(torch.matmul(xi,self.weight.data),xj)

第二问求助

我觉得是nn.module捕捉的,parameter只不过data和梯度值写入了一下

一个可能正确的实现

题1

class DimensionReduction(nn.Module):
    def __init__(self, i, j, k):
        super(DimensionReduction, self).__init__()
        self.net = nn.Conv2d(in_channels=1, out_channels=k, kernel_size=(i, j))

    def forward(self, X, Y):
        # 先用X和Y做矩阵乘法构成i*j矩阵,
        # 再用卷积层快捷地实现计算功能
        matrix = torch.bmm(x, torch.transpose(y, 1, 2))
        matrix = matrix.unsqueeze(1)  # B*1*i*j
        return self.net(matrix)  # B*5*i*j


myNet1 = DimensionReduction(2, 3, 5)
x = torch.ones(1, 2, 1)  # B*i*1
y = torch.rand(1, 3, 1)  # B*j*1
print(myNet1(x, y))

题2

class HalfFFT(nn.Module):
    def __init__(self):
        super(HalfFFT, self).__init__()

    def forward(self, X):
        """
        Compute FFT and return half of it
        :param X: size = B*L
        :return: size = B*round(L/2)
        """
        half_len = round(X.shape[1]/2)
        X_f = torch.fft.fft(X)
        return X_f[:, :half_len]


myNet2 = HalfFFT()
print(myNet2(torch.rand(2, 3)))

题一你再看下公式,你的实现和公式完全不一样

image

y = torch.sum(torch.mm(x.T,x)*w,dim=[1,2])

是因为weight和bias是nn.Parameter类的实例

#练习1可能的答案
class DemensionReduction(nn.Module):
def init(self,in_units, units):
super().init()
self.weight = nn.Parameter(torch.randn(in_units*in_units, units))
def forward(self, X):
Y = torch.matmul(X[0,:].reshape(-1,1),X[0,:].reshape(1,-1)).reshape(1,-1)
Z = torch.matmul(Y,self.weight)
for i in range(1,X.shape[0]):
Y = torch.matmul(X[i,:].reshape(-1,1),X[i,:].reshape(1,-1)).reshape(1,-1)
Z = torch.cat((Z,torch.matmul(Y,self.weight)),0)
return Z
dem = DemensionReduction(20,1)
X = torch.randn(5,20)
dem(X)

class Layer(nn.Module):
def init(self,k,i,j):
super(Layer, self).init()
self.weight=torch.randn(k,i,j)
def forward(self,xi,xj):
return torch.sum(torch.matmul(self.weight,torch.matmul(xi,xj),))

k,i,j=5,2,2
net=Layer(k,i,j)
print(net(torch.randn(2).reshape(2,1),torch.randn(2).reshape(1,2)))
不知道是否正确

这个可以看 python 元编程的内容,在没有看源码的情况下,猜测应该使用了 Python 的 MetaClass。