基于PyTorch的时序数据二分类CNN:输入张量与展平问题咨询
问题解答
1. 输入张量维度
PyTorch中nn.Conv1d要求输入张量形状为(batch_size, in_channels, sequence_length):
batch_size:批次内样本数量in_channels:输入的通道数,这里每个样本是单序列(30个传感器测量值组成的时序序列),所以设为1sequence_length:序列长度,即30个测量值的数量
你当前使用的(num_of_samples, 1, 30)是完全正确的,无需调整。之前转成(38,30,1)的步骤是多余的,可以直接从原始的(38,30)一步转成目标形状:
X_train = X_train.reshape(len(X_train), 1, 30)
2. 卷积后展平的问题
你遇到的RuntimeError: mat1 and mat2 shapes cannot be multiplied,核心原因是手动计算的卷积输出维度与实际输出不匹配,导致全连接层输入维度错误。
解决方法:
不要手动计算conv_linear_out,而是用自适应展平:
- 在
forward方法中,用x = x.flatten(1)或者x = x.view(x.size(0), -1)自动展平除了batch维度之外的所有维度,这样不管卷积层怎么调整,都不会出现维度不匹配的问题。
你的代码中的其他问题:
- 卷积层的
nn.Sequential里已经包含了nn.ReLU(),但forward里又叠加了F.leaky_relu,属于重复激活,会导致梯度消失或输出异常,二选一即可(推荐保留leaky_relu,去掉卷积层里的ReLU)。 nn.Linear(self.conv_linear_out, self.FN_1, nn.Dropout(0.2))写法错误,nn.Linear的第三个参数不是dropout层,需要把dropout单独作为一层添加到模型中。F.logsigmoid搭配CrossEntropyLoss不合理,CrossEntropyLoss要求最后一层是原始logits,不需要额外激活。
修改后的CNN类示例:
import torch import torch.nn as nn import torch.nn.functional as F class CNN(nn.Module): def __init__(self): super(CNN, self).__init__() # 简化卷积层参数,避免冗余操作 self.conv1 = nn.Sequential( nn.Conv1d(1, 16, kernel_size=3, padding=1), nn.LeakyReLU(), nn.MaxPool1d(kernel_size=2) ) self.conv2 = nn.Sequential( nn.Conv1d(16, 32, kernel_size=3, padding=1), nn.LeakyReLU(), nn.MaxPool1d(kernel_size=2) ) self.dropout = nn.Dropout(0.2) # 30经过两次池化(2*2)后长度为30//2//2=7,通道数32,所以输入维度是32*7 self.fc1 = nn.Linear(32 * 7, 50) self.fc2 = nn.Linear(50, 2) def forward(self, x): x = x.float() x = self.conv1(x) x = self.conv2(x) x = x.flatten(1) # 自适应展平,batch维度保留,其余维度合并 x = self.dropout(x) x = F.leaky_relu(self.fc1(x)) x = self.fc2(x) # CrossEntropyLoss不需要额外激活 return x
3. CNN结构合理性建议
你的原始模型存在几个冗余或不合理的点:
kernel_size=1的卷积层没有提取序列局部特征的作用,相当于线性变换,建议换成kernel_size=2/3,更适合捕捉时序数据的局部模式。MaxPool1d(kernel_size=1)完全没有池化效果,无法降低序列长度和计算量,建议设置为2或3,逐步压缩序列长度。- 训练集只有38个样本,模型层数过多(4个卷积层)容易过拟合,建议简化为2-3个卷积层,同时添加dropout层抑制过拟合。
- 可以尝试调整通道数(比如16、32,不要用17、18这种非2的幂次值,硬件计算更高效)。
额外优化点
- 数据预处理:对传感器测量值做标准化(比如用
sklearn.preprocessing.StandardScaler),让输入数据分布更稳定,加快模型收敛。 - 损失函数:如果样本不平衡(故障样本少),可以用
nn.BCELoss搭配sigmoid激活,或者给CrossEntropyLoss加类别权重。 - 优化器:SGD的收敛速度较慢,可以尝试
Adam优化器,学习率可以调到0.0001-0.001。
内容的提问来源于stack exchange,提问作者Rory Majule
相关产品推荐
相关产品推荐

