国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

時(shí)間序列預(yù)測(cè)實(shí)戰(zhàn)(二十五)PyTorch實(shí)現(xiàn)Seq2Seq進(jìn)行多元和單元預(yù)測(cè)(附代碼+數(shù)據(jù)集+完整解析)

這篇具有很好參考價(jià)值的文章主要介紹了時(shí)間序列預(yù)測(cè)實(shí)戰(zhàn)(二十五)PyTorch實(shí)現(xiàn)Seq2Seq進(jìn)行多元和單元預(yù)測(cè)(附代碼+數(shù)據(jù)集+完整解析)。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

一、本文介紹

本文給大家?guī)淼臅r(shí)間序列模型是Seq2Seq,這個(gè)概念相信大家都不陌生了,網(wǎng)上的講解已經(jīng)滿天飛了,但是本文給大家?guī)淼氖俏以赟eq2Seq思想上開發(fā)的一個(gè)模型和新的架構(gòu),架構(gòu)前面的文章已經(jīng)說過很多次了,其是專門為新手開發(fā)的,而且為了方便大家使用只定義了一個(gè)文件方便大家復(fù)制粘貼,架構(gòu)功能包括:結(jié)果可視化、支持單元預(yù)測(cè)、多元預(yù)測(cè)、模型擬合效果檢測(cè)、預(yù)測(cè)未知數(shù)據(jù)、以及滾動(dòng)長(zhǎng)期預(yù)測(cè)功能。Seq2Seq模型是一種處理序列數(shù)據(jù)的深度學(xué)習(xí)模型,廣泛用于機(jī)器翻譯、語(yǔ)音識(shí)別和文本摘要等任務(wù)(也能用于時(shí)間序列)。其核心思想是編碼器-解碼器。

需要注意得是本文的模型和結(jié)構(gòu)均為自研,在Seq2Seq的思想上進(jìn)行了一定的擴(kuò)展。

??專欄目錄:時(shí)間序列預(yù)測(cè)目錄:深度學(xué)習(xí)、機(jī)器學(xué)習(xí)、融合模型、創(chuàng)新模型實(shí)戰(zhàn)案例

專欄:?時(shí)間序列預(yù)測(cè)專欄:基礎(chǔ)知識(shí)+數(shù)據(jù)分析+機(jī)器學(xué)習(xí)+深度學(xué)習(xí)+Transformer+創(chuàng)新模型

預(yù)測(cè)功能效果展示(不是測(cè)試集是預(yù)測(cè)未知數(shù)據(jù),所以圖中沒有對(duì)比的數(shù)據(jù))->

時(shí)間序列預(yù)測(cè)實(shí)戰(zhàn)(二十五)PyTorch實(shí)現(xiàn)Seq2Seq進(jìn)行多元和單元預(yù)測(cè)(附代碼+數(shù)據(jù)集+完整解析),時(shí)間序列預(yù)測(cè)專欄,pytorch,人工智能,python,深度學(xué)習(xí),時(shí)序數(shù)據(jù)庫(kù),數(shù)據(jù)分析

損失截圖(損失這里我先展示一個(gè)訓(xùn)練過程中的后面會(huì)自動(dòng)生成損失圖像)->?

根據(jù)損失來看模型的擬合效果還是很好的,但后面還是做了檢驗(yàn)?zāi)P蛿M合效果的功能讓大家真正的評(píng)估模型的效果。

時(shí)間序列預(yù)測(cè)實(shí)戰(zhàn)(二十五)PyTorch實(shí)現(xiàn)Seq2Seq進(jìn)行多元和單元預(yù)測(cè)(附代碼+數(shù)據(jù)集+完整解析),時(shí)間序列預(yù)測(cè)專欄,pytorch,人工智能,python,深度學(xué)習(xí),時(shí)序數(shù)據(jù)庫(kù),數(shù)據(jù)分析

?

測(cè)試集狀況->

這個(gè)結(jié)構(gòu)是我發(fā)這么多基礎(chǔ)模型里效果最好的,模型擬合和測(cè)試集表現(xiàn)均為最好。

時(shí)間序列預(yù)測(cè)實(shí)戰(zhàn)(二十五)PyTorch實(shí)現(xiàn)Seq2Seq進(jìn)行多元和單元預(yù)測(cè)(附代碼+數(shù)據(jù)集+完整解析),時(shí)間序列預(yù)測(cè)專欄,pytorch,人工智能,python,深度學(xué)習(xí),時(shí)序數(shù)據(jù)庫(kù),數(shù)據(jù)分析

目錄

一、本文介紹

二、Seq2Seq思想原理

2.1 Seq2Seq的基本原理

2.1.1 編碼器-解碼器介紹

2.1.2 編碼器-解碼器結(jié)構(gòu)圖

三、數(shù)據(jù)集介紹

四、參數(shù)講解?

五、完整代碼

六、訓(xùn)練模型?

七、預(yù)測(cè)結(jié)果

7.1 預(yù)測(cè)未知數(shù)據(jù)效果圖

7.2 測(cè)試集效果圖?

7.3 CSV文件生成效果圖?

7.4 檢驗(yàn)?zāi)P蛿M合效果圖

八、全文總結(jié)


二、Seq2Seq思想原理

時(shí)間序列預(yù)測(cè)實(shí)戰(zhàn)(二十五)PyTorch實(shí)現(xiàn)Seq2Seq進(jìn)行多元和單元預(yù)測(cè)(附代碼+數(shù)據(jù)集+完整解析),時(shí)間序列預(yù)測(cè)專欄,pytorch,人工智能,python,深度學(xué)習(xí),時(shí)序數(shù)據(jù)庫(kù),數(shù)據(jù)分析


2.1 Seq2Seq的基本原理

Seq2Seq(Sequence-to-Sequence)模型是一種處理序列數(shù)據(jù)的深度學(xué)習(xí)模型,廣泛用于機(jī)器翻譯、語(yǔ)音識(shí)別和文本摘要等任務(wù)。其核心思想是將一個(gè)序列(如一句話)轉(zhuǎn)換成另一個(gè)序列,這兩個(gè)序列的長(zhǎng)度可以不同。

Seq2Seq模型主要包括以下幾個(gè)機(jī)制和原理:

1. 編碼器-解碼器架構(gòu):Seq2Seq模型通常由兩部分組成,編碼器和解碼器。編碼器負(fù)責(zé)讀取并理解輸入序列,將其轉(zhuǎn)換成一個(gè)固定長(zhǎng)度的上下文向量(context vector)。解碼器則利用這個(gè)上下文向量生成目標(biāo)序列(其實(shí)最核心的就是這個(gè),下面都是具體的應(yīng)用了)

2. 循環(huán)神經(jīng)網(wǎng)絡(luò)(RNN):在傳統(tǒng)的Seq2Seq模型中,編碼器和解碼器通常是循環(huán)神經(jīng)網(wǎng)絡(luò)(如LSTM或GRU)。RNN可以處理不同長(zhǎng)度的輸入序列,并在其隱藏層保持序列的狀態(tài)信息。

3.注意力機(jī)制(Attention):注意力機(jī)制是后來引入Seq2Seq模型的一項(xiàng)重要改進(jìn)。它允許模型在生成每個(gè)目標(biāo)詞時(shí)“關(guān)注”輸入序列的不同部分,從而提高了模型處理長(zhǎng)句子時(shí)的效果和準(zhǔn)確性。

4. 長(zhǎng)短期記憶網(wǎng)絡(luò)(LSTM)/門控循環(huán)單元(GRU):為了解決RNN中的長(zhǎng)期依賴問題,LSTM和GRU這樣的網(wǎng)絡(luò)結(jié)構(gòu)被引入。它們能更好地捕捉序列中的長(zhǎng)期依賴關(guān)系。

個(gè)人總結(jié):我個(gè)人覺得Seq2Seq模型就像是學(xué)習(xí)語(yǔ)言的人。首先通過“編碼器”理解輸入的句子,然后用“解碼器”來表達(dá)新的句子。就像我們學(xué)外語(yǔ)時(shí)先理解一句話的意思,再用自己的語(yǔ)言表達(dá)出來。加上“注意力機(jī)制”,模型還能更聰明地關(guān)注輸入句子中最重要的部分,就好比我們?cè)诼爠e人說話時(shí)會(huì)注意對(duì)方重點(diǎn)強(qiáng)調(diào)的內(nèi)容。


2.1.1 編碼器-解碼器介紹

通過上面我們知道Seq2Seq的主要核心思想是編碼器和解碼器,Seq2Seq一開始被發(fā)明出來是用于一些本文處理的,但是本文是時(shí)間序列領(lǐng)域的文章,所以我主要講解一下編碼器-解碼器在時(shí)間序列領(lǐng)域的應(yīng)用(大家需要注意的是這里的編碼器和解碼器和Transformer當(dāng)中的還不一樣是有著根本的區(qū)別的)。Seq2Seq模型的編碼器和解碼器如下工作:

編碼器在時(shí)間序列領(lǐng)域的作用是理解和編碼輸入序列的歷史數(shù)據(jù)。

1. 處理時(shí)間序列輸入:編碼器接收時(shí)間序列數(shù)據(jù),例如過去幾天的股票價(jià)格或氣溫記錄。這些數(shù)據(jù)通常是連續(xù)的數(shù)值。

2. 特征提?。?/strong>通過RNN(本文是用的GRU,類似于LSTM和RNN以后也會(huì)單獨(dú)出文章)網(wǎng)絡(luò),編碼器可以捕捉時(shí)間序列的特征和內(nèi)在模式。RNN通過其時(shí)間遞歸結(jié)構(gòu),有效地處理時(shí)間序列數(shù)據(jù)中的時(shí)序依賴關(guān)系。

3. 上下文向量:編碼器輸出一個(gè)上下文向量,該向量是輸入時(shí)間序列的壓縮表示,包含了對(duì)過去數(shù)據(jù)的理解和總結(jié)。

解碼器在時(shí)間序列領(lǐng)域的作用是基于編碼器提供的信息來預(yù)測(cè)未來的時(shí)間序列數(shù)據(jù)。

1. 初始狀態(tài)和輸入:解碼器的初始狀態(tài)通常由編碼器的最終狀態(tài)設(shè)置。解碼器的第一個(gè)輸入可能是序列的最后一個(gè)觀測(cè)值或特殊標(biāo)記(我設(shè)置為解碼器的輸入是編碼器的最后一個(gè)輸出,因?yàn)槲矣X得這個(gè)狀態(tài)的過去信息是最足的)。

2. 逐步預(yù)測(cè):在每個(gè)時(shí)間步,解碼器基于當(dāng)前狀態(tài)和前一步的預(yù)測(cè)輸出(或初始輸入)來生成下一個(gè)時(shí)間點(diǎn)的預(yù)測(cè)值。

3. 迭代更新:解碼器的輸出用于更新其狀態(tài),并作為下一個(gè)時(shí)間步的輸入。這個(gè)過程在生成整個(gè)預(yù)測(cè)序列期間重復(fù)進(jìn)行。

4. 序列生成:這個(gè)過程持續(xù)進(jìn)行,直到生成了預(yù)定長(zhǎng)度的預(yù)測(cè)序列。

總結(jié):在時(shí)間序列領(lǐng)域,Seq2Seq模型的編碼器-解碼器結(jié)構(gòu)使其能夠有效處理具有復(fù)雜時(shí)間依賴性的序列數(shù)據(jù)。編碼器學(xué)習(xí)并壓縮歷史數(shù)據(jù)的關(guān)鍵信息,而解碼器則利用這些信息來預(yù)測(cè)未來的趨勢(shì)和模式。


2.1.2 編碼器-解碼器結(jié)構(gòu)圖

下面的圖是我編碼器-解碼器的結(jié)構(gòu)圖,其中包含了編碼器(Encoder)和解碼器(Decoder)的具體實(shí)現(xiàn)細(xì)節(jié)(需要注意的是這個(gè)圖和本文模型無關(guān),這里舉出來只是為了讓大家對(duì)編碼器和解碼器的流程有一個(gè)更清晰的認(rèn)知)。下面是對(duì)這個(gè)圖示的詳細(xì)解釋:

時(shí)間序列預(yù)測(cè)實(shí)戰(zhàn)(二十五)PyTorch實(shí)現(xiàn)Seq2Seq進(jìn)行多元和單元預(yù)測(cè)(附代碼+數(shù)據(jù)集+完整解析),時(shí)間序列預(yù)測(cè)專欄,pytorch,人工智能,python,深度學(xué)習(xí),時(shí)序數(shù)據(jù)庫(kù),數(shù)據(jù)分析

編碼器部分(左側(cè))

  • 嵌入層(Embed):這個(gè)層將輸入的一熱編碼(one-hot vector)轉(zhuǎn)換為嵌入向量。在此圖中,嵌入層將每個(gè)輸入token轉(zhuǎn)換為一個(gè)256維的向量。

  • GRU層:門控循環(huán)單元(Gated Recurrent Unit,GRU)是RNN的一種變體,可以捕捉長(zhǎng)期依賴關(guān)系,同時(shí)緩解了傳統(tǒng)RNN的梯度消失問題。在此模型中,每個(gè)時(shí)間步的GRU層接收前一時(shí)間步的隱藏狀態(tài)和當(dāng)前時(shí)間步的嵌入向量,然后輸出新的隱藏狀態(tài)。

  • 時(shí)間步(t):時(shí)間步是序列中的位置指示,從t=?2開始,直至t=0,表示輸入序列的處理進(jìn)程。

  • 位置標(biāo)記(Pos. = T):這可能表示當(dāng)前處理的token位于輸入序列的最后一個(gè)位置,意味著編碼器即將完成對(duì)輸入序列的處理。

解碼器部分(右側(cè))

  • 嵌入層:解碼器的嵌入層將一熱編碼的輸出token轉(zhuǎn)換為嵌入向量。

  • GRU層:解碼器的GRU層接收來自上一時(shí)間步的隱藏狀態(tài)和當(dāng)前時(shí)間步的嵌入向量(或初始狀態(tài)從編碼器傳來的上下文向量),然后輸出新的隱藏狀態(tài)。

  • 全連接層:在每個(gè)時(shí)間步,全連接層將GRU的輸出轉(zhuǎn)換為詞匯表大小的向量,這個(gè)向量包含了輸出序列中下一個(gè)token的概率分布。

  • 輸出概率:這是解碼器產(chǎn)生的,表示下一個(gè)可能輸出token的概率分布。

  • SOS:這是“Start of Sequence”的縮寫,表示解碼器開始生成序列的信號(hào)。

  • 時(shí)間步(t):在解碼器部分,時(shí)間步從t=1開始,直至t=T+1,其中T可能表示目標(biāo)序列的長(zhǎng)度。

整個(gè)過程是這樣的:編碼器讀取輸入序列的token,并逐個(gè)更新其隱藏狀態(tài)。當(dāng)編碼器讀取完所有的輸入token后,最后的隱藏狀態(tài)(?0?)被傳遞到解碼器作為其初始狀態(tài)。解碼器從一個(gè)特殊的SOS token開始,逐步生成輸出序列的token。在每一步,解碼器基于當(dāng)前的隱藏狀態(tài)和上一步產(chǎn)生的token,預(yù)測(cè)下一個(gè)token,直到生成EOS token,表示序列生成結(jié)束。

概念部分的就講這么多,網(wǎng)上有很多概念理解的好博客,大家有興趣都可以自己查找看看,本文是實(shí)戰(zhàn)博客內(nèi)容不多講啦~?


三、數(shù)據(jù)集介紹

本文是實(shí)戰(zhàn)講解文章,上面主要是簡(jiǎn)單講解了一下網(wǎng)絡(luò)結(jié)構(gòu)比較具體的流程還是很復(fù)雜的涉及到很多的數(shù)學(xué)計(jì)算,下面我們來講一講模型的實(shí)戰(zhàn)內(nèi)容,第一部分是我利用的數(shù)據(jù)集。

本文我們用到的數(shù)據(jù)集是ETTh1.csv,該數(shù)據(jù)集是一個(gè)用于時(shí)間序列預(yù)測(cè)的電力負(fù)荷數(shù)據(jù)集,它是 ETTh 數(shù)據(jù)集系列中的一個(gè)。ETTh 數(shù)據(jù)集系列通常用于測(cè)試和評(píng)估時(shí)間序列預(yù)測(cè)模型。以下是 ETTh1.csv 數(shù)據(jù)集的一些內(nèi)容:

數(shù)據(jù)內(nèi)容:該數(shù)據(jù)集通常包含有關(guān)電力系統(tǒng)的多種變量,如電力負(fù)荷、價(jià)格、天氣情況等。這些變量可以用于預(yù)測(cè)未來的電力需求或價(jià)格。

時(shí)間范圍和分辨率數(shù)據(jù)通常按小時(shí)或天記錄,涵蓋了數(shù)月或數(shù)年的時(shí)間跨度。具體的時(shí)間范圍和分辨率可能會(huì)根據(jù)數(shù)據(jù)集的版本而異。?

以下是該數(shù)據(jù)集的部分截圖->

時(shí)間序列預(yù)測(cè)實(shí)戰(zhàn)(二十五)PyTorch實(shí)現(xiàn)Seq2Seq進(jìn)行多元和單元預(yù)測(cè)(附代碼+數(shù)據(jù)集+完整解析),時(shí)間序列預(yù)測(cè)專欄,pytorch,人工智能,python,深度學(xué)習(xí),時(shí)序數(shù)據(jù)庫(kù),數(shù)據(jù)分析


四、參數(shù)講解?


    parser.add_argument('-model', type=str, default='RNN', help="模型持續(xù)更新")
    parser.add_argument('-window_size', type=int, default=126, help="時(shí)間窗口大小, window_size > pre_len")
    parser.add_argument('-pre_len', type=int, default=24, help="預(yù)測(cè)未來數(shù)據(jù)長(zhǎng)度")
    # data
    parser.add_argument('-shuffle', action='store_true', default=True, help="是否打亂數(shù)據(jù)加載器中的數(shù)據(jù)順序")
    parser.add_argument('-data_path', type=str, default='ETTh1-Test.csv', help="你的數(shù)據(jù)數(shù)據(jù)地址")
    parser.add_argument('-target', type=str, default='OT', help='你需要預(yù)測(cè)的特征列,這個(gè)值會(huì)最后保存在csv文件里')
    parser.add_argument('-input_size', type=int, default=7, help='你的特征個(gè)數(shù)不算時(shí)間那一列')
    parser.add_argument('-feature', type=str, default='M', help='[M, S, MS],多元預(yù)測(cè)多元,單元預(yù)測(cè)單元,多元預(yù)測(cè)單元')

    # learning
    parser.add_argument('-lr', type=float, default=0.001, help="學(xué)習(xí)率")
    parser.add_argument('-drop_out', type=float, default=0.05, help="隨機(jī)丟棄概率,防止過擬合")
    parser.add_argument('-epochs', type=int, default=20, help="訓(xùn)練輪次")
    parser.add_argument('-batch_size', type=int, default=16, help="批次大小")
    parser.add_argument('-save_path', type=str, default='models')

    # model
    parser.add_argument('-hidden_size', type=int, default=64, help="隱藏層單元數(shù)")
    parser.add_argument('-kernel_sizes', type=int, default=3)
    parser.add_argument('-laryer_num', type=int, default=2)
    # device
    parser.add_argument('-use_gpu', type=bool, default=True)
    parser.add_argument('-device', type=int, default=0, help="只設(shè)置最多支持單個(gè)gpu訓(xùn)練")

    # option
    parser.add_argument('-train', type=bool, default=True)
    parser.add_argument('-test', type=bool, default=True)
    parser.add_argument('-predict', type=bool, default=True)
    parser.add_argument('-inspect_fit', type=bool, default=True)
    parser.add_argument('-lr-scheduler', type=bool, default=True)

為了大家方便理解,文章中的參數(shù)設(shè)置我都用的中文,所以大家應(yīng)該能夠更好的理解。下面我在進(jìn)行一遍講解。?

參數(shù)名稱 參數(shù)類型 參數(shù)講解
1 model str 模型名稱
2 window_size int 時(shí)間窗口大小,用多少條數(shù)據(jù)去預(yù)測(cè)未來的數(shù)據(jù)

3

pre_len int 預(yù)測(cè)多少條未來的數(shù)據(jù)
4 shuffle store_true 是否打亂輸入dataloader中的數(shù)據(jù),不是數(shù)據(jù)的順序

5

data_path str 你輸入數(shù)據(jù)的地址
6 target str 你想要預(yù)測(cè)的特征列

7

input_size int 輸入的特征數(shù)不包含時(shí)間那一列!??!

8

feature str [M, S, MS],多元預(yù)測(cè)多元,單元預(yù)測(cè)單元,多元預(yù)測(cè)單元
9 lr float 學(xué)習(xí)率大小

10

drop_out

float 丟棄概率
11 epochs int 訓(xùn)練輪次

12

batch_size int 批次大小
13 svae_path str 模型的保存路徑

14

hidden_size int 隱藏層大小
15 kernel_size int 卷積核大小

16

layer_num int lstm層數(shù)
17 use_gpu bool 是否使用GPU

18

device int GPU編號(hào)
19 train bool 是否進(jìn)行訓(xùn)練

20

predict bool 是否進(jìn)行預(yù)測(cè)

21

inspect_fit bool 是否進(jìn)行檢驗(yàn)?zāi)P?/td>
22 lr_schduler bool 是否使用學(xué)習(xí)率計(jì)劃

五、完整代碼

復(fù)制粘貼到一個(gè)文件下并且按照上面的從參數(shù)講解配置好參數(shù)即可運(yùn)行~(極其適合新手和剛?cè)腴T的讀者)

import argparse
import time
import numpy as np
import pandas as pd
import torch
import torch.nn as nn
from matplotlib import pyplot as plt
from torch.utils.data import DataLoader
from torch.utils.data import Dataset
from tqdm import tqdm
import torch.nn.functional as F

# 隨機(jī)數(shù)種子
np.random.seed(0)


class StandardScaler():
    def __init__(self):
        self.mean = 0.
        self.std = 1.

    def fit(self, data):
        self.mean = data.mean(0)
        self.std = data.std(0)

    def transform(self, data):
        mean = torch.from_numpy(self.mean).type_as(data).to(data.device) if torch.is_tensor(data) else self.mean
        std = torch.from_numpy(self.std).type_as(data).to(data.device) if torch.is_tensor(data) else self.std
        return (data - mean) / std

    def inverse_transform(self, data):
        mean = torch.from_numpy(self.mean).type_as(data).to(data.device) if torch.is_tensor(data) else self.mean
        std = torch.from_numpy(self.std).type_as(data).to(data.device) if torch.is_tensor(data) else self.std
        if data.shape[-1] != mean.shape[-1]:
            mean = mean[-1:]
            std = std[-1:]
        return (data * std) + mean


def plot_loss_data(data):
    # 使用Matplotlib繪制線圖
    plt.figure()
    plt.figure(figsize=(10, 5))
    plt.plot(data, marker='o')

    # 添加標(biāo)題
    plt.title("loss results Plot")

    # 顯示圖例
    plt.legend(["Loss"])

    plt.show()


class TimeSeriesDataset(Dataset):
    def __init__(self, sequences):
        self.sequences = sequences

    def __len__(self):
        return len(self.sequences)

    def __getitem__(self, index):
        sequence, label = self.sequences[index]
        return torch.Tensor(sequence), torch.Tensor(label)


def create_inout_sequences(input_data, tw, pre_len, config):
    # 創(chuàng)建時(shí)間序列數(shù)據(jù)專用的數(shù)據(jù)分割器
    inout_seq = []
    L = len(input_data)
    for i in range(L - tw):
        train_seq = input_data[i:i + tw]
        if (i + tw + pre_len) > len(input_data):
            break
        if config.feature == 'MS':
            train_label = input_data[:, -1:][i + tw:i + tw + pre_len]
        else:
            train_label = input_data[i + tw:i + tw + pre_len]
        inout_seq.append((train_seq, train_label))
    return inout_seq


def calculate_mae(y_true, y_pred):
    # 平均絕對(duì)誤差
    mae = np.mean(np.abs(y_true - y_pred))
    return mae


def create_dataloader(config, device):
    print(">>>>>>>>>>>>>>>>>>>>>>>>>>>>創(chuàng)建數(shù)據(jù)加載器<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<")
    df = pd.read_csv(config.data_path)  # 填你自己的數(shù)據(jù)地址,自動(dòng)選取你最后一列數(shù)據(jù)為特征列 # 添加你想要預(yù)測(cè)的特征列
    pre_len = config.pre_len  # 預(yù)測(cè)未來數(shù)據(jù)的長(zhǎng)度
    train_window = config.window_size  # 觀測(cè)窗口

    # 將特征列移到末尾
    target_data = df[[config.target]]
    df = df.drop(config.target, axis=1)
    df = pd.concat((df, target_data), axis=1)

    cols_data = df.columns[1:]
    df_data = df[cols_data]

    # 這里加一些數(shù)據(jù)的預(yù)處理, 最后需要的格式是pd.series
    true_data = df_data.values

    # 定義標(biāo)準(zhǔn)化優(yōu)化器
    scaler = StandardScaler()
    scaler.fit(true_data)

    train_data = true_data[int(0.3 * len(true_data)):]
    valid_data = true_data[int(0.15 * len(true_data)):int(0.30 * len(true_data))]
    test_data = true_data[:int(0.15 * len(true_data))]
    print("訓(xùn)練集尺寸:", len(train_data), "測(cè)試集尺寸:", len(test_data), "驗(yàn)證集尺寸:", len(valid_data))

    # 進(jìn)行標(biāo)準(zhǔn)化處理
    train_data_normalized = scaler.transform(train_data)
    test_data_normalized = scaler.transform(test_data)
    valid_data_normalized = scaler.transform(valid_data)

    # 轉(zhuǎn)化為深度學(xué)習(xí)模型需要的類型Tensor
    train_data_normalized = torch.FloatTensor(train_data_normalized).to(device)
    test_data_normalized = torch.FloatTensor(test_data_normalized).to(device)
    valid_data_normalized = torch.FloatTensor(valid_data_normalized).to(device)

    # 定義訓(xùn)練器的的輸入
    train_inout_seq = create_inout_sequences(train_data_normalized, train_window, pre_len, config)
    test_inout_seq = create_inout_sequences(test_data_normalized, train_window, pre_len, config)
    valid_inout_seq = create_inout_sequences(valid_data_normalized, train_window, pre_len, config)

    # 創(chuàng)建數(shù)據(jù)集
    train_dataset = TimeSeriesDataset(train_inout_seq)
    test_dataset = TimeSeriesDataset(test_inout_seq)
    valid_dataset = TimeSeriesDataset(valid_inout_seq)

    # 創(chuàng)建 DataLoader
    train_loader = DataLoader(train_dataset, batch_size=args.batch_size, shuffle=True, drop_last=True)
    test_loader = DataLoader(test_dataset, batch_size=args.batch_size, shuffle=False, drop_last=True)
    valid_loader = DataLoader(valid_dataset, batch_size=args.batch_size, shuffle=False, drop_last=True)

    print("通過滑動(dòng)窗口共有訓(xùn)練集數(shù)據(jù):", len(train_inout_seq), "轉(zhuǎn)化為批次數(shù)據(jù):", len(train_loader))
    print("通過滑動(dòng)窗口共有測(cè)試集數(shù)據(jù):", len(test_inout_seq), "轉(zhuǎn)化為批次數(shù)據(jù):", len(test_loader))
    print("通過滑動(dòng)窗口共有驗(yàn)證集數(shù)據(jù):", len(valid_inout_seq), "轉(zhuǎn)化為批次數(shù)據(jù):", len(valid_loader))
    print(">>>>>>>>>>>>>>>>>>>>>>>>>>>>創(chuàng)建數(shù)據(jù)加載器完成<<<<<<<<<<<<<<<<<<<<<<<<<<<")
    return train_loader, test_loader, valid_loader, scaler


class RNNEncoder(nn.Module):
    def __init__(self, rnn_num_layers=1, input_feature_len=1, sequence_len=168, hidden_size=100, bidirectional=False):
        super().__init__()
        self.sequence_len = sequence_len
        self.hidden_size = hidden_size
        self.input_feature_len = input_feature_len
        self.num_layers = rnn_num_layers
        self.rnn_directions = 2 if bidirectional else 1
        self.gru = nn.GRU(
            num_layers=rnn_num_layers,
            input_size=input_feature_len,
            hidden_size=hidden_size,
            batch_first=True,
            bidirectional=bidirectional
        )

    def forward(self, input_seq):
        ht = torch.zeros(self.num_layers * self.rnn_directions, input_seq.size(0), self.hidden_size, device='cuda')
        if input_seq.ndim < 3:
            input_seq.unsqueeze_(2)
        gru_out, hidden = self.gru(input_seq, ht)
        if self.rnn_directions > 1:
            gru_out = gru_out.view(input_seq.size(0), self.sequence_len, self.rnn_directions, self.hidden_size)
            gru_out = torch.sum(gru_out, axis=2)
        return gru_out, hidden.squeeze(0)

class AttentionDecoderCell(nn.Module):
    def __init__(self, input_feature_len, out_put, sequence_len, hidden_size):
        super().__init__()
        # attention - inputs - (decoder_inputs, prev_hidden)
        self.attention_linear = nn.Linear(hidden_size + input_feature_len, sequence_len)
        # attention_combine - inputs - (decoder_inputs, attention * encoder_outputs)
        self.decoder_rnn_cell = nn.GRUCell(
            input_size=hidden_size,
            hidden_size=hidden_size,
        )
        self.out = nn.Linear(hidden_size, input_feature_len)

    def forward(self, encoder_output, prev_hidden, y):
        if prev_hidden.ndimension() == 3:
            prev_hidden = prev_hidden[-1]  # 保留最后一層的信息
        attention_input = torch.cat((prev_hidden, y), axis=1)
        attention_weights = F.softmax(self.attention_linear(attention_input), dim=-1).unsqueeze(1)
        attention_combine = torch.bmm(attention_weights, encoder_output).squeeze(1)
        rnn_hidden = self.decoder_rnn_cell(attention_combine, prev_hidden)
        output = self.out(rnn_hidden)
        return output, rnn_hidden


class EncoderDecoderWrapper(nn.Module):
    def __init__(self, input_size, output_size, hidden_size, num_layers, pred_len, window_size, teacher_forcing=0.3):
        super().__init__()
        self.encoder = RNNEncoder(num_layers, input_size, window_size, hidden_size)
        self.decoder_cell = AttentionDecoderCell(input_size, output_size,  window_size, hidden_size)
        self.output_size = output_size
        self.input_size = input_size
        self.pred_len = pred_len
        self.teacher_forcing = teacher_forcing
        self.linear = nn.Linear(input_size,output_size)


    def __call__(self, xb, yb=None):
        input_seq = xb
        encoder_output, encoder_hidden = self.encoder(input_seq)
        prev_hidden = encoder_hidden
        if torch.cuda.is_available():
            outputs = torch.zeros(self.pred_len, input_seq.size(0), self.input_size, device='cuda')
        else:
            outputs = torch.zeros(input_seq.size(0), self.output_size)
        y_prev = input_seq[:, -1, :]
        for i in range(self.pred_len):
            if (yb is not None) and (i > 0) and (torch.rand(1) < self.teacher_forcing):
                y_prev = yb[:, i].unsqueeze(1)
            rnn_output, prev_hidden = self.decoder_cell(encoder_output, prev_hidden, y_prev)
            y_prev = rnn_output
            outputs[i, :, :] = rnn_output
        outputs = outputs.permute(1, 0, 2)
        if self.output_size == 1:
            outputs = self.linear(outputs)
        return outputs



def train(model, args, scaler, device):
    start_time = time.time()  # 計(jì)算起始時(shí)間
    model = model
    loss_function = nn.MSELoss()
    optimizer = torch.optim.Adam(model.parameters(), lr=0.005)
    epochs = args.epochs
    model.train()  # 訓(xùn)練模式
    results_loss = []
    for i in tqdm(range(epochs)):
        losss = []
        for seq, labels in train_loader:
            optimizer.zero_grad()

            y_pred = model(seq)

            single_loss = loss_function(y_pred, labels)

            single_loss.backward()

            optimizer.step()
            losss.append(single_loss.detach().cpu().numpy())
        tqdm.write(f"\t Epoch {i + 1} / {epochs}, Loss: {sum(losss) / len(losss)}")
        results_loss.append(sum(losss) / len(losss))


        torch.save(model.state_dict(), 'save_model.pth')
        time.sleep(0.1)

    # valid_loss = valid(model, args, scaler, valid_loader)
    # 尚未引入學(xué)習(xí)率計(jì)劃后期補(bǔ)上
    # 保存模型

    print(f">>>>>>>>>>>>>>>>>>>>>>模型已保存,用時(shí):{(time.time() - start_time) / 60:.4f} min<<<<<<<<<<<<<<<<<<")
    plot_loss_data(results_loss)


def valid(model, args, scaler, valid_loader):
    lstm_model = model
    # 加載模型進(jìn)行預(yù)測(cè)
    lstm_model.load_state_dict(torch.load('save_model.pth'))
    lstm_model.eval()  # 評(píng)估模式
    losss = []

    for seq, labels in valid_loader:
        pred = lstm_model(seq)
        mae = calculate_mae(pred.detach().numpy().cpu(), np.array(labels.detach().cpu()))  # MAE誤差計(jì)算絕對(duì)值(預(yù)測(cè)值  - 真實(shí)值)
        losss.append(mae)

    print("驗(yàn)證集誤差MAE:", losss)
    return sum(losss) / len(losss)


def test(model, args, test_loader, scaler):
    # 加載模型進(jìn)行預(yù)測(cè)
    losss = []
    model = model
    model.load_state_dict(torch.load('save_model.pth'))
    model.eval()  # 評(píng)估模式
    results = []
    labels = []
    for seq, label in test_loader:
        pred = model(seq)
        mae = calculate_mae(pred.detach().cpu().numpy(),
                            np.array(label.detach().cpu()))  # MAE誤差計(jì)算絕對(duì)值(預(yù)測(cè)值  - 真實(shí)值)
        losss.append(mae)
        pred = pred[:, 0, :]
        label = label[:, 0, :]
        pred = scaler.inverse_transform(pred.detach().cpu().numpy())
        label = scaler.inverse_transform(label.detach().cpu().numpy())
        for i in range(len(pred)):
            results.append(pred[i][-1])
            labels.append(label[i][-1])
    plt.figure(figsize=(10, 5))
    print("測(cè)試集誤差MAE:", losss)
    # 繪制歷史數(shù)據(jù)
    plt.plot(labels, label='TrueValue')

    # 繪制預(yù)測(cè)數(shù)據(jù)
    # 注意這里預(yù)測(cè)數(shù)據(jù)的起始x坐標(biāo)是歷史數(shù)據(jù)的最后一個(gè)點(diǎn)的x坐標(biāo)
    plt.plot(results, label='Prediction')

    # 添加標(biāo)題和圖例
    plt.title("test state")
    plt.legend()
    plt.show()


# 檢驗(yàn)?zāi)P蛿M合情況
def inspect_model_fit(model, args, train_loader, scaler):
    model = model
    model.load_state_dict(torch.load('save_model.pth'))
    model.eval()  # 評(píng)估模式
    results = []
    labels = []

    for seq, label in train_loader:
        pred = model(seq)[:, 0, :]
        label = label[:, 0, :]
        pred = scaler.inverse_transform(pred.detach().cpu().numpy())
        label = scaler.inverse_transform(label.detach().cpu().numpy())
        for i in range(len(pred)):
            results.append(pred[i][-1])
            labels.append(label[i][-1])
    plt.figure(figsize=(10, 5))
    # 繪制歷史數(shù)據(jù)
    plt.plot(labels, label='History')

    # 繪制預(yù)測(cè)數(shù)據(jù)
    # 注意這里預(yù)測(cè)數(shù)據(jù)的起始x坐標(biāo)是歷史數(shù)據(jù)的最后一個(gè)點(diǎn)的x坐標(biāo)
    plt.plot(results, label='Prediction')

    # 添加標(biāo)題和圖例
    plt.title("inspect model fit state")
    plt.legend()
    plt.show()


def predict(model, args, device, scaler):
    # 預(yù)測(cè)未知數(shù)據(jù)的功能
    df = pd.read_csv(args.data_path)
    df = df.iloc[:, 1:][-args.window_size:].values  # 轉(zhuǎn)換為nadarry
    pre_data = scaler.transform(df)
    tensor_pred = torch.FloatTensor(pre_data).to(device)
    tensor_pred = tensor_pred.unsqueeze(0)  # 單次預(yù)測(cè) , 滾動(dòng)預(yù)測(cè)功能暫未開發(fā)后期補(bǔ)上
    model = model
    model.load_state_dict(torch.load('save_model.pth'))
    model.eval()  # 評(píng)估模式

    pred = model(tensor_pred)[0]

    pred = scaler.inverse_transform(pred.detach().cpu().numpy())

    # 假設(shè) df 和 pred 是你的歷史和預(yù)測(cè)數(shù)據(jù)

    # 計(jì)算歷史數(shù)據(jù)的長(zhǎng)度
    history_length = len(df[:, -1])

    # 為歷史數(shù)據(jù)生成x軸坐標(biāo)
    history_x = range(history_length)
    plt.figure(figsize=(10, 5))
    # 為預(yù)測(cè)數(shù)據(jù)生成x軸坐標(biāo)
    # 開始于歷史數(shù)據(jù)的最后一個(gè)點(diǎn)的x坐標(biāo)
    prediction_x = range(history_length - 1, history_length + len(pred[:, -1]) - 1)

    # 繪制歷史數(shù)據(jù)
    plt.plot(history_x, df[:, -1], label='History')

    # 繪制預(yù)測(cè)數(shù)據(jù)
    # 注意這里預(yù)測(cè)數(shù)據(jù)的起始x坐標(biāo)是歷史數(shù)據(jù)的最后一個(gè)點(diǎn)的x坐標(biāo)
    plt.plot(prediction_x, pred[:, -1], marker='o', label='Prediction')
    plt.axvline(history_length - 1, color='red')  # 在圖像的x位置處畫一條紅色豎線
    # 添加標(biāo)題和圖例
    plt.title("History and Prediction")
    plt.legend()


if __name__ == '__main__':
    parser = argparse.ArgumentParser(description='Time Series forecast')
    parser.add_argument('-model', type=str, default='RNN', help="模型持續(xù)更新")
    parser.add_argument('-window_size', type=int, default=126, help="時(shí)間窗口大小, window_size > pre_len")
    parser.add_argument('-pre_len', type=int, default=24, help="預(yù)測(cè)未來數(shù)據(jù)長(zhǎng)度")
    # data
    parser.add_argument('-shuffle', action='store_true', default=True, help="是否打亂數(shù)據(jù)加載器中的數(shù)據(jù)順序")
    parser.add_argument('-data_path', type=str, default='ETTh1-Test.csv', help="你的數(shù)據(jù)數(shù)據(jù)地址")
    parser.add_argument('-target', type=str, default='OT', help='你需要預(yù)測(cè)的特征列,這個(gè)值會(huì)最后保存在csv文件里')
    parser.add_argument('-input_size', type=int, default=7, help='你的特征個(gè)數(shù)不算時(shí)間那一列')
    parser.add_argument('-feature', type=str, default='M', help='[M, S, MS],多元預(yù)測(cè)多元,單元預(yù)測(cè)單元,多元預(yù)測(cè)單元')

    # learning
    parser.add_argument('-lr', type=float, default=0.001, help="學(xué)習(xí)率")
    parser.add_argument('-drop_out', type=float, default=0.05, help="隨機(jī)丟棄概率,防止過擬合")
    parser.add_argument('-epochs', type=int, default=20, help="訓(xùn)練輪次")
    parser.add_argument('-batch_size', type=int, default=16, help="批次大小")
    parser.add_argument('-save_path', type=str, default='models')

    # model
    parser.add_argument('-hidden_size', type=int, default=128, help="隱藏層單元數(shù)")
    parser.add_argument('-laryer_num', type=int, default=1)

    # device
    parser.add_argument('-use_gpu', type=bool, default=True)
    parser.add_argument('-device', type=int, default=0, help="只設(shè)置最多支持單個(gè)gpu訓(xùn)練")

    # option
    parser.add_argument('-train', type=bool, default=True)
    parser.add_argument('-test', type=bool, default=True)
    parser.add_argument('-predict', type=bool, default=True)
    parser.add_argument('-inspect_fit', type=bool, default=True)
    parser.add_argument('-lr-scheduler', type=bool, default=True)
    args = parser.parse_args()

    if isinstance(args.device, int) and args.use_gpu:
        device = torch.device("cuda:" + f'{args.device}')
    else:
        device = torch.device("cpu")
    print("使用設(shè)備:", device)
    train_loader, test_loader, valid_loader, scaler = create_dataloader(args, device)

    if args.feature == 'MS' or args.feature == 'S':
        args.output_size = 1
    else:
        args.output_size = args.input_size

    # 實(shí)例化模型
    try:
        print(f">>>>>>>>>>>>>>>>>>>>>>>>>開始初始化{args.model}模型<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<")
        model = EncoderDecoderWrapper(args.input_size, args.output_size, args.hidden_size, args.laryer_num, args.pre_len, args.window_size).to(device)
        print(f">>>>>>>>>>>>>>>>>>>>>>>>>開始初始化{args.model}模型成功<<<<<<<<<<<<<<<<<<<<<<<<<<<")
    except:
        print(f">>>>>>>>>>>>>>>>>>>>>>>>>開始初始化{args.model}模型失敗<<<<<<<<<<<<<<<<<<<<<<<<<<<")

    # 訓(xùn)練模型
    if args.train:
        print(f">>>>>>>>>>>>>>>>>>>>>>>>>開始{args.model}模型訓(xùn)練<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<")
        train(model, args, scaler, device)
    if args.test:
        print(f">>>>>>>>>>>>>>>>>>>>>>>>>開始{args.model}模型測(cè)試<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<")
        test(model, args, test_loader, scaler)
    if args.inspect_fit:
        print(f">>>>>>>>>>>>>>>>>>>>>>>>>開始檢驗(yàn){args.model}模型擬合情況<<<<<<<<<<<<<<<<<<<<<<<<<<<")
        inspect_model_fit(model, args, train_loader, scaler)
    if args.predict:
        print(f">>>>>>>>>>>>>>>>>>>>>>>>>預(yù)測(cè)未來{args.pre_len}條數(shù)據(jù)<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<")
        predict(model, args, device, scaler)
    plt.show()


六、訓(xùn)練模型?

我們配置好所有參數(shù)之后就可以開始訓(xùn)練模型了,根據(jù)我前面講解的參數(shù)部分進(jìn)行配置,不懂得可以評(píng)論區(qū)留言。

時(shí)間序列預(yù)測(cè)實(shí)戰(zhàn)(二十五)PyTorch實(shí)現(xiàn)Seq2Seq進(jìn)行多元和單元預(yù)測(cè)(附代碼+數(shù)據(jù)集+完整解析),時(shí)間序列預(yù)測(cè)專欄,pytorch,人工智能,python,深度學(xué)習(xí),時(shí)序數(shù)據(jù)庫(kù),數(shù)據(jù)分析

?


七、預(yù)測(cè)結(jié)果

7.1 預(yù)測(cè)未知數(shù)據(jù)效果圖

Seq2Seq(GRU)的預(yù)測(cè)效果圖(這里我只預(yù)測(cè)了未來24個(gè)時(shí)間段的值為未來一天的預(yù)測(cè)值)->

時(shí)間序列預(yù)測(cè)實(shí)戰(zhàn)(二十五)PyTorch實(shí)現(xiàn)Seq2Seq進(jìn)行多元和單元預(yù)測(cè)(附代碼+數(shù)據(jù)集+完整解析),時(shí)間序列預(yù)測(cè)專欄,pytorch,人工智能,python,深度學(xué)習(xí),時(shí)序數(shù)據(jù)庫(kù),數(shù)據(jù)分析


7.2 測(cè)試集效果圖?

測(cè)試集上的表現(xiàn)->

時(shí)間序列預(yù)測(cè)實(shí)戰(zhàn)(二十五)PyTorch實(shí)現(xiàn)Seq2Seq進(jìn)行多元和單元預(yù)測(cè)(附代碼+數(shù)據(jù)集+完整解析),時(shí)間序列預(yù)測(cè)專欄,pytorch,人工智能,python,深度學(xué)習(xí),時(shí)序數(shù)據(jù)庫(kù),數(shù)據(jù)分析

?


7.3 CSV文件生成效果圖?

同時(shí)我也可以將輸出結(jié)果用csv文件保存,但是功能還沒有做,我在另一篇informer的文章里實(shí)習(xí)了這個(gè)功能大家如果有需要可以評(píng)論區(qū)留言,有時(shí)間我會(huì)移植過來,最近一直在搞圖像領(lǐng)域的文章因?yàn)闀r(shí)間序列看的人還是太少了。

另一篇文章鏈接->時(shí)間序列預(yù)測(cè)實(shí)戰(zhàn)(十九)魔改Informer模型進(jìn)行滾動(dòng)長(zhǎng)期預(yù)測(cè)(科研版本,結(jié)果可視化)

將滾動(dòng)預(yù)測(cè)結(jié)果生成了csv文件方便大家對(duì)比和評(píng)估,以下是我生成的csv文件可以說是非常的直觀。

時(shí)間序列預(yù)測(cè)實(shí)戰(zhàn)(二十五)PyTorch實(shí)現(xiàn)Seq2Seq進(jìn)行多元和單元預(yù)測(cè)(附代碼+數(shù)據(jù)集+完整解析),時(shí)間序列預(yù)測(cè)專欄,pytorch,人工智能,python,深度學(xué)習(xí),時(shí)序數(shù)據(jù)庫(kù),數(shù)據(jù)分析?

?我們可以利用其進(jìn)行畫圖從而評(píng)估結(jié)果->?

時(shí)間序列預(yù)測(cè)實(shí)戰(zhàn)(二十五)PyTorch實(shí)現(xiàn)Seq2Seq進(jìn)行多元和單元預(yù)測(cè)(附代碼+數(shù)據(jù)集+完整解析),時(shí)間序列預(yù)測(cè)專欄,pytorch,人工智能,python,深度學(xué)習(xí),時(shí)序數(shù)據(jù)庫(kù),數(shù)據(jù)分析

?


7.4 檢驗(yàn)?zāi)P蛿M合效果圖

檢驗(yàn)?zāi)P蛿M合情況->

(從下面的圖片可以看出模型擬合的情況還行,上一篇RNN的有一點(diǎn)過擬合了其實(shí),則會(huì)個(gè)表現(xiàn)還是很正常的)?

時(shí)間序列預(yù)測(cè)實(shí)戰(zhàn)(二十五)PyTorch實(shí)現(xiàn)Seq2Seq進(jìn)行多元和單元預(yù)測(cè)(附代碼+數(shù)據(jù)集+完整解析),時(shí)間序列預(yù)測(cè)專欄,pytorch,人工智能,python,深度學(xué)習(xí),時(shí)序數(shù)據(jù)庫(kù),數(shù)據(jù)分析


八、全文總結(jié)

到此本文的正式分享內(nèi)容就結(jié)束了,在這里給大家推薦我的時(shí)間序列專欄,本專欄目前為新開的平均質(zhì)量分98分,后期我會(huì)根據(jù)各種最新的前沿頂會(huì)進(jìn)行論文復(fù)現(xiàn),也會(huì)對(duì)一些老的模型進(jìn)行補(bǔ)充,目前本專欄免費(fèi)閱讀(暫時(shí),大家盡早關(guān)注不迷路~),如果大家覺得本文幫助到你了,訂閱本專欄,關(guān)注后續(xù)更多的更新~

?專欄回顧:?時(shí)間序列預(yù)測(cè)專欄——持續(xù)復(fù)習(xí)各種頂會(huì)內(nèi)容——科研必備

時(shí)間序列預(yù)測(cè)實(shí)戰(zhàn)(二十五)PyTorch實(shí)現(xiàn)Seq2Seq進(jìn)行多元和單元預(yù)測(cè)(附代碼+數(shù)據(jù)集+完整解析),時(shí)間序列預(yù)測(cè)專欄,pytorch,人工智能,python,深度學(xué)習(xí),時(shí)序數(shù)據(jù)庫(kù),數(shù)據(jù)分析

如果大家有不懂的也可以評(píng)論區(qū)留言一些報(bào)錯(cuò)什么的大家可以討論討論看到我也會(huì)給大家解答如何解決!最后希望大家工作順利學(xué)業(yè)有成!

時(shí)間序列預(yù)測(cè)實(shí)戰(zhàn)(二十五)PyTorch實(shí)現(xiàn)Seq2Seq進(jìn)行多元和單元預(yù)測(cè)(附代碼+數(shù)據(jù)集+完整解析),時(shí)間序列預(yù)測(cè)專欄,pytorch,人工智能,python,深度學(xué)習(xí),時(shí)序數(shù)據(jù)庫(kù),數(shù)據(jù)分析?文章來源地址http://www.zghlxwxcb.cn/news/detail-759312.html

到了這里,關(guān)于時(shí)間序列預(yù)測(cè)實(shí)戰(zhàn)(二十五)PyTorch實(shí)現(xiàn)Seq2Seq進(jìn)行多元和單元預(yù)測(cè)(附代碼+數(shù)據(jù)集+完整解析)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包