W3Cschool
恭喜您成為首批注冊用戶
獲得88經(jīng)驗(yàn)值獎(jiǎng)勵(lì)
在深度學(xué)習(xí)模型構(gòu)建過程中,時(shí)常需借助多種數(shù)學(xué)工具拓展神經(jīng)網(wǎng)絡(luò)功能。本教程講解如何利用 NumPy 和 SciPy 在 PyTorch 中創(chuàng)建擴(kuò)展。
先來看一個(gè)無參數(shù)的神經(jīng)網(wǎng)絡(luò)層示例。我們將創(chuàng)建一個(gè)名為 BadFFTFunction 的類,它雖無實(shí)際意義,但能幫助理解基礎(chǔ)框架。
import torch
from torch.autograd import Function
from numpy.fft import rfft2, irfft2
class BadFFTFunction(Function):
@staticmethod
def forward(ctx, input):
# 將輸入張量轉(zhuǎn)換為 NumPy 數(shù)組
numpy_input = input.detach().numpy()
#輸入 對數(shù)據(jù)進(jìn)行傅里葉變換并取絕對值
result = abs(rfft2(numpy_input))
# 將結(jié)果轉(zhuǎn)換回 PyTorch 張量返回
return input.new(result)
@staticmethod
def backward(ctx, grad_output):
# 將梯度輸出轉(zhuǎn)換為 NumPy 數(shù)組
numpy_go = grad_output.numpy()
# 對梯度進(jìn)行逆傅里葉變換
result = irfft2(numpy_go)
# 將結(jié)果轉(zhuǎn)換回 PyTorch 張量返回
return grad_output.new(result)
## 定義函數(shù)方便調(diào)用該層
def incorrect_fft(input):
return BadFFTFunction.apply(input)
使用示例:
## 創(chuàng)建一個(gè) 8x8 隨機(jī)張量,設(shè)置 requires_grad=True 表示需要計(jì)算梯度
input = torch.randn(8, 8, requires_grad=True)
## 通過我們定義的擴(kuò)展層進(jìn)行前向傳播
result = incorrect_fft(input)
print(result)
## 進(jìn)行反向傳播
result.backward(torch.randn(result.size()))
print(input)
接下來創(chuàng)建一個(gè)具有可學(xué)習(xí)權(quán)重的神經(jīng)網(wǎng)絡(luò)層,這里涉及 SciPy 的卷積操作。
from numpy import flip
import numpy as np
from scipy.signal import convolve2d, correlate2d
from torch.nn.modules.module import Module
from torch.nn.parameter import Parameter
class ScipyConv2dFunction(Function):
@staticmethod
def forward(ctx, input, filter, bias):
# 將輸入張量轉(zhuǎn)換為 NumPy 數(shù)組
input_np, filter_np, bias_np = input.detach().numpy(), filter.detach().numpy(), bias.detachnumpy().()
# 進(jìn)行互相關(guān)操作并加上偏置
result = correlate2d(input_np, filter_np, mode='valid') + bias_np
# 保存反向傳播所需數(shù)據(jù)
ctx.save_for_backward(input, filter, bias)
# 將結(jié)果轉(zhuǎn)換回 PyTorch 張量返回
return torch.as_tensor(result, dtype=input.dtype)
@staticmethod
def backward(ctx, grad_output):
# 獲取前向傳播保存的數(shù)據(jù)
input, filter, bias = ctx.saved_tensors
# 將梯度輸出轉(zhuǎn)換為 NumPy 數(shù)組
grad_output_np = grad_output.detach().numpy()
# 計(jì)算偏置梯度,對所有位置求和
grad_bias = np.sum(grad_output_np, keepdims=True)
# 計(jì)算輸入梯度,進(jìn)行卷積操作
grad_input = convolve2d(grad_output_np, filter.numpy(), mode='full')
# 計(jì)算濾波器梯度,進(jìn)行互相關(guān)操作
grad_filter = correlate2d(input.numpy(), grad_output_np, mode='valid')
# 將計(jì)算的梯度轉(zhuǎn)換回 PyTorch 張量返回
return torch.from_numpy(grad_input), torch.from_numpy(grad_filter).to(torch.float), torch.from_numpy(grad_bias).to(torch.float)
class ScipyConv2d(Module):
def __init__(self, filter_width, filter_height):
super(ScipyConv2d, self).__init__()
# 初始化濾波器和偏置為可學(xué)習(xí)參數(shù)
self.filter = Parameter(torch.randn(filter_width, filter_height))
self.bias = Parameter(torch.randn(1, 1))
def forward(self, input):
# 前向傳播調(diào)用函數(shù)
return ScipyConv2dFunction.apply(input, self.filter, self.bias)
使用示例:
## 創(chuàng)建一個(gè) 3x3 卷積層
module = ScipyConv2d(3, 3)
print("濾波器和偏置:", list(module.parameters()))
## 創(chuàng)建一個(gè) 10x10 隨機(jī)張量,設(shè)置 requires_grad=True 表示需要計(jì)算梯度
input = torch.randn(10, 10, requires_grad=True)
## 進(jìn)行前向傳播
output = module(input)
print("卷積輸出:", output)
## 進(jìn)行反向傳播
output.backward(torch.randn(8, 8))
print("輸入梯度:", input.grad)
我們可以使用 PyTorch 的 gradcheck 工具來檢查我們計(jì)算的梯度是否正確。
from torch.autograd.gradcheck import gradcheck
## 創(chuàng)建一個(gè) 3x3 卷積層
moduleConv = ScipyConv2d(3, 3)
## 創(chuàng)建輸入數(shù)據(jù)
input = [torch.randn(20, 20, dtype=torch.double, requires_grad=True)]
## 進(jìn)行梯度檢查
test = gradcheck(moduleConv, input, eps=1e-6, atol=1e-4)
print("梯度是否正確:", test)
通過本教程,大家可以在編程獅(W3Cschool)平臺上輕松掌握 PyTorch 結(jié)合 NumPy 和 SciPy 創(chuàng)建擴(kuò)展層的方法,為構(gòu)建更復(fù)雜的深度學(xué)習(xí)模型打下堅(jiān)實(shí)基礎(chǔ)。后續(xù)可在編程獅(W3Cschool)學(xué)習(xí)更多進(jìn)階內(nèi)容。
Copyright©2021 w3cschool編程獅|閩ICP備15016281號-3|閩公網(wǎng)安備35020302033924號
違法和不良信息舉報(bào)電話:173-0602-2364|舉報(bào)郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號
聯(lián)系方式:
更多建議: