时间序列模式识别

通过处理时间序列图,我想检测看起来类似于这样的模式:

在这里输入图像说明

以一个采样时间序列为例,我希望能够检测到这里标记的模式:

在这里输入图像说明

什么样的AIalgorithm(我假设marchine学习技术)我需要用来实现这个? 有没有我可以使用的库(以C / C ++)?

下面是一个分区ecg数据的小型项目的示例结果。

在这里输入图像说明

我的方法是“切换自回归HMM”(谷歌,如果你没有听说过),其中每个数据点是从以前的数据点预测使用贝叶斯回归模型。 我创build了81个隐藏状态:在每个节拍之间捕获数据的垃圾状态以及对应于心跳模式内的不同位置的80个分离的隐藏状态。 模式80状态是直接从二次采样的单拍模式构build的,并且具有两个转换 – 自我转换和转换到模式中的下一个状态。 模式中的最终状态转变为自身或垃圾状态。

我用维特比训练训练模型,只更新回归参数。

大多数情况下结果是足够的。 一个类似的结构条件随机场可能会performance更好,但是如果你还没有标记数据的话,训练一个CRF需要手动标记数据集中的模式。

编辑:

下面是一些python代码示例 – 它不是完美的,但它提供了一般的方法。 它实施EM而不是维特比训练,可能稍微更稳定。 ecg数据集来自~eamonn/discords/ECG_data.zip

import numpy as np import numpy.random as rnd import matplotlib.pyplot as plt import scipy.linalg as lin import re data=np.array(map(lambda l: map(float,filter(lambda x: len(x)>0,re.split('\\s+',l))),open('chfdb_chf01_275.txt'))).T dK=230 pattern=data[1,:dK] data=data[1,dK:] def create_mats(dat): ''' create A - an initial transition matrix pA - pseudocounts for A w - emission distribution regression weights K - number of hidden states ''' step=5 #adjust this to change the granularity of the pattern eps=.1 dat=dat[::step] K=len(dat)+1 A=np.zeros( (K,K) ) A[0,1]=1. pA=np.zeros( (K,K) ) pA[0,1]=1. for i in xrange(1,K-1): A[i,i]=(step-1.+eps)/(step+2*eps) A[i,i+1]=(1.+eps)/(step+2*eps) pA[i,i]=1. pA[i,i+1]=1. A[-1,-1]=(step-1.+eps)/(step+2*eps) A[-1,1]=(1.+eps)/(step+2*eps) pA[-1,-1]=1. pA[-1,1]=1. w=np.ones( (K,2) , dtype=np.float) w[0,1]=dat[0] w[1:-1,1]=(dat[:-1]-dat[1:])/step w[-1,1]=(dat[0]-dat[-1])/step return A,pA,w,K #initialize stuff A,pA,w,K=create_mats(pattern) eta=10. #precision parameter for the autoregressive portion of the model lam=.1 #precision parameter for the weights prior N=1 #number of sequences M=2 #number of dimensions - the second variable is for the bias term T=len(data) #length of sequences x=np.ones( (T+1,M) ) # sequence data (just one sequence) x[0,1]=1 x[1:,0]=data #emissions e=np.zeros( (T,K) ) #residuals v=np.zeros( (T,K) ) #store the forward and backward recurrences f=np.zeros( (T+1,K) ) fls=np.zeros( (T+1) ) f[0,0]=1 b=np.zeros( (T+1,K) ) bls=np.zeros( (T+1) ) b[-1,1:]=1./(K-1) #hidden states z=np.zeros( (T+1),dtype=np.int ) #expected hidden states ex_k=np.zeros( (T,K) ) # expected pairs of hidden states ex_kk=np.zeros( (K,K) ) nkk=np.zeros( (K,K) ) def fwd(xn): global f,e for t in xrange(T): f[t+1,:]=np.dot(f[t,:],A)*e[t,:] sm=np.sum(f[t+1,:]) fls[t+1]=fls[t]+np.log(sm) f[t+1,:]/=sm assert f[t+1,0]==0 def bck(xn): global b,e for t in xrange(T-1,-1,-1): b[t,:]=np.dot(A,b[t+1,:]*e[t,:]) sm=np.sum(b[t,:]) bls[t]=bls[t+1]+np.log(sm) b[t,:]/=sm def em_step(xn): global A,w,eta global f,b,e,v global ex_k,ex_kk,nkk x=xn[:-1] #current data vectors y=xn[1:,:1] #next data vectors predicted from current #compute residuals v=np.dot(x,wT) # (N,K) <- (N,1) (N,K) v-=y e=np.exp(-eta/2*v**2,e) fwd(xn) bck(xn) # compute expected hidden states for t in xrange(len(e)): ex_k[t,:]=f[t+1,:]*b[t+1,:] ex_k[t,:]/=np.sum(ex_k[t,:]) # compute expected pairs of hidden states for t in xrange(len(f)-1): ex_kk=A*f[t,:][:,np.newaxis]*e[t,:]*b[t+1,:] ex_kk/=np.sum(ex_kk) nkk+=ex_kk # max w/ respect to transition probabilities A=pA+nkk A/=np.sum(A,1)[:,np.newaxis] # solve the weighted regression problem for emissions weights # x and y are from above for k in xrange(K): ex=ex_k[:,k][:,np.newaxis] dx=np.dot(xT,ex*x) dy=np.dot(xT,ex*y) dy.shape=(2) w[k,:]=lin.solve(dx+lam*np.eye(x.shape[1]), dy) #return the probability of the sequence (computed by the forward algorithm) return fls[-1] if __name__=='__main__': #run the em algorithm for i in xrange(20): print em_step(x) #get rough boundaries by taking the maximum expected hidden state for each position r=np.arange(len(ex_k))[np.argmax(ex_k,1)<3] #plot plt.plot(range(T),x[1:,0]) yr=[np.min(x[:,0]),np.max(x[:,0])] for i in r: plt.plot([i,i],yr,'-r') plt.show() 

为什么不使用简单的匹配filter? 或者它的一般统计对应称为互相关。 给定一个已知的模式x(t)和一个含有在a,b,… z中移动的模式的噪声复合时间序列y(t) = x(ta) + x(tb) +...+ x(tz) + n(t). x和y之间的互相关函数应该在a,b,…,z中给出峰值

Weka是机器学习软件的一个强大的集合,并且支持一些时间序列分析工具,但是我对这个领域不够了解,推荐一个最好的方法。 但是,这是基于Java的; 你可以从C / C ++调用Java代码而不用大惊小怪。

时间序列操纵包主要针对股票市场。 我在评论中build议克罗诺斯 ; 我不知道如何用它进行模式识别,除了显而易见的:任何长度系列的好模型都应该能够预测,在距离最后一个小凹点一定距离处的小颠簸之后,会出现大的颠簸。 也就是说,你的系列具有自相似性,Cronos使用的模型是为了模拟而devise的。

如果你不介意C#,你应该从HCIL的人那里请求一个版本的TimeSearcher2 – 对于这个系统,模式识别就是绘制一个模式的样子,然后检查你的模型是否足够普遍以捕获大多数实例低假阳性率。 可能是最方便用户使用的方法; 所有其他人都需要相当的背景统计或模式识别策略。

我不确定哪个包最适合这个。 我在大学的某个地方做了类似的事情,我尝试在xy轴上自动检测一些类似的形状,用于一些不同的graphics。 你可以做如下的事情。

类标签如:

  • 没课
  • 地区的开始
  • 地区中部
  • 区域的末端

function如下:

  1. 窗口中每个周围点的相对y轴相对和绝对差为11点宽
  2. 像平均差异的function
  3. 点之前相对差,点之后

如果这是您的select,我正在使用深度学习。 这是在Java, Deeplearning4j完成的 。 我正在试验LSTM。 我尝试了1个隐藏层和2个隐藏层来处理时间序列。

 return new NeuralNetConfiguration.Builder() .seed(HyperParameter.seed) .iterations(HyperParameter.nItr) .miniBatch(false) .learningRate(HyperParameter.learningRate) .biasInit(0) .weightInit(WeightInit.XAVIER) .momentum(HyperParameter.momentum) .optimizationAlgo( OptimizationAlgorithm.STOCHASTIC_GRADIENT_DESCENT // RMSE: ???? ) .regularization(true) .updater(Updater.RMSPROP) // NESTEROVS // .l2(0.001) .list() .layer(0, new GravesLSTM.Builder().nIn(HyperParameter.numInputs).nOut(HyperParameter.nHNodes_1).activation("tanh").build()) .layer(1, new GravesLSTM.Builder().nIn(HyperParameter.nHNodes_1).nOut(HyperParameter.nHNodes_2).dropOut(HyperParameter.dropOut).activation("tanh").build()) .layer(2, new GravesLSTM.Builder().nIn(HyperParameter.nHNodes_2).nOut(HyperParameter.nHNodes_2).dropOut(HyperParameter.dropOut).activation("tanh").build()) .layer(3, // "identity" make regression output new RnnOutputLayer.Builder(LossFunctions.LossFunction.MSE).nIn(HyperParameter.nHNodes_2).nOut(HyperParameter.numOutputs).activation("identity").build()) // "identity" .backpropType(BackpropType.TruncatedBPTT) .tBPTTBackwardLength(100) .pretrain(false) .backprop(true) .build(); 

发现了几件事情:

  • LSTM或RNN非常擅长按时间顺序挑选图案。
  • 试了一个时间序列,和一组不同的时间序列。 模式很容易被挑出来。
  • 它也试图挑选模式不只是一个节奏。 如果按星期和月份有模式,两者都将被networking学习。