“mat1和 mat2的形状不能相乘”,但形状其实并不与数据相匹配?
我正在使用PyTorch,对这5 个数据集分别训练一个回归模型,每个数据集的形状都是10×3361。
然而,在运行PyTorch时,它抛出了错误 RuntimeError: mat1 and mat2 shapes cannot be multiplied (10x[some multiple of 1499, varying from dataset to dataset] and 3361x64)。
现在我知道这意味着nn.Module的第一层形状不对,但我更困惑的是,为什么它坚持数据集的形状要包含某个1499的倍数——或者为什么这个数字会因所用数据集不同而变化,尽管它们的形状相同。
Here's the nn.module:
# define neural network model for regression
class Regression(nn.Module):
def __init__(self):
super().__init__()
self.layers = nn.Sequential(
nn.Linear(3361, 64),
nn.ReLU(),
nn.Linear(64, 32),
nn.ReLU(),
nn.Linear(32, 1)
)
def forward(self, x):
'''
Forward pass
'''
return self.layers(x)
以及训练循环:
def training_loop(n_epochs, train_loader):
# training loop
for epoch in range(n_epochs):
# Set current loss value
current_loss = 0.0
# Iterate over the DataLoader for training data
for i, data in enumerate(train_loader, 0):
# Get and prepare inputs
inputs, targets = data
inputs, targets = inputs.float(), targets.float()
targets = targets.reshape((targets.shape[0],1))
# Zero the gradients
optimizer.zero_grad()
# Perform forward pass
outputs = model(inputs)
# Compute loss
loss = loss_function(outputs, targets)
# Perform backward pass
loss.backward()
# Perform optimization
optimizer.step()
return model
以及在上下文中的两者调用:
exo_file="exo_data_rp2500_set.csv"
exo_data=pd.read_csv(exo_file)
input_size = exo_data.shape[1]
batch_size = 10
model=Regression()
n_epochs=100
# loss function and optimizer
loss_function =nn.MSELoss()
# mean square error
optimizer = torch.optim.Adam(model.parameters(), lr=1e-4)
...
metrics=[#list of the nine categories of features I'm investigating]
for metric in metrics:
#split and format data
exo_target=exo_metrics[metric]
X_train, X_test, y_train, y_test = train_test_split(exo_spectra,exo_target, test_size=0.2, random_state=23)
X_train_tensor = torch.from_numpy(X_train)
X_train_tensor = torch.tensor(X_train_tensor,dtype=torch.float32)
y_train_tensor = torch.from_numpy(y_train.values)
y_train_tensor = torch.tensor(y_train_tensor,dtype=torch.float32)
X_test_tensor = torch.from_numpy(X_test)
X_test_tensor = torch.tensor(X_test_tensor,dtype=torch.float32)
y_test_tensor= torch.from_numpy(y_test.values)
y_test_tensor = torch.tensor(y_test_tensor,dtype=torch.float32)
# load data
train_dataset = TensorDataset(X_train_tensor, y_train_tensor)
train_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True)
# train data and assess accuracy
model=training_loop(n_epochs,train_loader)
y_pred = model(X_test_tensor)
model_score=r2_score(y_test_tensor.detach().numpy(),y_pred.detach().numpy())
scores.append(model_score)
有谁知道为什么会抛出这个错误?
解决方案
你已经把神经网络的第一层定义为期望输入大小为 in_features=3361,这意味着在 outputs = model(inputs) 中的 inputs 张量的最后一个维度必须是 3361(即 inputs.shape[-1] == 3361)。错误信息指示 inputs 张量的形状是 (10, some_multiple_of_1499),其中 10 是你在 DataLoader(train_dataset, batch_size=batch_size, shuffle=True) 中定义的 batch_size,而 some_multiple_of_1499 是数据集输入特征的维度。
在底层,nn.Linear 层对输入张量与该层权重矩阵的转置执行矩阵乘法(参见源码 此处 和 此处)。第一层 nn.Linear 的权重矩阵形状为 (64, 3361),因此输入张量必须具有 (batch_size, 3361) 的形状,才能与之进行矩阵乘法的兼容。
一个简单的修复是把 in_features 参数通过你在 Regression 类中的 __init__ 方法传递过去:
class Regression(nn.Module):
def __init__(self, in_features: int):
super().__init__()
self.layers = nn.Sequential(
nn.Linear(in_features, 64),
nn.ReLU(),
nn.Linear(64, 32),
nn.ReLU(),
nn.Linear(32, 1)
)
...
model = Regression(in_features=some_multiple_of_1499) # depending on the dataset you're using
另一种选择是使用 LazyLinear 层(请参阅 PyTorch文档):
在
LazyLinear模块中,weight和bias属于torch.nn.UninitializedParameter类。它们将在对forward的首次调用完成后被初始化,模块将成为一个常规的torch.nn.Linear模块。对Linear的in_features参数是从input.shape[-1]推断得到的。