AnyMath 文档
Notebook

使用混合方法预测多维时间序列

导言

在时间序列分析和预测中,经典问题仍然是将观测信号分离为确定性和随机分量。 如果确定性部分允许精确的参数描述,那么其余部分通常包含一个相关结构,该结构不会减少到简单的噪声,但也不会用线性方法描述。 将经典分解与余数的神经网络建模相结合的混合方案使得可以利用这两种方法的优势。

在本文中,我们考虑了一种预测多维时间序列的混合方法,该方法包括三个阶段:

  1. 最小二乘线性趋势去除(OLS);
  2. 用Nelder-Mead方法选择频率优化的两个主要正弦分量;
  3. 由循环神经网络lstm预测余数。

使用RMSE和MAE度量评估预测的质量,并且还与没有神经网络块的模型进行比较。

让我们考虑在这项工作中使用的一些定义。:

*趋势是反映其变化的大方向的时间序列的长期,单调的组成部分:增长,下降或停滞。
*季节性是一个系列的周期性成分,它以大致相等的时间间隔以恒定的幅度和相位重复。
*Lstm(长期短期记忆)是一种循环神经网络,能够以较长的时间间隔存储有关序列先前状态的信息。 与经典的循环神经网络不同,LSTM使用一种机制来控制隐藏状态下信息的写入,读取和擦除,这使其能够有效地对时间序列中的长期依赖关系进行建模。
*剩余能量是信号与其模型之间差异的平方和。: . 这是一个标准的OLS目标函数;最小化它意味着找到它最好描述信号的模型参数。 本文将残余能量作为正弦频率优化的标准。
*RMS(均方根,均方根值)–值的均方根: ​​. 对于该系列的其余部分,RMS以与信号相同的单位显示差异的典型幅度。 训练区域中剩余部分的RMS表征该系列的"未解释"部分,然后将其传输到LSTM输入。
*RMSE(均方根误差,均方根误差)-预测质量的度量: ​. 它以信号单位测量,比MAE更强烈地惩罚大失误。
*MAE(平均绝对误差)-公制: . 它显示了信号单位的平均"典型"预测误差,并且对异常值的敏感度低于RMSE。
*Mnc(最小二乘法)是一种用于估计线性模型的参数的方法,该参数最小化平方残差的总和。 它用于估计正弦曲线的线性趋势和振幅。
*Nelder-Mead方法是一种不需要导数的无条件优化算法;它用于通过残余能量的准则细化一对正弦频率。

加入图书馆

连接必要的库:

Flux -神经网络训练及应用;

Optim -正弦频率的优化;

Statistics-计算余数统计进行归一化;

LinearAlgebra -计算线性趋势和正弦振幅的MNC系统的解决方案;

Random -学习的可重复性。

In [ ]:
for pkg in ["Flux", "Optim", "Statistics", "LinearAlgebra", "Random"]
    try
        eval(Meta.parse("using $pkg"))
    catch
        Pkg.add(pkg)
        eval(Meta.parse("using $pkg"))
    end
end
Random.seed!(42)
Out[0]:
TaskLocalRNG()

数据生成

我们将生成三个时间序列 , , 5000点长。

每一行都包含一个总体趋势 和季节性成分 具有相移和恒定 . 为 和 整体趋势的幅度正在缩放,季节性分量的相位正在转移。

让我们绘制所有三行。

In [ ]:
t = 0:1:4999
B = 8 .* sin.(0.006 .* t) .+ 0.006 .* t
c = 30
X = B .+ 5 .* sin.(0.016 .* t)               .+ c
Y = 0.8 .* B .+ 5 .* sin.(0.016 .* t .+ π/3) .+ c
Z = 1.2 .* B .+ 5 .* sin.(0.016 .* t .+ 2π/3) .+ c
plot(t, [X Y Z], title="时间序列", lw=1.8, label=["X" "Y" "Z"])
Out[0]:

分成训练和测试样本

让我们将数据拆分为训练样本(前4000个点)和测试样本(最后1000个点),并形成一个公共数组。 данные_все (5000×3)和时间向量 tt. 让我们分别突出时间轴。 t_обуч 为训练区。

In [ ]:
N_обуч = 4000
N_тест  = 1000
N = N_обуч + N_тест
данные_все   = hcat(X, Y, Z)                 
данные_обуч  = данные_все[1:N_обуч, :]
данные_тест  = данные_все[N_обуч+1:end, :]
tt = collect(Float64, 0:N-1)
t_обуч = tt[1:N_обуч]
Out[0]:
4000-element Vector{Float64}:
    0.0
    1.0
    2.0
    3.0
    4.0
    5.0
    6.0
    7.0
    8.0
    9.0
   10.0
   11.0
   12.0
    ⋮
 3988.0
 3989.0
 3990.0
 3991.0
 3992.0
 3993.0
 3994.0
 3995.0
 3996.0
 3997.0
 3998.0
 3999.0

消除线性趋势

让我们使用每行的最小二乘(OLS)训练样本估计线性趋势,沿着其整个长度绘制趋势并从源数据中减去它。 结果,我们得到了减损的数据。 детренд_все 和 детренд_обуч.

In [ ]:
A = hcat(ones(N_обуч), t_обуч)
коэф = A \ данные_обуч                         
тренд_все = hcat(ones(N), tt) * коэф   
детренд_все   = данные_все   .- тренд_все
детренд_обуч  = детренд_все[1:N_обуч, :]
Out[0]:
4000×3 Matrix{Float64}:
 -2.05727    2.91277    2.60508
 -1.92836    2.9912     2.62286
 -1.79948    3.06851    2.63953
 -1.67064    3.14469    2.65511
 -1.54187    3.21973    2.66961
 -1.41318    3.29362    2.68304
 -1.28461    3.36634    2.6954
 -1.15617    3.43789    2.70671
 -1.02789    3.50826    2.71697
 -0.89978    3.57744    2.7262
 -0.771873   3.64541    2.73441
 -0.644186   3.71218    2.7416
 -0.516743   3.77772    2.74779
  ⋮                    
 -1.76054   -0.549052  -7.43301
 -1.69803   -0.570166  -7.49135
 -1.63633   -0.592207  -7.54943
 -1.57544   -0.615167  -7.60724
 -1.51537   -0.639036  -7.66476
 -1.45614   -0.663805  -7.72197
 -1.39776   -0.689464  -7.77885
 -1.34024   -0.716004  -7.83538
 -1.28359   -0.743413  -7.89154
 -1.22782   -0.771681  -7.94732
 -1.17294   -0.800798  -8.00268
 -1.11896   -0.830753  -8.05761

剩余能量函数

定义函数 остаточная_энергия(частоты, сигнал, t),它基于给定的频率对,建立常数,余弦和正弦的基础,选择OLS的系数并返回残差的平方和。 该函数将作为频率优化的目标函数。

In [ ]:
function остаточная_энергия(частоты, сигнал, t)
    f1, f2 = частоты
    (f1 <= 0 || f2 <= 0) && return 1e30
    M = hcat(ones(length(t)),
             cos.(2π*f1*t), sin.(2π*f1*t),
             cos.(2π*f2*t), sin.(2π*f2*t))
    β = M \ сигнал
    r = сигнал .- M*β
    return sum(abs2, r)
end
Out[0]:
остаточная_энергия (generic function with 1 method)

两个正弦搜索功能

定义函数 синусоиды(сигнал, t),它在信号中搜索两个主导频率:首先,它通过网格暴力搜索找到第一个频率,然后,通过减去其贡献,第二个,然后使用NelderMead方法澄清两个频率。 返回找到的对(f1,f2)。

In [ ]:
function синусоиды(сигнал, t)
    сетка_частот = 1e-5 : 1e-5 : 1.2e-2
    лучшая_f1 = 0.0; лучший_r = Inf
    for f in сетка_частот
        M = hcat(ones(length(t)), cos.(2π*f*t), sin.(2π*f*t))
        β = M \ сигнал
        r = sum(abs2, сигнал .- M*β)
        if r < лучший_r
            лучший_r = r; лучшая_f1 = f
        end
    end

    M1 = hcat(ones(length(t)), cos.(2π*лучшая_f1*t), sin.(2π*лучшая_f1*t))
    сигнал2 = сигнал .- M1 * (M1 \ сигнал)

    лучшая_f2 = 0.0; лучший_r2 = Inf
    for f in сетка_частот
        abs(f - лучшая_f1) < 5e-4 && continue
        M = hcat(ones(length(t)), cos.(2π*f*t), sin.(2π*f*t))
        β = M \ сигнал2
        r = sum(abs2, сигнал2 .- M*β)
        if r < лучший_r2
            лучший_r2 = r; лучшая_f2 = f
        end
    end

    целевая = частоты -> остаточная_энергия(частоты, сигнал, t)
    res = Optim.optimize(целевая, [лучшая_f1, лучшая_f2],
                         NelderMead(),
                         Optim.Options(x_tol=1e-12, f_tol=1e-15,
                                       iterations=N))
    f1, f2 = Optim.minimizer(res)
    return f1, f2
end
Out[0]:
синусоиды (generic function with 1 method)

按级数选择正弦曲线

应用函数 синусоиды 对于三个确定的系列中的每一个,将找到的频率与真实值进行比较 和 . 我们将在训练区域中执行振幅的最终MNC选择,并沿着行的整个长度构造正弦分量。 我们将为每行输出RMS。

In [ ]:
_, n_сигн = size(данные_все)
синус_все = zeros(N, n_сигн)
частоты_итог = zeros(n_сигн, 2)

for k in 1:n_сигн
    сигнал = детренд_обуч[:, k]
    f1, f2 = синусоиды(сигнал, t_обуч)
    частоты_итог[k, :] = [f1, f2]

    f1_истина = 0.006 / (2π)
    f2_истина = 0.016 / (2π)
    println("Ряд $k: f1 = $(round(f1, digits=10))  (истина $(round(f1_истина, digits=10)), Δ = $(abs(f1-f1_истина)))")
    println("       f2 = $(round(f2, digits=10))  (истина $(round(f2_истина, digits=10)), Δ = $(abs(f2-f2_истина)))")

    M_обуч = hcat(ones(N_обуч),
                   cos.(2π*f1*t_обуч), sin.(2π*f1*t_обуч),
                   cos.(2π*f2*t_обуч), sin.(2π*f2*t_обуч))
    β = M_обуч \ сигнал

    M_все = hcat(ones(N),
                 cos.(2π*f1*tt), sin.(2π*f1*tt),
                 cos.(2π*f2*tt), sin.(2π*f2*tt))
    синус_все[:, k] = M_все * β
end

остаток_все   = детренд_все   .- синус_все
остаток_обуч  = остаток_все[1:N_обуч, :]

println("\nRMS:")
for k in 1:n_сигн
    println("  Ряд $k: $(round(sqrt(mean(abs2, остаток_обуч[:,k])), sigdigits=3))")
end
┌ Warning: x_tol is deprecated. Use x_abstol or x_reltol instead. The provided value (1.0e-12) will be used as x_abstol.
└ @ Optim /opt/depot/demos/packages/Optim/z6105/src/types.jl:128
┌ Warning: f_tol is deprecated. Use f_abstol or f_reltol instead. The provided value (1.0e-15) will be used as f_reltol.
└ @ Optim /opt/depot/demos/packages/Optim/z6105/src/types.jl:138
Ряд 1: f1 = 0.0009511555  (истина 0.0009549297, Δ = 3.7741976086258684e-6)
       f2 = 0.0025495928  (истина 0.0025464791, Δ = 3.113760232510091e-6)
Ряд 2: f1 = 0.000951996  (истина 0.0009549297, Δ = 2.933630766334557e-6)
       f2 = 0.0025460388  (истина 0.0025464791, Δ = 4.402527278529571e-7)
┌ Warning: x_tol is deprecated. Use x_abstol or x_reltol instead. The provided value (1.0e-12) will be used as x_abstol.
└ @ Optim /opt/depot/demos/packages/Optim/z6105/src/types.jl:128
┌ Warning: f_tol is deprecated. Use f_abstol or f_reltol instead. The provided value (1.0e-15) will be used as f_reltol.
└ @ Optim /opt/depot/demos/packages/Optim/z6105/src/types.jl:138
Ряд 3: f1 = 0.0009523338  (истина 0.0009549297, Δ = 2.5958343298196265e-6)
       f2 = 0.0025436879  (истина 0.0025464791, Δ = 2.791216266237375e-6)

RMS:
┌ Warning: x_tol is deprecated. Use x_abstol or x_reltol instead. The provided value (1.0e-12) will be used as x_abstol.
└ @ Optim /opt/depot/demos/packages/Optim/z6105/src/types.jl:128
┌ Warning: f_tol is deprecated. Use f_abstol or f_reltol instead. The provided value (1.0e-15) will be used as f_reltol.
└ @ Optim /opt/depot/demos/packages/Optim/z6105/src/types.jl:138
  Ряд 1: 1.02
  Ряд 2: 0.662
  Ряд 3: 0.815

平衡正常化

计算平均值 和标准偏差 剩下的训练样本,我们来替换那些太小的 通过1.0,我们得到归一化余数。 остаток_норм 每行的均值和单位方差为零。

In [ ]:
μ = mean(остаток_обуч, dims=1)
σ = std(остаток_обуч,  dims=1)
σ[σ .< 1e-10] .= 1.0
остаток_норм = (остаток_обуч .- μ) ./ σ     
Out[0]:
4000×3 Matrix{Float64}:
 -1.84503  -2.04697  -1.95095
 -1.84156  -2.04278  -1.94441
 -1.83812  -2.03856  -1.93787
 -1.83471  -2.03432  -1.93134
 -1.83132  -2.03005  -1.92483
 -1.82797  -2.02577  -1.91834
 -1.82465  -2.02146  -1.91185
 -1.82135  -2.01712  -1.90539
 -1.81809  -2.01277  -1.89894
 -1.81485  -2.0084   -1.89252
 -1.81165  -2.00401  -1.88611
 -1.80848  -1.99959  -1.87972
 -1.80534  -1.99516  -1.87336
  ⋮                  
  1.69907   1.76467   1.58288
  1.70712   1.76956   1.58819
  1.71519   1.77445   1.59355
  1.72328   1.77934   1.59896
  1.73139   1.78422   1.60442
  1.73952   1.7891    1.60992
  1.74766   1.79398   1.61547
  1.75582   1.79885   1.62107
  1.76399   1.80372   1.62671
  1.77218   1.80859   1.6324
  1.78038   1.81345   1.63814
  1.78859   1.8183    1.64392

为LSTM创建窗口

让我们为LSTM创建训练序列:窗口长度为l=100,对于三个通道中的每一个。 获取数组 X_посл 表格(3,100,3900)-入口窗户及 Y_посл 表格(3,3900)是目标值。

In [ ]:
L = 100
N = N_обуч - L
K = 3

X_посл = zeros(Float32, K, L, N)
Y_посл = zeros(Float32, K, N)
for i in 1:N
    X_посл[:, :, i] = Float32.(остаток_норм[i:i+L-1, :]')
    Y_посл[:, i]    = Float32.(остаток_норм[i+L, :])
end

LSTM培训

让我们定义一个lstm模型(输入3→隐藏状态32→输出3),在输出端有一个完全连接的层。 让我们设置Adam优化器并以每个64个示例的迷你批次中的10个epoch训练模型,最大限度地减少窗口最后一步的预测与真实值之间的MSE。 我们将输出每个epoch的损失函数值。

In [ ]:
модель = Chain(LSTM(K => 32), Dense(32 => K))

function потери(модель, x, y)
    Flux.reset!(модель)
    ŷ = модель(x)                    
    return Flux.mse(ŷ[:, end, :], y)
end

сост_опт = Flux.setup(Flux.Adam(1e-3), модель)
размер_батча = 64
эпох = 10
n_батчей = div(N, размер_батча)

for эпоха in 1:эпох
    перест = randperm(N)
    потери_эпохи = 0.0
    for b in 1:n_батчей
        idx = перест[(b-1)*размер_батча+1 : b*размер_батча]
        xb = X_посл[:, :, idx]
        yb = Y_посл[:, idx]
        Flux.reset!(модель)
        l, grads = Flux.withgradient(модель) do m
            Flux.mse(m(xb)[:, end, :], yb)
        end
        Flux.update!(сост_опт, модель, grads[1])
        потери_эпохи += l
    end
    println("эпоха $эпоха  потери = $(round(потери_эпохи/n_батчей, sigdigits=4))")
end
эпоха 1  потери = 0.5232
эпоха 2  потери = 0.01699
эпоха 3  потери = 0.004644
эпоха 4  потери = 0.003566
эпоха 5  потери = 0.003047
эпоха 6  потери = 0.002708
эпоха 7  потери = 0.002429
эпоха 8  потери = 0.002257
эпоха 9  потери = 0.002112
эпоха 10  потери = 0.002007

余额预测

定义函数 прогноз_остатка,它通过递归预测余数 N_тест 前进的步骤:在每一步,长度的最后一个窗口被采取 L,被馈送到LSTM,接收到的预测被添加到缓冲器并用于形成下一个窗口。 然后,我们使用以下方法将预测反规范化回原始比例 和 . 结果,我们得到 остаток_полн 尺寸为5000×3。

In [ ]:
function прогноз_остатка(модель, остаток_норм, μ, σ, N_обуч, L, горизонт)
    K = 3
    всего = N_обуч + горизонт
    буфер = zeros(Float32, всего, K)
    буфер[1:N_обуч, :] = Float32.(остаток_норм)

    Flux.reset!(модель)
    for i in 1:горизонт
        idx = N_обуч + i
        окно = буфер[idx-L:idx-1, :]'
        x_вх   = reshape(окно, K, L, 1)
        ŷ = модель(x_вх)
        буфер[idx, :] = vec(ŷ[:, end, :])
    end

    return Float64.(буфер) .* Float64.(σ) .+ Float64.(μ)
end

остаток_полн = прогноз_остатка(модель, остаток_норм, μ, σ, N_обуч, L, N_тест)
Out[0]:
5000×3 Matrix{Float64}:
 -1.88057  -1.35504  -1.58977
 -1.87703  -1.35226  -1.58444
 -1.87352  -1.34947  -1.57911
 -1.87004  -1.34666  -1.57379
 -1.86659  -1.34384  -1.56849
 -1.86317  -1.341    -1.56319
 -1.85979  -1.33815  -1.55791
 -1.85643  -1.33528  -1.55265
 -1.8531   -1.3324   -1.54739
 -1.84981  -1.3295   -1.54216
 -1.84654  -1.3266   -1.53693
 -1.84331  -1.32367  -1.53173
 -1.84011  -1.32074  -1.52655
  ⋮                  
  1.92881   1.13253   1.40256
  1.92881   1.13253   1.40256
  1.92881   1.13253   1.40256
  1.92881   1.13253   1.40256
  1.92881   1.13253   1.40256
  1.92881   1.13253   1.40256
  1.92881   1.13253   1.40256
  1.92881   1.13253   1.40256
  1.92881   1.13253   1.40256
  1.92881   1.13253   1.40256
  1.92881   1.13253   1.40256
  1.92881   1.13253   1.40256

最终预测

让我们把三个部分加起来:线性趋势 тренд_все,正弦分量синус_все 和余额的预测 остаток_полн. 我们会得到完整的预测 y_полн 让我们突出显示测试部分 y_прогноз. 我们将保存真实值以供比较 y_истина.

In [ ]:
y_полн = тренд_все .+ синус_все .+ остаток_полн
y_прогноз = y_полн[N_обуч+1:end, :]
y_истина = данные_тест
Out[0]:
1000×3 Matrix{Float64}:
 51.3555  47.4012  49.5032
 51.4128  47.3738  49.4556
 51.4691  47.3456  49.4086
 51.5245  47.3166  49.362
 51.5789  47.2869  49.316
 51.6324  47.2563  49.2705
 51.685   47.2251  49.2256
 51.7365  47.193   49.1813
 51.7871  47.1603  49.1375
 51.8368  47.1269  49.0944
 51.8854  47.0927  49.0519
 51.9331  47.0579  49.0101
 51.9797  47.0224  48.969
  ⋮                
 47.1826  43.8875  57.4425
 47.1695  43.9503  57.5326
 47.1579  44.0142  57.6226
 47.1479  44.0793  57.7128
 47.1393  44.1455  57.8029
 47.1323  44.2128  57.893
 47.1268  44.2812  57.9831
 47.1228  44.3507  58.0731
 47.1204  44.4213  58.163
 47.1196  44.4929  58.2529
 47.1203  44.5655  58.3426
 47.1225  44.6392  58.4322

质量指标

让我们计算测试区域中每三行的RMSE和MAE指标。 此外,我们将计算预测而不考虑lstm进行比较。 它将显示LSTM提高预测质量的程度。

In [ ]:
rmse(a, p) = sqrt(mean((a .- p).^2))
mae(a, p)  = mean(abs.(a .- p))
имена = ["X", "Y", "Z"]
y_прогноз_безLSTM = (тренд_все .+ синус_все .+ vcat(остаток_обуч, zeros(N_тест,3)))[N_обуч+1:end, :]
println("\nКачество прогноза (t = $N_обуч..$(N_обуч+N_тест-1)):\n")
println(rpad("排", 5), rpad("RMSE(带LSTM)", 16), rpad("RMSE / размах", 16),
        rpad("MAE (с LSTM)", 16), rpad("RMSE без LSTM", 16), "Улучшение по RMSE")
for k in 1:3
    истина_k  = y_истина[:, k]
    прогноз_k = y_прогноз[:, k]
    безLSTM_k = y_прогноз_безLSTM[:, k]

    r_с   = rmse(истина_k, прогноз_k)
    r_без = rmse(истина_k, безLSTM_k)
    m_с   = mae(истина_k, прогноз_k)
    размах = maximum(истина_k) - minimum(истина_k)
    доля   = 100 * r_с / размах
    улучш  = r_без / r_с

    println(rpad(имена[k], 5),
            rpad(round(r_с, digits=3), 16),
            rpad("≈ $(round(доля, digits=1)) %", 16),
            rpad(round(m_с, digits=3), 16),
            rpad(round(r_без, digits=3), 16),
            "в $(round(улучш, digits=1)) раза")
end
Качество прогноза (t = 4000..4999):

Ряд  RMSE (с LSTM)   RMSE / размах   MAE (с LSTM)    RMSE без LSTM   Улучшение по RMSE
X    0.517           ≈ 2.3 %         0.472           2.327           в 4.5 раза
Y    0.38            ≈ 2.0 %         0.333           1.477           в 3.9 раза
Z    0.516           ≈ 2.1 %         0.45            1.845           в 3.6 раза

预测的可视化

让我们建立三个子图(, , ),在蓝色的每个训练区域上,测试上的真实值以橙色点缀,预测为红色。

In [ ]:
p1 = plot(tt[1:N_обуч], X[1:N_обуч], label="", color=:blue, linewidth=2,
          title="X", legend=false)
plot!(p1, tt[N_обуч+1:end], X[N_обуч+1:end], label="",
      color=:orange, linestyle=:dash, linewidth=3)
plot!(p1, tt[N_обуч+1:end], y_прогноз[:,1], label="",
      color=:red, linewidth=3)
vline!(p1, [N_обуч+0.5], color=:black, linestyle=:dash, label="", linewidth=1)

p2 = plot(tt[1:N_обуч], Y[1:N_обуч], label="", color=:blue, linewidth=2,
          title="Y", legend=false)
plot!(p2, tt[N_обуч+1:end], Y[N_обуч+1:end], label="",
      color=:orange, linestyle=:dash, linewidth=3)
plot!(p2, tt[N_обуч+1:end], y_прогноз[:,2], label="",
      color=:red, linewidth=3)
vline!(p2, [N_обуч+0.5], color=:black, linestyle=:dash, label="", linewidth=1)

p3 = plot(tt[1:N_обуч], Z[1:N_обуч], label="", color=:blue, linewidth=2,
          title="Z", legend=false)
plot!(p3, tt[N_обуч+1:end], Z[N_обуч+1:end], label="",
      color=:orange, linestyle=:dash, linewidth=3)
plot!(p3, tt[N_обуч+1:end], y_прогноз[:,3], label="",
      color=:red, linewidth=3)
vline!(p3, [N_обуч+0.5], color=:black, linestyle=:dash, label="", linewidth=1)

display(plot(p1, p2, p3, layout=(3,1), size=(950, 950), legend=false))

结论

本文构建并研究了一种多维时间序列预测的混合方法,将OLS分解与余数的LSTM建模相结合。 所提出的方法表现出高质量:测试区域的预测误差为信号范围的≈2%(RMSE≈0.38–0.52,范围为≈25单位),与没有神经网络单元的模型相比,精度提高了3.5-4.5倍。

混合方案在广泛的应用中有需求:预测电网的能耗和负荷,需求和销售,财务和产品范围,气象和气候指标,技术过程和遥测参数,交通和物流。 经典分解为小样本提供了可解释性和稳定性,而LSTM考虑了其余部分中的非线性和长期依赖性。