??這次項目是大二老師給我的,具體什么時候做的,我已經忘記了,現在重溫一下;
??首先我們都知道Informer的圖像如圖1,但是我覺得太復雜了,我便將中間的兩層做了刪掉,并對他們自帶的測試集做了些測試,發現他們在時間方面的差距并不大(甚至可以說微乎其微),至于效率方面,這個與測試集有關,筆者在自己的項目和原論文項目中小小的測試了幾次,效率并沒有多大差距,但是我的老師在一些時序預測項目中發現有一定差距,但是因為當時的時間限制,也沒有做太多“計較”
??我的老師當時問了幾個問題:
- 模型結構上由5層->3層,可以降低復雜度和提高速度,降低的復雜度和提高的速度具體是多少,可以量化嗎?
- 復雜度降低是因為減少了參數嗎?那參數由多少降低到多少呢?
- 模型減少了2層,這兩層具體作用是什么?(作用如果比較重要的話,去掉之后會不會對模型有什么影響?)如果不重要,去掉又可以有哪些好處?
- 為什么減少2層?
- 為什么增加激活函數splice,有什么好處?增加該激活函數之后,復雜度會增加嗎?增加多少?
??我做了相應的回答:
- 不同數據,時間降低不一樣,所以不可以量化。
- 復雜度降低不是因為參數的減少,對比分析原來和現在的模型參數,其大小都為11.31M;參數沒有減少,但是時間的減少是因為模型層數的減少,模型層數的減少,減少了整體時間和空間的使用。
- 一個是卷積層,另一個是編碼層;
(1)卷積層會提取出更重要的數據;
(2)編碼層會對卷積層提取出來的重要數據做自注意力機制等處理;
(3)這兩個層都比較重要,數據通過這兩個層,其序列長度會從L/2變為L/4,這樣篩選了更重要的數據,但在篩選的過程中難免會多篩選一部分有用數據;當減少這兩層后,模型的效果會減弱,為了達到原來的效果,需要一個新的方法來處理數據:希望讓有用數據更有用或者維持不變,讓無用數據的值接近為0而不對模型產生副作用。 - 減少兩層主要是增加了有用數據的數量,由于原先Informer將長度L的序列轉變為L/4,那么新模型只是將L轉變為L/3,這樣增加了有用數據的數量,使得模型更精確。
- 新模型將序列長度從L變為L/3,對比原來informer將序列長度從L變為L/4,有效數據在增加的同時,無效數據量也會增加,而Splice激活函數,可以使無效數據穩定在0左右(這是因為注意力機制的稀疏性),使有效數據做非線性變化,這樣拉大了有效數據和無效數據的數值差距,使得最后的效果更顯著;其次Splice激活函數左飽和,而右側不飽和解決了梯度爆炸的問題并且加快了收斂的速度;其中有效數據指的是x>0,無效數據指的是x<0,重要數據指的是通過任意一卷積層而被篩選出的數據。
??我在這里也給出Splice激活函數的圖像
??這是我的最終結果,每一個測試集跑了10次,平且去除最低和最高后平均的結果
??從效果上來看,還不錯,這是我的第一次小小的“成功”,因為時間、mse(均方誤差)、mae(均值絕對誤差)大部分要比論文好很多;
??這篇文章僅僅記錄一下我的大二下的第一次科研項目(重要的是,那個時候我前女友還陪著我)
??關于實驗源碼,我不能公開,但是我可以將我的Splice激活函數的代碼公開(其實有了公式,就算不公開,讀者也能自己寫出來):
class Splice(nn.Module):
def __init__(self):
super(Splice, self).__init__()Q
self.weight = nn.Parameter(torch.FloatTensor(1), requires_grad=True)
self.reset_parameters()
def reset_parameters(self):
self.weight.data.fill_(1.0)
def forward(self, input):
return exp(self.weight *input) / (1 + abs(input))
1.init(self)函數:
??super(Splice, self).init() 是調用 nn.Module 的構造函數,這是 PyTorch 模塊化設計的標準做法。它允許 Splice 繼承所有 nn.Module 的功能。
??self.weight = nn.Parameter(torch.FloatTensor(1), requires_grad=True)用來計算梯度。
????* nn.Parameter 是 PyTorch 中專門用于存儲需要梯度計算的參數的類。它本質上是一個 torch.Tensor,并且在模型訓練時,會自動將其梯度計算包含在優化過程中。
????* torch.Tensor 是 PyTorch 中的基礎數據結構,用于存儲和操作多維數組(即張量)。
????* 這里初始化了一個單個浮點數的張量,即 torch.FloatTensor(1),意味著 weight 是一個大小為 1 的標量。
????* requires_grad=True 確保在反向傳播時計算梯度。
2.reset_parameters(self)函數:
??self.weight.data.fill_(1.0) 用來將 self.weight 張量的值填充為 1.0,即將 weight 重置為 1。
????* 雖然我在__init__(self)中設置了權重=1,但是為了保證初始化的一致性、代碼的可拓展性、模型的安全性,我加了這個函數,去掉也沒問題
????* data 屬性允許直接修改張量數據,而不觸發梯度計算,避免不必要的反向傳播影響。
3.forward(self, input)函數:
??即上面展示的公式
浙公網安備 33010602011771號