自求導實現線性回歸與PyTorch張量詳解

目錄

  • 前言
  • 一、自求導的方法實現線性回歸
  • 1.1自求導的方法實現線性回歸的理論講解
  • 1.1.1 線性回歸是什么?
  • 1.1.2線性回歸方程是什么?
  • 1.1.3散點輸入
  • 1.2參數初始化
  • 1.2.1?參數與超參數
  • 1.2.1.1?參數定義
  • 1.2.1.2 參數內容
  • 1.2.1.3 超參數定義
  • 1.2.1.4 超參數內容
  • 1.2.2 參數設定
  • 1.3 損失函數
  • 1.4 開始迭代
  • 1.5 反向傳播
  • 1.6 顯示頻率設置
  • 1.9 梯度下降顯示
  • 2.0 自求導實現線性回歸程序?
  • 二、深度學習框架Pytorch的tensor
  • 2.2 PyTorch是什么?
  • 2.3 PyTorch的特點
  • 2.4 tensor是什么?
  • 2.5 torch 安裝命令
  • 2.6 tensor的存儲機制
  • 2.6.1?tensor
  • 2.6.2 數據類型
  • 2.6.2.1 基本構成
  • 2.6.2.2 計算方式
  • 2.6.2.3 實戰計算
  • 2.6.3? Storage 存儲與共享
  • 2.7 tensor的步長
  • 2.8 tensor的偏移
  • 2.9 Tensor的連續性
  • 2.9.1 tensor的連續性是什么?
  • 2.9.2 tensor的不連續性是什么?
  • 2.9.3 不連續的缺點與解決方案
  • 總結

前言

書接上文

線性回歸的前向傳播、反向傳播與數學求解詳解-CSDN博客文章瀏覽閱讀1k次,點贊40次,收藏19次。本文從前向傳播的代碼實現出發,展示了如何利用線性模型對二維數據進行擬合及誤差分析,接著深入講解了反向傳播中的學習率和梯度下降算法的理論基礎及優化方法,結合Python代碼動態演示了參數更新和損失函數的變化過程;最后,文章通過數學推導詳細揭示了線性回歸模型參數的計算公式,并用代碼實現了數學解法的擬合過程,幫助讀者全面掌握線性回歸的基本原理、優化方法及編程實現。 https://blog.csdn.net/qq_58364361/article/details/147264719?spm=1011.2415.3001.10575&sharefrom=mp_manage_link


一、自求導的方法實現線性回歸

從以下2個方面對自求導的方法實現線性回歸算法進行介紹
1.自求導的方法實現線性回歸算法理論講解
2.編程實例與步驟
上面這2方面的內容,讓大家,掌握并理解自求導的方法實現線性回歸算法。


1.1自求導的方法實現線性回歸的理論講解

在了解前向傳播、反向傳播、損失函數、學習率、梯度下降這些概念后,我們就可以通過自求導的方式來實現線性回歸算法。


1.1.1 線性回歸是什么?

定義:

線性回歸是一種用于建立自變量與因變量之間關系的統計方法。

它假設因變量(或響應變量)與一個或多個自變量(或預測變量)之間的關系是線性的。

其主要目標是通過擬合一個線性模型來預測因變量的數值。


1.1.2線性回歸方程是什么?

公式:

線性回歸模型可以表示為:

Y=β_0+β_1X_1+β_2X_2+...+β_nX_n+ε

其中:

Y是因變量

X_1,X_2,...,X_n是自變量

β_0,β_1,...,β_n是模型的系數,表示自變量對因變量的影響。

ε是誤差項,表示模型無法解釋的隨機誤差


1.1.3散點輸入

算法實現需要的數據,一些散點,將它們繪制在一個二維坐標中,其分布如下圖所示:


1.2參數初始化

1.2.1?參數與超參數

1.2.1.1?參數定義

模型中可調整的變量,它們用來捕捉數據中的模式和特征。這些參數在模型訓練過程中被不斷調整以最小化損失函數或優化某種目標。


1.2.1.2 參數內容

權重(Weights):用來表示不同輸入特征與神經元之間的連接強度

偏置(Biases):用于調整每個神經元的激活閾值,使模型能夠更好地擬合數據。


1.2.1.3 超參數定義

超參數不是通過訓練數據學習得到的,而是在訓練過程之前需要手動設置的參數。


1.2.1.4 超參數內容

包括學習率正則化參數迭代次數批量大小神經網絡層數和每層的神經元數量激活函數

學習率(Learning Rate):用于控制優化算法中每次更新參數時的步長。較小的學習率會導致訓練收斂較慢,而較大的學習率可能導致訓練不穩定或震蕩。

正則化參數(Regularization Parameter):用于控制正則化的強度,如L1正則化和L2正則化。較大的正則化參數會增強正則化效果,有助于防止過擬合。

迭代次數(Number of Iterations):用于控制訓練的迭代次數。迭代次數太小可能導致模型未完全學習數據的特征,而迭代次數太大可能導致過擬合。

批量大小(Batch Size):用于控制每次訓練時用于更新參數的樣本數量。批量大小的選擇會影響訓練速度和內存消耗。

神經網絡層數和每層的神經元數量(Number of Layers and Neurons per Layer):用于定義神經網絡的結構。

激活函數(Activation Function):用于控制神經網絡每個神經元的輸出范圍,如Sigmoid、ReLU等。


1.2.2 參數設定

在前向傳播實驗中,知道了參數不同時對應的損失函數值也不同,所以需要先初始化一下參數和超參數,進行一次前向傳播,得到損失值,這樣才能通過反向傳播減小損失,使直線的擬合效果更好。這里通過“參數初始化”組件來初始化w和b以及學習率這三個參數/超參數


1.3 損失函數

與前向傳播實驗和反向傳播實驗不同,此時b的值不再是0,也就意味著損失函數不僅僅受到w的影響,還會受到b的影響,將 y=wx+b 帶入損失函數的表達式后,新的損失函數就變成了如下圖所示的表達式:

1.4 開始迭代

迭代次數通常指的是反向傳播的次數,即通過反向傳播來更新模型的參數,直到達到一定的迭代次數或者達到收斂的條件為止。

迭代的次數越多,模型參數就越接近最優解,從而使得損失函數達到最小值,但是可能會造成過擬合(過擬合在之后的實驗會講到)。

一般來說,迭代次數需要根據具體情況來確定,通常需要進行多次迭代來更新模型參數,直到達到收斂的條件為止,在“開始迭代”組件中默認的是500次。

1.5 反向傳播

當參數和損失函數都設置好之后,就開始反向傳播了,也就是損失函數對w和b進行求導并且不斷更新w和b的過程,是一個復合函數

求導的過程。損失函數對w和b的求導過程如下:


1.6 顯示頻率設置

求導完成之后,使用梯度下降的方法來更新w和b的值。為了更好的在實驗中看現象,這里有一個“顯示頻率設置”組件,就是每經過多少次迭代,繪制一次當前參數的擬合線及損失函數的大小。


1.9 梯度下降顯示

迭代的結果通過“梯度下降顯示”組件進行查看。如下圖所示,38.4是w 的實時值,24.58是b的實時值,42.68是最后的損失值。

除此之外,該組件還有三個圖,左邊的是實時的直線圖,參數每更新一次,該直線就更新一次,右邊的是損失值的圖像,顯示的是經過迭代后的損失值的大小,下方的圖是W和B隨著不斷的更新而變化的等高線圖


2.0 自求導實現線性回歸程序?

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspecfrom 機器學習.test import iter_num_list  # 導入外部模塊中的iter_num_list(此處未使用)# 1. 準備數據:散點坐標
data = [[-0.5, 7.7],[1.8, 98.5],[0.9, 57.8],[0.4, 39.2],[-1.4, -15.7],[-1.4, -37.3],[-1.8, -49.1],[1.5, 75.6],[0.4, 34],[0.8, 62.3]]# 轉換為numpy數組,便于矩陣運算
data = np.array(data)
x_data = data[:, 0]  # 取第一列作為x數據
y_data = data[:, 1]  # 取第二列作為y數據# 初始化線性模型參數w和b
w = 0
b = 0# 設置學習率
learning_rate = 0.01# 定義損失函數(均方誤差)
def loss_function(x_data, y_data, w, b):predicted = np.dot(x_data, w) + b  # 線性預測y_mean = np.mean((y_data - predicted) ** 2)  # 均方誤差計算return y_mean# 創建畫布,采用2行2列的格子布局
fig = plt.figure("show figure")
gs = gridspec.GridSpec(2, 2)# 左上子圖:繪制散點圖及擬合直線
ax1 = fig.add_subplot(gs[0, 0])
ax1.set_xlabel('X')
ax1.set_ylabel('y')
ax1.set_title('figure1 data')# 左下子圖:繪制損失隨迭代變化圖
ax2 = fig.add_subplot(gs[1, 0])
ax2.set_xlabel('iter')
ax2.set_ylabel('e')
ax2.set_title('figure2 data')# 右上子圖:繪制損失函數關于w和b的三維表面
ax3 = fig.add_subplot(gs[0, 1], projection='3d')# 設置權重w和偏置b的取值范圍
w_values = np.linspace(-20, 80, 100)
b_values = np.linspace(-20, 80, 100)# 生成網格數據用于繪制曲面
W, B = np.meshgrid(w_values, b_values)# 初始化對應損失函數值矩陣
loss_values = np.zeros_like(W)# 計算每個(w, b)組合的損失值
for i, w_value in enumerate(w_values):for j, b_value in enumerate(b_values):loss_values[j, i] = loss_function(x_data, y_data, w_value, b_value)# 繪制三維曲面圖(顏色映射采用viridis)
ax3.plot_surface(W, B, loss_values, cmap='viridis', alpha=0.8)# 設置三維坐標軸標簽和標題
ax3.set_xlabel('w')
ax3.set_ylabel('b')
ax3.set_zlabel('loss')
ax3.set_title('figure3  surface plot')# 右下子圖:繪制損失函數的等高線填充圖
ax4 = fig.add_subplot(gs[1, 1])
ax4.set_xlabel('w')
ax4.set_ylabel('b')
ax4.set_title('coutour plot')
ax4.contourf(W, B, loss_values, levels=20, cmap='viridis')# 迭代次數設置
num_iterations = 100# 初始化列表,用于存儲損失(sh)、迭代次數(cs)、和參數軌跡(gj)
sh = []  # 記錄每次迭代的損失
cs = []  # 記錄迭代次數
gj = []  # 記錄每次迭代的(w, b)參數值軌跡# 梯度下降主循環
for i in range(1, num_iterations + 1):gj.append((w, b))  # 保存當前參數yc = np.dot(x_data, w) + b  # 預測值e = np.mean((y_data - yc) ** 2)  # 當前均方誤差sh.append(e)  # 記錄損失cs.append(i)  # 記錄迭代次數# 計算梯度(損失對w和b的偏導數)dw = (-2 * (y_data - yc).dot(x_data)) / len(x_data)db = np.mean(-2 * (y_data - yc))# 參數更新,梯度下降法w = w - learning_rate * dwb = b - learning_rate * db# 每隔10次迭代或第1次迭代,更新繪圖顯示f = 10if i % f == 0 or i == 1:# 清空左上子圖,重新繪制散點和擬合直線ax1.clear()ax1.set_xlabel('X')ax1.set_ylabel('y')ax1.set_title('figure1 data')ax1.scatter(x_data, y_data, c='b', marker='o')  # 繪制散點x_min, x_max = x_data.min(), x_data.max()y_min, y_max = w * x_min + b, w * x_max + bax1.plot([x_min, x_max], [y_min, y_max], c='r')  # 繪制擬合直線# 清空左下子圖,重新繪制損失隨迭代次數的變化曲線ax2.clear()ax2.set_xlabel('iter')ax2.set_ylabel('e')ax2.set_title('figure2 data')ax2.plot(cs, sh, c='g')  # 繪制損失曲線# 繪制右上三維曲面上的梯度下降軌跡if len(gj) > 0:g_w, g_b = zip(*gj)  # 解包軌跡參數# 繪制軌跡點(散點線)ax3.plot(g_w, g_b, [loss_function(x_data, y_data, w_, b_) for w_, b_ in gj], c='b')ax3.set_xlim(-20, 80)ax3.set_ylim(-20, 80)ax3.set_xlabel('w')ax3.set_ylabel('b')ax3.set_zlabel('loss')ax3.set_title('figure3  surface plot')# 繪制當前參數對應的點,用黑點高亮ax3.scatter(w, b, loss_function(x_data, y_data, w, b), c='b', s=20)# 右下等高線圖繪制迭代軌跡曲線ax4.plot(g_w, g_b)# 暫停0.01秒,更新動畫效果

二、深度學習框架Pytorch的tensor

從以下4個方面對深度學習框架Pytorch的tensor進行介紹
1.PyTorch是什么?
2.tensor是什么?
3.tensor的存儲機制
4.tensor的連續性
上面這4方面的內容,讓大家,掌握并理解深度學習框架Pytorch的tensor。


2.2 PyTorch是什么?

概念:

PyTorch是一個開源的深度學習框架,由Meta公司(原名:Facebook)的人工智能團隊開發和維護。它提供了一個靈活、動態的計算圖計算模型,使得在深度學習領域進行實驗和開發變得更加簡單和直觀

pytorch網址

PyTorch documentation — PyTorch 2.6 documentationhttps://pytorch.org/docs/stable/index.html


2.3 PyTorch的特點

2.1動態計算圖

PyTorch使用動態計算圖,這意味著計算圖在運行時構建的,而不是在編譯時靜態定義的。

2.2 自動求導(微分)

PyTorch提供了自動求導機制,稱為Autograd。它能夠自動計算張量的梯度,這對于訓練神經網絡和其他深度學習模型非常有用。

2.3 豐富的神經網絡庫

PyTorch 提供了豐富的神經網絡庫,包括各種各樣的層,損失函數、優化器等。這些庫使得構建和訓練神經網

絡變得更加容易。

2.4支持GPU加速

PyTorch 充分利用了GPU的并行計算能力,能夠在GPU上高效地進行計算,加速模型訓練過程。


2.4 tensor是什么?

tensor是一種多維數組,類似于NumPy的ndarray.它是Pytorch中最基本的數據結構,用于存儲和操作數據。

tensor可以是標量向量矩陣或者更高維度的數組,可以包含整數、浮點數或者其他數據類型的元素。

PyTorch的Tensor和NumPy的ndarray非常相似,但在設計和功能上有一些不同之處。主要的區別包括:GPU加速自動求導動態計算圖


2.5 torch 安裝命令

python -m pip install --upgrade pip

pip install torch==2.4.1 -i https://pypi.tuna.tsinghua.edu.cn/simple

!pip install torch==2.4.1 -i Simple Index

import torch""" 01
-------------------打印標量 向量 矩陣
"""# 打印一個標量張量
# 標量是只有一個數值的張量,這里值為3.14
scalar_tensor = torch.tensor(3.14)
print("scalar_tensor:", scalar_tensor, "\n")# 打印一個向量張量
# 向量是1維張量,這里包含5個元素:[1, 2, 3, 4, 5]
vector_tensor = torch.tensor([1, 2, 3, 4, 5])
print("vector_tensor:", vector_tensor, "\n")# 打印一個矩陣張量
# 矩陣是2維張量,這里是2行2列的矩陣[[1, 2], [3, 4]]
matrix_tensor = torch.tensor([[1, 2], [3, 4]])
print("matrix_tensor:", matrix_tensor, "\n")
D:\python_huanjing\.venv1\Scripts\python.exe C:\Users\98317\PycharmProjects\study_python\機器學習\test.py 
scalar_tensor: tensor(3.1400) vector_tensor: tensor([1, 2, 3, 4, 5]) matrix_tensor: tensor([[1, 2],[3, 4]]) 進程已結束,退出代碼為 0

2.6 tensor的存儲機制

2.6.1?tensor

在PyTorch中,tensor包含了兩個部分,即Storage 和metadata。Storage(存儲):存儲是tensor中包含的實際的底層緩沖區,它是一維數組,存儲了tensor的元素值。不同tensor可能共享相同的存儲,即使它們具有不同的形狀和步幅。存儲是一塊連續的內存區域,實際上存儲了tensor中的數據。

Metadata(元數據):元數據是tensor的描述性信息,包括tensor的形狀、數據類型、步幅、存儲偏移量、設備等。元數據提供了關于tensor的結構和屬性信息,但并不包括tensor中的實際數據。元數據允許PyTorch知道如何正確地解釋存儲中的數據以及如何訪問它們。

描述性信息元數據:

tensor

tensor:tensor([[1,2,3],[4,5,6]])

Metadata

形狀

數據類型

步幅/步長

存儲偏移量

設備

Storage

一維數組

import torch

import torch# tensor 存儲示例
# 創建一個2行3列的浮點數張量
tensor_2_3_float = torch.tensor([[1.0, 2.0, 3.0], [4, 5, 6]])# 打印張量的數據類型(dtype),比如float32
print(tensor_2_3_float.dtype, "\n")# 打印張量的底層存儲結構(storage),顯示存儲的數據信息
print(tensor_2_3_float.storage(), "\n")# 將底層存儲的數據轉換為列表,方便查看具體元素順序
print(tensor_2_3_float.storage().tolist(), "\n")# 打印存儲偏移量,表示張量數據起始位置相對底層存儲的偏移索引
print(tensor_2_3_float.storage_offset(), "\n")# 再次打印存儲偏移量,結果相同
print(tensor_2_3_float.storage_offset(), "\n")
D:\python_huanjing\.venv1\Scripts\python.exe C:\Users\98317\PycharmProjects\study_python\機器學習\test.py 
torch.float32 1.02.03.04.05.06.0
[torch.storage.TypedStorage(dtype=torch.float32, device=cpu) of size 6] [1.0, 2.0, 3.0, 4.0, 5.0, 6.0] 0 0 C:\Users\98317\PycharmProjects\study_python\機器學習\test.py:11: UserWarning: TypedStorage is deprecated. It will be removed in the future and UntypedStorage will be the only storage class. This should only matter to you if you are using storages directly.  To access UntypedStorage directly, use tensor.untyped_storage() instead of tensor.storage()print(tensor_2_3_float.storage(), "\n")進程已結束,退出代碼為 0

2.6.2 數據類型

整型、無符號整數類型

浮點型

torch.Float16,也被稱為FP16或半精度浮點數,是一種用于表示浮點數的數據類型,在計算機科學中廣泛應用于各種領域。以下是對Float16的詳細說明:


2.6.2.1 基本構成

Float16使用16位(即2個字節)來表示一個浮點數,這16位被分為三部分:

符號位:1位,用于表示數的正負。0代表正數,1代表負數。

指數位:5位,用于表示數的大小。其范圍是00001~11110,對應的十進制數是1~30。為了得到實際的指數值,需要從這些值中減去一個偏置值15,因此實際指數的范圍是-14~15。

尾數位:10位,用于表示數的精度。其范圍是0~1023,這些值除以1024后得到實際的尾數值,范圍是0~0.9990234375。


2.6.2.2 計算方式

Float16類型的數的計算公式是:


2.6.2.3 實戰計算

對于給出的float16值:0011101000000000

根據計算公式得出:為0.75

符號位:0(表示這是一個正數)

指數部分:01110(二進制),轉換為十進制是2^3+2^2+2^1=8+4+2=14

小數部分(尾數):1000000000(二進制)

接下來,將指數部分轉換為實際的指數值。在float16中,指數的偏移量是15,因為最大為2^(5-1)-1=15,所以實際的指數是14-15=-1。

將小數部分轉成十進制:2^(9)=512; 512/1024=0.5; 0.5+1=1.5

最終計算方法:(-1)^符號位×2^(-1)×1.5=0.75。


2.6.3? Storage 存儲與共享

tensor結構圖

對張量進行操作時(比如調整形狀(不是reshape是view),轉置等),它不會創建一個新的張量,而是返回一個指向相同數據的視圖。即PyTorch通常會共享相同的存儲對象,以節省內存和提高效率。

import torch# 驗證storage存儲與共享
# 1. 查看兩個張量的底層存儲是否相同,判斷它們是否共享存儲
# 2. 通過比較存儲的內容和內存地址,確認它們是否指向同一塊內存空間
# 3. 如果兩者的底層存儲內容和內存地址都一致,則說明它們共享同一份數據# 使用 arange 生成0到11的連續整數,共12個元素
# 然后使用 reshape 將其變形成3行4列的張量
tensorA = torch.arange(12).reshape(3, 4)# 打印張量tensorA的底層storage內容(以列表形式)
print(tensorA.storage().tolist())# 對tensorA進行轉置操作,交換第0維和第1維,生成tensorB
tensorB = tensorA.transpose(0, 1)# 打印tensorB的底層storage內容(以列表形式)
# 可觀察轉置操作后底層存儲數據是否發生變化
print(tensorB.storage().tolist(), "\n")# 打印tensorA存儲內容的內存地址(指針)
print(tensorA.storage().data_ptr(), "\n")# 打印tensorB存儲內容的內存地址(指針)
print(tensorB.storage().data_ptr(), "\n")# 打印tensorA對象的id(內存地址,用于區分不同對象)
print(id(tensorA), "\n")# 打印tensorB對象的id,和tensorA相比確認是否為不同對象
print(id(tensorB), "\n")
D:\python_huanjing\.venv1\Scripts\python.exe C:\Users\98317\PycharmProjects\study_python\機器學習\test.py 
C:\Users\98317\PycharmProjects\study_python\機器學習\test.py:13: UserWarning: TypedStorage is deprecated. It will be removed in the future and UntypedStorage will be the only storage class. This should only matter to you if you are using storages directly.  To access UntypedStorage directly, use tensor.untyped_storage() instead of tensor.storage()print(tensorA.storage().tolist())
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11] 5948693287232 5948693287232 1573108881744 1573115855632 進程已結束,退出代碼為 0

Storage存儲的具體過程

在PyTorch中,張量的存儲是通過torch.Storage類來管理的。張量的值被分配在連續的內存塊中,這些內存塊中,這些內存塊是大小可變的一維數組,可以包含不同類型的數據,如float或int32。

具體來說,當我們創建一個張量時,PyTorch會根據我們提供的數據和指定的數據類型來分配一塊連續的內存空間。這塊內存空間由torch.Storage對象管理,而張量本身則提供了一種視圖,讓我們可以通過索引來訪問這些數據。

此外,PyTorch還提供了一系列的函數和方法來操作張量,包括改變形狀,獲取元素、拼接和拆分等。這些操作通常不會改變底層的存儲,而是返回一個新的張量視圖,這個視圖指向相同的數據但是可能有不同的形狀或索引方式。

總的來說,張量的存儲實現是PyTorch能夠高效進行張量運算的關鍵。通過管理一塊連續的內存空間,并提供了豐富的操作方法,使得用戶可以方便地對多維數組進行各種計算和變換。


2.7 tensor的步長

步長指的是在每個維度上移動一個元素時在底層存儲中需要跨越的元素數。

import torch""" 
04
展示張量的步長(stride)概念及其轉置操作對步長和存儲的影響
"""
# 創建一個3行4列的張量,元素為0到11,數據類型為float32
tensor_A = torch.arange(12, dtype=torch.float32).reshape(3, 4)# 打印原張量
print(tensor_A, "\n")# 打印原張量的步長,每個維度跨越內存元素的步長
print(tensor_A.stride(), "\n")# 打印原張量的轉置(交換行列)
print(tensor_A.T, "\n")# 打印轉置后張量的步長,步長的變化反映了維度的交換
print(tensor_A.T.stride(), "\n")# 打印轉置張量底層存儲的所有元素,存儲不變只是視圖變換
print(tensor_A.T.untyped_storage().tolist())
D:\python_huanjing\.venv1\Scripts\python.exe C:\Users\98317\PycharmProjects\study_python\機器學習\test.py 
tensor([[ 0.,  1.,  2.,  3.],[ 4.,  5.,  6.,  7.],[ 8.,  9., 10., 11.]]) (4, 1) tensor([[ 0.,  4.,  8.],[ 1.,  5.,  9.],[ 2.,  6., 10.],[ 3.,  7., 11.]]) (1, 4) [0, 0, 0, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 0, 0, 128, 64, 0, 0, 160, 64, 0, 0, 192, 64, 0, 0, 224, 64, 0, 0, 0, 65, 0, 0, 16, 65, 0, 0, 32, 65, 0, 0, 48, 65]進程已結束,退出代碼為 0

tensor([[ 0, 1, 2, 3],

[ 4, 5, 6, 7],

[ 8, 9, 10, 11]])

(4, 1)

第一個數字4表示矩陣的行(第一個維度)上移動一個元素時需要跨越的存儲單元數。因為矩陣的每行包含4個元素,所以每次沿著行移動一個元素需要跨越4個存儲單元。

第二個數字1表示在矩陣的列(第二個維度)上移動一個元素時需要跨越的存儲單元數,因為矩陣的列數是1,所以在列上移動一個元素時只需要跨越一個存儲單元。


2.8 tensor的偏移

偏移是指從張量的第一個元素開始的索引位置。

偏移程序演示

tensor的偏移

import torch""" 04
張量偏移(storage_offset)示例說明
"""
# 創建一個3行4列的浮點型張量,元素為0到11
tensor_A = torch.arange(12, dtype=torch.float32).reshape(3, 4)# 打印張量tensor_A的內容
print("tensor_A的內容:\n", tensor_A)# 打印張量tensor_A底層存儲的所有元素列表
print("tensor_A的底層存儲元素列表:\n", tensor_A.storage().tolist())# 打印tensor_A的存儲偏移量,指示張量數據在底層存儲中的起始位置
print("tensor_A的存儲偏移量:\n", tensor_A.storage_offset())# 利用切片選取tensor_A第2行到第3行、第2列的數據,生成子張量tensorB
tensorB = tensor_A[1:3, 1:2]# 打印子張量tensorB的內容
print("tensorB的內容:\n", tensorB)# 打印tensorB的存儲偏移量,可以看到相對于底層存儲的起始位置發生了變化
print("tensorB的存儲偏移量:\n", tensorB.storage_offset())# 打印tensorB底層存儲的所有元素,注意存儲仍為tensor_A共享的完整元素列表
print("tensorB的底層存儲元素列表:\n", tensorB.storage().tolist())
D:\python_huanjing\.venv1\Scripts\python.exe C:\Users\98317\PycharmProjects\study_python\機器學習\test.py 
C:\Users\98317\PycharmProjects\study_python\機器學習\test.py:13: UserWarning: TypedStorage is deprecated. It will be removed in the future and UntypedStorage will be the only storage class. This should only matter to you if you are using storages directly.  To access UntypedStorage directly, use tensor.untyped_storage() instead of tensor.storage()print("tensor_A的底層存儲元素列表:\n", tensor_A.storage().tolist())
tensor_A的內容:tensor([[ 0.,  1.,  2.,  3.],[ 4.,  5.,  6.,  7.],[ 8.,  9., 10., 11.]])
tensor_A的底層存儲元素列表:[0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0]
tensor_A的存儲偏移量:0
tensorB的內容:tensor([[5.],[9.]])
tensorB的存儲偏移量:5
tensorB的底層存儲元素列表:[0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0]進程已結束,退出代碼為 0

2.9 Tensor的連續性

2.9.1 tensor的連續性是什么?

Tensor的連續性指的是其元素在內存中按照其在張量中的順序緊密存儲,沒有間隔。

生成的tensor根據"行優先"策略,在展開后與Storage存儲的順序一致,即該tensor連續


2.9.2 tensor的不連續性是什么?

對上面的tensor進行轉置操作

生成的tensor根據"行優先"策略,在展開后與Storage存儲的順序不一致,即該tensor不連續


2.9.3 不連續的缺點與解決方案

當對Tensor進行某些操作,如轉置(transpose)時,可能會導致Tensor變得不連續。

連續的tensor優勢

高效的內存訪問:連續的張量在內存中占用一塊連續的空間,這使得CPU可以高效地按順序訪問數據,減少了內存尋址的時間,從而提高了數據處理的速度。

優化的計算性能:在進行數學運算時,連續張量可以減少數據的移動和復制,因為數據已經按照計算所需的順序排序排列,這樣可以減少計算中的延遲,提高整體的計算性能。

其它:在不連續的tensor上進行view()操作會報錯

連續性和非連續性編程

import torch"""06 
連續性和非連續性示例說明
"""
# 創建一個包含0到11的張量,并將其形狀調整為3行4列
tensorA = torch.arange(12).reshape(3, 4)  # arange生成0到11的序列,reshape調整形狀為3x4# 將tensorA展平成一維張量,默認按行優先順序
print("tensorA展平結果:", tensorA.flatten())  # 按行優先展平# 轉置tensorA,交換0軸和1軸,生成tensorB
tensorB = tensorA.transpose(0, 1)# 嘗試將tensorB展平成一維張量,默認按行優先順序
print("tensorB展平結果:", tensorB.flatten())# 打印tensorB數據在內存中的起始地址
print("tensorB數據起始地址:", tensorB.data_ptr())# 判斷tensorB是否是內存中連續存儲的張量,返回False表示不連續
print("tensorB是否連續:", tensorB.is_contiguous())# 由于tensorB不是連續的,不能直接使用view改變形狀,以下語句會報錯
# tensorB.view(1, 12)# 將tensorB轉化為內存連續的張量,生成新的tensorB
tensorB = tensorB.contiguous()# 對轉化后的tensorB執行展平操作,按行優先順序展開
print("轉化為連續后tensorB展平結果:", tensorB.flatten())# 查看tensorB底層存儲中的元素列表
print("tensorB底層存儲元素列表:", tensorB.storage().tolist())# 打印轉化后tensorB的數據起始地址,地址可能改變
print("連續化后tensorB數據起始地址:", tensorB.data_ptr())# 使用view成功改變tensorB的形狀為1行12列
print("使用view改變形狀為(1,12):", tensorB.view(1, 12))
D:\python_huanjing\.venv1\Scripts\python.exe C:\Users\98317\PycharmProjects\study_python\機器學習\test.py 
tensorA展平結果: tensor([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11])
tensorB展平結果: tensor([ 0,  4,  8,  1,  5,  9,  2,  6, 10,  3,  7, 11])
tensorB數據起始地址: 4949521994112
tensorB是否連續: False
轉化為連續后tensorB展平結果: tensor([ 0,  4,  8,  1,  5,  9,  2,  6, 10,  3,  7, 11])
tensorB底層存儲元素列表: [0, 4, 8, 1, 5, 9, 2, 6, 10, 3, 7, 11]
連續化后tensorB數據起始地址: 4949521994432
使用view改變形狀為(1,12): tensor([[ 0,  4,  8,  1,  5,  9,  2,  6, 10,  3,  7, 11]])
C:\Users\98317\PycharmProjects\study_python\機器學習\test.py:34: UserWarning: TypedStorage is deprecated. It will be removed in the future and UntypedStorage will be the only storage class. This should only matter to you if you are using storages directly.  To access UntypedStorage directly, use tensor.untyped_storage() instead of tensor.storage()print("tensorB底層存儲元素列表:", tensorB.storage().tolist())進程已結束,退出代碼為 0

解決方案:

通過contiguous()方法將不連續的張量轉換為連續的張量。

如果tensor不是連續的,則會重新開辟一塊內存空間保證數據是在內存中是連續的。

如果tensor是連續的,則contiguous()無操作

不論是reshape view 或者其他的操作 如果連續就只改變形狀不改變storage ,如果不連續就直接申請新的內存確保連續。


總結

????????本文系統介紹了自求導方法實現線性回歸的理論基礎與具體實現步驟,首先闡述線性回歸的定義、模型方程及參數初始化,詳細講解了損失函數構建、迭代優化過程及反向傳播求導更新參數的原理與過程,輔以完整的Python編程實例,直觀展示了梯度下降的迭代效果和損失變化。此外,文章深入解析了深度學習框架PyTorch中的張量(tensor)結構,包括其定義、存儲機制、數據類型以及連續性等關鍵概念,說明了tensor底層的Storage及元數據構成,探討了步長和偏移對內存訪問的影響,并通過代碼示例演示了tensor的存儲共享、不連續性的成因及解決方案,幫助讀者全面理解PyTorch tensor的底層機制及高效操作方法,為實際深度學習模型開發打下堅實基礎。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/79426.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/79426.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/79426.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

2025年機電一體化、機器人與人工智能國際學術會議(MRAI 2025)

重要信息 時間:2025年4月25日-27日 地點:中國濟南 官網:http://www.icmrai.org 征稿主題 機電一體化機器人人工智能 傳感器和執行器 3D打印技術 智能控制 運動控制 光電系統 光機電一體化 類人機器人 人機界面 先進的運動控制 集成制造系…

線性代數 | 知識點整理 Ref 3

注:本文為 “線性代數 | 知識點整理” 相關文章合輯。 因 csdn 篇幅合并超限分篇連載,本篇為 Ref 3。 略作重排,未整理去重。 圖片清晰度限于引文原狀。 如有內容異常,請看原文。 《線性代數》總復習要點、公式、重要結論與重點釋…

CFD中的動量方程非守恒形式詳解

在計算流體力學(CFD)中,動量方程可以寫成守恒形式和非守恒形式,兩者在數學上等價,但推導方式和應用場景不同。以下是對非守恒形式的詳細解釋: 1. 動量方程的守恒形式 首先回顧守恒形式的動量方程&#xff…

Leetcode 1504. 統計全 1 子矩形

1.題目基本信息 1.1.題目描述 給你一個 m x n 的二進制矩陣 mat ,請你返回有多少個 子矩形 的元素全部都是 1 。 1.2.題目地址 https://leetcode.cn/problems/count-submatrices-with-all-ones/description/ 2.解題方法 2.1.解題思路 單調棧 時間復雜度&…

【Docker】運行錯誤提示 unknown shorthand flag: ‘d‘ in -d ----詳細解決方法

使用docker拉取Dify的時候遇到錯誤 錯誤提示 unknown shorthand flag: d in -dUsage: docker [OPTIONS] COMMAND [ARG...]錯誤原因解析 出現 unknown shorthand flag: d in -d 的根本原因是 Docker 命令格式與當前版本不兼容,具體分為以下兩種情況: 新…

華為OD機試真題——攀登者2(2025A卷:200分)Java/python/JavaScript/C++/C語言/GO六種最佳實現

2025 A卷 200分 題型 本文涵蓋詳細的問題分析、解題思路、代碼實現、代碼詳解、測試用例以及綜合分析; 并提供Java、python、JavaScript、C、C語言、GO六種語言的最佳實現方式! 2025華為OD真題目錄全流程解析/備考攻略/經驗分享 華為OD機試真題《攀登者2…

qt硬件與軟件通信中 16進制與十進制轉化

1. 首先上代碼, 這是在qt語言上的操作 截取 01 03 0C 00 00 00 00 00 00 00 0C 00 0C 00 0C 93 70 這串16進制數值進行處理,截取這樣一段內容 00 0C 00 0C 00 0C 字節數組轉字符串。從bytearray數組轉換為string. QString CustomTcpSocket::recieveInfo() {QByteArr…

圖形變換算法

一、學習目的 (1)掌握多面體的存儲方法。 (2)掌握圖形的幾何變換及投影變換。 (3)掌握三維形體不同投影方法的投影圖的生成原理。 (4)掌握多面體投影圖繪制的編程方法。 二、學…

【JAVAFX】自定義FXML 文件存放的位置以及使用

情況 1:FXML 文件與調用類在同一個包中(推薦) 假設類 MainApp 的包是 com.example,且 FXML 文件放在 resources/com/example 下: 項目根目錄 ├── src │ └── sample │ └── Main.java ├── src/s…

Ubuntu20.04安裝企業微信

建議先去企業微信官網看一下有沒有linux版本,沒有的話在按如下方式安裝,不過現在是沒有的。 方案 1、使用docker容器 2、使用deepin-wine 3、使用星火應用商店 4. 使用星火包deepin-wine 5、使用ukylin-wine 本人對docker不太熟悉,現…

CSS appearance 屬性:掌握UI元素的原生外觀

在現代網頁設計中,為了達到一致的用戶體驗,我們有時需要讓HTML元素模仿操作系統的默認控件樣式。CSS中的appearance屬性提供了一種簡便的方式來控制這些元素是否以及如何顯示其默認外觀。本文將詳細介紹appearance屬性,并通過實際代碼示例來展…

十四、C++速通秘籍—函數式編程

目錄 上一章節: 一、引言 一、函數式編程基礎 三、Lambda 表達式 作用: Lambda 表達式捕獲值的方式: 注意: 四、函數對象 函數對象與普通函數對比: 五、函數適配器 1、適配普通函數 2、適配 Lambda 表達式 …

大模型Rag-指令調度

本文主要記錄根據用戶問題指令,基于大模型做Rag,匹配最相關描述集進行指令調度,可用于匹配后端接口以及展示答案及圖表等。 1.指令查詢處理邏輯 1.實現思路 指令識別:主要根據用戶的問題q計算與指令描述集is [i0, ... , im]和指…

音視頻學習 - ffmpeg 編譯與調試

編譯 環境 macOS Ventrua 13.4 ffmpeg 7.7.1 Visual Studio Code Version: 1.99.0 (Universal) 操作 FFmpeg 下載源碼 $ cd ffmpeg-x.y.z $ ./configure nasm/yasm not found or too old. Use --disable-x86asm for a crippled build.If you think configure made a mistake…

golang-常見的語法錯誤

https://juejin.cn/post/6923477800041054221 看這篇文章 Golang 基礎面試高頻題詳細解析【第一版】來啦~ 大叔說碼 for-range的坑 func main() { slice : []int{0, 1, 2, 3} m : make(map[int]*int) for key, val : range slice {m[key] &val }for k, v : …

音視頻之H.265/HEVC預測編碼

H.265/HEVC系列文章: 1、音視頻之H.265/HEVC編碼框架及編碼視頻格式 2、音視頻之H.265碼流分析及解析 3、音視頻之H.265/HEVC預測編碼 預測編碼是視頻編碼中的核心技術之一。對于視頻信號來說,一幅圖像內鄰近像素之間有著較強的空間相關性,相鄰圖像之…

基于政務問答的dify接口請求測試

Dify 的智能體后端服務 API 為開發者提供便捷方式,能讓前端應用直接調用大語言模型能力。在請求時,需先前往應用左側導航的 “API Access” 部分,在此可查看文檔和管理訪問憑據。為保障安全,API 密鑰應通過后端調用,避…

VMware Workstation 保姆級 Linux(CentOS) 創建教程(附 iso)

文章目錄 一、下載二、創建 一、下載 CentOS-7.9-x86_64-DVD-2009.iso 二、創建 VMware Workstation 保姆級安裝教程(附安裝包) VMware Workstation 保姆級安裝教程(附安裝包) VMware Workstation 保姆級安裝教程(附安裝包)

擴增子分析|基于R語言microeco包進行微生物群落網絡分析(network網絡、Zi-Pi關鍵物種和subnet子網絡圖)

一、引言 microeco包是福建農林大學姚敏杰教授團隊開發的擴增子測序集成分析。該包綜合了擴增子測序下游分析的多種功能包括群落組成、多樣性、網絡分析、零模型等等。通過簡單的幾行代碼可實現復雜的分析。因此,microeco包發表以來被學界廣泛關注,截止2…

GO語言-數據類型

文章目錄 變量定義1. 整數類型2. 浮點類型3. 字符類型4. 布爾類型5. 字符串類型5.1 字符串的本質5.2 常用字符串處理函數(strings包)5.3 修改字符串的方式 6. 數據默認值7. 類型轉換 變量定義 代碼如下: package mainimport "fmt"var i1 1000 var i2 i…