2024/7/28周报

摘要

本周阅读了一篇基于LSTM和注意机制的水质预测的文章,以澳大利亚Burnett河为研究对象。本文利用LSTM和AT-LSTM模型对伯内特河溶解氧进行了一步预报和多步预报,并对预报结果进行了比较。研究结果表明,包含注意力机制提高了LSTM模型的预测性能。此外,还对自注意力机制等相关内容进行补充学习。

Abstract

This week, an article on water quality prediction based on LSTM and attention mechanism is readed. The author takes Burnett River in Australia as the research object. In this paper, LSTM and AT-LSTM models are used to make one-step and multi-step predictions of dissolved oxygen in Burnett River, and the prediction results are compared. The results show that including attention mechanism improves the prediction performance of LSTM model. In addition, self-attention mechanism and other related contents are supplemented.

文献阅读

题目

Water Quality Prediction Based on LSTM and Attention Mechanism: A Case Study of the Burnett River, Australia

引言

水质预测是指利用长期收集的水质数据,预测未来一段时间内可能出现的水质趋势。为提前评价水环境状况,预防水污染问题的大规模发生提供科学的决策依据。本研究以水质评价的关键参数溶解氧作为建模和预测评价的目标,在LSTM模型的基础上开发了一个AT-LSTM模型,重点是更好地捕捉水质变量。利用水质监测原始数据对澳大利亚伯内特河的溶解氧浓度进行了预测。

创新点

1) 本研究开发的模型在Burnett河断面水质数据特征提取后引入注意机制,考虑不同时刻序列对预测结果的影响,增强关键特征对预测结果的影响。
2) 本文利用LSTM和AT-LSTM模型对伯内特河溶解氧进行了一步预报和多步预测,并对预测结果进行了比较。

数据处理

研究区域和数据

本研究使用的数据是伯内特河自动监测站的水质数据,其位置和集水区边界如下图:
在这里插入图片描述

研究使用了2015年1月至2020年1月收集的伯内特河水质监测数据。数据每半小时收集一次,包括五个特征:水温(Temp)、pH值、溶解氧(DO)、电导率(EC)、叶绿素a(Chl-a)和浊度(NTU)。本文以39,752个特征的逐时水质数据和溶解氧作为输出变量:
在这里插入图片描述

溶解氧DO的变化如下所示:
在这里插入图片描述

缺失值处理

如果一次监测中只有一个指标缺失,则采用线性插值的方法进行数据填充。通过线性插值后,数据集成为等时间间隔的连续时间序列。

线性插值描述:假设在坐标(x0,y0)和坐标(x1,y1)之间存在缺失值(x,y),使用如下等式(1):
在这里插入图片描述

其中x是已知的,并且y的值如下等式(2)中获得:
在这里插入图片描述

如果连续缺失一个监测值,则删除监测时刻的数据,避免人为填充造成较大误差。

水质相关分析

使用皮尔逊相关系数描述变量之间的线性相关程度,如等式(3)所示:
在这里插入图片描述

本研究通过皮尔逊相关性检验,得出与水质预测指标DO相关的主要元素特征为pH、Chl-a和Temp。水质预测将把这些因子作为输入特征。

方法和模型

LSTM

LSTM网络适用于处理和预测时间序列中具有很长间隔和延迟的时间序列特征,在解决传统递归神经网络中容易出现的梯度消失和梯度爆炸问题方面也很有效。LSTM模型有一个输入门、一个输出门和一个遗忘门。
在这里插入图片描述
在这里插入图片描述

输入门和输出门主要用于控制输入特性和输出内容,而遗忘门主要用于决定存储单元中哪些存储器应该保留,哪些存储器可以遗忘。

Attention机制

在这里插入图片描述

注意力机制的本质是对于给定的目标,生成权重系数并与输入相乘,以识别输入中的哪些特征对目标重要,哪些特征不重要。

注意力的计算有三个步骤:第一步是计算Query和key之间的相似度以获得权重,常见的相似度函数有点积,拼接和感知器,第二步是使用softmax函数将这些权重归一化,第三步是将权重乘以相应的键值以获得最终的注意力。
计算权重系数W的公式如式(10)所示:
在这里插入图片描述

等式(11)将注意力权重系数W乘以值以获得包含注意力的输出a:
在这里插入图片描述

AT-LSTM模型

该模型的主要思想是通过对神经网络隐层元素进行自适应加权,减少无关因素对预测结果的影响,突出相关因素的影响,从而提高预测精度。模型框架如下图所示,主要组件是LSTM层和attention层。
在这里插入图片描述

模型结构和主要参数见下表:
在这里插入图片描述

实验结果

从下图中,可以看到AT-LSTM模型在Burnett River测试集的水质预测方面优于LSTM模型:
在这里插入图片描述

在图(b)中,蓝色曲线表示实际值,橙色曲线表示建模的预测值。虽然LSTM可以预测水质变化,但AT-LSTM的预测与实际值的差异较小,表明AT-LSTM的泛化能力比LSTM更强。
在这里插入图片描述

下表总结了LSTM和AT-LSTM模型在监测段中预测溶解氧DO任务的性能:
在这里插入图片描述

以下是两种模型多步预测结果的比较:
在这里插入图片描述

从这些表中可以看出,本文提出的方法在MAE,RMSE和R²等方面比起LSTM都有显著改善。

深度学习transformer代码实现

1 模型输入

输入部分包含两个模块,Embedding和Positional Encoding。

1.1 Embedding层

Embedding层的作用是将某种格式的输入数据,例如文本,转变为模型可以处理的向量表示,来描述原始数据所包含的信息。Embedding层输出的可以理解为当前时间步的特征,如果是文本任务,这里就可以是Word Embedding,如果是其他任务,就可以是任何合理方法所提取的特征。构建Embedding层的代码很简单,核心是借助torch提供的nn.Embedding,如下:

class Embeddings(nn.Module):
    def __init__(self, d_model, vocab):
        """
        类的初始化函数
        d_model:指词嵌入的维度
        vocab:指词表的大小
        """
        super(Embeddings, self).__init__()
        #之后就是调用nn中的预定义层Embedding,获得一个词嵌入对象self.lut
        self.lut = nn.Embedding(vocab, d_model)
        #最后就是将d_model传入类中
        self.d_model =d_model
    def forward(self, x):
        """
        Embedding层的前向传播逻辑
        参数x:这里代表输入给模型的单词文本通过词表映射后的one-hot向量
        将x传给self.lut并与根号下self.d_model相乘作为结果返回
        """
        embedds = self.lut(x)
        return embedds * math.sqrt(self.d_model)

1.2 位置编码

Positional Encodding位置编码的作用是为模型提供当前时间步的前后出现顺序的信息。

class PositionalEncoding(nn.Module):
    def __init__(self, d_model, dropout, max_len=5000):
        """
        位置编码器类的初始化函数
        
        共有三个参数,分别是
        d_model:词嵌入维度
        dropout: dropout触发比率
        max_len:每个句子的最大长度
        """
        super(PositionalEncoding, self).__init__()
        self.dropout = nn.Dropout(p=dropout)
        
        # Compute the positional encodings
        # 注意下面代码的计算方式与公式中给出的是不同的,但是是等价的,你可以尝试简单推导证明一下。
        # 这样计算是为了避免中间的数值计算结果超出float的范围,
        pe = torch.zeros(max_len, d_model)
        position = torch.arange(0, max_len).unsqueeze(1)
        div_term = torch.exp(torch.arange(0, d_model, 2) *
                             -(math.log(10000.0) / d_model))
        pe[:, 0::2] = torch.sin(position * div_term)
        pe[:, 1::2] = torch.cos(position * div_term)
        pe = pe.unsqueeze(0)
        self.register_buffer('pe', pe)
        
    def forward(self, x):
        x = x + Variable(self.pe[:, :x.size(1)], requires_grad=False)
        return self.dropout(x)

2 Encoder

2.1 编码器

编码器作用是用于对输入进行特征提取,为解码环节提供有效的语义信息整体来看编码器由N个编码器层简单堆叠而成,因此实现非常简单,代码如下:

# 定义一个clones函数,来更方便的将某个结构复制若干份
def clones(module, N):
    "Produce N identical layers."
    return nn.ModuleList([copy.deepcopy(module) for _ in range(N)])


class Encoder(nn.Module):
    """
    Encoder
    The encoder is composed of a stack of N=6 identical layers.
    """
    def __init__(self, layer, N):
        super(Encoder, self).__init__()
        # 调用时会将编码器层传进来,我们简单克隆N分,叠加在一起,组成完整的Encoder
        self.layers = clones(layer, N)
        self.norm = LayerNorm(layer.size)
        
    def forward(self, x, mask):
        "Pass the input (and mask) through each layer in turn."
        for layer in self.layers:
            x = layer(x, mask)
        return self.norm(x)

2.2 编码器层

class EncoderLayer(nn.Module):
    "EncoderLayer is made up of two sublayer: self-attn and feed forward"                                                                                                         
    def __init__(self, size, self_attn, feed_forward, dropout):
        super(EncoderLayer, self).__init__()
        self.self_attn = self_attn
        self.feed_forward = feed_forward
        self.sublayer = clones(SublayerConnection(size, dropout), 2)
        self.size = size   # embedding's dimention of model, 默认512

    def forward(self, x, mask):
        # attention sub layer
        x = self.sublayer[0](x, lambda x: self.self_attn(x, x, x, mask))
        # feed forward sub layer
        z = self.sublayer[1](x, self.feed_forward)
        return z

2.3注意力机制

def attention(query, key, value, mask=None, dropout=None):
    "Compute 'Scaled Dot Product Attention'"

    #首先取query的最后一维的大小,对应词嵌入维度
    d_k = query.size(-1)
    #按照注意力公式,将query与key的转置相乘,这里面key是将最后两个维度进行转置,再除以缩放系数得到注意力得分张量scores
    scores = torch.matmul(query, key.transpose(-2, -1)) / math.sqrt(d_k)
    
    #接着判断是否使用掩码张量
    if mask is not None:
        #使用tensor的masked_fill方法,将掩码张量和scores张量每个位置一一比较,如果掩码张量则对应的scores张量用-1e9这个置来替换
        scores = scores.masked_fill(mask == 0, -1e9)
        
    #对scores的最后一维进行softmax操作,使用F.softmax方法,这样获得最终的注意力张量
    p_attn = F.softmax(scores, dim = -1)
    
    #之后判断是否使用dropout进行随机置0
    if dropout is not None:
        p_attn = dropout(p_attn)
    
    #最后,根据公式将p_attn与value张量相乘获得最终的query注意力表示,同时返回注意力张量
    return torch.matmul(p_attn, value), p_attn

2.4多头注意力机制

class MultiHeadedAttention(nn.Module):
    def __init__(self, h, d_model, dropout=0.1):
        #在类的初始化时,会传入三个参数,h代表头数,d_model代表词嵌入的维度,dropout代表进行dropout操作时置0比率,默认是0.1
        super(MultiHeadedAttention, self).__init__()
        #在函数中,首先使用了一个测试中常用的assert语句,判断h是否能被d_model整除,这是因为我们之后要给每个头分配等量的词特征,也就是embedding_dim/head个
        assert d_model % h == 0
        #得到每个头获得的分割词向量维度d_k
        self.d_k = d_model // h
        #传入头数h
        self.h = h
        
        #创建linear层,通过nn的Linear实例化,它的内部变换矩阵是embedding_dim x embedding_dim,然后使用,为什么是四个呢,这是因为在多头注意力中,Q,K,V各需要一个,最后拼接的矩阵还需要一个,因此一共是四个
        self.linears = clones(nn.Linear(d_model, d_model), 4)
        #self.attn为None,它代表最后得到的注意力张量,现在还没有结果所以为None
        self.attn = None
        self.dropout = nn.Dropout(p=dropout)
        
    def forward(self, query, key, value, mask=None):
        #前向逻辑函数,它输入参数有四个,前三个就是注意力机制需要的Q,K,V,最后一个是注意力机制中可能需要的mask掩码张量,默认是None
        if mask is not None:
            # Same mask applied to all h heads.
            #使用unsqueeze扩展维度,代表多头中的第n头
            mask = mask.unsqueeze(1)
        #接着,我们获得一个batch_size的变量,他是query尺寸的第1个数字,代表有多少条样本
        nbatches = query.size(0)
        
        # 1) Do all the linear projections in batch from d_model => h x d_k 
        # 首先利用zip将输入QKV与三个线性层组到一起,然后利用for循环,将输入QKV分别传到线性层中,做完线性变换后,开始为每个头分割输入,这里使用view方法对线性变换的结构进行维度重塑,多加了一个维度h代表头,这样就意味着每个头可以获得一部分词特征组成的句子,其中的-1代表自适应维度,计算机会根据这种变换自动计算这里的值,然后对第二维和第三维进行转置操作,为了让代表句子长度维度和词向量维度能够相邻,这样注意力机制才能找到词义与句子位置的关系,从attention函数中可以看到,利用的是原始输入的倒数第一和第二维,这样我们就得到了每个头的输入
        query, key, value = \
            [l(x).view(nbatches, -1, self.h, self.d_k).transpose(1, 2)
             for l, x in zip(self.linears, (query, key, value))]

        # 2) Apply attention on all the projected vectors in batch. 
        # 得到每个头的输入后,接下来就是将他们传入到attention中,这里直接调用我们之前实现的attention函数,同时也将mask和dropout传入其中
        x, self.attn = attention(query, key, value, mask=mask, 
                                 dropout=self.dropout)

        # 3) "Concat" using a view and apply a final linear. 
        # 通过多头注意力计算后,我们就得到了每个头计算结果组成的4维张量,我们需要将其转换为输入的形状以方便后续的计算,因此这里开始进行第一步处理环节的逆操作,先对第二和第三维进行转置,然后使用contiguous方法。这个方法的作用就是能够让转置后的张量应用view方法,否则将无法直接使用,所以,下一步就是使用view重塑形状,变成和输入形状相同。  
        x = x.transpose(1, 2).contiguous() \
             .view(nbatches, -1, self.h * self.d_k)
        #最后使用线性层列表中的最后一个线性变换得到最终的多头注意力结构的输出
        return self.linears[-1](x)

3 Decoder

3.1 解码器整体结构

#使用类Decoder来实现解码器
class Decoder(nn.Module):
    "Generic N layer decoder with masking."
    def __init__(self, layer, N):
        #初始化函数的参数有两个,第一个就是解码器层layer,第二个是解码器层的个数N
        super(Decoder, self).__init__()
        #首先使用clones方法克隆了N个layer,然后实例化一个规范化层,因为数据走过了所有的解码器层后最后要做规范化处理。
        self.layers = clones(layer, N)
        self.norm = LayerNorm(layer.size)
        
    def forward(self, x, memory, src_mask, tgt_mask):
        #forward函数中的参数有4个,x代表目标数据的嵌入表示,memory是编码器层的输出,source_mask,target_mask代表源数据和目标数据的掩码张量,然后就是对每个层进行循环,当然这个循环就是变量x通过每一个层的处理,得出最后的结果,再进行一次规范化返回即可。
        for layer in self.layers:
            x = layer(x, memory, src_mask, tgt_mask)
        return self.norm(x)

3.2 解码器层

每个解码器层由三个子层连接结构组成,第一个子层连接结构包括一个多头自注意力子层和规范化层以及一个残差连接,第二个子层连接结构包括一个多头注意力子层和规范化层以及一个残差连接,第三个子层连接结构包括一个前馈全连接子层和规范化层以及一个残差连接。

#使用DecoderLayer的类实现解码器层
class DecoderLayer(nn.Module):
    "Decoder is made of self-attn, src-attn, and feed forward (defined below)"
    def __init__(self, size, self_attn, src_attn, feed_forward, dropout):
        #初始化函数的参数有5个,分别是size,代表词嵌入的维度大小,同时也代表解码器的尺寸,第二个是self_attn,多头自注意力对象,也就是说这个注意力机制需要Q=K=V,第三个是src_attn,多头注意力对象,这里Q!=K=V,第四个是前馈全连接层对象,最后就是dropout置0比率
        super(DecoderLayer, self).__init__()
        self.size = size
        self.self_attn = self_attn
        self.src_attn = src_attn
        self.feed_forward = feed_forward
        #按照结构图使用clones函数克隆三个子层连接对象
        self.sublayer = clones(SublayerConnection(size, dropout), 3)
 
    def forward(self, x, memory, src_mask, tgt_mask):
        #forward函数中的参数有4个,分别是来自上一层的输入x,来自编码器层的语义存储变量memory,以及源数据掩码张量和目标数据掩码张量,将memory表示成m之后方便使用。
        "Follow Figure 1 (right) for connections."
        m = memory
        #将x传入第一个子层结构,第一个子层结构的输入分别是x和self-attn函数,因为是自注意力机制,所以Q,K,V都是x,最后一个参数时目标数据掩码张量,这时要对目标数据进行遮掩,因为此时模型可能还没有生成任何目标数据。
        #比如在解码器准备生成第一个字符或词汇时,我们其实已经传入了第一个字符以便计算损失,但是我们不希望在生成第一个字符时模型能利用这个信息,因此我们会将其遮掩,同样生成第二个字符或词汇时,模型只能使用第一个字符或词汇信息,第二个字符以及之后的信息都不允许被模型使用。
        x = self.sublayer[0](x, lambda x: self.self_attn(x, x, x, tgt_mask))
        #接着进入第二个子层,这个子层中常规的注意力机制,q是输入x;k,v是编码层输出memory,同样也传入source_mask,但是进行源数据遮掩的原因并非是抑制信息泄露,而是遮蔽掉对结果没有意义的padding。
        x = self.sublayer[1](x, lambda x: self.src_attn(x, m, m, src_mask))
        
        #最后一个子层就是前馈全连接子层,经过它的处理后就可以返回结果,这就是我们的解码器结构
        return self.sublayer[2](x, self.feed_forward)

以下搭建出整个网络的结构:

# Model Architecture
#使用EncoderDecoder类来实现编码器-解码器结构
class EncoderDecoder(nn.Module):
    """
    A standard Encoder-Decoder architecture. 
    Base for this and many other models.
    """
    def __init__(self, encoder, decoder, src_embed, tgt_embed, generator):
        #初始化函数中有5个参数,分别是编码器对象,解码器对象,源数据嵌入函数,目标数据嵌入函数,以及输出部分的类别生成器对象.
        super(EncoderDecoder, self).__init__()
        self.encoder = encoder
        self.decoder = decoder
        self.src_embed = src_embed    # input embedding module(input embedding + positional encode)
        self.tgt_embed = tgt_embed    # ouput embedding module
        self.generator = generator    # output generation module
        
    def forward(self, src, tgt, src_mask, tgt_mask):
        "Take in and process masked src and target sequences."
        #在forward函数中,有四个参数,source代表源数据,target代表目标数据,source_mask和target_mask代表对应的掩码张量,在函数中,将source source_mask传入编码函数,得到结果后与source_mask target 和target_mask一同传给解码函数
        memory = self.encode(src, src_mask)
        res = self.decode(memory, src_mask, tgt, tgt_mask)
        return res
    
    def encode(self, src, src_mask):
        #编码函数,以source和source_mask为参数,使用src_embed对source做处理,然后和source_mask一起传给self.encoder
        src_embedds = self.src_embed(src)
        return self.encoder(src_embedds, src_mask)
    
    def decode(self, memory, src_mask, tgt, tgt_mask):
        #解码函数,以memory即编码器的输出,source_mask target target_mask为参数,使用tgt_embed对target做处理,然后和source_mask,target_mask,memory一起传给self.decoder
        target_embedds = self.tgt_embed(tgt)
        return self.decoder(target_embedds, memory, src_mask, tgt_mask)


# Full Model
def make_model(src_vocab, tgt_vocab, N=6, d_model=512, d_ff=2048, h=8, dropout=0.1):
    """
    构建模型
    params:
        src_vocab:
        tgt_vocab:
        N: 编码器和解码器堆叠基础模块的个数
        d_model: 模型中embedding的size,默认512
        d_ff: FeedForward Layer层中embedding的size,默认2048
        h: MultiHeadAttention中多头的个数,必须被d_model整除
        dropout:
    """
    c = copy.deepcopy
    attn = MultiHeadedAttention(h, d_model)
    ff = PositionwiseFeedForward(d_model, d_ff, dropout)
    position = PositionalEncoding(d_model, dropout)
    model = EncoderDecoder(
        Encoder(EncoderLayer(d_model, c(attn), c(ff), dropout), N),
        Decoder(DecoderLayer(d_model, c(attn), c(attn), c(ff), dropout), N),
        nn.Sequential(Embeddings(d_model, src_vocab), c(position)),
        nn.Sequential(Embeddings(d_model, tgt_vocab), c(position)),
        Generator(d_model, tgt_vocab))
    
    # This was important from their code. 
    # Initialize parameters with Glorot / fan_avg.
    for p in model.parameters():
        if p.dim() > 1:
            nn.init.xavier_uniform_(p)
    return model

下面用一个人造的玩具级的小任务,来实战体验下Transformer的训练,加深理解,并且验证代码是否work。任务描述:针对数字序列进行学习,学习的最终目标是使模型学会输出与输入的序列删除第一个字符之后的相同的序列,如输入[1,2,3,4,5],尝试让模型学会输出[2,3,4,5]:
训练大致流程如下:

# Train the simple copy task.
device = "cuda"
nrof_epochs = 20
batch_size = 32
V = 11    # 词典的数量
sequence_len = 15  # 生成的序列数据的长度
nrof_batch_train_epoch = 30    # 训练时每个epoch多少个batch                                                                                                                       
nrof_batch_valid_epoch = 10    # 验证时每个epoch多少个batch
criterion = LabelSmoothing(size=V, padding_idx=0, smoothing=0.0)
model = make_model(V, V, N=2)
optimizer = torch.optim.Adam(model.parameters(), lr=0, betas=(0.9, 0.98), eps=1e-9)
model_opt = NoamOpt(model.src_embed[0].d_model, 1, 400, optimizer)
if device == "cuda":
    model.cuda()

for epoch in range(nrof_epochs):
    print(f"\nepoch {epoch}")
    print("train...")
    model.train()
    data_iter = data_gen(V, sequence_len, batch_size, nrof_batch_train_epoch, device)   
    loss_compute = SimpleLossCompute(model.generator, criterion, model_opt)
    train_mean_loss = run_epoch(data_iter, model, loss_compute, device)
    print("valid...")
    model.eval()
    valid_data_iter = data_gen(V, sequence_len, batch_size, nrof_batch_valid_epoch, device)
    valid_loss_compute = SimpleLossCompute(model.generator, criterion, None)
    valid_mean_loss = run_epoch(valid_data_iter, model, valid_loss_compute, device)
    print(f"valid loss: {valid_mean_loss}")

训好模型后,使用贪心解码的策略,进行预测。
运行训练脚本,训练过程与预测结果打印如下:
在这里插入图片描述
测试用例[1,2,3,4,5,6,7,8,9,10] 的预测结果为[2,3,4,5,6,7,8,9,10],符合预期。

总结

Transformer 突破了 RNN 模型不能并行计算的限制,CNN需要增加卷积层数来扩大视野,RNN需要从1到n逐个进行计算,而self-attention只需要一步矩阵计算就可以。所以也可以看出,self-attention可以比rnn更好地解决长时依赖问题。自注意力可以产生更具可解释性的模型,self-attention模型更可解释,attention结果的分布表明了该模型学习到了一些语法和语义信息,我们可以从模型中检查注意力分布,各个注意头(attention head)可以学会执行不同的任务,有更强的建模能力。Transformer 通过验证的哲学来建立图节点之间的关系,具有较好的通用性:无论节点多么异构,它们之间的关系都可以通过投影到一个可以比较的空间里计算相似度来建立,在大模型和大数据方面展示了强大的可扩展性。

2024/1/1 123.75 141.44978233067818 2024/1/7 168.571428571429 164.58807061400717 2024/1/7 168.571428571429 88.90894227150248 2024/1/14 205 149.4715770893992 2024/1/16 52.5 136.41907987248615 2024/1/17 38.75 48.555230155374 2024/1/28 88.75 98.74711815669839 2024/2/2 32.857142857142904 50.54266038039505 2024/2/2 32.857142857142904 51.77056225639738 2024/2/5 82.5 97.3466728624111 2024/2/6 95 77.28656265637308 2024/2/7 110 82.90365797321212 2024/2/8 120 107.29023222927522 2024/2/10 151.428571428571 112.40124095463952 2024/2/11 116.25 121.88067651092562 2024/2/18 47.99999999999999 56.003677776515694 2024/2/19 67.5 55.847826096774526 2024/2/20 26.5 74.12894162493086 2024/2/22 47.1428571428572 50.037483558704345 2024/2/23 57.5 58.72629260822178 2024/2/23 57.5 59.90278324034665 2024/2/25 85 71.33576752872008 2024/2/28 122.5 108.9989900963616 2024/3/11 85 84.32848045698128 2024/3/16 100 75.57018610879334 2024/3/22 65 64.63852076852191 2024/3/24 36 62.39492082209007 2024/3/25 41 45.1101102285979 2024/3/28 56.6666666666667 66.59210042370242 2024/3/31 87.5 85.55500914218962 2024/4/1 54.16666666666671 51.4276556700062 2024/4/3 75 36.78731342930887 2024/4/3 75 73.76915442987828 2024/4/6 49.49999999999999 57.76058767045256 2024/4/7 56.25 59.90187152601827 2024/4/10 50.83333333333331 57.4928560934163 2024/4/11 63.75 51.59536811040737 2024/4/14 66.6666666666667 74.62430391378464 2024/4/16 44 49.86779586148121 2024/4/21 91.6666666666667 80.99920808671243 2024/4/25 94 95.1916784497183 2024/4/25 94 101.6468276165237 2024/4/26 123.636363636364 101.54226255724868 2024/5/1 47.1428571428572 58.50932702270208 2024/5/2 68.3333333333333 64.01621832767732 2024/5/4 40.5 53.42829426027681 2024/5/11 63 79.31938023373458 2024/5/13 123.636363636364 109.90295137443077 2024/5/14 121.818181818182 103.38721464003619 2024/5/22 50.83333333333331 55.79412608640662 2024/5/23 77.5 80.42939479500879 2024/5/27 73.3333333333333 71.32283060586244 2024/6/3 96.6666666666667 88.01209786222385 2024/6/9 68.3333333333333 108.56864781513396 2024/6/11 83.3333333333333 48.55482492203493 2024/6/13 110 88.15962441453412 2024/6/14 122.727272727273 107.61549578817458 2024/6/27 46.50000000000001 44.078713021115306 2024/6/29 33 26.44193350991658 2024/7/1 42 52.59867325205077 2024/7/3 44.5 89.82048738852457 2024/7/4 39 52.19653144726541 2024/7/5 47.99999999999999 48.08958368353323 2024/7/9 49 57.59646598524163 2024/7/9 49 53.60283014788386 2024/7/11 63.3333333333333 66.97868019503072 2024/7/17 53.3333333333333 63.34636274774507 2024/7/19 41.5 42.89947272348277 2024/7/21 64.1666666666667 66.09878524599225 2024/7/22 66.6666666666667 65.00890057786901 2024/7/26 45.00000000000001 71.21665897622492 2024/7/28 40.5 44.13470403198099 2024/8/1 44.5 47.583181504691126 2024/8/2 45.00000000000001 47.583181504691126 2024/8/2 45.00000000000001 46.9087841595428 2024/8/3 51.6666666666667 45.23014594969053 2024/8/4 55.8333333333333 58.65054857410897 2024/8/6 68.3333333333333 54.60578952020746 2024/8/9 62.5 65.85809400034259 2024/8/10 75.8333333333333 71.9206795742283 2024/8/11 94.1666666666667 70.96740036589514 2024/8/15 90 80.34604289750527 2024/8/18 90 94.47656346062271 2024/8/22 81.6666666666667 86.53461449155253 2024/8/22 81.6666666666667 108.27781523932805 2024/8/23 65.8333333333333 82.53817106629121 2024/9/3 88.3333333333333 113.16247944014161 2024/9/3 88.3333333333333 88.23748357200765 2024/9/8 108.181818181818 101.89782847813537 2024/9/9 115.454545454545 96.45857559537323 2024/9/13 44 50.29448003948117 2024/9/18 80 83.8067648044246 2024/9/28 75 72.56515720406895 2024/9/29 100 70.64652960614046 2024/10/2 74.1666666666667 60.570719215034764 2024/10/5 102.727272727273 93.99401752385478 2024/10/11 130.909090909091 91.43861631520019 2024/10/11 130.909090909091 107.36748520058795 2024/10/13 63.75 70.11378396004059 2024/10/15 86.6666666666667 85.31855469197326 2024/10/16 71.6666666666667 67.85859636969488 2024/10/17 35.5 40.568489434724526 2024/10/22 37.5 41.13715300481026 2024/10/24 75.8333333333333 75.07703363794025 2024/10/26 56.6666666666667 59.31423576916348 2024/10/27 67.5 77.72187997314686 2024/10/30 78.3333333333333 74.72658701406004 2024/11/1 71.6666666666667 74.32719194724612 2024/11/1 71.6666666666667 78.99471579045824 2024/11/3 107.5 96.12724021398316 2024/11/5 55 88.70741079334934 2024/11/5 55 63.17230961245132 2024/11/7 70.8333333333333 69.40951088280127 2024/11/8 52.5 70.58982172647461 2024/11/9 50.5 65.39850926077335 2024/11/11 61.6666666666667 67.08648185133565 2024/11/13 66.6666666666667 67.06290561067581 2024/11/14 69.1666666666667 74.92724767621056 2024/11/16 62.5 67.72309837940713 2024/11/20 31.25 39.791267230677306 2024/11/21 56.25 53.09328772113596 2024/11/21 56.25 45.96954038585586 2024/11/22 67.5 55.89475640940251 2024/11/22 67.5 72.07171621764438 2024/11/29 60 63.75168781309595 2024/12/3 121.25 123.51751061089429 2024/12/3 121.25 85.35092998366582 2024/12/4 78.75 118.96571575050625 2024/12/5 48.5714285714286 77.23522342869911 2024/12/5 48.5714285714286 56.760071551348034 2024/12/6 50.00000000000001 55.67542260586588 2024/12/9 63.75 77.29555462085865 2024/12/11 90 91.88546031226497 2024/12/11 90 87.43060672017323 2024/12/12 105 89.23105190131274 2024/12/12 105 83.14521582557892 2024/12/28 44 51.14349839579385 2024/12/29 73.75 70.82581380052193 2024/12/31 145 113.7323729139217 2025/1/2 174.285714285714 158.40406690058774 2025/1/3 204 168.67990876026008 2025/1/4 157.142857142857 131.7945723625761 2025/1/5 75 92.88837622077833 2025/1/6 77.5 90.9308700022185 2025/1/10 44.28571428571429 53.946620996090516 2025/1/10 44.28571428571429 49.57827863490396 2025/1/11 78.75 78.29644384995049 2025/1/12 81.25 73.87610905688891 2025/1/13 106.25 80.38639509127034 2025/1/20 151.428571428571 136.6081186621433 2025/1/21 133.75 129.94744729140956 2025/1/22 135 130.24655227366316 2025/1/24 91.25 146.3767752344893 2025/1/27 55 71.46727057951108 2025/1/28 62.5 66.31463541778702 2025/2/1 67.5 71.37098161035166 2025/2/2 58.75 66.17426845 2025/2/5 58.75 88.75667212785046 2025/2/8 39 77.88252871091174 2025/2/9 45.7142857142857 52.18881850959389 2025/2/15 86.25 82.4133355641056 2025/2/16 82.5 80.27288373068554 2025/2/19 63.75 77.16937696990621 2025/2/23 116.25 86.76096912509652 2025/2/24 120 100.18931943988112 2025/2/28 76.25 62.27437528664383 2025/3/3 28 49.49588667705353 2025/3/4 42.857142857142904 31.204205454247344 2025/3/5 48.5714285714286 57.89927257633713 2025/3/6 72.5 63.413358717767835 2025/3/7 80 78.92374488524504 2025/3/9 80 74.84065901246376 2025/3/9 80 86.94889436125919 2025/3/11 65 68.96484811264284 2025/3/15 42.5 47.68307768671133 2025/3/17 54.16666666666671 54.844184083948534 2025/3/19 70 71.32317723530358 2025/3/21 75.8333333333333 76.9746305766928 2025/3/24 70 74.65521786082064 2025/3/29 70 77.40180710328875 2025/4/1 71 80.57870505575087 2025/4/2 81.6666666666667 81.99531424941331 2025/4/5 84.1666666666667 78.8368811413689 2025/4/6 97.5 94.72271732958869 2025/4/7 84.1666666666667 89.88488096255729 2025/4/14 98 95.67823824552184 2025/4/21 42 111.53290689851633 2025/4/23 81.6666666666667 57.141737161191365 2025/4/24 61.5 83.99447487776038 2025/4/26 91.6666666666667 84.24149848760464 2025/4/27 58.3333333333333 62.870282372247104 2025/4/28 95 59.83136943842301 2025/4/30 68.3333333333333 73.1449341049362 2025/5/1 80.8333333333333 82.50448713333525 2025/5/2 86.6666666666667 83.55990976104009 2025/5/3 80.8333333333333 87.13972460673028 2025/5/4 103.636363636364 98.5090122230891 2025/5/7 135.5 94.65732498676186 2025/5/7 135.5 118.08517354632647 2025/5/10 50.00000000000001 56.534837994279506 2025/5/15 50.83333333333331 55.91271636914875 2025/5/19 80 80.8946332197781 2025/5/21 55.8333333333333 57.6135692788171 2025/5/22 38.5 42.75042106739687 2025/5/22 38.5 63.47590727436925 2025/5/24 80.8333333333333 73.64128586482872 2025/5/25 123.636363636364 79.50115966335561 2025/5/27 97.5 106.27753198307643 2025/5/28 64.1666666666667 69.30680223618985 2025/5/31 33.5 70.81933813357111 2025/5/31 33.5 34.34381152519421 2025/6/1 43 38.11541438169796 2025/6/11 65.8333333333333 40.703264716877996 2025/6/14 44.5 71.8059471813712 2025/6/15 67.5 47.3519258804609 2025/6/16 80.8333333333333 76.75751861199961 2025/6/18 40.5 56.99724051629258 2025/6/21 52.5 50.91048391171709 2025/6/24 67.5 70.32261502977192 2025/6/25 85.8333333333333 83.64395823861886 2025/6/26 47.99999999999999 47.11187595527804 2025/6/26 47.99999999999999 82.26586779001731 2025/6/27 27.5 32.61973525719978 2025/6/29 33 38.471384454153934 2025/7/2 40.5 41.8137903149492 2025/7/3 41.5 41.55174601833187 2025/7/4 62.5 42.555910187138494 2025/7/6 89.1666666666667 67.94355289605272 2025/7/10 47.99999999999999 50.420961530730615 2025/7/12 38.5 53.933623933134314 2025/7/13 61.6666666666667 68.87604276458451 2025/7/14 57.5 75.07816532 2025/7/15 63.3333333333333 61.27539132564982 2025/7/16 61.6666666666667 61.2199272323314 2025/7/18 89.1666666666667 85.1940043760954 2025/7/19 109.090909090909 85.80104582479294 2025/7/21 44.5 51.048631974115125 2025/7/23 47 68.68200192813825 2025/7/24 70.8333333333333 72.70514810854169 2025/7/24 70.8333333333333 66.72884559566981 2025/7/28 41.5 44.24787044978878 2025/7/31 68.3333333333333 68.10199967482542 2025/8/1 58.3333333333333 57.21891596330586 2025/8/2 66.6666666666667 73.0065068273534 2025/8/2 66.6666666666667 59.566026288096104 2025/8/3 85 83.71691559565357 2025/8/3 85 79.21006390845372 2025/8/8 47.99999999999999 60.629516790631705 2025/8/17 67.5 46.08474692761816 2025/8/18 55 71.73300540615286 2025/8/21 43.5 42.74603613157312 2025/8/26 95 96.662891741162 2025/8/27 80 96.21714056534087 2025/8/28 85 72.027393057495 2025/9/1 60 47.6061644310276 2025/9/3 74.1666666666667 68.11991657351632 2025/9/4 68.3333333333333 70.02119887103083 2025/9/5 73.3333333333333 70.02119887103083 2025/9/5 73.3333333333333 70.89262161791024 2025/9/21 32 35.474220745225495 2025/9/23 29.5 47.931426661999886 2025/9/25 25.5 33.93622542134888 2025/9/25 25.5 36.402784316544256 2025/9/29 32.5 37.61827081824134 列名依次为时间、真实值、预测值,对以上预测结果进行分析
最新发布
11-26
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值