# 时间序列分段算法 [Time series Breakout Detection]

1. 单变量线性回归，用来拟合某一段时序

2. 动态规划算法，  用来全局最大化断点检测效果。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include "lsp.h"

static double loss(double * s, int n){
int i;
double t;
double g0   = 0.0, g1   = 0.0;
double h00  = 0.0, h01  = 0.0, h10  = 0.0, h11  = 0.0;
double hv00 = 0.0, hv01 = 0.0, hv10 = 0.0, hv11 = 0.0;
double l0, l1;

for (i = 0; i < n; i++){
t    = s[i];
g0  += t;
g1  += t * (1.0 + i);
h00 += 1.0;
h01 += 1.0 + i;
h11 += (1.0 + i) * (1.0 + i);
}
h10 = h01;

// inverse of hessian
t = h00 * h11 - h01 * h10;
hv00 = h11 / t;
hv01 = hv10 = -h01 / t;
hv11 = h00 /t;

// the theta
l0 = hv00 * g0 + hv01 * g1;
l1 = hv10 * g0 + hv11 * g1;

// sqare loss
t = 0.0;
for (i = 0; i < n; i++){
t += (l0 + l1 * (i + 1) - s[i]) * (l0 + l1 * (i + 1) - s[i]);
}
return t;
}

int * lsp(double * ts, int n, int min_size, double beta, int *ol){

if (!ts || min_size < 2 || n < 2 * min_size || !ol){
return NULL;
}

// prev breakout point
int * prev = (int*)malloc(sizeof(int) * (n + 1));
memset(prev, 0, sizeof(int) * (n + 1));

// number of breakout point
int * num  = (int*)malloc(sizeof(int) * (n + 1));
memset(num, 0, sizeof(int) * (n + 1));

// F scores
double * F = (double*)malloc(sizeof(double) * (n + 1));
memset(F, 0, sizeof(double) * (n + 1));

// loss
double * lossv = (double*)malloc(sizeof(double) * (n + 1));
memset(lossv, 0, sizeof(double) * (n + 1));

for (int s = 2 * min_size; s < n + 1; ++s){
for (int t = min_size; t < s - min_size + 1; ++t){
//double ls = loss(ts + prev[t], t - prev[t]);
double ls = lossv[t];
double rs = loss(ts + t, s - t);
double as = loss(ts + prev[t], s - prev[t]);
double score = (as - ls - rs) * (t - prev[t]) * (s - t) /    \
((s - prev[t]) * (s - prev[t])) - num[t] * beta;
score += F[t];
if (score > F[s]){
num[s] = num[t] + 1;
F[s] = score;
prev[s] = t;
lossv[s] = rs;
}
}
}

int k = num[n];
*ol = k;
int * re = (int*)malloc(sizeof(int) * k);
memset(re, 0, sizeof(int) * k);
int i = n;
while(i > 0){
if (prev[i])
re[--k] = prev[i];
i = prev[i];
}

free(prev);  prev  = NULL;
free(num);   num   = NULL;
free(F);     F     = NULL;
free(lossv); lossv = NULL;
return re;
}

©️2019 CSDN 皮肤主题: 大白 设计师: CSDN官方博客