You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于真值构建非图像分类器:自定义前馈神经网络的数据集输入与训练方法问询

适配概率型多类别数据集到前馈神经网络的训练方案

先给你梳理下当前的问题,然后一步步解决:

一、先修正你的网络结构bug

你当前的NNO类有几个明显的错误,会导致无法正常运行:

  • 重复赋值self.hidden:三次赋值后只有最后一个nn.Linear(20,20)生效,前面的输入层和第一个隐藏层都被覆盖了,而且你明确说网络接收15维输入,所以第一个线性层的输入维度必须是15
  • forward函数参数不匹配:定义的参数是y,但函数里用的是未定义的x,会直接引发报错
  • 隐藏层未分层命名:多个隐藏层需要单独命名(比如hidden1、hidden2),不然无法按顺序调用

修正后的网络结构代码如下:

import torch
import torch.nn as nn

class NNO(nn.Module):
    def __init__(self):
        super(NNO, self).__init__()
        # 输入层:15维输入 → 20维隐藏层1
        self.hidden1 = nn.Linear(15, 20)
        # 隐藏层2:20维 → 20维
        self.hidden2 = nn.Linear(20, 20)
        # 输出层:20维 → 15维(对应0-14共15个类别;如果实际是14个类别,改成14即可)
        self.output = nn.Linear(20, 15)
        self.sigmoid = nn.Sigmoid()
        self.softmax = nn.Softmax(dim=1)

    def forward(self, x):
        # 前向传播流程:输入→隐藏层1→激活→隐藏层2→激活→输出层→softmax
        x = self.hidden1(x)
        x = self.sigmoid(x)
        x = self.hidden2(x)
        x = self.sigmoid(x)
        x = self.output(x)
        x = self.softmax(x)
        return x

二、处理你的概率型数据集

你的数据集有两个核心特点:

  • 共10个有效样本(缺失编号为8的样本),每个样本对应一组浮点概率值(你提到14个类别,但输出是0-14,这里默认按15个类别处理,若实际是14个,可调整对应维度)
  • 每个样本的真实类别标签,应该是该概率向量中概率最高的类别(比如你举例的样本项2,归属于类别2的概率最高,真实标签就是2)

1. 构建数据集张量

首先把你的样本数据转换成PyTorch兼容的张量格式:

# 示例:模拟你的数据集,key是样本项编号,value是对应类别的概率向量
sample_data = {
    0: [0.001, 0.99, 0.002, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001],
    1: [0.003, 0.001, 0.98, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.002],
    2: [0.002, 0.001, 0.995275, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001],
    # 补充样本项3、4、5、6、7、9的概率向量
}

# 提取输入特征和真实标签
inputs = []
labels = []
for prob_vec in sample_data.values():
    inputs.append(prob_vec)
    # 找到概率最大的索引作为该样本的真实类别标签
    true_label = prob_vec.index(max(prob_vec))
    labels.append(true_label)

# 转换为PyTorch张量:输入用float32,标签用long(多分类任务要求)
inputs_tensor = torch.tensor(inputs, dtype=torch.float32)
labels_tensor = torch.tensor(labels, dtype=torch.long)

2. 用DataLoader包装数据集(推荐)

虽然你的样本量很小,但用DataLoader可以方便后续扩展批量处理、打乱数据等操作:

from torch.utils.data import TensorDataset, DataLoader

# 创建数据集对象
dataset = TensorDataset(inputs_tensor, labels_tensor)
# 批大小设为样本总数,也可以根据需求调整
dataloader = DataLoader(dataset, batch_size=10, shuffle=True)

三、启动训练循环

现在可以正式开始训练了,完整的训练流程代码如下:

# 初始化模型、损失函数、优化器
model = NNO()
# 多分类任务优先用CrossEntropyLoss,它会自动适配softmax输出(也可以去掉模型里的softmax,直接用logits输入,计算更稳定)
criterion = nn.CrossEntropyLoss()
# 用Adam优化器,学习率可根据训练情况调整
optimizer = torch.optim.Adam(model.parameters(), lr=0.001)

# 训练循环
epochs = 100
for epoch in range(epochs):
    # 切换到训练模式
    model.train()
    running_loss = 0.0
    for batch_inputs, batch_labels in dataloader:
        # 清空上一轮的梯度
        optimizer.zero_grad()
        # 前向传播得到预测结果
        outputs = model(batch_inputs)
        # 计算损失
        loss = criterion(outputs, batch_labels)
        # 反向传播更新梯度
        loss.backward()
        # 优化器更新参数
        optimizer.step()
        # 累计损失值
        running_loss += loss.item()
    # 打印每轮的平均损失
    print(f"Epoch {epoch+1}/{epochs}, Loss: {running_loss/len(dataloader):.4f}")

# 训练完成后测试模型效果
model.eval()
with torch.no_grad():  # 关闭梯度计算,节省资源
    test_outputs = model(inputs_tensor)
    # 获取每个样本概率最大的类别作为预测标签
    pred_labels = torch.argmax(test_outputs, dim=1)
    print("\n预测标签:", pred_labels.numpy())
    print("真实标签:", labels_tensor.numpy())

额外注意事项

  • 因为你的样本量只有10个,很容易出现过拟合,建议尝试减少隐藏层维度、添加nn.Dropout()层,或者降低学习率
  • 如果你的概率向量是其他模型的输出(用于模型融合),这个处理方案同样适用
  • 若实际类别数是14个,记得把网络输出层维度改成14,同时概率向量的长度也要对应调整为14

内容的提问来源于stack exchange,提问作者mchd

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 04:37:28