原帖在 Dataset 中把图像特征 astype(np.uint8),DataLoader 因而得到 Byte 张量,第一层 Linear 却使用浮点权重:
RuntimeError: expected scalar type Float but found Byte
Byte 特征和 long 标签承担不同角色
原题在数据读取时转 np.uint8,模型前向又需要浮点权重。先把实际进入 Linear 的 images 与权重对齐,不要把标签也一起变成浮点。还应检查是否误丢最后一列特征,避免类型修复掩盖 CSV 读取错误。
失败发生在模型前向,不是 NLLLoss 的标签类型检查。先在 logps = model(images) 前打印两个实际矩阵的类型:
print("josh050608")
print("images:", images.shape, images.dtype, images.device)
print("weight:", model[0].weight.shape, model[0].weight.dtype, model[0].weight.device)
print("labels:", labels.shape, labels.dtype)
若特征确实是 Byte,先保留 batch 维展平,再按权重的设备和 dtype 转换:
weight = model[0].weight
images = images.flatten(1).to(device=weight.device, dtype=weight.dtype)
assert images.shape[1] == model[0].in_features
logps = model(images)
labels = labels.to(device=logps.device, dtype=torch.long)
loss = criterion(logps, labels)
代码需已有 import torch。只有确认原始像素范围是 0–255 时,才额外除以 255;若文件里已经是小数特征,原先转 uint8 反而可能截断信息,应该在 Dataset 阶段保留 float32。
原帖用 iloc[idx,1:-1],可能把最后一列丢掉。应先检查文件是否有尾部空列以及实际特征列数,确保每张图恰有 256 个值,再 reshape 到 16×16。不能靠修改 Linear 掩盖读取错列。
修复后验证输入类型与权重一致、logps 为 [N,10],标签是 0–9 编号,再执行 backward。
从 0–255 合成像素走通 NLLLoss
下面明确使用 uint8 像素,因此转换后除以 255 有依据。真实文件若本来就是浮点特征,应在读取阶段保留,不要先截断为 Byte:
import torch
from torch import nn
pixels = torch.arange(2 * 256).remainder(256).to(torch.uint8).reshape(2, 1, 16, 16)
labels = torch.tensor([2, 7], dtype=torch.long)
model = nn.Sequential(nn.Linear(256, 32), nn.ReLU(), nn.Linear(32, 10), nn.LogSoftmax(dim=1))
weight = model[0].weight
features = pixels.flatten(1).to(dtype=weight.dtype, device=weight.device) / 255.0
assert features.shape == (2, 256)
assert features.dtype == weight.dtype
log_probs = model(features)
loss = nn.NLLLoss()(log_probs, labels)
loss.backward()
assert model[0].weight.grad is not None
assert torch.isfinite(loss)
print("source/converted/loss:", pixels.dtype, features.dtype, loss.item())
原题 iloc[idx,1:-1] 会排除最后一列。先看原表列数、最后一列是否真为空、去掉标签后是否恰有 256 个特征,再决定切片。若最后一列是有效像素,应该保留;若是文件尾部解析出的空列,应明确清理规则。
若转换过的 .to() 或 .float() 没接返回值,后续模型仍使用旧 Byte 张量,检查实际失败行传入的对象,而非另一份变量。类型统一应在 Dataset 或统一 batch 入口完成,训练和验证走同一路径。
验收输入范围、特征数、模型 dtype 与 [N,10] 输出,再做 backward。把标签改成 long 只解决分类目标约定,不会替图像输入完成浮点化。
参考:原始求助帖;技术依据:torch.from_numpy(2.5)、Linear(2.5)、NLLLoss(2.5)、pandas 2.2 to_numpy。