简介:本资源面向计算机、人工智能、自动化、通信工程等专业的在校学生与教师,以及从事轨道交通信号故障诊断的工程人员,提供一套基于LSTM多时间序列特征提取的道岔故障诊断完整实现方案。项目以Python为开发语言,围绕道岔动作电流等多维时序信号展开特征提取与故障分类建模,适合作为毕业设计、课程设计、学科竞赛或项目初期立项的参考范例,也便于具备一定基础的学习者在此基础上二次修改与功能扩展。压缩包共9个文件,包含7个py源码文件、1个md说明文档和1个docx实验报告,整体约872KB,源码覆盖特征提取、LSTM模型构建、多线程处理与测试脚本等模块,实验报告则系统梳理了方法原理与实验流程。目前已有202人学习关注。下载后可先阅读README了解目录结构与运行方式,借助源码与报告快速复现实验、理解建模思路,并掌握时序特征工程与深度学习故障诊断的落地方法。
1. 道岔故障诊断项目:从多时间序列到 LSTM 的完整落地路径
道岔是铁路信号系统里最容易出故障的环节之一,动作电流曲线一旦出现异常,轻则晚点,重则影响行车安全。传统做法靠人工看曲线、比对模板,经验门槛高且难以复用。这个项目用 LSTM 对道岔动作电流的多时间序列做特征提取和故障分类,把「看曲线」变成「跑模型」,适合做人工智能、通信工程、自动化方向的课程设计或毕设,也适合想入门时序分类的开发者拿来练手。源码包里包含特征工程脚本、LSTM 模型定义、训练与测试入口,以及一份完整的实验报告文档,拿到手就能跑通一条从原始数据到分类结果的链路。
2. 项目结构与技术栈:先看清每个文件在干什么
2.1 目录文件清单与职责划分
拿到railway_fault_detect-master这个包,第一件事不是急着python xxx.py,而是把文件按职责分个类。这个项目的文件命名比较直白,但有几个脚本名字相近,容易点错。下面是我整理后的职责表:
| 文件名 | 职责 | 是否入口 |
|---|---|---|
features.py | 多时间序列特征提取,把原始电流曲线转成特征矩阵 | 否,被调用 |
LSTM.py | LSTM 网络结构定义与训练/预测逻辑 | 否,被调用 |
xiecheng.py | 训练主流程串联,加载特征、切分数据、启动训练 | 是 |
test.py | 模型评估与测试集推理 | 是 |
pythontest.py/Python_test.py | 环境自检与依赖验证脚本 | 是 |
thread.py | 多线程数据预处理或批量推理辅助 | 否 |
基于LSTM多时间序列特征提取的道岔故障诊断方法new.docx | 实验报告,含方法论述与结果分析 | 否 |
README.md | 运行说明与依赖列表 | 否 |
注意:
pythontest.py和Python_test.py在部分文件系统下会被视为不同文件,但功能高度重叠,跑通一个即可,不要两个都执行,否则可能重复占用端口或重复写日志。
2.2 技术栈与依赖环境
项目是纯 Python 技术栈,核心依赖集中在深度学习与数据处理两块。按这个场景下合格开发最常用的组合,环境大致如下:
# 建议 Python 3.8 ~ 3.10,过高版本部分旧版 API 会有兼容提示 pip install numpy pandas matplotlib scikit-learn pip install torch # 或 tensorflow,视 LSTM.py 实际导入而定numpy和pandas负责时间序列的切片、对齐和归一化;scikit-learn用于标签编码、混淆矩阵和分类报告;matplotlib画训练损失曲线和混淆矩阵图;深度学习框架承担 LSTM 层的构建。我一般会先建一个干净的虚拟环境,避免和本机已有的框架版本打架:
python -m venv venv # Linux / macOS source venv/bin/activate # Windows venv\Scripts\activate虚拟环境激活后再装依赖,这样即使框架版本冲突,删掉venv重来就行,不会污染全局环境。这一步看着简单,但后面模型跑不起来时,能省掉大量「到底是代码问题还是环境问题」的排查时间。
2.3 数据流走向:从原始曲线到分类标签
理解这个项目的数据流,比死记函数名有用得多。整体链路是:原始道岔动作电流序列 → 特征提取 → 序列样本构造 → LSTM 输入 → 分类输出。features.py负责前半段,LSTM.py负责后半段,xiecheng.py把两段接起来。
常见做法是先把每条动作曲线按时间窗口切分,再对每个窗口提取统计特征(均值、方差、峰值、上升时间等),拼成固定长度的特征向量。LSTM 需要的输入形状通常是(样本数, 时间步, 特征数),所以特征矩阵还要做一次 reshape。这个形状转换是新手最容易翻车的地方,后面避坑章节会专门讲。
3. 核心模块拆解:特征提取与 LSTM 模型怎么配合
3.1 features.py:多时间序列特征提取
这个脚本是整个项目的地基。道岔动作电流是一条随时间变化的曲线,直接丢给 LSTM 也能跑,但收敛慢、易过拟合。先做特征提取,相当于把「原始波形」翻译成「模型能读懂的语言」。下面是一段典型的特征提取逻辑:
import numpy as np import pandas as pd def extract_features(series, window_size=50, step=10): """ 对单条时间序列做滑窗特征提取 series: 一维电流序列 window_size: 每个窗口的时间步长度 step: 滑窗步长,控制样本重叠程度 """ features = [] for start in range(0, len(series) - window_size + 1, step): window = series[start:start + window_size] feat = { "mean": np.mean(window), # 均值,反映整体电流水平 "std": np.std(window), # 标准差,反映波动程度 "max": np.max(window), # 峰值,异常时通常偏高 "min": np.min(window), # 谷值 "ptp": np.ptp(window), # 峰谷差 "energy": np.sum(window ** 2), # 能量,对突变敏感 } features.append(feat) return pd.DataFrame(features)逻辑说明:滑窗把长序列切成多个短片段,每个片段提取 6 个统计量。window_size决定单个样本覆盖多长时间范围,太小则特征不稳定,太大则样本数不够;step控制重叠度,步长小于窗口长度时样本之间有重叠,能增加训练数据量,但要注意别把同一段曲线重复喂太多次导致过拟合。参数没有绝对标准,我一般先用window_size=50, step=10跑一版,看验证集准确率再微调。
3.2 LSTM.py:网络结构与训练循环
特征提取完,接下来是模型。LSTM 适合处理这种带时间依赖的序列,因为它能通过门控机制记住长距离的模式。下面是一个结构清晰、便于修改的 LSTM 定义:
import torch import torch.nn as nn class FaultLSTM(nn.Module): def __init__(self, input_size, hidden_size=64, num_layers=2, num_classes=4): super(FaultLSTM, self).__init__() self.lstm = nn.LSTM( input_size=input_size, # 每个时间步的特征数 hidden_size=hidden_size, # 隐藏层维度,越大容量越强 num_layers=num_layers, # 堆叠层数,2 层通常够用 batch_first=True, # 输入形状 (batch, seq, feature) dropout=0.3 # 防过拟合 ) self.fc = nn.Linear(hidden_size, num_classes) # 分类头 def forward(self, x): out, _ = self.lstm(x) # out: (batch, seq, hidden) out = out[:, -1, :] # 取最后一个时间步的输出 return self.fc(out)逻辑说明:input_size要和特征提取输出的特征数对齐,比如上面提取了 6 个统计量,这里就填 6。hidden_size和num_layers是容量参数,数据量小的时候调大反而容易过拟合。out[:, -1, :]取最后一个时间步,是因为分类结果依赖整段序列的累积信息。如果换成取平均池化,也是一种常见做法,可以都试试对比效果。
训练循环部分通常包含损失函数、优化器和早停逻辑:
criterion = nn.CrossEntropyLoss() optimizer = torch.optim.Adam(model.parameters(), lr=1e-3) for epoch in range(epochs): model.train() for xb, yb in train_loader: optimizer.zero_grad() pred = model(xb) loss = criterion(pred, yb) loss.backward() optimizer.step()lr=1e-3是 Adam 的常用起点,损失不下降就降到1e-4;epochs不要设太大,配合验证集早停,避免训练集准确率很高但测试集一塌糊涂。
3.3 xiecheng.py:训练主流程串联
这个脚本是入口,负责把前面两块拼起来。典型流程是:读数据 → 调features.py提特征 → 构造序列样本 → 划分训练测试集 → 实例化模型 → 训练 → 保存权重。
from features import extract_features from LSTM import FaultLSTM import numpy as np import torch # 1. 读取原始序列并提取特征 raw_series = np.load("data/switch_current.npy") feat_df = extract_features(raw_series) # 2. 构造 LSTM 需要的三维输入 (样本, 时间步, 特征) # 这里假设每 10 个连续特征向量组成一个序列样本 seq_len = 10 X, y = [], [] values = feat_df.values for i in range(len(values) - seq_len): X.append(values[i:i + seq_len]) y.append(labels[i + seq_len]) # 标签与序列末端对齐 X = torch.tensor(np.array(X), dtype=torch.float32) y = torch.tensor(np.array(y), dtype=torch.long)逻辑说明:seq_len决定 LSTM 展开的时间步数,太短学不到长依赖,太长则计算量上升且容易梯度消失。标签对齐方式要和业务含义一致——用序列末端对应的故障类型作为整段样本的标签,是时序分类里最常见的做法。如果标签对不齐,模型会学到错误映射,表现为训练准确率虚高但实际预测全错。
4. 运行与验证:从零跑通一条完整链路
4.1 环境准备与依赖安装
先把包解压到不含中文和空格的路径下,比如D:\projects\railway_fault_detect。路径带中文在某些框架加载数据时会报编码错误,这是血泪经验。然后按 2.2 节建虚拟环境、装依赖。装完后跑一下自检脚本:
python pythontest.py这个脚本一般会打印 Python 版本、各依赖库版本,以及一个简单的张量运算测试。如果这里就报错,先解决环境问题,不要往下走。
4.2 训练与测试执行顺序
确认环境没问题后,按下面顺序执行:
# 第一步:启动训练,生成模型权重 python xiecheng.py # 第二步:用测试集评估模型 python test.pyxiecheng.py跑完后通常会生成一个权重文件(如model.pth)和训练日志。test.py加载权重,在测试集上输出准确率、混淆矩阵等指标。如果test.py报找不到权重文件,检查xiecheng.py是否真的跑完,以及权重保存路径和加载路径是否一致。
4.3 结果怎么看:指标与曲线
评估结果一般看三个东西:准确率、混淆矩阵、损失曲线。准确率是整体指标,但类别不均衡时会有误导;混淆矩阵能看出哪类故障容易被误判成哪类,这对调特征特别有用;损失曲线看训练是否收敛、有没有过拟合。实验报告文档里通常有这些图和分析,可以对照自己的运行结果,确认复现是否一致。
提示:如果准确率和报告里差距很大,先检查数据划分的随机种子是否一致,再检查特征提取参数是否被改过。这两处是复现差异的主要来源。
5. 避坑与常见问题:那些让我反复调试的细节
5.1 输入形状不匹配
现象:模型 forward 时报维度错误,提示期望 3 维输入却收到 2 维。原因:特征提取输出的是二维表格,直接喂给 LSTM 少了时间步维度。解决:用滑窗或 reshape 把(样本, 特征)变成(样本, 时间步, 特征),并确认batch_first=True时第一维是 batch。
5.2 标签与序列错位
现象:训练损失正常下降,但测试准确率接近随机猜测。原因:构造序列样本时标签索引偏移了一位,模型学到的是「前一段序列对应后一段标签」。解决:明确标签对齐规则,用序列末端或序列起始对齐,全流程统一,并在小批量数据上手动核对几条样本。
5.3 过拟合导致验证集崩盘
现象:训练集准确率 99%,验证集只有 60% 上下。原因:数据量小、模型容量大、训练轮数过多。解决:加 dropout、减小hidden_size、加早停、做数据增强(如加噪声、时间缩放)。我一般先降模型容量,再考虑增强数据。
5.4 路径与编码问题
现象:读数据时报FileNotFoundError或编码错误。原因:路径含中文、空格,或 CSV 编码不是 UTF-8。解决:项目放到纯英文路径下,读 CSV 时显式指定encoding='utf-8'或gbk,逐个试。
5.5 框架版本不兼容
现象:LSTM.py导入报错,提示某个 API 不存在。原因:代码基于旧版框架写的,本机装了新版。解决:按 README 或实验报告里的版本装对应框架,或把旧 API 替换为新版等价写法。不要盲目升级,先跑通再考虑迁移。
6. 二次开发与改造:把项目变成你自己的
跑通之后,真正有价值的是改。这个项目的结构比较清晰,改造点主要集中在三处:特征、模型、数据。
先说特征改造。features.py里的统计特征是最容易替换的。你可以加入频域特征,比如对每个窗口做 FFT 取主频幅值;也可以加入差分特征,反映电流变化率。改完后记得同步修改LSTM.py里的input_size,否则第一层就会报维度错误。我一般会在特征函数里加一个return feature_names的选项,方便打印特征顺序,排查对齐问题。
再说模型改造。把 LSTM 换成 GRU 或双向 LSTM 是最省事的尝试,只需改nn.LSTM为nn.GRU或加bidirectional=True,注意双向时hidden_size拼接后维度翻倍,全连接层输入要相应调整。如果想做注意力机制,可以在 LSTM 输出后加一个简单的注意力池化,替代取最后一个时间步的做法。下面是一个可参考的注意力池化片段:
class AttentionPool(nn.Module): def __init__(self, hidden_size): super().__init__() self.attn = nn.Linear(hidden_size, 1) def forward(self, lstm_out): # lstm_out: (batch, seq, hidden) weights = torch.softmax(self.attn(lstm_out), dim=1) return torch.sum(weights * lstm_out, dim=1)逻辑说明:attn给每个时间步打一个分数,softmax 归一化成权重,再对 LSTM 输出加权求和。这样模型能自动决定哪些时间步更重要,比固定取最后一步更灵活。改完后同样要检查全连接层输入维度。
最后说数据改造。如果你想用自己的数据,关键是保持输入格式一致:一条样本是一个(时间步, 特征数)的二维数组,标签是整数类别。建议先写一个小脚本,把你的数据转成和项目一致的.npy或 CSV 格式,再替换xiecheng.py里的读取路径。改造过程中,每改一处就跑一次小规模训练,确认损失能下降,再继续下一步。一次性改太多地方,出问题很难定位。
验证改造是否有效,我习惯用固定随机种子跑三次,取平均准确率对比基线。单次结果波动大,不能作为判断依据。另外,混淆矩阵比准确率更能反映改造是否真的解决了某类误判。
从那以后我每次改这类时序项目,都强制先跑通原始版本、记录基线指标,再动任何一行代码。希望帮到你。
本文还有配套的精品资源,点击获取