【求助帖(已解决)】用PyTorch搭建MLP网络时遇到奇怪的问题

(已解决,看最后)

求助:我在测试自己搭建的通用MLP网络时,发现它与等价的参数写死的MLP网络相比效果奇差无比,不知道是哪里出了问题,请大佬们帮忙看下。

我写的通用MLP网络:

python 复制代码
class MLP(nn.Module):
    def __init__(self, feature_num, class_num, *hidden_nums):
        super().__init__()
        self.feature_num = feature_num
        self.class_num = class_num
        self.hidden_nums = hidden_nums

        input_num = feature_num
        for i, hidden_num in enumerate(hidden_nums):
            self.__dict__['fc' + str(i)] = nn.Linear(input_num, hidden_num)
            input_num = hidden_num
        self.output = nn.Linear(input_num, class_num)

    def forward(self, x):
        for i in range(len(self.hidden_nums)):
            x = F.relu(self.__dict__['fc' + str(i)](x))
        x = self.output(x)[..., 0] if self.class_num == 1 else F.sigmoid(self.output(x))
        return x

按理说这样实例化时:

python 复制代码
model = MLP(57, 2, 30, 10)

它应该与下面这个网络等价:

python 复制代码
class MLPclassification(nn.Module):
    def __init__(self):
        super().__init__()
        self.fc0 = nn.Linear(57, 30)
        self.fc1 = nn.Linear(30, 10)
        self.output = nn.Linear(10, 2)

    def forward(self, x):
        x = F.relu(self.fc0(x))
        x = F.relu(self.fc1(x))
        x = F.sigmoid(self.output(x))
        return x

但当我用model = MLP(57, 2, 30, 10)训练网络时,在二分类问题中,它把所有数据都预测成了类别0:

而用 model = MLPclassification()训练网络时,预测的效果很好:

我检查了半天,不知道是哪里出了问题,有没有大佬懂的,帮忙看下,十分感谢!


解决了!我检查了nn.Module的__setattr__()方法(向对象的name属性赋值、即定义实例变量时自动调用的方法),发现__setattr__()会将Module类型的变量移到_modules属性下面:

所以批量定义全连接层时不能直接向__dict__属性赋值,这样会绕过__setattr__()方法的类型检查,导致最后优化器无法通过model.parameters()获取并更新隐藏层的权重。所以应该在__dict__'_modules'属性中批量定义全连接层,就能解决这个问题了。更新后的通用MLP网络代码如下:

python 复制代码
class MLP(nn.Module):
    def __init__(self, feature_num, class_num, *hidden_nums):
        super().__init__()
        self.feature_num = feature_num
        self.class_num = class_num
        self.hidden_nums = hidden_nums

        input_num = feature_num
        for i, hidden_num in enumerate(hidden_nums):
            self.__dict__['_modules']['fc' + str(i)] = nn.Linear(input_num, hidden_num)
            input_num = hidden_num
        self.output = nn.Linear(input_num, class_num)

    def forward(self, x):
        for i in range(len(self.hidden_nums)):
            x = F.relu(self.__dict__['_modules']['fc' + str(i)](x))
        x = self.output(x)[..., 0] if self.class_num == 1 else F.softmax(self.output(x), dim=-1)
        return x

预测效果非常好:

感悟:看来没啥事还是不要随便动下划线开头的东西,你不知道会不会牵动到别的地方,出了问题处理起来挺麻烦的。

相关推荐
江畔柳前堤36 分钟前
大语言模型分布式训练:从并行策略到万卡工程的系统梳理
人工智能·分布式·深度学习·算法·目标检测·机器学习·语言模型
AI创界者1 小时前
MiniMax-H3 本地一键部署整合包:8G 显存玩转文图生视频、视频参考、角色替换与超分补帧全流程
人工智能·深度学习
北斗落凡尘3 小时前
LangGraph 入门实战(2)
python·langchain
ttod_qzstudio3 小时前
Java 常用语法极简通关(五):类与对象——字段、方法、构造器、this 与 static
java·开发语言·python
论文避坑指南4 小时前
论文写作全流程AI合规边界:从选题到投稿的“红绿灯“清单
大数据·人工智能·深度学习
蛋先生DX4 小时前
大模型参数存储格式揭秘:BF不是男朋友
深度学习·算法·llm
jufeng13074 小时前
【系列:手搓自主 AI Agent:Hermes 架构原理剖析 · 第 1 篇】
人工智能·python·架构·agent
杀生丸学AI5 小时前
【前馈三维重建】SAF3R:前馈式3D重建Transformer的动态稀疏注意力(加速)
深度学习·3d·transformer
月光船幽幽5 小时前
影子模式下保护 logits 不被修改
人工智能·python·算法
_oP_i7 小时前
python 后缀 mjs文件
开发语言·python