关于机器学习:时间序列中的模式识别

Pattern recognition in time series

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

enter image description here

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

enter image description here

为此,我需要使用哪种AI算法(我假设是行销学习技术)? 我可以使用任何库(C / C ++)吗?


这是我对ecg数据进行分区的一个小项目的示例结果。

enter image description here

我的方法是"切换自回归HMM"(如果您尚未听说的话,请点击Google),其中每个数据点都是使用贝叶斯回归模型从上一个数据点预测出来的。我创建了81个隐藏状态:一个用于捕获每个心跳之间数据的垃圾状态,以及80个单独的隐藏状态,分别对应于心跳模式中的不同位置。模式80状态直接从子采样的单拍模式中构建,并具有两个过渡-自过渡和过渡到模式中下一个状态。模式中的最终状态转换为自身或垃圾状态。

我通过维特比(Viterbi)训练对模型进行了训练,仅更新了回归参数。

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

编辑:

这是一些示例python代码-它不是完美的,但是它提供了通用方法。它执行EM而不是Viterbi训练,后者可能会稍微稳定一些。
心电图数据集来自http://www.cs.ucr.edu/~eamonn/discords/ECG_data.zip

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
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()


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


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

类标签如下:

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

功能如下:

  • 每个y轴的相对和绝对差
    窗口中的周围点宽11点
  • 与平均差异之类的功能
  • 前点与后点之间的相对差

  • Weka是功能强大的机器学习软件集合,并且支持某些时间序列分析工具,但是我对该领域的了解还不足以推荐最佳方法。但是,它基于Java。您可以轻松地从C / C ++调用Java代码。

    用于时间序列操纵的程序包主要针对股市。我在评论中建议了克罗诺斯;除了显而易见的之外,我不知道如何使用模式识别:系列中任何长度的良好模型都应能够预测,在距最后一个小凸起一定距离的小凸起之后,还会出现大凸起。也就是说,您的系列表现出自相似性,并且在Cronos中使用的模型旨在对其进行建模。

    如果您不介意C#,则应从HCIL的人员那里请求一个TimeSearcher2版本-模式识别对于该系统来说,是绘制模式的样子,然后检查您的模型是否足够通用以捕获大多数实例。假阳性率低。您可能会找到最人性化的方法;所有其他要求在统计或模式识别策略方面具有相当的背景。


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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    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非常擅长选择时间序列中的模式。
    • 尝试了一个时间序列,并尝试了一组不同的时间序列。图案很容易挑出来。
    • 它还试图挑选出一种节奏而不只是一种节奏的模式。如果有按周和按月的模式,则两者都将通过网络获悉。