PyTorch回归模型训练报错:mat1与mat2 dtype不一致求助
问题描述
我正尝试构建一个神经网络,基于美国县居民的教育水平预测该县的人均收入。已确认输入特征X和标签y的dtype均为torch.int64,但训练时仍报错。
数据集示例
county_FIPS state county per_capita_personal_income_2019 0 51013 VA Arlington, VA 97629 per_capita_personal_income_2020 per_capita_personal_income_2021 0 100687 107603 associate_degree_numbers_2016_2020 bachelor_degree_numbers_2016_2020 0 19573 132394
网络代码
import torch import pandas as pd df = pd.read_csv("./input/US counties - education vs per capita personal income - results-20221227-213216.csv") X = torch.tensor(df[["bachelor_degree_numbers_2016_2020", "associate_degree_numbers_2016_2020"]].values) y = torch.tensor(df["per_capita_personal_income_2020"].values) X.dtype torch.int64 y.dtype torch.int64 import torch.nn as nn class BaseNet(nn.Module): def __init__(self, in_dim, hidden_dim, out_dim): super(BaseNet, self).__init__() self.classifier = nn.Sequential( nn.Linear(in_dim, hidden_dim, bias=True), nn.ReLU(), nn.Linear(feature_dim, out_dim, bias=True)) def forward(self, x): return self.classifier(x) from torch import optim import matplotlib.pyplot as plt in_dim, hidden_dim, out_dim = 2, 20, 1 lr = 1e-3 epochs = 40 loss_fn = nn.CrossEntropyLoss() classifier = BaseNet(in_dim, hidden_dim, out_dim) optimizer = optim.SGD(classifier.parameters(), lr=lr) def train(classifier, optimizer, epochs, loss_fn): classifier.train() losses = [] for epoch in range(epochs): out = classifier(X) loss = loss_fn(out, y) loss.backward() optimizer.step() optimizer.zero_grad() losses.append(loss/len(X)) print("Epoch {} train loss: {}".format(epoch+1, loss/len(X))) plt.plot([i for i in range(1, epochs + 1)]) plt.xlabel("Epoch") plt.ylabel("Training Loss") plt.show() train(classifier, optimizer, epochs, loss_fn)
报错信息
--------------------------------------------------------------------------- RuntimeError Traceback (most recent call last) Input In [77], in <cell line: 39>() 36 plt.ylabel("Training Loss") 37 plt.show() ---> 39 train(classifier, optimizer, epochs, loss_fn) Input In [77], in train(classifier, optimizer, epochs, loss_fn) 24 losses = [] 25 for epoch in range(epochs): ---> 26 out = classifier(X) 27 loss = loss_fn(out, y) 28 loss.backward() File ~/opt/anaconda3/lib/python3.9/site-packages/torch/nn/modules/module.py:1194, in Module._call_impl(self, *input, **kwargs) 1190 # If we don't have any hooks, we want to skip the rest of the logic in 1191 # this function, and just call forward. 1192 if not (self._backward_hooks or self._forward_hooks or self._forward_pre_hooks or _global_backward_hooks 1193 or _global_forward_hooks or _global_forward_pre_hooks): -> 1194 return forward_call(*input, **kwargs) 1195 # Do not call functions when jit is used 1196 full_backward_hooks, non_full_backward_hooks = [], [] Input In [77], in BaseNet.forward(self, x) 10 def forward(self, x): ---> 11 return self.classifier(x) File ~/opt/anaconda3/lib/python3.9/site-packages/torch/nn/modules/module.py:1194, in Module._call_impl(self, *input, **kwargs) 1190 # If we don't have any hooks, we want to skip the rest of the logic in 1191 # this function, and just call forward. 1192 if not (self._backward_hooks or self._forward_hooks or self._forward_pre_hooks or _global_backward_hooks 1193 or _global_forward_hooks or _global_forward_pre_hooks): -> 1194 return forward_call(*input, **kwargs) 1195 # Do not call functions when jit is used 1196 full_backward_hooks, non_full_backward_hooks = [], [] File ~/opt/anaconda3/lib/python3.9/site-packages/torch/nn/modules/container.py:204, in Sequential.forward(self, input) 202 def forward(self, input): 203 for module in self: ---> 204 input = module(input) 205 return input File ~/opt/anaconda3/lib/python3.9/site-packages/torch/nn/modules/module.py:1194, in Module._call_impl(self, *input, **kwargs) 1190 # If we don't have any hooks, we want to skip the rest of the logic in 1191 # this function, and just call forward. 1192 if not (self._backward_hooks or self._forward_hooks or self._forward_pre_hooks or _global_backward_hooks 1193 or _global_forward_hooks or _global_forward_pre_hooks): -> 1194 return forward_call(*input, **kwargs) 1195 # Do not call functions when jit is used 1196 full_backward_hooks, non_full_backward_hooks = [], [] File ~/opt/anaconda3/lib/python3.9/site-packages/torch/nn/modules/linear.py:114, in Linear.forward(self, input) 113 def forward(self, input: Tensor) -> Tensor: --> 114 return F.linear(input, self.weight, self.bias) RuntimeError: mat1 and mat2 must have the same dtype
更新
尝试将X和y转换为float张量后,出现新错误:expected scalar type Long but found Float。
解决方案
1. 修复数据类型不匹配问题
PyTorch的Linear层参数默认是float32类型,输入X的int64类型和权重类型不一致,导致矩阵乘法报错。需将X转为float32:
X = torch.tensor(df[["bachelor_degree_numbers_2016_2020", "associate_degree_numbers_2016_2020"]].values, dtype=torch.float32)
2. 替换损失函数
当前任务是回归任务(预测连续的人均收入),但误用了分类任务的CrossEntropyLoss,该损失要求标签为Long类型,这也是转float后报错的原因。回归任务应使用MSELoss:
loss_fn = nn.MSELoss()
同时标签y也要转为float32,和模型输出 dtype 一致:
y = torch.tensor(df["per_capita_personal_income_2020"].values, dtype=torch.float32)
3. 修正网络定义的变量错误
网络__init__方法中第二个Linear层使用了未定义的feature_dim,需替换为hidden_dim:
self.classifier = nn.Sequential( nn.Linear(in_dim, hidden_dim, bias=True), nn.ReLU(), nn.Linear(hidden_dim, out_dim, bias=True) )
4. 修复绘图代码
原绘图代码未传入损失值,无法显示损失曲线,需修改为:
plt.plot([i for i in range(1, epochs + 1)], losses)
完整修正后代码
import torch import pandas as pd df = pd.read_csv("./input/US counties - education vs per capita personal income - results-20221227-213216.csv") # 转换X为float32 X = torch.tensor(df[["bachelor_degree_numbers_2016_2020", "associate_degree_numbers_2016_2020"]].values, dtype=torch.float32) # 转换y为float32 y = torch.tensor(df["per_capita_personal_income_2020"].values, dtype=torch.float32) import torch.nn as nn class BaseNet(nn.Module): def __init__(self, in_dim, hidden_dim, out_dim): super(BaseNet, self).__init__() self.classifier = nn.Sequential( nn.Linear(in_dim, hidden_dim, bias=True), nn.ReLU(), nn.Linear(hidden_dim, out_dim, bias=True)) def forward(self, x): return self.classifier(x) from torch import optim import matplotlib.pyplot as plt in_dim, hidden_dim, out_dim = 2, 20, 1 lr = 1e-3 epochs = 40 # 使用回归任务损失函数 loss_fn = nn.MSELoss() classifier = BaseNet(in_dim, hidden_dim, out_dim) optimizer = optim.SGD(classifier.parameters(), lr=lr) def train(classifier, optimizer, epochs, loss_fn): classifier.train() losses = [] for epoch in range(epochs): out = classifier(X) loss = loss_fn(out, y) loss.backward() optimizer.step() optimizer.zero_grad() losses.append(loss.item()/len(X)) print("Epoch {} train loss: {}".format(epoch+1, loss.item()/len(X))) # 正确绘制损失曲线 plt.plot([i for i in range(1, epochs + 1)], losses) plt.xlabel("Epoch") plt.ylabel("Training Loss") plt.show() train(classifier, optimizer, epochs, loss_fn)
内容的提问来源于stack exchange,提问作者George Garman
相关产品推荐
相关产品推荐

