我正在尝试构建一个模型来根据个体预测保险费用。这是相关的代码。
import torchimport torch.nn as nnimport torch.nn.functional as Ffrom torch.utils.data import DataLoader, TensorDatasetimport numpy as npimport pandas as pdfrom LSR import ListSearchReplace as LSRcsv = pd.read_csv("main.csv")partialInputs = csv[["age", "bmi", "children"]]smoker, sex = list(csv["smoker"]), list(csv["sex"])L1 = LSR(smoker)L1.replace("yes", 1, True)L1.replace("no", 0, True)L2 = LSR(sex)L2.replace("female", 1, True)L2.replace("male", 0, True)pdReadySmoker = pd.DataFrame({"smoker": smoker})pdReadySex = pd.DataFrame({"sex": sex})SmokerAndSex = pd.merge(pdReadySmoker, pdReadySex, how="outer", left_index=True, right_index=True)INPUTS = pd.merge(partialInputs, SmokerAndSex, how="outer", left_index=True, right_index=True)TARGETS = csv["charges"]INPUTS = torch.from_numpy(np.array(INPUTS, dtype='float32'))TARGETS = torch.from_numpy(np.array(TARGETS, dtype='float32'))print(INPUTS.shape, TARGETS.shape)loss_fn = F.mse_lossmodel = nn.Linear(5, 3) # <-- changing this, changes the error message.opt = torch.optim.SGD(model.parameters(), lr=1e-5)trainDataset = TensorDataset(INPUTS, TARGETS)BATCH_SIZE = 5trainDataloader = DataLoader(trainDataset, BATCH_SIZE, shuffle=True)def fit(numEpochs, model, loss_fn, opt, trainDataloader): for epochs in range(numEpochs): for inputBatch, targetBatch in trainDataloader: preds = model(inputBatch) loss = loss_fn(preds, targetBatch) loss.backward() opt.step() opt.zero_grad() e = epoch + 1 if e % 10 == 0: print(f"Epoch: {e/numEpochs}, loss: {loss.item():.4f}")fit(100, model, loss_fn, opt, trainDataloader) <-- error
产生的错误:
<ipython-input-7-b7028a3d94fd>:5: UserWarning: 使用的目标大小(torch.Size([5]))与输入大小(torch.Size([5, 3]))不同。这可能会导致由于广播而产生错误的结果。请确保它们具有相同的大小。 loss = loss_fn(preds, targetBatch)---------------------------------------------------------------------------RuntimeError Traceback (most recent call last)<ipython-input-20-d8f5bcdc847d> in <module>----> 1 fit(100, model, loss_fn, opt, trainDataloader)<ipython-input-7-b7028a3d94fd> in fit(numEpochs, model, loss_fn, opt, trainDataloader) 3 for inputBatch, targetBatch in trainDataloader: 4 preds = model(inputBatch)----> 5 loss = loss_fn(preds, targetBatch) 6 loss.backward() 7 D:\coding\machine-learning\env-ml\lib\site-packages\torch\nn\functional.py in mse_loss(input, target, size_average, reduce, reduction) 2657 reduction = _Reduction.legacy_get_string(size_average, reduce) 2658 -> 2659 expanded_input, expanded_target = torch.broadcast_tensors(input, target) 2660 return torch._C._nn.mse_loss(expanded_input, expanded_target, _Reduction.get_enum(reduction)) 2661 D:\coding\machine-learning\env-ml\lib\site-packages\torch\functional.py in broadcast_tensors(*tensors) 69 if any(type(t) is not Tensor for t in tensors) and has_torch_function(tensors): 70 return handle_torch_function(broadcast_tensors, tensors, *tensors)---> 71 return _VF.broadcast_tensors(tensors) # type: ignore 72 73 RuntimeError: 张量 a 的大小(3)必须与张量 b 的大小(5)在非单例维度 1 上匹配
我尝试更改模型的维度,以下是一些更改和相关的错误:
model = nn.Linear(5, 1338)Error:RuntimeError: 张量 a 的大小(1338)必须与张量 b 的大小(5)在非单例维度 1 上匹配
model = nn.Linear(1338, 1338)Error:RuntimeError: mat1 和 mat2 的形状无法相乘(5x5 和 1338x1338)
有时这个错误会让我将矩阵调整到正确的形状,但这会导致之前关于non-singleton dimension
的错误
回答:
这应该相当简单,你只有一个层。这是关于正确排序形状的问题。
你正在向一个形状为input_shape
的输入喂入一个nn.Linear
层。这种类型的层接受两个参数:in_features
,输入向量中的特征数量,以及out_features
,结果向量中的特征数量。因为你使用的是F.mse_loss
,你的目标向量需要与你的预测具有相同的形状。
请记住,第一个维度是批处理维度。总结一下,你的输入张量形状为(batch, input_size)
,你的密集层定义为nn.Linear(input_size, out_size)
,你的目标张量形状为(batch, output_size)
。
回到你的情况,你的TARGETS
张量形状为(1338)
,所以你要么是:
-
想要一个具有
1338
个组件的单一预测,这将匹配nn.Linear(?, 1338)
,实际上对应于(1, 1338)
(批处理中的单个元素)。这可以通过TARGETS = TARGETS.unsqueeeze(0)
来修复。 -
或者,实际上有
1338
个预测,每个预测一个元素,这将匹配nn.Linear(?, 1)
,适当的目标形状将是(1338, 1)
。这可以通过TARGETS = TARGETS.unsqueeeze(-1)
(在最后一个维度之后添加一个额外的轴)来修复。