Numpy 理解nn.Linear在PyTorch中正向传播的用法

Numpy 理解nn.Linear在PyTorch中正向传播的用法,numpy,pytorch,Numpy,Pytorch,本研究的目的是建立一个简化的前向传播模型,该模型再现PyTorch中的代码结构,但不使用任何PyTorch库。其思想是在模拟代码结构的同时进行矩阵乘法,包括pyTorch中的类定义 用于正向传播的PyTorch代码 from torch import nn #DEFINE THE REQUIRED CLASS class Network(nn.Module): def __init__(self): super().__init__()

本研究的目的是建立一个简化的前向传播模型,该模型再现PyTorch中的代码结构,但不使用任何PyTorch库。其思想是在模拟代码结构的同时进行矩阵乘法,包括pyTorch中的类定义

用于正向传播的PyTorch代码

from torch import nn
#DEFINE THE REQUIRED CLASS

class Network(nn.Module):
    def __init__(self):
        super().__init__()
        
        # Inputs to hidden layer linear transformation
        self.hidden = nn.Linear(784, 256)
        # Output layer, 10 units - one for each digit
        self.output = nn.Linear(256, 10)
        
        # Define sigmoid activation and softmax output 
        self.sigmoid = nn.Sigmoid()
        self.softmax = nn.Softmax(dim=1)
        
    def forward(self, x):
        # Pass the input tensor through each of our operations
        x = self.hidden(x)
        x = self.sigmoid(x)
        x = self.output(x)
        x = self.softmax(x)
        
        return x
#use
model = Network()
...
ps = model.forward(some_tensor)
这是我的复制机代码:

class my_mul:
        def __init__(self, h, w):
                self.dim1 = h
                self.dim2 = w
                self.layer = LAYER(self.dim1, self.dim2)
        def forward(self, X):
                X =  self.layer.doit( X)
                return X

class LAYER:
        def __init__(self, h, w):
                self.dim1 = h
                self.dim2 = w
        def __call__(self, Z):
                self.matrix2 = Z
        def doit(self, X):
                self.matrix1 = np.random.rand(self.dim1, self.dim2)
                print('matrix 1 in class LAYER ',self.matrix1)
                X =  np.matmul(self.matrix1, self.matrix2)

import numpy as np
#
np.random.seed(0)
# initialize matrix2 which emulates the tensor being passed down to the forward 
# propagation step within a deep network training

matrix2 = np.random.rand(2,2)
print('matrix2 ',matrix2)
#
# use the __call__ method of LAYER to pass matrix2 to LL
LL = LAYER(2,2)
LL(matrix2)

MM = my_mul(2,2)
P = MM.forward(matrix2)
print('the product of the 2 matrices is ', P)

上述“复制器代码”失败如下。问题是数据传递不正确,我不知道如何使它工作

matrix2  [[0.5488135  0.71518937]
 [0.60276338 0.54488318]]
matrix 1 in class LAYER  [[0.4236548  0.64589411]
 [0.43758721 0.891773  ]]
Traceback (most recent call last):
  File "all_s.py", line 30, in <module>
    P = MM.forward(matrix2)
  File "all_s.py", line 7, in forward
    X =  self.layer.doit( X)
  File "all_s.py", line 19, in doit
    X =  np.matmul(self.matrix1, self.matrix2)
AttributeError: 'LAYER' object has no attribute 'matrix2'

matrix2[[0.5488135 0.71518937]
[0.60276338 0.54488318]]
类层中的矩阵1[[0.4236548 0.64589411]
[0.43758721 0.891773  ]]
回溯(最近一次呼叫最后一次):
文件“all_.py”,第30行,在
P=前向毫米(X 2)
文件“all_.py”,第7行,向前
X=self.layer.doit(X)
文件“all_.py”,第19行,在doit中
X=np.matmul(self.matrix1,self.matrix2)
AttributeError:“LAYER”对象没有属性“matrix2”

问题是,当您在初始化的模型上调用前向函数时,
self.matrix2
尚未定义,因为错误提示:

AttributeError:“LAYER”对象没有属性“matrix2”

需要说明的是:
MM()
相当于调用
MM.\uu调用\uuu()
。您没有调用它,因此出现了错误

我不知道为什么您会在
转发
调用
中都有一个实现。在PyTorch中,高级API调用是通过
\uuuuu-call\uuuuu
进行的,这正是您所期望的。而且,
\uuuu call\uuu
将调用
forward
,并触发模块上已注册的挂钩

快速修复方法是在初始化中定义矩阵(线性层的底层组件)(即在
\uuuuuu init\uuuu
内部)。然后,当调用时,执行输入和该矩阵之间的矩阵乘法

class LAYER:
    def __init__(self, h, w):
        self.dim1 = h
        self.dim2 = w
        self.matrix1 = np.random.rand(self.dim1, self.dim2)

    def __call__(self, Z):
        return self.doit(Z)

    def doit(self, X):
        return np.matmul(X, self.matrix1)

不过,类似这样的情况会更清楚:

class Model:
    def __init__(self, h, w):
        self.layer = Linear(h, w)

    def __call__(self, x):
        return self.forward(x)

    def forward(self, x):
        x =  self.layer(x)
        return x

class Linear:
    def __init__(self, h, w):
        self.weights = np.random.rand(h, w)

    def __call__(self, x):
        return self.forward(x)

    def forward(self, x):
        return np.matmul(x, self.weights)


x = np.random.rand(2, 2)
model = Model(2, 2)
model(x)

现在,您可以在
模型
类中使用其他层。并向后传递
线性

问题是,当您在初始化的模型上调用向前函数时,
self.matrix2
尚未定义,因为错误提示:

AttributeError:“LAYER”对象没有属性“matrix2”

需要说明的是:
MM()
相当于调用
MM.\uu调用\uuu()
。您没有调用它,因此出现了错误

我不知道为什么您会在
转发
调用
中都有一个实现。在PyTorch中,高级API调用是通过
\uuuuu-call\uuuuu
进行的,这正是您所期望的。而且,
\uuuu call\uuu
将调用
forward
,并触发模块上已注册的挂钩

快速修复方法是在初始化中定义矩阵(线性层的底层组件)(即在
\uuuuuu init\uuuu
内部)。然后,当调用时,执行输入和该矩阵之间的矩阵乘法

class LAYER:
    def __init__(self, h, w):
        self.dim1 = h
        self.dim2 = w
        self.matrix1 = np.random.rand(self.dim1, self.dim2)

    def __call__(self, Z):
        return self.doit(Z)

    def doit(self, X):
        return np.matmul(X, self.matrix1)

不过,类似这样的情况会更清楚:

class Model:
    def __init__(self, h, w):
        self.layer = Linear(h, w)

    def __call__(self, x):
        return self.forward(x)

    def forward(self, x):
        x =  self.layer(x)
        return x

class Linear:
    def __init__(self, h, w):
        self.weights = np.random.rand(h, w)

    def __call__(self, x):
        return self.forward(x)

    def forward(self, x):
        return np.matmul(x, self.weights)


x = np.random.rand(2, 2)
model = Model(2, 2)
model(x)

现在,您可以在
模型
类中使用其他层。并向后传递
线性

我使用了Ivan提供的指南:

class my_mul:
        def __init__(self, h, w):
                self.dim1 = h
                self.dim2 = w
                self.layer = LAYER(self.dim1, self.dim2)
        def forward(self, X):
                X =  self.layer.doit( X)
                return X

class LAYER:
        def __init__(self, h, w):
                self.dim1 = h
                self.dim2 = w
                self.matrix1 = np.random.rand(self.dim1, self.dim2)
                print('matrix 1 in class LAYER ',self.matrix1)
        def __call__(self, Z):
                Y = self.doit(Z)
                return Y
        def doit(self, X):
                X =  np.matmul(self.matrix1, X)
                return X

import numpy as np
#
np.random.seed(0)
# initialize matrix2 which emulates the tensor being passed down to the forward
# propagation step within a deep network training

matrix2 = np.random.rand(2,2)
print('matrix2 ',matrix2)

MM = my_mul(2,2)
P = MM.forward(matrix2)
print('the product of the 2 matrices is ', P)
解释

F:\x\finance-2019\AI\udacity\ML_introduction\pytorch\Linear>python all_s.py
matrix2  [[0.5488135  0.71518937]
 [0.60276338 0.54488318]]
matrix 1 in class LAYER  [[0.4236548  0.64589411]
 [0.43758721 0.891773  ]]
the product of the 2 matrices is  [[0.62182879 0.65493025]
 [0.77768188 0.79886983]]

该行:

MM = my_mul(2,2)
P = MM.forward(matrix2)
创建类my_mul的对象MM,并调用my_mul的init方法: 以MM为单位的对象由类层创建,该类层通过自己的init方法使用提供的高度和宽度维度初始化matrix1

该行:

MM = my_mul(2,2)
P = MM.forward(matrix2)
调用my_mul的forward方法,该方法将matrix2传递给LAYER的doit方法,该方法执行matmul操作并返回矩阵乘积

结果

F:\x\finance-2019\AI\udacity\ML_introduction\pytorch\Linear>python all_s.py
matrix2  [[0.5488135  0.71518937]
 [0.60276338 0.54488318]]
matrix 1 in class LAYER  [[0.4236548  0.64589411]
 [0.43758721 0.891773  ]]
the product of the 2 matrices is  [[0.62182879 0.65493025]
 [0.77768188 0.79886983]]


结果已通过手动计算验证,并且是正确的。

我使用了Ivan提供的指南:

class my_mul:
        def __init__(self, h, w):
                self.dim1 = h
                self.dim2 = w
                self.layer = LAYER(self.dim1, self.dim2)
        def forward(self, X):
                X =  self.layer.doit( X)
                return X

class LAYER:
        def __init__(self, h, w):
                self.dim1 = h
                self.dim2 = w
                self.matrix1 = np.random.rand(self.dim1, self.dim2)
                print('matrix 1 in class LAYER ',self.matrix1)
        def __call__(self, Z):
                Y = self.doit(Z)
                return Y
        def doit(self, X):
                X =  np.matmul(self.matrix1, X)
                return X

import numpy as np
#
np.random.seed(0)
# initialize matrix2 which emulates the tensor being passed down to the forward
# propagation step within a deep network training

matrix2 = np.random.rand(2,2)
print('matrix2 ',matrix2)

MM = my_mul(2,2)
P = MM.forward(matrix2)
print('the product of the 2 matrices is ', P)
解释

F:\x\finance-2019\AI\udacity\ML_introduction\pytorch\Linear>python all_s.py
matrix2  [[0.5488135  0.71518937]
 [0.60276338 0.54488318]]
matrix 1 in class LAYER  [[0.4236548  0.64589411]
 [0.43758721 0.891773  ]]
the product of the 2 matrices is  [[0.62182879 0.65493025]
 [0.77768188 0.79886983]]

该行:

MM = my_mul(2,2)
P = MM.forward(matrix2)
创建类my_mul的对象MM,并调用my_mul的init方法: 以MM为单位的对象由类层创建,该类层通过自己的init方法使用提供的高度和宽度维度初始化matrix1

该行:

MM = my_mul(2,2)
P = MM.forward(matrix2)
调用my_mul的forward方法,该方法将matrix2传递给LAYER的doit方法,该方法执行matmul操作并返回矩阵乘积

结果

F:\x\finance-2019\AI\udacity\ML_introduction\pytorch\Linear>python all_s.py
matrix2  [[0.5488135  0.71518937]
 [0.60276338 0.54488318]]
matrix 1 in class LAYER  [[0.4236548  0.64589411]
 [0.43758721 0.891773  ]]
the product of the 2 matrices is  [[0.62182879 0.65493025]
 [0.77768188 0.79886983]]

通过人工计算,验证了计算结果的正确性