在现代化生产线上,设备突发故障导致的停机每分钟都可能造成上万元的经济损失。传统基于固定阈值的报警系统存在明显局限性——它只能识别已经发生的异常,而无法预测即将发生的故障。这正是机器学习技术在工业领域大显身手的地方。
我最近在一个汽车零部件制造项目中,成功部署了基于C#和ML.NET的决策树预警系统。这套方案最突出的优势在于:
在评估了Python、Java等多种方案后,我们最终选择这个技术组合基于以下考量:
工业现场的特殊需求:
决策树的独特优势:
mermaid复制graph TD
A[原始数据] --> B[特征工程]
B --> C{决策树训练}
C --> D[规则提取]
D --> E[可解释预警]
实际项目中发现:当向工厂主管展示"当电机温度均值>78.3℃且波动标准差>4.2时触发预警"这样的规则时,他们的接受度明显高于深度学习模型的概率输出。
工业设备数据的特征构造需要领域知识加持,以下是经过验证的有效特征类型:
统计特征(最核心):
趋势特征:
周期性特征:
这是我们项目中使用的特征计算类:
csharp复制public class PlcFeatureCalculator
{
public float CalculateTrendSlope(float[] windowData)
{
// 使用最小二乘法计算趋势斜率
float sumX = 0, sumY = 0, sumXY = 0, sumX2 = 0;
for (int i = 0; i < windowData.Length; i++)
{
sumX += i;
sumY += windowData[i];
sumXY += i * windowData[i];
sumX2 += i * i;
}
return (windowData.Length * sumXY - sumX * sumY) /
(windowData.Length * sumX2 - sumX * sumX);
}
public float CalculatePeriodicity(float[] windowData)
{
// 简化版的周期强度计算
float avg = windowData.Average();
float sumCos = 0, sumSin = 0;
for (int i = 0; i < windowData.Length; i++)
{
float rad = 2 * MathF.PI * i / windowData.Length;
sumCos += (windowData[i] - avg) * MathF.Cos(rad);
sumSin += (windowData[i] - avg) * MathF.Sin(rad);
}
return MathF.Sqrt(sumCos * sumCos + sumSin * sumSin) / windowData.Length;
}
}
工业数据标注是个挑战,我们采用半自动方式:
正常数据采集:
故障数据标注:
csharp复制// 数据标注示例代码
public void LabelHistoricalData(DateTime faultTime)
{
var data = LoadRawData(faultTime.AddMinutes(-60), faultTime);
// 自动标记故障前30分钟为预警期
foreach (var record in data)
{
record.IsFault = (faultTime - record.Timestamp) <= TimeSpan.FromMinutes(30);
record.FaultType = "bearing_wear"; // 从MES获取
}
SaveLabeledData(data);
}
ML.NET提供了两种训练方式,各有适用场景:
AutoML快速入门:
csharp复制var experimentSettings = new BinaryExperimentSettings
{
MaxExperimentTimeInSeconds = 1200, // 20分钟足够
OptimizingMetric = BinaryClassificationMetric.AreaUnderPrecisionRecallCurve,
CacheDirectory = null
};
var experiment = mlContext.Auto().CreateBinaryClassificationExperiment(experimentSettings);
var result = experiment.Execute(trainData, validationData: validData);
手动调优进阶:
csharp复制var pipeline = mlContext.Transforms
.Concatenate("Features", featureColumns)
.Append(mlContext.BinaryClassification.Trainers.FastTree(
new FastTreeBinaryTrainer.Options
{
NumberOfLeaves = 31, // 2^5-1
NumberOfTrees = 100,
MinimumExampleCountPerLeaf = 10,
LearningRate = 0.1,
FeatureFraction = 0.8 // 防止过拟合
}));
// 早停机制
var cvResults = mlContext.BinaryClassification.CrossValidate(
trainData, pipeline, numberOfFolds: 5);
我们采用分层预警策略降低误报:
code复制[PLC数据] -> [1分钟滑动窗口] -> [特征计算] -> [模型预测] -> [预警决策] -> [HMI展示]
-> [规则引擎] -> [PLC写回]
关键实现代码:
csharp复制public class RealTimePredictor
{
private readonly PredictionEngine<PlcFeatures, FaultPrediction> _engine;
private readonly Queue<FaultPrediction> _predictionBuffer = new(3);
public RealTimePredictor(string modelPath)
{
var mlContext = new MLContext();
var model = mlContext.Model.Load(modelPath, out _);
_engine = mlContext.Model.CreatePredictionEngine<PlcFeatures, FaultPrediction>(model);
}
public (bool isFault, float confidence) Predict(PlcFeatures features)
{
var prediction = _engine.Predict(features);
// 缓冲最近3次预测
_predictionBuffer.Enqueue(prediction);
if (_predictionBuffer.Count > 3)
_predictionBuffer.Dequeue();
// 只有连续3次预测为故障才触发
bool consensusFault = _predictionBuffer.Count == 3 &&
_predictionBuffer.All(p => p.IsFault);
return (consensusFault, prediction.Probability);
}
}
在低配工控机上的优化经验:
内存优化:
CPU优化:
IO优化:
csharp复制// 高性能特征计算示例
public unsafe void CalculateFeaturesOptimized(Span<float> window, ref PlcFeatures features)
{
fixed (float* ptr = window)
{
float sum = 0, sumSq = 0;
float min = float.MaxValue, max = float.MinValue;
for (int i = 0; i < window.Length; i++)
{
float val = ptr[i];
sum += val;
sumSq += val * val;
min = Math.Min(min, val);
max = Math.Max(max, val);
}
features.Mean = sum / window.Length;
features.StdDev = MathF.Sqrt((sumSq - sum*sum/window.Length) / (window.Length - 1));
features.Range = max - min;
}
}
我们建立了完整的模型健康度监测体系:
| 指标名称 | 预警阈值 | 检查频率 | 应对措施 |
|---|---|---|---|
| 预测概率漂移 | KS值>0.15 | 每日 | 触发增量训练 |
| 特征分布变化 | PSI>0.25 | 每周 | 检查传感器是否异常 |
| 预警准确率 | F1<0.7 | 每月 | 重新标注数据并全量训练 |
| 推理耗时 | >10ms | 实时 | 优化特征计算代码 |
建立自动化再训练流水线:
csharp复制// 自动化再训练服务
public class ModelRetrainService : BackgroundService
{
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
var stats = await _monitor.GetPerformanceStatsAsync();
if (stats.Psi > 0.25 || stats.F1 < 0.7)
{
var newData = await _dataService.GetRecentLabeledDataAsync();
var retrainedModel = await _trainer.RetrainAsync(newData);
await _validator.ValidateAgainstShadowModel(retrainedModel);
await _deployer.DeployToStagingAsync(retrainedModel);
}
await Task.Delay(TimeSpan.FromHours(6), stoppingToken);
}
}
}
在三个工厂的落地过程中,我们总结了这些实战经验:
问题1:样本不均衡
csharp复制var options = new FastTreeBinaryTrainer.Options
{
// 调整类别权重
PositiveInstanceWeight = 10f,
NegativeInstanceWeight = 1f
};
问题2:概念漂移
csharp复制public float AdaptiveNormalize(float value, string sensorId)
{
var stats = _sensorStats[sensorId];
return (value - stats.MovingAverage) / stats.MovingStdDev;
}
问题3:误报干扰生产
text复制Level1: 概率>0.7 → 记录日志
Level2: 连续2次>0.8 → 通知班长
Level3: 连续3次>0.9 → 自动降速
这套系统在某电机生产线运行12个月后,实现了:
对于想要复现的开发者,建议从最简单的振动信号监测开始,逐步扩展到多传感器融合预警。关键是要与设备维护人员紧密合作,将领域知识融入特征工程环节。