Python运行报错exit code 139(SIGSEGV),排查孪生网络或数据加载器问题
运行孪生网络(SiameseNetwork)相关代码时触发SIGSEGV错误,不确定是网络设计还是DataLoader实现导致,推测可能是网络参数过大,但无法确定具体根源。
代码实现
import torch import torch.nn as nn import torch.nn.functional as F from torch.utils.data import Dataset, DataLoader import torch.optim as optim import random class SiameseNetwork(nn.Module): def __init__(self): super(SiameseNetwork, self).__init__() self.conv1 = nn.Conv1d(1, 8, kernel_size=3) self.pool = nn.MaxPool1d(2) self.fc1 = nn.Linear(8 * 999, 128) self.fc_out = nn.Linear(128, 1) def shared_network(self, x): x = F.relu(self.conv1(x)) x = self.pool(x) x = x.view(x.size(0), -1) # Aplatir la sortie x = F.relu(self.fc1(x)) x = self.fc_out(x) return x def forward(self, x1, x2): out1 = self.shared_network(x1) out2 = self.shared_network(x2) return out1, out2 class SignalDataset(Dataset): def __init__(self, signals): self.signals = signals def __len__(self): return len(self.signals) def __getitem__(self, index): sig0 = random.choice(self.signals) sig1 = random.choice(self.signals) max_length = 2000 # Mise à jour de la longueur maximale if sig0.shape[1] > max_length: sig0 = sig0[:, :max_length] if sig1.shape[1] > max_length: sig1 = sig1[:, :max_length] if len(sig0.shape) == 1: sig0 = sig0[None, :] if len(sig1.shape) == 1: sig1 = sig1[None, :] sig0 = torch.tensor(sig0, dtype=torch.float32) sig1 = torch.tensor(sig1, dtype=torch.float32) # Debugging print statements print(f"sig0 shape: {sig0.shape}, sig1 shape: {sig1.shape}") return sig0, sig1, torch.tensor(self.signals[index], dtype=torch.float32) # Convert signals to PyTorch tensors and create dataset and dataloader def create_dataloader(signals): dataset = SignalDataset(signals) return DataLoader(dataset, batch_size=16, shuffle=True, num_workers=0) class ContrastiveLoss(nn.Module): def __init__(self, margin=2.0): super(ContrastiveLoss).__init__() self.margin = margin def forward(self, out1, out2, label): euclidean_distance = F.pairwise_distance(out1, out2, keepdim=True) loss_constractive = torch.mean((1 - label) * torch.pow(euclidean_distance, 2) + (label) * torch.pow(torch.clamp(self.margin - euclidean_distance, min=0.0), 2)) return loss_constractive # Example data loader train_dataloader = create_dataloader(signals) print(len(train_dataloader)) # Initialize model, criterion, and optimizer device = torch.device('cuda' if torch.cuda.is_available() else 'cpu') model = SiameseNetwork().to((device)) criterion = ContrastiveLoss() optimizer = optim.Adam(model.parameters(), lr=0.001) print(model) counter = [] loss_history = [] iteration_number = 0 epochs = 5 for epoch in range(epochs): model.train() for i, (sig0, sig1, label) in enumerate(train_dataloader): print(f"sig0: {sig0.shape}, sig1: {sig1.shape}, label: {label.shape}") sig0, sig1, label = sig0.to(device), sig1.to(device), label.to(device) optimizer.zero_grad() out1, out2 = model(sig0, sig1) print(f"out1: {out1.shape}, out2: {out2.shape}") loss_constrative = criterion(out1, out2, label) loss_constrative.backward() optimizer.step() if i % 10 == 0: print(f"Epoch number: {epoch}, || Current loss: {loss_constrative.item()}") iteration_number += 10 counter.append(iteration_number) loss_history.append(loss_constrative.item())
错误输出
Process finished with exit code 139 (interrupted by signal 11: SIGSEGV) sig0: torch.Size([16, 1, 2000]), sig1: torch.Size([16, 1, 2000]), label: torch.Size([16, 1, 2000])
全连接层输入维度不匹配
输入信号长度若小于2000,经过卷积(Conv1d(1,8,kernel_size=3))和池化(MaxPool1d(2))后,特征长度会小于999,导致x.view(x.size(0), -1)展开的维度与fc1硬编码的8*999不匹配,触发内存访问错误。
修复:预处理时对短信号补零,确保长度统一为2000:# 在截断逻辑后添加补零 if sig0.shape[1] < max_length: pad_length = max_length - sig0.shape[1] sig0 = torch.nn.functional.pad(sig0, (0, pad_length)) if sig1.shape[1] < max_length: pad_length = max_length - sig1.shape[1] sig1 = torch.nn.functional.pad(sig1, (0, pad_length))ContrastiveLoss初始化错误
super(ContrastiveLoss).__init__()缺少self参数,导致Loss类初始化不完整,引发后续内存异常。
修复:改为Python3标准写法super().__init__()或Python2兼容写法super(ContrastiveLoss, self).__init__()。标签维度与类型完全错误
当前返回的label是原始信号(形状[16,1,2000]),但对比损失需要的是表示两个信号是否相似的二元标签(0或1,形状[16])。维度不匹配会触发张量广播,导致内存暴涨甚至SIGSEGV。
修复:在__getitem__中生成正确的二元标签,示例如下:# 示例:随机生成相似/不相似标签(实际需根据业务逻辑,比如按信号类别判断) label = torch.tensor(1 if random.random() > 0.5 else 0, dtype=torch.float32)DataLoader中标签转换冗余
__getitem__返回label时直接转换self.signals[index],但该值是原始信号而非标签,完全不符合需求,需替换为上述二元标签逻辑。
内容的提问来源于stack exchange,提问作者Vincent Kounkou

