时间序列中的模式识别

Posted

技术标签:

【中文标题】时间序列中的模式识别【英文标题】:Pattern recognition in time series [closed] 【发布时间】:2012-07-29 23:08:36 【问题描述】:

通过处理时间序列图,我想检测类似于以下的模式:

以示例时间序列为例,我希望能够检测到此处标记的模式:

我需要使用什么样的 AI 算法(我假设是 marine 学习技术)来实现这一点?有没有我可以使用的库(C/C++)?

【问题讨论】:

你能澄清一下:你正在寻找的模式,它们的大小是否固定(总是延伸到相同数量的时间步长)?另外,您是否看过滑动窗口方法? 【参考方案1】:

这是我为分区心电图数据所做的一个小项目的示例结果。

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

我使用Viterbi training 训练模型,只更新回归参数。

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

编辑:

这是一些示例 python 代码 - 它并不完美,但它提供了一般方法。它实现了 EM 而不是 Viterbi 训练,后者可能会稍微稳定一些。 心电数据集来自http://www.cs.ucr.edu/~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,w.T) # (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(x.T,ex*x)
        dy=np.dot(x.T,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()

【讨论】:

抱歉,我是这个领域的新手,我仍然对与模式识别相关的大量信息感到不知所措。我大致了解您的建议,但如果可能的话可能需要更多解释。我了解 HMM 的工作原理,但我现在的问题是如何将我的问题映射到 HMM 中,您能否通过类似于此处示例的格式来帮助我更好地理解:en.wikipedia.org/wiki/Hidden_Markov_model#A_concrete_example Rabiner 的“隐马尔可夫模型简介”是一个很好的起点。我还包含代码来展示 HMM 在实践中的工作原理。 chfdb_chf13_45590.txt中各列的内容是什么 第一列是时间。第 2 列和第 3 列是电信号。我只是使用第 2 列信号来简化事情。 LSTM 是否有可能因为它的记忆特性而成为处理这类事情的合适工具?【参考方案2】:

为什么不使用简单的匹配过滤器?或者它的一般统计对应物,称为互相关。给定一个已知模式 x(t) 和一个嘈杂的复合时间序列,其中包含您的模式在 a,b,...,z 中移动,例如 y(t) = x(t-a) + x(t-b) +...+ x(t-z) + n(t). x 和 y 之间的互相关函数应该给出峰值在 a,b, ...,z

【讨论】:

【参考方案3】:

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

时间序列操作包主要针对股票市场。我在 cmets 中建议了Cronos;我不知道如何用它进行模式识别,除了显而易见的:你的系列长度的任何好的模型都应该能够预测,在与最后一个小凹凸有一定距离的小凹凸之后,大凹凸随之而来。也就是说,您的系列表现出自相似性,而 Cronos 中使用的模型旨在对其进行建模。

如果您不介意 C#,您应该向 HCIL 的人员请求 TimeSearcher2 的版本 - 对于此系统,模式识别是绘制模式的样子,然后检查您的模型是否足够通用以低误报率捕获大多数实例。可能是您会发现的最用户友好的方法;所有其他人都需要相当多的统计或模式识别策略背景。

【讨论】:

是的,我已经标记了可用于监督学习的数据集。 Weka 似乎是针对 Java 语言的,有没有 C/C++ 的等效库? 抱歉,没有阅读问题的那部分内容...... cronos 呢? stat.cmu.edu/~abrock/oldcronos 不好意思,你知道怎么用cronos做模式识别吗?我浏览了网站,我看到的只是估计和预测。 我认为这些之间有很强的关系。在用部分序列训练后,给定小尖峰,GARCH 等应该生成一个预测大尖峰的信号......【参考方案4】:

我不确定哪个包最适合这个。我在大学的某个时候做过类似的事情,我试图在 x-y 轴上自动检测一些不同图形的某些相似形状。您可以执行以下操作。

类标签如:

没有课 区域开始 区域中部 区域结束

功能如下:

    相对 y 轴的相对和绝对差值 11 点宽的窗口中的周围点 与平均值的差异等特征 前后点的相对差异

【讨论】:

【参考方案5】:

如果您愿意,我正在使用深度学习。它是用 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 非常擅长挑选时间序列中的模式。 尝试了一个时间序列和一组不同的时间序列。图案很容易被挑选出来。 它还试图挑选出不仅仅是一种节奏的模式。如果有按周和按月的模式,两者都会被网络学习。

【讨论】:

这种方法有分类问题吗?数据集是什么样子的? 这是一个预测实验。要使用 LSTM 进行分类,您可以使用带有预期标签的最后一个时间步来训练网络,这样网络就可以学习生成标签,而不是我正在做的预测。希望对您有所帮助。 不使用 LSTM,Transformer Achitecture (Attention is all you need) 可能是一种更现代的方法,可以得到类似的结果。 已经有一段时间了,但我正在尝试识别股市时间序列中的特定模式。我可以为此使用 LSTM/RNN,任何有你经验的 cmet 吗?谢谢 LSTM 训练速度较慢,我不记得它对我的情况有多好。如果通过“识别特定模式”的方式进行分类,可以使用 CNN,1-D CNN 可以用于时间序列模式识别。您只需要将数据转换为一维数据,在数据上有一个滑动窗口,然后通过 CNN 运行它。 CNN 会将其分类为匹配“模式”或不匹配。我记得我使用 RNN 来预测下一步。我现在对使用 RNN 不太感兴趣。

以上是关于时间序列中的模式识别的主要内容,如果未能解决你的问题,请参考以下文章

Node.js 或 PHP 中的模式识别算法?

分类和模式识别有啥区别?

如何:模式识别

如何为神经网络中的模式识别编写matlab代码

JSON- 正则表达式来识别 JSON 中的模式

使用最近邻算法进行图像模式识别