分析趋势并发现异常行为

时间:2012-11-29 13:51:02

标签: python mysql database analytics

我正在创建一个用于记录传感器数据的系统。 (只是一系列数字)

我希望能够将系统置于“学习”模式几天,这样它就可以看到它的“正常”操作值是什么,并且一旦它超出了这个过去的任何偏离这种行为可以标记某个点。数据全部存储在MySQL数据库中。

欢迎任何有关如何实现这一目标的建议,以及有关该主题的进一步阅读的地点。

我最好使用python来完成这项任务。

在白天访问和使用的温控区域内,数据温度和湿度值均为5分钟。这意味着它在使用和温度变化时会有波动。但是需要检测与冷却或加热系统失效相关的任何不同之处

2 个答案:

答案 0 :(得分:1)

基本上你应该看的是density estimation:确定一些变量如何表现的模型的任务,以便你可以寻找与它的偏差。

这是一些非常简单的示例代码。我假设温度和湿度在其未转换的尺度上具有独立的正态分布:

import numpy as np
from matplotlib.mlab import normpdf
from itertools import izip

class TempAndHumidityModel(object):
    def __init__(self):
        self.tempMu=0
        self.tempSigma=1
        self.humidityMu=0
        self.humiditySigma=1

    def setParams(self, tempMeasurements, humidityMeasurements, quantile):
        self.tempMu=np.mean(tempMeasurements)
        self.tempSigma=np.std(tempMeasurements)
        self.humidityMu=np.mean(humidityMeasurements)
        self.humiditySigma=np.std(humidityMeasurements)

        if not 0 < quantile <= 1:
            raise ValueError("Quantile for threshold must be between 0 and 1")

        self._thresholdDensity(quantile, tempMeasurements, humidityMeasurements)

    def _thresholdDensity(self, quantile, tempMeasurements, humidityMeasurements):
        tempDensities = np.apply_along_axis(
            lambda x: normpdf(x, self.tempMu, self.tempSigma),0,tempMeasurements)
        humidityDensities = np.apply_along_axis(
            lambda x: normpdf(x, self.humidityMu, self.humiditySigma),0,humidityMeasurements)

        densities = sorted(tempDensities * humidityDensities, reverse=True)
        #Here comes the massive oversimplification: just choose the
        #density value at the quantile*length position, and use this as the threshold
        self.threshold = densities[int(np.round(quantile*len(densities)))]

    def probOfObservation(self, temp, humidity):
        return normpdf(temp, self.tempMu, self.tempSigma) * \
               normpdf(humidity, self.humidityMu, self.humiditySigma)

    def isNormalMeasurement(self, temp, humidity):
        return self.probOfObservation(temp, humidity) > self.threshold

if __name__ == '__main__':
    #Create some simulated data
    temps = np.random.randn(100)*10 + 50
    humidities = np.random.randn(100)*2 + 10

    thm = TempAndHumidityModel()
    #going to hard code in the 95% threshold
    thm.setParams(temps, humidities, 0.95) 

    #Create some new data from same dist and see how many false positives
    newTemps = np.random.randn(100)*10 + 50
    newHumidities = np.random.randn(100)*2 + 10

    numFalseAlarms = sum(~thm.isNormalMeasurement(t,h) for t,h in izip(newTemps,newHumidities))
    print '{} false alarms!'.format(numFalseAlarms)

    #Now create some abnormal data: mean temp drops to 20
    lowTemps = np.random.randn(100)*10 + 20
    normalHumidities = np.random.randn(100)*2 + 10

    numDetections = sum(~thm.isNormalMeasurement(t,h) for t,h in izip(lowTemps,normalHumidities))
    print '{} abnormal measurements flagged'.format(numDetections)

示例输出:

>> 3 false alarms!
>> 77 abnormal measurements flagged

现在,我不知道正常假设是否适合您的数据(您可能希望将数据转换为不同的比例,以便它);假设温度和湿度之间的独立性可能非常不准确;我用来找到对应于所请求的分布分位数的密度值的技巧应该被使用分布的逆CDF的东西代替。但是,这应该会让你了解该怎么做。

另外请注意,有许多好的非参数密度估算器:kernel density estimators立即浮现在脑海中。如果您的数据看起来不像任何标准分发,这些可能更合适。

答案 1 :(得分:0)

看起来您正在尝试执行anomaly detection,但您对数据的描述含糊不清。一般来说,您应该首先尝试定义/约束它意味着您的数据是“正常”的。

  1. 每个传感器都有不同的“正常”吗?
  2. 传感器测量是否某种程度上取决于之前的测量?
  3. “正常”会在一天内发生变化吗?
  4. 来自传感器的“正常”测量值是否可以用统计模型表征(例如,数据是高斯还是对数正态)?
  5. 一旦您回答了这些类型的问题,您就可以使用数据库中的一批数据训练分类器或异常检测器,并使用结果来评估未来的日志输出。如果机器学习算法适用于您的数据,您可以考虑使用scikit-learn。对于统计模型,您可以使用SciPystats子包。当然,对于python中的任何数值数据操作,NumPy都是你的朋友。