PyTorch训练神经网络报错RuntimeError:期望Long类型却得到Float
问题描述
尝试训练一个以整数为输入的基础神经网络,无法直接传入整数因此将其转换为tensor,但运行训练代码时出现错误:RuntimeError: expected scalar type Long but found Float。
用户代码如下:
模型定义
class Net(nn.Module): def __init__(self,dim_input,hidden_dim,dim_output): super(Net, self).__init__() self.inp = dim_input self.oup = dim_output self.l1 = nn.Linear(dim_input,hidden_dim); self.l2 = nn.Linear(hidden_dim,dim_output); #self.l3 = nn.Linear(hidden_dim,dim_output); def forward(self,x): # x = self.converter(x) #x = torch.tensor(x) x = F.sigmoid(self.l1(x)) x = self.l2(x) return x def converter(self,x): n = x; n = bin(n).replace("0b", "") a = [] for i in n: a.append(int(i)) a.reverse() while(len(a) < self.inp): a.append(0) a.reverse() a = torch.tensor(a) a = a.to(dtype=torch.int64) return a
数据集准备
def prepare(): global primes,batch_size,net inp = [] oup = [] for i in range(batch_size): a = random.choice(primes) b = random.choice(primes) inp.append(net.converter(a*b)) oup.append(net.converter(min(a,b))) print(inp[0]) return inp,oup;
训练代码
loss_fn = nn.BCELoss() # binary cross entropy optimizer = optim.Adam(net.parameters(), lr=0.001) for i in range(n_epochs): inp,oup = prepare() for j in range(0,batch_size): y_pred = net(inp[j]); y_out = net(oup[j]); loss = loss_fn(y_pred,y_out) optimizer.zero_grad() loss.backward() optimizer.step() print(f'Finished epoch {i}, latest loss {loss}')
错误原因分析
数据类型不匹配:
converter方法返回torch.int64(Long类型)张量,但PyTorch线性层nn.Linear的参数默认是Float32类型,Long张量无法直接参与线性运算,触发类型冲突。BCELoss要求预测值和目标值都为Float类型,当前数据类型不满足要求。
目标值处理逻辑错误:
训练代码中y_out = net(oup[j])是错误操作,目标值应直接使用oup[j](转换后的真实标签),而非将标签再次传入模型生成输出。
修正方案
1. 修正模型类
调整converter返回Float类型张量,确保forward输入类型统一,同时为最后一层添加sigmoid(适配BCELoss要求):
class Net(nn.Module): def __init__(self, dim_input, hidden_dim, dim_output): super(Net, self).__init__() self.inp = dim_input self.oup = dim_output self.l1 = nn.Linear(dim_input, hidden_dim) self.l2 = nn.Linear(hidden_dim, dim_output) def forward(self, x): # 确保输入为Float32类型 x = x.to(dtype=torch.float32) x = F.sigmoid(self.l1(x)) # BCELoss要求输出在0-1区间,最后一层添加sigmoid x = F.sigmoid(self.l2(x)) return x def converter(self, x): n = bin(x).replace("0b", "") a = [int(i) for i in n] a.reverse() while len(a) < self.inp: a.append(0) a.reverse() # 直接返回Float32类型张量 return torch.tensor(a, dtype=torch.float32)
2. 修正训练代码
直接使用真实标签作为目标值,同时确保类型匹配:
loss_fn = nn.BCELoss() optimizer = optim.Adam(net.parameters(), lr=0.001) for i in range(n_epochs): inp, oup = prepare() total_loss = 0.0 for j in range(batch_size): x = inp[j] y_true = oup[j] y_pred = net(x) # 确保目标值为Float类型 loss = loss_fn(y_pred, y_true.to(dtype=torch.float32)) optimizer.zero_grad() loss.backward() optimizer.step() total_loss += loss.item() # 打印 epoch 平均损失更合理 print(f'Finished epoch {i}, average loss {total_loss / batch_size}')
3. 可选:优化数据集准备(批量张量提升效率)
将返回的列表转换为批量张量,支持后续批量训练:
def prepare(): global primes, batch_size, net inp = [] oup = [] for i in range(batch_size): a = random.choice(primes) b = random.choice(primes) inp.append(net.converter(a*b)) oup.append(net.converter(min(a,b))) # 转换为批量张量 return torch.stack(inp), torch.stack(oup)
对应批量训练代码:
for i in range(n_epochs): x_batch, y_batch = prepare() y_pred = net(x_batch) loss = loss_fn(y_pred, y_batch) optimizer.zero_grad() loss.backward() optimizer.step() print(f'Finished epoch {i}, loss {loss.item()}')
关键注意点
- 神经网络输入和参数统一使用
Float32类型,避免类型冲突。 - 使用
BCELoss时,模型最后一层必须加sigmoid激活,且预测值、目标值都需为Float类型。 - 训练时目标值是真实标签,无需再传入模型处理。
内容的提问来源于stack exchange,提问作者Kaushal Tiwari
相关产品推荐
相关产品推荐

