滚动轴承故障诊断

前言

今天更新的是多尺度卷积+BiLSTM的故障诊断模型。利用不同大小的卷积核能够提取丰富的特征信息,再经过双向LSTM获取时序特征,增强模型的分类效果。

改进

  • 多尺度卷积块 (self.convs)

    • 我们使用了 nn.ModuleList,这是PyTorch中存储一系列nn.Module的标准容器。

    • 创建了三个并行的 nn.Conv1d 层,它们的kernel_size分别为3, 5, 7,用于捕捉不同长度的模式。

    • padding被设置为 (kernel_size - 1) // 2,这是一个常用的技巧,可以确保卷积操作后序列的长度保持不变,方便后续拼接。

  • 特征拼接 (torch.cat)

    • forward 方法中,我们将三个卷积分支的输出在一个列表 multi_scale_features 中收集起来。

    • torch.cat(multi_scale_features, dim=1) 将这些特征图沿着通道维度 (维度1)进行拼接。如果每个分支输出 (N, 32, L),拼接后就得到 (N, 32*3, L),即 (N, 96, L)。这比逐元素相乘保留了更多的原始信息。

  • 特征整合 (self.conv_mixer)

    • 在拼接了多尺度特征之后,我们添加了一个常规的卷积层 (self.conv_mixer)来学习如何组合这些来自不同尺度的信息,并统一输出通道数(例如,减少到64),为后续的LSTM层做准备。
  • 批量归一化 (nn.BatchNorm1d)

    • 在卷积和激活函数之间加入了 nn.BatchNorm1d。这层可以规范化每层的数据分布,使得训练过程更加稳定,通常能带来性能提升。
  • 双向LSTM (bidirectional=True)

    • 这是一个可选但通常很有效的改进。双向LSTM可以同时从过去和未来两个方向学习序列信息,对于很多任务都能提升性能。注意,这会导致全连接层的输入特征维度加倍(hidden_size * 2)。
  • 代码健壮性

    • 去除了硬编码的batch_size,模型现在可以接受任意批次大小的输入。

    • 改用 x.unsqueeze(1) 来增加通道维度,这比 .view() 更安全,因为它不会意外地改变数据布局。

代码

python 复制代码
import torch
import torch.nn as nn
import torch.nn.functional as F


class MultiScaleModel(nn.Module):
    def __init__(self):
        """
        在 __init__ 中不再需要传入 batch_size。
        """
        super(MultiScaleModel, self).__init__()

        # 1. 定义多尺度卷积模块 (Multi-Scale Convolutional Block)
        # 我们将使用三个并行的卷积层,核大小分别为 3, 5, 7
        # 使用 ModuleList 来方便地管理这些层
        self.convs = nn.ModuleList([
            # 分支1: 小尺度特征
            nn.Conv1d(in_channels=1, out_channels=32, kernel_size=3, stride=1, padding=1),
            # 分支2: 中尺度特征
            nn.Conv1d(in_channels=1, out_channels=32, kernel_size=5, stride=1, padding=2),
            # 分支3: 大尺度特征
            nn.Conv1d(in_channels=1, out_channels=32, kernel_size=7, stride=1, padding=3)
        ])
        # 注意: padding = (kernel_size - 1) // 2 可以保持序列长度不变

        # 拼接后的通道数是 32 * 3 = 96
        # 添加一个后续的卷积层来整合多尺度特征
        self.conv_mixer = nn.Conv1d(in_channels=96, out_channels=64, kernel_size=3, stride=1, padding=1)

        # 添加批量归一化层,可以稳定训练并加速收敛
        self.batch_norm = nn.BatchNorm1d(num_features=64)

        self.pool = nn.MaxPool1d(kernel_size=2)

        # 2. 定义解码器 (dc) 的层 (与原来保持一致)
        # LSTM的input_size现在是conv_mixer的输出通道数(64)
        self.dc_layer1 = nn.LSTM(input_size=64, hidden_size=128, batch_first=True)
        self.dc_layer2 = nn.LSTM(input_size=128, hidden_size=256, batch_first=True, bidirectional=True)  # 尝试使用双向LSTM
        self.dc_layer3 = nn.Dropout(0.5)
        # 双向LSTM的输出是 hidden_size * 2
        self.dc_layer4 = nn.Linear(in_features=256 * 2, out_features=10)

    def forward(self, x):
        # 3. 动态获取 batch_size 并调整输入形状
        # 假设输入 x 的 shape: (batch_size, sequence_length), 例如 (32, 1024)
        # .unsqueeze(1) 比 view 更灵活,它会在第1维增加一个通道维度
        x_reshaped = x.unsqueeze(1)  # -> (batch_size, 1, 1024)

        # 4. 多尺度卷积前向传播
        # 对每个卷积分支进行计算,并将结果保存在列表中
        multi_scale_features = [conv(x_reshaped) for conv in self.convs]

        # 使用 torch.cat 在通道维度(dim=1)上拼接特征
        x_cat = torch.cat(multi_scale_features, dim=1)  # -> (batch_size, 96, 1024)

        # 5. 整合特征并通过后续层
        # 使用 ReLU 激活函数替代 tanh
        x = F.relu(self.conv_mixer(x_cat))
        x = self.batch_norm(x)  # 应用批量归一化
        encoder_outputs = self.pool(x)  # -> (batch_size, 64, 512)

        # 6. 调整维度以匹配 LSTM 的输入格式
        # Conv1d 输出: (N, C, L) -> LSTM 输入: (N, L, C)
        lstm_input = encoder_outputs.permute(0, 2, 1)

        # 7. 解码器 (dc) 的前向传播
        dc, _ = self.dc_layer1(lstm_input)
        dc, _ = self.dc_layer2(dc)

        # 8. 获取 LSTM 最后一个时间步的输出
        # 对于双向LSTM,我们需要拼接前向和后向的最后一个隐藏状态
        # dc shape: (batch_size, seq_len, 256 * 2)
        # 我们取最后一个时间步的输出
        dc = dc[:, -1, :]

        # 9. Dropout 和全连接层
        dc = self.dc_layer3(dc)
        output = self.dc_layer4(dc)

        # 10. 输出
        # 在使用 nn.CrossEntropyLoss 作为损失函数时,不需要手动应用softmax
        # 它会内部完成 log_softmax。因此,通常直接返回logits(全连接层的输出)。
        return output


# --- 如何使用模型 ---
# 创建一个模型实例
model = MultiScaleModel()

# 创建一个假的输入张量来测试
# batch_size=32, sequence_length=1024
#dummy_input = torch.randn(32, 1024)
#output = model(dummy_input)

# 打印模型结构和输出形状
#print(model)
#print("Output shape:", output.shape)
相关推荐
awonw23 分钟前
[python][flask]Flask-Login 使用详解
开发语言·python·flask
awonw24 分钟前
[python][flask]flask中session管理
开发语言·python·flask
Mryan200529 分钟前
✨ 使用 Flask 实现头像文件上传与加载功能
后端·python·flask
程序员是干活的35 分钟前
Java EE前端技术编程脚本语言JavaScript
java·大数据·前端·数据库·人工智能
chaofan9801 小时前
ERNIE-4.5-0.3B 实战指南:文心一言 4.5 开源模型的轻量化部署与效能跃升
人工智能·开源·文心一言
hppyhjh1 小时前
【昇腾CANN训练营】深入cann-ops仓算子编译出包流程
人工智能
飞凌嵌入式1 小时前
飞凌嵌入式亮相第九届瑞芯微开发者大会:AIoT模型创新重做产品
人工智能·嵌入式硬件·嵌入式·飞凌嵌入式
大模型工程师1 小时前
TongYiLingMa插件下Qwen3-Coder
人工智能
大模型工程师1 小时前
独立开发:高效集成大模型,看这篇就够了
人工智能
程序员的世界你不懂1 小时前
Jmeter的元件使用介绍:(四)前置处理器详解
开发语言·python·jmeter