PyTorch训练CNN报错:input type(double)与bias type(float)类型不匹配
问题修复方案
核心问题分析
报错PyTorch Runtime Error: input type (double) and bias type (float) should be the same主要由以下原因导致:
- 输入数据类型为
float64(numpy默认类型),但PyTorch模型参数默认是float32,类型不匹配 - 输入张量维度不符合Conv2d要求(缺少通道维度)
- 训练循环中模型变量名错误
- 损失函数与输出/标签的格式不匹配
具体修复步骤
1. 统一数据与模型的数值类型
将输入数据转为float32,确保和模型参数类型一致:
# 修改训练数据生成部分 train_dat = torch.utils.data.TensorDataset( torch.tensor(test_data_x, dtype=torch.float32).to(device), torch.tensor(test_data_y, dtype=torch.float32).to(device) )
2. 修正输入张量维度
模型第一个Conv2d的in_channels=1,但输入是(batch, 19, 1000),需要增加通道维度(将19视为高度维度,通道设为1):
# 在训练循环的forward前修改输入维度 inputs = inputs.unsqueeze(1) # 从(16,19,1000)变为(16,1,19,1000)
3. 修正训练循环中的模型变量名
定义的模型是test_model,调用时误写为model,修改为:
outputs = test_model(inputs)
4. 调整损失函数与输出层的匹配
- CrossEntropyLoss要求输入是logits(不需要Softmax,损失函数内部已包含),移除最后一层的Softmax:
# 修改fc层的最后部分 self.fc = torch.nn.Sequential( torch.nn.Dropout1d(p = 0.5), torch.nn.Linear(in_features = channels * 64 * samples, out_features = 32), torch.nn.BatchNorm1d(32, eps = 0.001, momentum = 0.99), torch.nn.ReLU(), torch.nn.Dropout1d(p = 0.3), torch.nn.Linear(in_features = 32, out_features = outputs) # 移除Softmax() )
- CrossEntropyLoss的标签需要是类别索引(不是one-hot向量),如果是one-hot标签,要转为索引:
# 训练循环中修改标签处理 labels = torch.argmax(labels, dim=1).to(device)
5. 修正模型初始化中的计算错误
模型初始化中使用了floor但未导入,需要添加:
from math import floor
完整修正后的关键代码片段
模型定义(修正后)
import torch from math import floor class NNnet(torch.nn.Module): def __init__(self, channels = 19, samples = 1000.0, outputs = 4): super(NNnet, self).__init__() #Sequential 1 self.seq1 = torch.nn.Sequential( torch.nn.Conv2d(in_channels = 1, out_channels = 32, kernel_size = (1,20), stride = 1), torch.nn.Conv2d(in_channels = 32, out_channels = 32, kernel_size = (3,1), stride = 1), torch.nn.BatchNorm2d(32, eps = 0.001, momentum = 0.99), torch.nn.ReLU(), torch.nn.MaxPool2d(kernel_size = [1,5], stride = [1,2]) ) #calculate output of sample at each opeartion samples = (samples - 20) + 1 samples = (samples - 1) + 1 channels = channels - 3 + 1 samples = floor((samples - 5) / 2 + 1) #Sequential 2 self.seq2 = torch.nn.Sequential( torch.nn.Conv2d(in_channels = 32, out_channels = 64, kernel_size = (1,20)), torch.nn.BatchNorm2d(64, eps = 0.001, momentum = 0.99), torch.nn.ReLU(), torch.nn.MaxPool2d(kernel_size = [1,7], stride = [1,2]) ) samples = (samples - 20) + 1 samples = floor((samples- 7) / 2 + 1) #Sequential 3 self.seq3 = torch.nn.Sequential( torch.nn.Conv2d(in_channels = 64, out_channels = 64, kernel_size = (1,10)), torch.nn.BatchNorm2d(64, eps = 0.001, momentum = 0.99), torch.nn.ReLU(), torch.nn.MaxPool2d(kernel_size = [1,5], stride = [1,2]) ) samples = (samples - 10) + 1 samples = floor((samples - 5) / 2 + 1) #fully connect self.fc = torch.nn.Sequential( torch.nn.Dropout1d(p = 0.5), torch.nn.Linear(in_features = channels * 64 * samples, out_features = 32), torch.nn.BatchNorm1d(32, eps = 0.001, momentum = 0.99), torch.nn.ReLU(), torch.nn.Dropout1d(p = 0.3), torch.nn.Linear(in_features = 32, out_features = outputs) ) def forward(self, x): x = self.seq1(x) x = self.seq2(x) x = self.seq3(x) x = torch.flatten(x, start_dim = 1, end_dim = -1) x = self.fc(x) return x
训练循环(修正后)
import torch import numpy as np device = torch.device("cuda" if torch.cuda.is_available() else "cpu") #dummy data of 540 instances, 19 channel and 1000 sample test_data_x = np.ones(shape = (540,19,1000)) #dummy label - 改为类别索引(示例用0),如果是one-hot后续要转 test_data_y = np.zeros(shape = (540,), dtype=np.int64) train_dat = torch.utils.data.TensorDataset( torch.tensor(test_data_x, dtype=torch.float32).to(device), torch.tensor(test_data_y).to(device) ) train_loader = torch.utils.data.DataLoader(train_dat, batch_size = 16, shuffle = True) test_model = NNnet(channels = 19, samples = 1000, outputs = 4) optimizer = torch.optim.Adam(test_model.parameters(), lr = 0.001, weight_decay = 0.0001) criterion = torch.nn.CrossEntropyLoss() test_model.to(device) criterion.to(device) #train loop----------------------------------------------- for epoch in range(10): running_loss = 0.0 for i, data in enumerate(train_loader,0): inputs, labels = data inputs, labels = inputs.to(device), labels.to(device) # 增加通道维度 inputs = inputs.unsqueeze(1) optimizer.zero_grad() outputs = test_model(inputs) loss = criterion(outputs, labels) loss.backward() optimizer.step() running_loss += loss.item() print(f'Epoch {epoch+1}, Loss: {running_loss/len(train_loader):.4f}')
内容的提问来源于stack exchange,提问作者G.P
相关产品推荐
相关产品推荐

