【Pytorch】(一)張量(tensor)

      網友投稿 1070 2025-04-01

      三階多項式擬合正弦函數(numpy, ndarray)


      張量

      直接由數據得到

      由NumPy array得到

      由另一個張量得到

      初始化隨機或常量值張量

      三階多項式擬合正弦函數(numpy, ndarray)

      張量

      直接由數據得到

      由NumPy array得到

      由另一個張量得到

      初始化隨機或常量值張量

      張量的屬性

      張量運算

      標準numpy式的索引和切片

      連接張量[2]

      算術運算

      單元素張量

      就地(In-place)操作[3]

      張量與Numpy 數組

      張量 到 NumPy 數組

      NumPy 數組 到 張量

      三階多項式擬合正弦函數(pytorch,tensor)

      三階多項式擬合正弦函數(numpy, ndarray)

      Numpy是科學計算的框架,不是專門用于計算圖、深度學習或梯度的。但我們可以使用numpy實現網絡的正向和反向傳播。例如,用三階多項式擬合正弦函數:

      # -*- coding: utf-8 -*- import numpy as np import math import time time_start = time.time() # 隨機初始化輸入和輸出數據 x = np.linspace(-math.pi, math.pi, 2000) y = np.sin(x) # 隨機初始化權重 a = np.random.randn() b = np.random.randn() c = np.random.randn() d = np.random.randn() learning_rate = 1e-6 for t in range(2000): # 前向傳播:計算預測值 y # y = a + b x + c x^2 + d x^3 y_pred = a + b * x + c * x ** 2 + d * x ** 3 # 計算損失 loss = np.square(y_pred - y).sum() if t % 100 == 99: print(f'迭代次數:{t+1},損失值:{loss}') # 反向傳播:計算損失關于a, b, c, d 的梯度 grad_y_pred = 2.0 * (y_pred - y) grad_a = grad_y_pred.sum() grad_b = (grad_y_pred * x).sum() grad_c = (grad_y_pred * x ** 2).sum() grad_d = (grad_y_pred * x ** 3).sum() # 梯度下降更新權重 a -= learning_rate * grad_a b -= learning_rate * grad_b c -= learning_rate * grad_c d -= learning_rate * grad_d time_end = time.time() print('消耗時間:', time_end - time_start, 's') print(f'結果: y = {a} +  x + {c} x^2 + gs2w0wm x^3')

      輸出:

      ... ... 迭代次數:2000,損失值:9.68922650914574 消耗時間: 0.6189007759094238 s 結果: y = -0.03123761638932383 + 0.8577752449653959 x + 0.0053890086233387485 x^2 + -0.09347752370202965 x^3

      既然numpy也可以實現網絡的正向和反向傳播,那為什么還要pytorch呢?

      Numpy是一個很棒的框架,但它不能利用GPU來加速計算,這使得它不適用于大計算量的深度學習。而pytorch的一種數據結構——張量(tensor)則可以在GPU或其他硬件加速器上運行。另外,pytorch的自動求導機制,能自動的幫我們把反向傳播全部計算好。

      下面,我們將進入本文的主題:張量(tensor)。

      張量

      張量(tensor)是一種特殊的數據結構,與數組和矩陣非常相似。在pytorch中,我們使用張量對模型的輸入和輸出以及模型的參數進行編碼。張量與NumPy的數組很相似,只是它可以在GPU或其他硬件加速器上運行。

      In[2]: import torch In[3]: import numpy as np

      直接由數據得到

      使用torch.tensor()

      In[4]: data = [[1, 2],[3, 4]] In[5]: x_data = torch.tensor(data) In[6]: x_data Out[6]: tensor([[1, 2], [3, 4]])

      由NumPy array得到

      使用torch.from_numpy()

      np_array = np.array(data) x_np = torch.from_numpy(np_array) x_np Out[9]: tensor([[1, 2], [3, 4]], dtype=torch.int32)

      由另一個張量得到

      除非顯式重寫,否則新的張量將保留參數張量的屬性(形狀、數據類型)。

      In[10]: x_ones = torch.ones_like(x_data) In[11]: x_ones Out[11]: tensor([[1, 1], [1, 1]]) In[12]: x_rand = torch.rand_like(x_data, dtype=torch.float) # 類型重寫 In[13]: x_rand Out[13]: tensor([[0.2792, 0.9185], [0.5906, 0.8662]]) In[14]: x_rand.dtype Out[14]: torch.float32

      初始化隨機或常量值張量

      shape是表示張量維度的元組。在下面的函數中,它決定了輸出張量的維數。

      【Pytorch】(一)張量(tensor)

      In[15]: shape = (2,3,) ...: rand_tensor = torch.rand(shape) ...: ones_tensor = torch.ones(shape) ...: zeros_tensor = torch.zeros(shape) In[16]: rand_tensor Out[16]: tensor([[0.3380, 0.0584, 0.5423], [0.6003, 0.6216, 0.9982]]) In[17]: ones_tensor Out[17]: tensor([[1., 1., 1.], [1., 1., 1.]]) In[18]: zeros_tensor Out[18]: tensor([[0., 0., 0.], [0., 0., 0.]])

      張量的屬性

      張量屬性描述它們的形狀(shape)、數據類型(dtype)和存儲它們的設備(device)。

      In[19]: tensor = torch.rand(3,4) In[20]: tensor.shape Out[20]: torch.Size([3, 4]) In[21]: tensor.dtype Out[21]: torch.float32 In[22]: tensor.device Out[22]: device(type='cpu')

      張量運算

      pytorch對張量有超過100種運算操作(傳送門)。每個操作都可以在GPU上運算(速度通常高于CPU)。

      默認情況下,創建張量都是在CPU上運算。我們需要使用.to顯式地將張量移動到GPU中(在GPU可用的前提下)。但請記住,跨設備復制大量張量需要耗費許多時間和內存!

      In[23]: tensor Out[23]: tensor([[0.0061, 0.1010, 0.5185, 0.8282], [0.7172, 0.8436, 0.0652, 0.0033], [0.2006, 0.7263, 0.8957, 0.8063]]) In[25]: # 如果GPU可用,將張量移動到GPU ...: if torch.cuda.is_available(): ...: tensor = tensor.to('cuda') In[26]: tensor Out[26]: tensor([[0.0061, 0.1010, 0.5185, 0.8282], [0.7172, 0.8436, 0.0652, 0.0033], [0.2006, 0.7263, 0.8957, 0.8063]], device='cuda:0')

      下面列舉一些簡單的操作。如果你熟悉NumPy API,您會發現Tensor API很容易使用。

      標準numpy式的索引和切片

      In[33]: tensor = torch.rand(4, 4) In[34]: tensor Out[34]: tensor([[0.1227, 0.2580, 0.4331, 0.9736], [0.3351, 0.5426, 0.5793, 0.1816], [0.7569, 0.6747, 0.0966, 0.9883], [0.1359, 0.1780, 0.0796, 0.9142]]) In[35]: tensor[0] # 第一行 Out[35]: tensor([0.1227, 0.2580, 0.4331, 0.9736]) In[36]: tensor[:, 0] #第一列 Out[36]: tensor([0.1227, 0.3351, 0.7569, 0.1359]) In[37]: tensor[..., -1] # 最后一列 Out[37]: tensor([0.9736, 0.1816, 0.9883, 0.9142])

      連接張量[2]

      連接張量有兩種方法:torch.cat()或torch.stack()

      In[39]: tensor = torch.ones(2, 3) In[40]: tensor Out[40]: tensor([[1., 1., 1.], [1., 1., 1.]])

      首先看一下torch.cat():

      dim=1時,形狀變為[2, 6]

      In[41]: t1 = torch.cat([tensor, tensor, tensor], dim=1) In[42]: t1 Out[42]: tensor([[1., 1., 1., 1., 1., 1., 1., 1., 1.], [1., 1., 1., 1., 1., 1., 1., 1., 1.]])

      dim=0時,形狀變為[6, 2]

      In[43]: t0 = torch.cat([tensor, tensor, tensor], dim=0) In[44]: t0 Out[44]: tensor([[1., 1., 1.], [1., 1., 1.], [1., 1., 1.], [1., 1., 1.], [1., 1., 1.], [1., 1., 1.]])

      與torch.cat()不同,torch.stack()是沿著一個新維度對輸入張量序列進行連接。 序列中所有的張量都應該為相同形狀。

      淺顯說法:就是把多個2維的張量湊成一個3維的張量;多個3維的湊成一個4維的張量……以此類推,也就是在增加新的維度進行堆疊。

      例子:

      準備2個[3,3]的張量數據。

      In[45]: T1 = torch.tensor([[1, 2, 3], ...: [4, 5, 6], ...: [7, 8, 9]]) ...: T2 = torch.tensor([[10, 20, 30], ...: [40, 50, 60], ...: [70, 80, 90]])

      dim=0時,形狀變為[2, 3, 3]

      In[48]: stack_0=torch.stack((T1,T2),dim=0) In[49]: stack_0 Out[49]: tensor([[[ 1, 2, 3], [ 4, 5, 6], [ 7, 8, 9]], [[10, 20, 30], [40, 50, 60], [70, 80, 90]]]) In[50]: stack_0.shape Out[50]: torch.Size([2, 3, 3])

      dim=1時,形狀變為[3, 2, 3]

      In[51]: stack_1=torch.stack((T1,T2),dim=1) In[52]: stack_1 Out[52]: tensor([[[ 1, 2, 3], [10, 20, 30]], [[ 4, 5, 6], [40, 50, 60]], [[ 7, 8, 9], [70, 80, 90]]]) In[53]: stack_1.shape Out[53]: torch.Size([3, 2, 3])

      dim=2時,形狀變為[3, 3, 2]

      In[54]: stack_2=torch.stack((T1,T2),dim=2) In[55]: stack_2 Out[55]: tensor([[[ 1, 10], [ 2, 20], [ 3, 30]], [[ 4, 40], [ 5, 50], [ 6, 60]], [[ 7, 70], [ 8, 80], [ 9, 90]]]) In[56]: stack_2.shape Out[56]: torch.Size([3, 3, 2])

      算術運算

      下面是計算兩個張量之間的矩陣乘法的方法。y1、y2、y3將具有相同的值

      In[62]: tensor=torch.ones(3,3) In[63]: y1 = tensor @ tensor.t() #.t():矩陣轉置 In[64]: y2 = tensor.matmul(tensor.t()) In[65]: y3 = torch.rand_like(tensor) In[66]: torch.matmul(tensor, tensor.t(), out=y3) Out[66]: tensor([[3., 3., 3.], [3., 3., 3.], [3., 3., 3.]]) In[67]: y1 Out[67]: tensor([[3., 3., 3.], [3., 3., 3.], [3., 3., 3.]]) In[68]: y2 Out[68]: tensor([[3., 3., 3.], [3., 3., 3.], [3., 3., 3.]]) In[69]: y3 Out[69]: tensor([[3., 3., 3.], [3., 3., 3.], [3., 3., 3.]])

      下面將計算逐元素的乘積。z1、z2、z3將具有相同的值

      In[70]: z1 = tensor * tensor In[71]: z2 = tensor.mul(tensor) In[72]: z3 = torch.rand_like(tensor) In[73]: torch.mul(tensor, tensor, out=z3); In[74]: z1 Out[74]: tensor([[1., 1., 1.], [1., 1., 1.], [1., 1., 1.]]) In[75]: z2 Out[75]: tensor([[1., 1., 1.], [1., 1., 1.], [1., 1., 1.]]) In[77]: z3 Out[77]: tensor([[1., 1., 1.], [1., 1., 1.], [1., 1., 1.]])

      單元素張量

      如果有一個單元素張量,例如將張量的所有值加起來得到一個值,那么可以使用item()將其轉換為Python數值:

      In[82]: agg = tensor.sum() In[83]: agg Out[83]: tensor(9.) In[84]: agg_item = agg.item() In[85]: agg_item Out[85]: 9.0 In[86]: type(agg_item) Out[86]: float In[87]: type(agg) Out[87]: torch.Tensor

      就地(In-place)操作[3]

      就地操作是直接更改給定張量的內容而不會為變量分配新的內存進行復制。

      將結果存儲到操作數中的操作稱為就地調用。它們由一個后綴表示。例如:x.copy_(y), x.t_()。這種操作將更改x。

      In[88]: tensor Out[88]: tensor([[1., 1., 1.], [1., 1., 1.], [1., 1., 1.]]) In[89]: tensor.add_(5) Out[89]: tensor([[6., 6., 6.], [6., 6., 6.], [6., 6., 6.]]) In[90]: tensor Out[90]: tensor([[6., 6., 6.], [6., 6., 6.], [6., 6., 6.]])

      注意:

      就地操作可以節省一些內存,但在計算導數時可能會出現問題,因為會立即丟失歷史記錄。因此,不鼓勵使用它們。

      張量與Numpy 數組

      在CPU的tensor和NumPy的array會共享其底層內存,即更改其中一個的同時另一個也會被更改。

      張量 到 NumPy 數組

      In[91]: t = torch.ones(5) In[92]: n = t.numpy() In[93]: t Out[93]: tensor([1., 1., 1., 1., 1.]) In[94]: n Out[94]: array([1., 1., 1., 1., 1.], dtype=float32)

      張量的改變將導致對應NumPy數組的改變。

      In[95]: t.add_(1) Out[95]: tensor([2., 2., 2., 2., 2.]) In[96]: t Out[96]: tensor([2., 2., 2., 2., 2.]) In[97]: n Out[97]: array([2., 2., 2., 2., 2.], dtype=float32)

      NumPy 數組 到 張量

      In[99]: n = np.ones(5) In[99]: t = torch.from_numpy(n) In[100]: np.add(n, 1, out=n) Out[100]: array([2., 2., 2., 2., 2.]) In[101]: t Out[101]: tensor([2., 2., 2., 2., 2.], dtype=torch.float64) In[102]: n Out[102]: array([2., 2., 2., 2., 2.])

      三階多項式擬合正弦函數(pytorch,tensor)

      下面我們基于PyTorch的張量,將三階多項式擬合正弦函數。

      # -*- coding: utf-8 -*- import torch import math import time time_start = time.time() dtype = torch.float device = torch.device("cpu") #device = torch.device("cuda:0") # 取消這一行注釋以在GPU上運行 # 隨機初始化輸入和輸出數據 x = torch.linspace(-math.pi, math.pi, 2000, device=device, dtype=dtype) y = torch.sin(x) # 隨機初始化權重 a = torch.randn((), device=device, dtype=dtype) b = torch.randn((), device=device, dtype=dtype) c = torch.randn((), device=device, dtype=dtype) d = torch.randn((), device=device, dtype=dtype) learning_rate = 1e-6 for t in range(2000): # 前向傳播:計算預測值 y y_pred = a + b * x + c * x ** 2 + d * x ** 3 # 計算損失 loss = (y_pred - y).pow(2).sum().item() if t % 100 == 99: print(f'迭代次數:{t + 1},損失值:{loss}') # 反向傳播:計算損失關于a, b, c, d 的梯度 grad_y_pred = 2.0 * (y_pred - y) grad_a = grad_y_pred.sum() grad_b = (grad_y_pred * x).sum() grad_c = (grad_y_pred * x ** 2).sum() grad_d = (grad_y_pred * x ** 3).sum() # 梯度下降更新權重 a -= learning_rate * grad_a b -= learning_rate * grad_b c -= learning_rate * grad_c d -= learning_rate * grad_d time_end = time.time() print('消耗時間:', time_end - time_start, 's') print(f'Result: y = {a.item()} + {b.item()} x + {c.item()} x^2 + {d.item()} x^3')

      使用CPU,輸出:

      ... ... 迭代次數:2000,損失值:14.256892204284668 消耗時間: 0.8661777973175049 s Result: y = 0.05625741183757782 + 0.8070318698883057 x + -0.00970533862709999 x^2 + -0.08625971525907516 x^3

      使用GPU,輸出:

      ... ... 迭代次數:2000,損失值:9.254937171936035 消耗時間: 8.750219345092773 s Result: y = -0.000127201754366979 + 0.8364022374153137 x + 2.19428966374835e-05 x^2 + -0.0904374048113823 x^3

      ???說好的GPU加速呢?

      用電鋸切菜能快么,電鋸是用來砍樹的。同樣道理,GPU在大規模網絡才有明顯的加速。

      GPU比CPU慢的原因大致為[4]:

      數據傳輸會有很大的開銷,而GPU處理數據傳輸要比CPU慢,而GPU的專長矩陣計算在小規模神經網絡中無法明顯體現出來。

      下面以單純的矩陣乘法做對比:

      import torch import time a = torch.ones(10000, 1000) b = torch.ones(1000, 10000) t0 = time.time() c = torch.matmul(a, b) t1 = time.time() print('CPU:', t1 - t0, 's') device = torch.device('cuda') a = a.to(device) b = b.to(device) t0 = time.time() c = torch.matmul(a, b) t1 = time.time() print('GPU:', t1 - t0, 's')

      輸出:

      CPU: 2.434323310852051 s GPU: 0.5386180877685547 s

      這不,快了。

      參考:

      [1] https://pytorch.org/tutorials/beginner/basics/tensorqs_tutorial.html

      [2] https://blog.csdn.net/xinjieyuan/article/details/105205326

      [3]https://zhuanlan.zhihu.com/p/344455805

      [4]https://blog.csdn.net/qq_43673118/article/details/90305340

      Numpy pytorch

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      上一篇:wps刪除節不刪除內容
      下一篇:java--反射九個預定義Class對象(二)
      相關文章
      亚洲成aⅴ人片久青草影院按摩| 亚洲av乱码一区二区三区香蕉| 国产精品亚洲片夜色在线| 久久亚洲精品成人AV| 午夜在线a亚洲v天堂网2019| 亚洲激情校园春色| 精品亚洲成AV人在线观看| 久久亚洲日韩看片无码| 91嫩草私人成人亚洲影院| 911精品国产亚洲日本美国韩国| 亚洲专区先锋影音| 久久久亚洲欧洲日产国码aⅴ| 久久亚洲精品无码aⅴ大香| 亚洲激情黄色小说| 亚洲三级在线观看| 亚洲国产精品无码第一区二区三区| 亚洲一区AV无码少妇电影| 亚洲国产成人无码AV在线| 在线观看亚洲网站| 亚洲另类少妇17p| 中文字幕无码精品亚洲资源网| 亚洲人av高清无码| 亚洲乱色伦图片区小说| 校园亚洲春色另类小说合集| 国产亚洲成在线播放va| 亚洲人成色7777在线观看不卡| 国产成人麻豆亚洲综合无码精品| 国产精品亚洲专区无码牛牛 | 亚洲成人高清在线| 亚洲一区二区三区在线播放 | 中文字幕精品亚洲无线码一区应用| 成人午夜亚洲精品无码网站| 国产亚洲AV无码AV男人的天堂| 国产亚洲欧洲精品| 亚洲人成在线观看| 亚洲乱码一二三四区麻豆| 亚洲欧美中文日韩视频| 亚洲精品成a人在线观看| 亚洲精品无码成人AAA片| 91亚洲va在线天线va天堂va国产| 国产精品亚洲自在线播放页码|