基于 SCCAN 模型的序列数据分类实战:从一维卷积到结果分析

引言

在序列数据分类任务中,一维卷积神经网络(1D-CNN)因其对局部特征的高效提取能力而被广泛应用。本文介绍一种简单高效的序列分类模型 SCCAN(Simple Convolutional Classifier for Attribute Networks),基于 PyTorch 实现完整的训练、评估与结果保存流程,适用于时间序列、特征序列等数据的多分类任务。

对应代码和数据链接:https://download.csdn.net/download/lestatlu/90691726

一、SCCAN 模型架构解析

1. 模型定义

class SCCAN(nn.Module):
    def __init__(self, input_dim, num_classes):
        super(SCCAN, self).__init__()
        self.conv1 = nn.Conv1d(1, 16, kernel_size=3, padding=1)
        self.conv2 = nn.Conv1d(16, 32, kernel_size=3, padding=1)
        self.conv3 = nn.Conv1d(32, 64, kernel_size=3, padding=1)
        self.conv4 = nn.Conv1d(64, 128, kernel_size=3, padding=1)
        self.conv5 = nn.Conv1d(128, 256, kernel_size=3, padding=1)
        self.pool = nn.MaxPool1d(2)
        self.global_avg_pool = nn.AdaptiveAvgPool1d(1)
        self.fc1 = nn.Linear(256, 256)
        self.fc2 = nn.Linear(256, num_classes)
        self.dropout = nn.Dropout(0.5)

    def forward(self, x):
        x = F.relu(self.conv1(x))
        x = self.pool(F.relu(self.conv2(x)))
        x = self.pool(F.relu(self.conv3(x)))
        x = self.pool(F.relu(self.conv4(x)))
        x = F.relu(self.conv5(x))
        x = self.global_avg_pool(x).squeeze(-1)  # 全局平均池化
        x = F.relu(self.fc1(x))
        x = self.dropout(x)
        x = self.fc2(x)
        return x

2. 核心组件

  • 一维卷积层:5 层卷积逐步提取特征,通道数从 16 到 256 逐层翻倍,捕捉多尺度局部模式
  • 最大池化:每次池化后序列长度减半,降低维度并增强平移不变性
  • 全局平均池化:替代全连接层前的展平操作,保留全局特征并减少参数量
  • Dropout 层:在全连接层前加入 50% dropout,防止过拟合

二、数据加载与预处理

1. 数据加载(替换为你的路径)

# 加载全局数据(请将路径替换为你的数据存储路径)
X_all_samples = np.load(r'your_path\X_all_samples.npy')
y_all_samples = np.load(r'your_path\y_all_samples.npy')
train_indices = np.load(r'your_path\global_train_indices.npy')
test_indices = np.load(r'your_path\global_test_indices.npy')

# 划分训练集与测试集
X_train = X_all_samples[train_indices]
y_train = y_all_samples[train_indices]
X_test = X_all_samples[test_indices]
y_test = y_all_samples[test_indices]

# 确定类别数
num_classes = np.max(y_train) + 1

2. 数据预处理

# 转换为Tensor并添加通道维度(1D-CNN输入需为[batch, channels, sequence_length])
x_train = torch.tensor(X_train[:, np.newaxis, :], dtype=torch.float32, device=device)
x_test = torch.tensor(X_test[:, np.newaxis, :], dtype=torch.float32, device=device)
y_train = torch.tensor(y_train, dtype=torch.long, device=device)
y_test = torch.tensor(y_test, dtype=torch.long, device=device)

# 创建数据加载器(支持批量训练)
train_loader = DataLoader(TensorDataset(x_train, y_train), batch_size=32, shuffle=True)
test_loader = DataLoader(TensorDataset(x_test, y_test), batch_size=32, shuffle=False)

  • 维度调整:通过np.newaxis添加通道维度(从 [N, D] 到 [N, 1, D]),适配一维卷积输入
  • 数据加载器:使用DataLoader实现批量处理,训练集随机打乱顺序提升泛化性

三、训练流程与关键配置

1. 训练参数设置

n_epochs = 1000          # 训练轮次
lr = 0.001                # 学习率
batch_size = 32           # 批量大小
device = 'cuda' if torch.cuda.is_available() else 'cpu'  # 自动选择设备

2. 训练循环

model = SCCAN(input_dim=x_train.shape[2], num_classes=num_classes).to(device)
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=lr)

for epoch in range(n_epochs):
    model.train()
    running_loss = 0.0
    for inputs, labels in train_loader:
        optimizer.zero_grad()
        outputs = model(inputs)
        loss = criterion(outputs, labels)
        loss.backward()
        optimizer.step()
        running_loss += loss.item()
    
    # 每100轮打印平均损失
    if (epoch + 1) % 100 == 0:
        avg_loss = running_loss / len(train_loader)
        print(f"Epoch [{epoch+1}/{n_epochs}], Loss: {avg_loss:.4f}")

  • 优化器:使用 Adam 优化器,自适应调整学习率
  • 损失函数:交叉熵损失(适用于多分类任务)
  • 梯度下降:批量梯度下降(BGD),通过DataLoader实现 mini-batch 训练

四、结果评估与保存

1. 评估指标计算

from sklearn.metrics import accuracy_score, recall_score, precision_score, cohen_kappa_score

def evaluate_to_dataframe(y_true, y_pred, method_name):
    oa = accuracy_score(y_true, y_pred) * 100          # 总体精度
    aa = recall_score(y_true, y_pred, average='macro') * 100  # 宏平均召回率
    pa = precision_score(y_true, y_pred, average=None) * 100  # 各类别精度
    kappa = cohen_kappa_score(y_true, y_pred)          # Kappa系数
    
    metrics_dict = {
        'Method': method_name,
        'OA (%)': oa,
        'AA (%)': aa,
        'Kappa': kappa,
    }
    for i, precision in enumerate(pa):
        metrics_dict[f'PA_Class_{i} (%)'] = round(precision, 2)
    
    print(f"\n[{method_name}] Metrics:")
    print(f"OA: {oa:.2f}%, AA: {aa:.2f}%, Kappa: {kappa:.4f}")
    print(classification_report(y_true, y_pred))
    return metrics_dict

2. 测试集评估与保存

model.eval()
y_true, y_pred = [], []
with torch.no_grad():
    for inputs, labels in test_loader:
        outputs = model(inputs)
        _, predicted = torch.max(outputs, 1)
        y_true.extend(labels.cpu().numpy())
        y_pred.extend(predicted.cpu().numpy())

test_metrics = evaluate_to_dataframe(y_true, y_pred, "SCCAN")
metrics_df = pd.DataFrame([test_metrics])
metrics_df.to_excel('SCCAN.xlsx', index=False, float_format="%.2f")
print("Test results saved to 'SCCAN.xlsx'.")
  • 评估指标
    • OA:所有类别分类正确的比例,反映整体精度
    • AA:各类别召回率的平均值,平衡类别不平衡问题
    • Kappa:考虑随机分类的校正精度,值越高模型越可靠
  • 结果保存:生成包含所有指标的 Excel 表格,便于对比分析

五、完整代码与运行说明

1. 完整代码(关键部分)

# 设备选择
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
print(f"Using device: {device}")
start = time.time()

# 数据加载与预处理(见前文)
# 模型定义(见前文)
# 训练循环(见前文)
# 结果评估与保存(见前文)

# 计时输出
end = time.time()
print(f"Total training time: {end - start:.2f} seconds")

2. 依赖安装

pip install torch pandas scikit-learn numpy

3. 运行步骤

  1. 将数据文件(.npy 格式)放入your_path目录
  2. 确保 PyTorch 环境配置正确(CPU/GPU 均可)
  3. 运行代码,训练完成后生成SCCAN.xlsx

六、模型优化与适用场景

1. 调优建议

参数 作用 建议范围
batch_size 批量大小 16/32/64
n_epochs 训练轮次 500-2000
dropout 随机失活率 0.3-0.7
kernel_size 卷积核大小 3/5/7

2. 适用场景

  • 时间序列分类:如传感器数据、金融时序
  • 特征序列分类:高维特征的序列输入(如文本嵌入、光谱特征)
  • 轻量模型需求:相比 Transformer,参数量少,适合资源有限环境

七、总结

本文通过 SCCAN 模型演示了一维卷积神经网络在序列分类中的完整应用流程,重点包括:

  1. 数据预处理中的维度适配与批量加载
  2. 多层卷积网络的特征提取策略
  3. 多指标评估与结果可视化保存

SCCAN 模型通过简单的卷积 - 池化 - 全连接结构,在保证精度的同时保持高效性。实际应用中,可通过调整卷积层数、通道数或添加注意力机制进一步优化性能。完整代码支持一键运行,适用于快速验证序列分类任务的基线模型。

结果展示:

对应代码和数据链接:https://download.csdn.net/download/lestatlu/90691726

请大家多多关注

你可能感兴趣的:(分类,人工智能,数据挖掘)