【原创】StreamInsight查询系列(二十三)——查询模式之指数平滑法
上篇文章介绍了查询模式中如何进行持续更新,这篇博文将介绍StreamInsight中如何实现指数平滑法。
概念介绍
在我们进行具体实现之前,让我们了解一下什么是指数平滑法?
概念介绍:指数平滑法是一个可以应用于时间序列上的计算方法,最初由Robert G..Brown提出。指数平滑法可以用来生成平滑数据以供展示之用,也可以用于预测未来趋势。它通常应用在金融市场和经济数据中,当然它本质上可以应用于任何不断重复的离散集合中。
我们通常将原始数据序列写作{xt},将指数平滑法的结果序列记为{st},用以估计下一个出现的x值。在t=0时刻,一个比较简单的指数平滑法公式可以写作:
其中α为平滑因子,它的取值范围为0<α<1。
指数平滑法
问题:怎样在StreamInsight中实现指数平滑法?
下面向读者展示的是如何通过用户自定义操作符(UDO,User-defined Operator)对StreamInsight事件流实现指数平滑法。
首先创建包含10个随机浮点数的事件流:
var random = new Random(); var startTime = DateTimeOffset.UtcNow; var xs = (from i in Enumerable.Range(0, 10) select PointEvent.CreateInsert(startTime.AddSeconds(i), random.NextDouble())).ToStream( Application, AdvanceTimeSettings.StrictlyIncreasingStartTime);
我们希望实现一个用户自定义操作符SmoothingOperator,并指定平滑因子,以对原事件序列进行指数平滑处理,如下:
xs.Scan(new SmoothingOperator(0.5));
下面的部分具体介绍SmoothingOperator的实现:
/// <summary> /// 实现指数平滑 /// </summary> [DataContract] public sealed class SmoothingOperator : CepPointStreamOperator<double, double> { [DataMember] readonly double _smoothingFactor; [DataMember] double? _previousValue; public SmoothingOperator(double smoothingFactor) { _smoothingFactor = smoothingFactor; } public override IEnumerable<double> ProcessEvent(PointEvent<double> inputEvent) { // 结果是上一次计算结果和当前输入值的综合 _previousValue = _previousValue.HasValue ? (1.0 - _smoothingFactor) * _previousValue.Value + _smoothingFactor * inputEvent.Payload : inputEvent.Payload; yield return _previousValue.Value; } public override bool IsEmpty { get { return false; } } }
注意必须给SmoothingOperator加上序列化的标志,否则会得到如下异常“Type 'UserQuery+SmoothingOperator' cannot be serialized. Consider marking it with the DataContractAttribute attribute, and marking all of its members you want serialized with the DataMemberAttribute attribute. If the type is a collection, consider marking it with the CollectionDataContractAttribute. See the Microsoft .NET Framework documentation for other supported types.” 。当然这里并非必须使用DataContract,也可以使用其他诸如Xml相关的序列化特性。
运行结果如下:
下一篇将介绍StreamInsight查询模式中如何实现模式匹配。