如何使用 PyTorch 将参数(网络的权重)应用于输入向量?

How to apply the parameters (weights of a network) to a vector of inputs using PyTorch?

我有一个简单的“神经网络”,它接受两个输入并计算一个线性组合并输出一个标量。在一个方程的情况下,即在 1D 中,我们将有:weight1*inputA + weight2*inputB = output。现在,我对多维输入感兴趣,即 inputA 是一个向量。所以我希望我的网络将 weight1 应用于向量,例如:weight1 * [input1, input2] + weight2 * [input3, input4]。在此设置中,我希望输出也为向量:[out1, out2],其中 out1 = weight1*inputA + weight2*inputB。但是,我不想更改网络的输入和输出维度。与一维情况一样,我会将网络初始化为 net = LinearNet(2,1),因为我们采用两个输入,inputAinputB,并得到一个输出。我明白输入和输出本身是多维的,但这不应该打扰我的网络。

以下是一分钟。工作示例:

import numpy as np 
import torch
from torch import nn

def f(x,a,b,c,d):
    x_next = np.zeros((2,))
    x_next[0] = x[0]*(a-b*x[1])
    x_next[1] = -x[1]*(c-d*x[0])
    return x_next #returns [2,:]

a = 1
b = 0.5
c = 1
d = 0.5
x01 = 1 #init cond. varA
x02 = 2 #init cond. varB
params = [a,b,c,d,x01,x02]

# ==================
h = 0.001
T = 10
K = int(T/h)

# forward euler approx.
x_traj_FE = np.zeros((2,K))
a, b, c, d, x_traj_FE[0,0], x_traj_FE[1,0] = params
for k in range(K-1):
    x_traj_FE[:,k+1] = x_traj_FE[:,k] + h*f(x_traj_FE[:,k],a,b,c,d)


# ==================
class LinearNet(nn.Module):
    def __init__(self, input_dim, output_dim):
        super(LinearNet, self).__init__()

        self.layer1 = nn.Linear(input_dim, output_dim, bias=False)
        
        #no activation function

    def forward(self, x):
        x = self.layer1(x)
        #no activation
        return x

torch.manual_seed(789)
net = LinearNet(2,1)

x_traj = np.zeros((2,K))
a, b, c, d, x_traj[0,0], x_traj[1,0] = params
for k in range(K-1):
    print(net.layer1.weight)    
    input1 = x_traj[:,k]
    input2 = f(x_traj[:,k],a,b,c,d)
    inputs = torch.Tensor(np.array([input1, input2]))
    print('input:  '+str(inputs))
    print('shape:  '+str(inputs.shape))
    print('output: '+str(net(inputs)))
    break

如果我们运行这个,我们将收到以下输出:

Parameter containing:
tensor([[0.3871, 0.5595]], requires_grad=True)
input:  tensor([[ 1.,  2.],
        [ 0., -1.]])
shape:  torch.Size([2, 2])
output: tensor([[ 1.5060],
        [-0.5595]], grad_fn=<MmBackward0>)

最终,我想计算耦合方程 f 的前向欧拉步,其中 input1 是系统 f 中每个方程的初始条件,并且input2 是在上一步评估的系统。如果我们手动执行,一步可以计算为(给定上面网络的权重):

weights = [0.3871, 0.5595]
x_traj = np.zeros((2,K))
a, b, c, d, x_traj[0,0], x_traj[1,0] = params
for k in range(K-1):
    x_traj[:,k+1] = weights[0]*x_traj[:,k] + weights[1]*f(x_traj[:,k],a,b,c,d)
    break
x_traj

输出为:

array([[1.    , 0.3871, 0.    , ..., 0.    , 0.    , 0.    ],
       [2.    , 0.2147, 0.    , ..., 0.    , 0.    , 0.    ]])

正如我们所见,网络的输出与人工计算不同。我看不到网络如何计算这个标量向量乘法,因此,我无法理解如何检索与手动计算相同的输出。

当您执行 inputs = torch.Tensor(np.array([input1, input2])) 时,您正在创建一个张量,其中第一个 input1,第二个 input2。当您手动相乘时,您的第一个 等于之前的 input1input2 也是如此。为了获得与第一种情况相同的结果,您可以将循环中的语句更改为(但是我不知道在您的用例中两者中哪一个在逻辑上是正确的):

inp = torch.stack([x_traj[:,k], f(x_traj[:,k],a,b,c,d)],dim=0) # This gives the same matrix as `inputs` in the first case
x_traj[:,k+1] = weights[0]*inp[:,0] + weights[1]*inp[:,1] # This is equivalent to calling the network in the first case