V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
zckun
V2EX  ›  Python

pytorch 多分类的问题

  •  
  •   zckun · 2020-08-12 14:27:58 +08:00 · 2526 次点击
    这是一个创建于 1567 天前的主题,其中的信息可能已经有所发展或是发生改变。

    训练的数据是 300x10 的矩阵,一共 14000 个,每个矩阵对应三种情况,表示为 0 1 2

    需要特别说明的是,大部分的数据所对应的类别是 0,少数是对应着 1 2 的。可以理解为数据中 50%是 0 类,剩下的 50%分给了 1 2 类

    我使用的是逻辑回归

    网络如下

    class LogisticRegression(nn.Module):
        def __init__(self):
            super(LogisticRegression, self).__init__()
            self.lr = Linear(300 * 10, 3)
            self.sm = nn.Sigmoid()
           
        def forward(self, x: Tensor):
        	# 展开
        	x = x.view(-1, self.in_features)
            x = self.lr(x)
            x = self.sm(x)
            return x
    

    优化器使用的是 SGD 梯度下降,学习率是 0.001 损失函数用的是 CrossEntropyLoss

    训练部分代码如下 其中 x_train 是训练数据,y_train 对应的类别,y_train 中的每个元素均为 0/1/2,没有经过独热编码 x_train 的 shape 为torch.Size([14000, 300, 10]) y_train 的 shape 为torch.Size([14000, 1])

    model = LogisticRegression().to(device)
    
    optimizer = optim.SGD(model.parameters(), lr=1e-3)
    criterion = nn.CrossEntropyLoss()
    
    for epoch in range(1, 10001):
        for i, (data, target) in enumerate(zip(x_train, y_train)):
            x, y = data.to(device), target.to(device)
    
            y_pred = model(x)
    		
            loss = criterion(y_pred, y)
            optimizer.zero_grad()
            loss.backward()
            optimizer.step()
            if epoch % 100 == 0:
                if y == 2:
                    print(f'Epoch: {epoch}, Loss: {loss.item()}')
    

    如果训练所有数据,会出现 loss 前期下降快,后面基本不动 我请教过他人,提出我的网络层数太少,出现了过拟合,让我多加几层网络 加了几层后我的网络是这样的

    class LogisticRegression(nn.Module):
        def __init__(self):
            super(LogisticRegression, self).__init__()
            self.lr = Linear(300 * 10, 200 * 10)
            self.lr2 = Linear(200 * 10, 3)
            self.sm = nn.Sigmoid()
           
        def forward(self, x: Tensor):
            # 展开
        	x = x.view(-1, self.in_features)
            x = self.lr(x)
            x = self.lr(x)
            x = self.sm(x)
            return x
    

    接着我训练,loss 会一直增长

    期间我试过取 0 和 2 两个类别的数据训练 10000 次,结果是 97 的准确率

    我想知道问题出在哪了,谢谢

    13 条回复    2020-08-12 21:08:25 +08:00
    python35
        1
    python35  
       2020-08-12 14:49:21 +08:00
    交叉熵 loss 里面里面做 softmax 了 前面放 sigmoid 可能有影响??把这个节点去掉试试
    zckun
        2
    zckun  
    OP
       2020-08-12 15:00:01 +08:00
    @python35 不是这个原因
    xcnick
        3
    xcnick  
       2020-08-12 15:49:59 +08:00
    激活函数要放在线性层中间,不然多个线性层等价于一个线性层
    EggtartZ
        4
    EggtartZ  
       2020-08-12 17:05:17 +08:00
    为什么要 sigmoid 加 softmax 呢,我觉得这样可能会抹除数据之间的差异性吧,是不是 0 和 2 类别的差异性比较大,所以单独拿出来准确率还行
    suith27
        5
    suith27  
       2020-08-12 17:10:44 +08:00
    恕我愚钝,没看出来问题是什么
    whenov
        6
    whenov  
       2020-08-12 17:16:57 +08:00
    层数少应该是欠拟合而不是过拟合吧
    shikimoon
        7
    shikimoon  
       2020-08-12 17:23:27 +08:00
    1.CrossEntropy 前面不需要再加 sigmoid 或 softmax
    2.多个线性层直接叠加相当于一个
    daweii
        8
    daweii  
       2020-08-12 17:27:18 +08:00 via iPhone
    你需要用 training loss 跟 validation loss 对比才能知道真正的情况。我下面所说的前提是你文中说的 loss 是 training loss 。

    > loss 前期下降快,后面基本不动。
    说明你的模型太小了,即使一直 train 也不能完全拟合数据。这是 underfitting 而不是 overfitting 。不过增加层数确实是解决 underfitting 的方法。

    > 接着我训练,loss 会一直增长
    训练 loss 只可能是一直下降。训练 loss 出现一直上涨的情况肯定是代码出 bug 了。建议检查代码。
    lv2016
        9
    lv2016  
       2020-08-12 17:30:48 +08:00
    看楼主的代码应该是只有当 epoch 为 100 的倍数且标签为 2 的样本才打印 loss,可以先改成全体样本的平均 loss 看看,一般来说后期的 loss 确实下降的比较慢;同时可以尝试一下 mini-batch,单个样本的梯度方向的偏差可能过大了
    Porphet
        10
    Porphet  
       2020-08-12 17:37:14 +08:00
    模型能训练的情况下,首先要考虑训练数据的质量,尽量不要出现一个训练条目既是 1 又是 2
    tfdetang
        11
    tfdetang  
       2020-08-12 19:25:31 +08:00
    没用过 pytorch,不是特别理解,为什么 y_train 不做独热编码? 你用, sigmoid 做输出,最后输出都是 0~1 之间吧。 那你如何输出 2 这个标签呢?
    diggerdu
        12
    diggerdu  
       2020-08-12 19:52:00 +08:00 via iPhone
    别的不论 初始化先做好
    zckun
        13
    zckun  
    OP
       2020-08-12 21:08:25 +08:00
    已经解决,谢谢各位讨论
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3986 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 29ms · UTC 04:13 · PVG 12:13 · LAX 20:13 · JFK 23:13
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.