TsFresh(TimeSeries Fresh)是一个Python第三方工具包。它可以方便地对时间序列数据进行处理,获得大量的特征。这些特征可以用以训练分类器,以高效地实现对时间序列数据的分类、识别等。然而,在工程实现时,更多地是采用Java等语言,这需要利用Java实现对TsFresh的特征进行直接计算,故需要对TsFresh的某些特征进行深入地分析,并在Java语言下实现。
特征change_quantiles简介
命令格式:change_quantiles(x, ql, qh, isabs, f_agg)
对给定时间序列x,由分位数ql与qh确定的区间。计算区间内时间序列x的均值、连续变化的绝对值等。
参数:
- x:时间序列,数据类型:numpy.ndarray
- ql:数据的下分位数,数据类型:float
- qh:数据的上分位数,数据类型:float
- isabs:是否取绝对值,数据类型:bool
- f_agg:应用于数据的聚合函数名称,如mean, var, std, median等,数据类型:str
特征change_quantiles计算原理
1. 计算时间序列x的一阶差分div
2. 根据参数isabs的值确定是否对div取绝对值。True时为取绝对值,False时不取绝对值
3. 计算时间序列x的上、下分位数,确定统计区间
计算分位数的方法是采用基于N-1计算分位数
- 将数据从小到大排序,计为数组a(1 to n),n代表数据的长度
- 确定分位数的位置:b= 1+(n-1) × quanty,b的整数部分计为c b的小数部分计为d
- 计算分位数:若c<n,则result=a(c)+[a(c+1)-a(c)]*d,若c=n,则result=a(c)
4. 建立一个与x等长度的索引序列ind,将x中处于统计区间内的值所对应的索引在ind中赋值为1,而其它索引赋值为0.
5. 将索引序列ind与其移位1位的ind逐位进行“与”操作,形成新的索引序列ind
6. 将索引序列ind为1的索引所对就的div中的数据,根据f_agg给出的函数进行统计分析
f_agg = "mean":均值
f_agg = "var":方差
注:这里的var采用的是方差公式,而不是样本方差公式,因此分母为N,而不是N-1。
Java实现
实现change_quantiles特征的代码
public static double change_quantiles(double[] x, double ql, double qh, boolean isabs, String f_agg) {
double result = 0;
double[] x_diff = new double[x.length - 1];
for (int idx = 0; idx < (x.length-1); idx++) {
x_diff[idx] = x[idx+1] - x[idx];
if (isabs)
x_diff[idx] = Math.abs(x_diff[idx]);
}
double quantyLow = Quantiles_INC(x, ql);
double quantyHig = Quantiles_INC(x, qh);
int[] flag4Used = new int[x.length];
for (int idx = 0; idx < x.length; idx++) {
if ((x[idx] >= quantyLow) & (x[idx] <= quantyHig)) {
flag4Used[idx] = 1;
} else {
flag4Used[idx] = 0;
}
}
int num = 0;
int[] flag4Diff = new int[x.length - 1];
for (int idx = 0; idx < flag4Diff.length; idx++) {
flag4Diff[idx] = flag4Used[idx] * flag4Used[idx+1];
if (flag4Diff[idx] > 0) {
num++;
}
}
double[] x_short = new double[num];
int ind = 0;
for (int idx = 0; idx < flag4Diff.length; idx++) {
if (flag4Diff[idx] > 0) {
x_short[ind] = x_diff[idx];
ind++;
}
}
switch (f_agg) {
case "var":{
result = Var(x_short);
break;
}
}
return result;
}
求解分位数的代码
public static double Quantiles_INC(double[] x, double quanty) {
double result = 0;
Arrays.sort(x);
double b = (x.length - 1) * quanty;
double c = Math.floor(b);
double d = b-c;
if (c < (x.length - 1)) {
result = x[(int) c] + (x[(int) c+1] - x[(int) c])*d;
} else {
result = x[(int) c];
}
return result;
}