深入淺出torch.autograd

一、介紹autograd

torch.autograd 模塊是 PyTorch 中的自動微分引擎。它支持任意數量的計算圖,可以自動執行前向傳遞、後向傳遞和計算梯度,同時提供很多有用的函數來處理各種計算圖。它與程序中的其它部分緊密結合使用,使得使用 PyTorch 構建神經網絡得以簡單而高效實現。

二、期望值反向傳播

我們簡單介紹一下期望值反向傳播(REINFORCE)及其PyTorch實現。期望值反向傳播是一種用於直接優化policy的算法。在許多強化學習任務中,我們需要優化一個策略,使其能夠最大化累積獎勵的期望值。在連續動作空間或高維狀態空間下,直接優化該策略是非常困難的,因此我們通常使用一些策略梯度方法,它們依據一些目標構建策略的估計,並更新策略以優化該估計。

在期望值反向傳播中,我們計算得到目標的期望值,然後對該期望值的對數化為一組權重,分別賦給每一步的回報。然後用一個對策略參數的公式求導。這將給出一組價值函數的梯度,此外,我們還可以使用Torch中的鏈式法則很容易地獲得策略梯度。

import torch

def REINFORCE(policy, episodes, learning_rate):
    optimizer = torch.optim.Adam(policy.parameters(), lr=learning_rate) #定義一個優化器
    episode_rewards = []
    for i in range(episodes):
        log_probs = []
        rewards = []

        state = env.reset()
        episode_reward = 0

        while(True):
            action, log_prob = policy.get_action(state)
            new_state, reward, done, _ = env.step(action.item())
            log_probs.append(log_prob)
            rewards.append(reward)
            state = new_state
            episode_reward += reward
            if done:
                break

        episode_rewards.append(episode_reward)

        # 計算期望梯度,更新策略參數
        eps = torch.finfo(torch.float32).eps
        discounts = [np.power(0.99, i) for i in range(len(rewards))]
        discounts = torch.from_numpy(np.array(discounts, dtype=np.float32)).to(device)
        rewards = torch.stack(rewards).to(device)
        log_probs = torch.stack(log_probs).to(device)
        
        R = (rewards * discounts).sum(dim=0)
        R = (R - R.mean()) / (R.std() + eps) # 標準化策略梯度

        policy_loss = (-log_probs * R).sum(dim=0)

        optimizer.zero_grad()
        policy_loss.backward()
        optimizer.step()

    return episode_rewards

三、autograd.Function的使用

本節將詳細介紹PyTorch中 autograd.Function 的使用,以及如何使用它們自定義您的操作。在PyTorch中,Variable的每個操作都是如何在計算圖中回溯到其他變量,並且每個操作同樣可以回溯到其他函數。為了允許用戶實現自己的操作,PyTorch為我們提供了一個非常簡單和強大的類」。該autograd.Function類被Pytorch用於允許我們定義隨時可導的用戶自定義運算。

class Exp(Function):

    @staticmethod
    def forward(ctx, i):
        result = i.exp()
        ctx.save_for_backward(result)
        return result

    @staticmethod
    def backward(ctx, grad_output):
        result, = ctx.saved_variables
        return grad_output * result

四、Variable以及在計算圖中的應用

在PyTorch中,算子可以添加到計算圖中,以實現自動求導。在計算圖中,每一個節點都表示一個Tensor,其中一些Tensor節點是輸入節點(InputNode),而其他節點是操作節點(FunctionNode)。在輕鬆編寫深度學習模型時,我們很少手動添加節點和邊,PyTorch很好地隱藏了這些內容並隱式執行了它。 Variable 是 PyTorch 中圖計算的重要概念之一。它是具有梯度的張量,可以直接放入計算圖中,並可以通過它的backward()函數產生梯度信號。

Variable是Tensor的一個封裝,不同的是Variable有 tensor的一些屬性和方法,比如shape,size()等, 同時它有一些附加的屬性,比如grad( Variable的梯度)、requires_grad(是不是需要求 Variable的梯度)、data(保存 Variable的 tensor)等。 我們在需要求 Variable的梯度時才需要調用 backward() 函數.

import torch
from torch.autograd import Variable

x_data = [1.0, 2.0, 3.0]
y_data = [2.0, 4.0, 6.0]

w = Variable(torch.Tensor([1.0]), requires_grad=True)

def forward(x):
    return x * w

def loss(x, y):
    y_pred = forward(x)
    return (y_pred - y) * (y_pred - y)

for epoch in range(10):
    for x_val, y_val in zip(x_data, y_data):
        l = loss(x_val, y_val)
        l.backward()
        print("grad: ", x_val, y_val, w.grad.data[0])
        w.data = w.data - 0.01 * w.grad.data

        # Manually zero the gradients after updating weights
        w.grad.data.zero_()

五、tensor.detach()函數的應用

在PyTorch中, tensor.detach()函數是用於獲得沒有對原始變量的梯度的新張量的,這也就是一個detachdetensor。總之,當您需要獲取不需要梯度的張量時, detach() 函數非常有用。在使用GPU時,您必須對張量調用detach(),以便在進行數據移動時清除存儲,否則它會導致內存泄漏;因為我們需要計算二階梯度。 沒有從圖中分離張量屬性。因此, detach() 使您可以在不影響計算圖的情況下使用張量。

import torch

tensor = torch.randn(3, requires_grad=True)
print('tensor:', tensor)

# 移動到GPU上
tensor_gpu = tensor.cuda()

# 加點於tensor在GPU上產生的梯度
result_gpu = (tensor_gpu ** 2).sum()
result_gpu.backward()

# TensorFlow,tensor與 tensor_gpu 的梯度不匹配。
# Do a slow transfer back to CPU memory
result = (tensor.detach().cpu() ** 2).sum()
result.backward()

print('tensor_grad:', tensor.grad)
print('tensor_gpu_grad:', tensor_gpu.grad)

原創文章,作者:GLWYF,如若轉載,請註明出處:https://www.506064.com/zh-hk/n/372475.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
GLWYF的頭像GLWYF
上一篇 2025-04-24 06:40
下一篇 2025-04-24 06:40

相關推薦

  • 深入淺出統計學

    統計學是一門關於收集、分析、解釋和呈現數據的學科。它在各行各業都有廣泛應用,包括社會科學、醫學、自然科學、商業、經濟學、政治學等等。深入淺出統計學是指想要學習統計學的人能夠理解統計…

    編程 2025-04-25
  • 深入淺出SQL佔位符

    一、什麼是SQL佔位符 SQL佔位符是一種佔用SQL語句中某些值的標記或佔位符。當執行SQL時,將使用該標記替換為實際的值,並將這些值傳遞給查詢。SQL佔位符使查詢更加安全,防止S…

    編程 2025-04-24
  • 深入淺出ThinkPHP框架

    一、簡介 ThinkPHP是一款開源的PHP框架,它遵循Apache2開源協議發佈。ThinkPHP具有快速的開發速度、簡便的使用方式、良好的擴展性和豐富的功能特性。它的核心思想是…

    編程 2025-04-24
  • 深入淺出:理解nginx unknown directive

    一、概述 nginx是目前使用非常廣泛的Web服務器之一,它可以運行在Linux、Windows等不同的操作系統平台上,支持高並發、高擴展性等特性。然而,在使用nginx時,有時候…

    編程 2025-04-24
  • 深入淺出arthas火焰圖

    arthas是一個非常方便的Java診斷工具,包括很多功能,例如JVM診斷、應用診斷、Spring應用診斷等。arthas使診斷問題變得更加容易和準確,因此被廣泛地使用。artha…

    編程 2025-04-24
  • 深入淺出AWK -v參數

    一、功能介紹 AWK是一種強大的文本處理工具,它可以用於數據分析、報告生成、日誌分析等多個領域。其中,-v參數是AWK中一個非常有用的參數,它用於定義一個變量並賦值。下面讓我們詳細…

    編程 2025-04-24
  • 如何卸載torch——多方面詳細闡述

    一、卸載torch的必要性 隨着人工智能領域的不斷發展,越來越多的深度學習框架被廣泛應用,torch也是其中之一。然而,在使用torch過程中,我們也不可避免會遇到需要卸載的情況。…

    編程 2025-04-23
  • 深入淺出Markdown文字顏色

    一、Markdown文字顏色的背景 Markdown是一種輕量級標記語言,由於其簡單易學、易讀易寫,被廣泛應用於博客、文檔、代碼注釋等場景。Markdown支持使用HTML標籤,因…

    編程 2025-04-23
  • 深入淺出runafter——異步任務調度器的實現

    一、runafter是什麼? runafter是一個基於JavaScript實現的異步任務調度器,可以幫助開發人員高效地管理異步任務。利用runafter,開發人員可以輕鬆地定義和…

    編程 2025-04-23
  • 深入淺出TermQuery

    一、TermQuery概述 TermQuery是Lucene中最基本、最簡單、最常見的查詢方法之一。它完全符合其名字,意味着只能對一個單詞進行查詢。 TermQuery可以用於搜索…

    編程 2025-04-23

發表回復

登錄後才能評論