SparseAdam¶
- class torch.optim.SparseAdam(params, lr=0.001, betas=(0.9, 0.999), eps=1e-08, maximize=False)[source][source]¶
SparseAdam 實作了 Adam 演算法的遮罩版本,適用於稀疏梯度。目前,由於實作上的限制(如下所述),SparseAdam 僅適用於少數使用案例,特別是具有密集佈局的參數和具有稀疏佈局的梯度。 這種情況發生在模組反向傳播產生已經是稀疏佈局的梯度時的特殊情況。 一個表現如此的 NN 模組範例是
nn.Embedding(sparse=True)
。SparseAdam 透過遮罩掉梯度中零值對應的參數和動量更新來近似 Adam 演算法。 Adam 演算法將根據梯度的所有值更新一階動量、二階動量和參數,而 SparseAdam 僅更新梯度非零值對應的動量和參數。
一種簡化的思考 預期 實作的方式如下
建立稀疏梯度中非零值的遮罩。 例如,如果您的梯度看起來像 [0, 5, 0, 0, 9],則遮罩將是 [0, 1, 0, 0, 1]。
將此遮罩應用於運行中的動量,並且僅對非零值執行計算。
將此遮罩應用於參數,並且僅對非零值套用更新。
實際上,我們使用稀疏佈局張量來優化此近似值,這意味著被遮罩(由於未被實例化)的梯度越多,優化效能就越高。 由於我們依賴使用稀疏佈局張量,因此我們推斷稀疏佈局中任何實例化的值都是非零的,並且我們實際上並**不**驗證所有值都不是零! 不要混淆語義上的稀疏張量(其中許多值為零的張量)與稀疏佈局張量(其中
.is_sparse
返回True
的張量)。 SparseAdam 近似旨在用於 語義上 的稀疏張量,而稀疏佈局僅是實作細節。 更清晰的實作是使用 MaskedTensors,但這些是實驗性的。注意
如果您懷疑您的梯度在語義上是稀疏的(但沒有稀疏佈局),則此變體可能不適合您。 理想情況下,您應該避免實例化任何被懷疑為稀疏的東西,因為需要將所有梯度從密集佈局轉換為稀疏佈局可能會超過效能提升。 在這裡,除非您可以輕鬆地將模組設置為輸出類似於
nn.Embedding(sparse=True)
的稀疏梯度,否則使用 Adam 可能是最佳替代方案。 如果您堅持轉換梯度,您可以在呼叫.step()
之前,使用它們的稀疏等效項手動覆蓋參數的.grad
欄位來實現。- 參數
- add_param_group(param_group)[source]¶
將參數群組添加到
Optimizer
的 param_groups。當微調預先訓練的網路時,這可能很有用,因為可以使凍結的層可訓練,並在訓練過程中將它們添加到
Optimizer
中。- 參數
param_group (dict) – 指定應與群組特定的優化選項一起優化的張量。
- load_state_dict(state_dict)[source]¶
載入優化器狀態。
- 參數
state_dict (dict) – 優化器狀態。 應該是從呼叫
state_dict()
返回的物件。
注意
參數名稱(如果它們存在於
state_dict()
中每個 param group 的 "param_names" 鍵下)不會影響載入過程。若要使用參數名稱於自定義情況(例如,當已載入的 state dict 中的參數與優化器中初始化的參數不同時),應該實作自定義的register_load_state_dict_pre_hook
以適應載入的 dict。如果已載入的 state dict 的param_groups
中存在param_names
,它們將會被儲存並覆蓋優化器狀態中目前的名字(如果存在)。如果已載入的 state dict 中不存在它們,則優化器的param_names
將保持不變。
- register_load_state_dict_post_hook(hook, prepend=False)[source]¶
註冊一個 load_state_dict 後處理 hook,它將在
load_state_dict()
呼叫後被呼叫。它應該具有以下簽名:hook(optimizer) -> None
optimizer
參數是正在使用的優化器實例。在
self
上呼叫load_state_dict
後,將使用參數self
呼叫 hook。註冊的 hook 可用於在load_state_dict
載入state_dict
後執行後處理。- 參數
hook (可呼叫物件) – 要註冊的使用者定義的 hook。
prepend (bool) – 如果為 True,則提供的 post
hook
將在load_state_dict
上所有已註冊的 post-hook 之前觸發。 否則,提供的hook
將在所有已註冊的 post-hook 之後觸發。(預設值:False)
- 回傳
一個 handle,可用於通過呼叫
handle.remove()
來移除新增的 hook- 回傳型別
torch.utils.hooks.RemoveableHandle
- register_load_state_dict_pre_hook(hook, prepend=False)[source]¶
註冊一個 load_state_dict 前處理 hook,它將在
load_state_dict()
呼叫之前被呼叫。它應該具有以下簽名:hook(optimizer, state_dict) -> state_dict or None
optimizer
參數是正在使用的優化器實例,state_dict
參數是使用者傳遞給load_state_dict
的state_dict
的淺複製。該 hook 可以就地修改 state_dict,或者選擇性地返回一個新的 state_dict。 如果返回一個 state_dict,它將被用來載入到優化器中。在
self
上呼叫load_state_dict
之前,將使用參數self
和state_dict
呼叫 hook。在呼叫load_state_dict
之前,註冊的 hook 可用於執行前處理。- 參數
hook (可呼叫物件) – 要註冊的使用者定義的 hook。
prepend (bool) – 如果為 True,則提供的 pre
hook
將在load_state_dict
上所有已註冊的 pre-hook 之前觸發。 否則,提供的hook
將在所有已註冊的 pre-hook 之後觸發。(預設值:False)
- 回傳
一個 handle,可用於通過呼叫
handle.remove()
來移除新增的 hook- 回傳型別
torch.utils.hooks.RemoveableHandle
- register_state_dict_post_hook(hook, prepend=False)[source]¶
註冊一個 state dict 後處理 hook,它將在
state_dict()
呼叫後被呼叫。它應該具有以下簽名:
hook(optimizer, state_dict) -> state_dict or None
在
self
上產生state_dict
之後,將使用參數self
和state_dict
呼叫 hook。該 hook 可以就地修改 state_dict,或者選擇性地返回一個新的 state_dict。 註冊的 hook 可用於在返回state_dict
之前對其執行後處理。- 參數
hook (可呼叫物件) – 要註冊的使用者定義的 hook。
prepend (bool) – 如果為 True,提供的 post
hook
將會在state_dict
上所有已註冊的 post-hook 之前觸發。否則,提供的hook
將會在所有已註冊的 post-hook 之後觸發。(預設值:False)
- 回傳
一個 handle,可用於通過呼叫
handle.remove()
來移除新增的 hook- 回傳型別
torch.utils.hooks.RemoveableHandle
- register_state_dict_pre_hook(hook, prepend=False)[source]¶
註冊一個 state dict pre-hook,它會在呼叫
state_dict()
之前被呼叫。它應該具有以下簽名:
hook(optimizer) -> None
optimizer
參數是正在使用的 optimizer 實例。 在呼叫self
上的state_dict
之前,將會使用參數self
呼叫 hook。註冊的 hook 可用於在呼叫state_dict
之前執行預處理。- 參數
hook (可呼叫物件) – 要註冊的使用者定義的 hook。
prepend (bool) – 如果為 True,提供的 pre
hook
將會在state_dict
上所有已註冊的 pre-hook 之前觸發。否則,提供的hook
將會在所有已註冊的 pre-hook 之後觸發。(預設值:False)
- 回傳
一個 handle,可用於通過呼叫
handle.remove()
來移除新增的 hook- 回傳型別
torch.utils.hooks.RemoveableHandle
- register_step_post_hook(hook)[source]¶
註冊一個 optimizer step post hook,它會在 optimizer step 之後被呼叫。
它應該具有以下簽名:
hook(optimizer, args, kwargs) -> None
optimizer
參數是正在使用的優化器實例。- 參數
hook (可呼叫物件) – 要註冊的使用者定義的 hook。
- 回傳
一個 handle,可用於通過呼叫
handle.remove()
來移除新增的 hook- 回傳型別
torch.utils.hooks.RemovableHandle
- register_step_pre_hook(hook)[source]¶
註冊一個 optimizer step pre hook,它會在 optimizer step 之前被呼叫。
它應該具有以下簽名:
hook(optimizer, args, kwargs) -> None or modified args and kwargs
optimizer
參數是正在使用的 optimizer 實例。 如果 args 和 kwargs 被 pre-hook 修改,則轉換後的值將作為包含 new_args 和 new_kwargs 的元組返回。- 參數
hook (可呼叫物件) – 要註冊的使用者定義的 hook。
- 回傳
一個 handle,可用於通過呼叫
handle.remove()
來移除新增的 hook- 回傳型別
torch.utils.hooks.RemovableHandle
- state_dict()[source]¶
以
dict
形式返回 optimizer 的狀態。它包含兩個條目
state
:一個包含當前優化狀態的 Dict。 它的內容因 optimizer 類別而異,但一些常見特性成立。 例如,狀態是按參數保存的,並且參數本身不保存。
state
是一個將參數 ID 映射到具有每個參數對應狀態的 Dict 的字典。
param_groups
:一個包含所有參數組的列表,其中每個參數組是一個 Dict。 每個參數組都包含特定於 optimizer 的元數據,例如學習率和權重衰減,以及該組中參數的參數 ID 列表。 如果使用
named_parameters()
初始化了 param group,則名稱內容也將保存在 state dict 中。
注意:參數 ID 可能看起來像索引,但它們只是將狀態與 param_group 關聯的 ID。 從 state_dict 載入時,optimizer 會將 param_group 的
params
(int IDs) 和 optimizer 的param_groups
(實際的nn.Parameter
s) 壓縮在一起,以便在沒有額外驗證的情況下匹配狀態。返回的 state dict 可能看起來像這樣
{ 'state': { 0: {'momentum_buffer': tensor(...), ...}, 1: {'momentum_buffer': tensor(...), ...}, 2: {'momentum_buffer': tensor(...), ...}, 3: {'momentum_buffer': tensor(...), ...} }, 'param_groups': [ { 'lr': 0.01, 'weight_decay': 0, ... 'params': [0] 'param_names' ['param0'] (optional) }, { 'lr': 0.001, 'weight_decay': 0.5, ... 'params': [1, 2, 3] 'param_names': ['param1', 'layer.weight', 'layer.bias'] (optional) } ] }
- step(closure=None)[source][source]¶
執行單個優化步驟。
- 參數
closure (Callable, optional) – 一個重新評估模型並返回損失的 closure。
- zero_grad(set_to_none=True)[source]¶
重置所有優化的
torch.Tensor
s 的梯度。- 參數
set_to_none (bool) – 不要將梯度設為零,而是將梯度設為 None。這通常會減少記憶體佔用,並可能稍微提高效能。但是,它會改變某些行為。例如:1. 當使用者嘗試存取梯度並對其執行手動操作時,None 屬性或充滿 0 的 Tensor 將會表現出不同的行為。2. 如果使用者請求
zero_grad(set_to_none=True)
接著執行反向傳播,則保證未接收到梯度的參數的.grad
值為 None。3. 如果梯度為 0 或 None,torch.optim
優化器的行為會有所不同(在一种情况下,它使用梯度 0 執行步驟,而在另一種情况下,它完全跳過該步驟)。