深度學習第一篇---pytorch入門

1 什么是pytorch?

PyTorch是一個基于Numpy的科學計算包,它主要有兩個特點:第一,是GPU加速的張量計算;第二,是構(gòu)建和訓練神經(jīng)網(wǎng)絡的強大支持。PyTorch是Facebook人工智能研究團隊開源的一個機器學習框架,它支持動態(tài)計算圖,這意味著可以按照想要的方式定義、修改和執(zhí)行計算圖,而不是預先定義靜態(tài)計算圖。這樣,PyTorch可以靈活地支持不同形式的計算圖,并且非常適合用于研究和實驗。同時,PyTorch也具有很好的可視化工具,方便用戶對模型進行調(diào)試和優(yōu)化。

2 張量

概念:幾何代數(shù)中定義的張量是基于向量和矩陣的推廣,比如我們可以將標量視為零階張量,矢量可以視為一階張量,矩陣就是二階張量

張量維度

2.1張量創(chuàng)建

import torch

# 創(chuàng)建一個2x3的張量
x = torch.tensor([[1, 2, 3], [4, 5, 6]])

# 打印張量的形狀和數(shù)據(jù)類型
print(x.shape)      # 輸出: torch.Size([2, 3])
print(x.dtype)      # 輸出: torch.int64

# 創(chuàng)建一個隨機初始化的3x3浮點數(shù)張量
y = torch.rand(3, 3)
print(y)

# 創(chuàng)建一個隨機初始化的3x3浮點數(shù)張量,符合正態(tài)分布
y = torch.randn(3, 3)
print(y)

# 創(chuàng)建一個全0的5x5張量
z = torch.zeros(5, 5)
print(z)

# 創(chuàng)建一個全1的4x4張量
w = torch.ones(4, 4)
print(w)

# 創(chuàng)建一個等差數(shù)列的張量
a = torch.linspace(0, 1, 5)
print(a)

# 創(chuàng)建一個隨機整數(shù)的張量
b = torch.randint(low=0, high=10, size=(3, 3))
print(b)

x = x.new_ones(4, 3, dtype=torch.double) 
# 創(chuàng)建一個新的全1矩陣tensor,返回的tensor默認具有相同的torch.dtype和torch.device
# 也可以像之前的寫法 x = torch.ones(4, 3, dtype=torch.double)
print(x)
x = torch.randn_like(x, dtype=torch.float)
# 重置數(shù)據(jù)類型
print(x)
# 結(jié)果會有一樣的size
# 獲取它的維度信息
print(x.size())
print(x.shape)


2.2 張量的操作

import torch

# 創(chuàng)建兩個張量
a = torch.tensor([[1, 2, 3], [4, 5, 6]])
b = torch.tensor([[2, 3, 4], [5, 6, 7]])

# 加法方式1
c = a + b
print(c)

# 方式2
print(torch.add(a, b))

# 方式3 in-place,原值修改
a.add_(b) 
print(a)

# 減法
d = b - a
print(d)

# 乘法
e = a * b
print(e)

# 除法
f = b / a
print(f)

# 矩陣乘法
g = torch.matmul(a, b.T)
print(g)

# 求和
h = a.sum()
print(h)

# 求平均值
i = b.mean()
print(i)

# 求最大值
j = a.max()
print(j)

# 求最小值
k = b.min()
print(k)

# 如果x中只有一個元素,可以把x的數(shù)值取出來
print(type(x.item()))

# 怎么改變張量的形狀
a = b.view(16)  
c = a.view(-1, 8) # -1是指這一維的維數(shù)由其他維度決定
print(a.size(), b.size(), c.size())

# Torch Tensors和Numpy array 共享底層的內(nèi)存空間,當改變其中的一個值,另外一個值也隨之被改變
a = torch.ones(5);# 5個1
print (a)

b = a.numpy(); #將tensor 轉(zhuǎn) numpy array
print (b)

a.add_(1); #改變a的值

print (a);
print (b);


a = np.ones(5);
print (a)

b =  torch.from_numpy(a); # 將numpy array 轉(zhuǎn)tensor
print (b);

b.add_(1);

print (b);
print (a);

另外張量的計算時候需要注意在哪個設備上,若不同設備是不能參與計算的。

#判斷服務器上已經(jīng)安裝了cuda和GPU
if torch.cuda.is_available():
   #將設備指定為GPU
   device = torch.device("cuda");
   #直接在GPU創(chuàng)建張量y,在CPU上創(chuàng)建張量X
   x = torch.randn(1);
   y = torch.ones_like(x,device=device);
   #將X轉(zhuǎn)移到GPU上
   x = x.to(device);
   z = x.add(y); #此時和的結(jié)果z在GPU上
   print (z);
   print(z.to("cpu"),torch.double);

2.3 張量的實際意義

在電商中,通常需要對用戶-品牌-時間-購買行為等多維數(shù)據(jù)進行建模和分析。這些數(shù)據(jù)可以被理解為張量的不同維度,每個維度都代表著不同的特征或?qū)傩浴@?,假設我們需要對用戶-品牌-時間-購買行為進行建模,我們可以構(gòu)建一個四維張量來存儲這些數(shù)據(jù)。其中,第一維表示用戶,第二維表示品牌,第三維表示時間,第四維表示購買行為。張量中的每個元素則代表著對應維度上的具體數(shù)值,例如張量中[i, j, k, l]元素代表著第i個用戶在第j個品牌上在第k個時間點的購買行為。
通過這種方式,我們可以在PyTorch中輕松地對這些張量進行各種數(shù)學操作和函數(shù),例如對購買行為進行求和、求平均值、求最大值、求最小值等,或者對用戶-品牌-時間進行矩陣運算,以便提取特征和進行預測。通過PyTorch中的張量,我們可以將復雜的電商數(shù)據(jù)轉(zhuǎn)化為多維數(shù)組,從而更好地進行建模和分析,幫助電商企業(yè)實現(xiàn)數(shù)據(jù)驅(qū)動決策和智能化運營。

import torch

# 創(chuàng)建一個四維張量表示用戶-品牌-時間-購買行為
tensor = torch.randn(10, 5, 20, 2)

# 求購買行為的總和
buy_sum = tensor[:, :, :, 1].sum()
print("購買行為總和:", buy_sum)

# 求用戶-品牌的交叉統(tǒng)計
user_brand_count = tensor.sum(dim=2)
print("用戶-品牌交叉統(tǒng)計:\n", user_brand_count)

# 對時間進行降維,求平均值
time_mean = tensor.mean(dim=2)
print("時間降維后的平均值:\n", time_mean)

# 對用戶-品牌進行矩陣運算
user_brand_tensor = tensor[:, :, 0, :]
user_tensor = user_brand_tensor.sum(dim=1)
brand_tensor = user_brand_tensor.sum(dim=0)
user_brand_matrix = torch.matmul(user_tensor.T, brand_tensor)
print("用戶-品牌矩陣:\n", user_brand_matrix)


上述代碼中,我們首先創(chuàng)建了一個四維張量tensor,表示用戶-品牌-時間-購買行為。然后,我們對這個張量進行了各種數(shù)學操作和函數(shù)。具體來說,我們使用sum()函數(shù)對購買行為進行求和,使用sum(dim=2)函數(shù)對用戶-品牌進行交叉統(tǒng)計,使用mean(dim=2)函數(shù)對時間進行降維,使用matmul()函數(shù)對用戶-品牌進行矩陣運算,以獲得用戶-品牌之間的相關性。這些操作可以幫助我們更好地理解和分析電商數(shù)據(jù)。

import torch

# 創(chuàng)建一個2x3的張量
x = torch.tensor([[1, 2, 3], [4, 5, 6]])

# 創(chuàng)建一個1x3的張量
y = torch.tensor([10, 20, 30])

# 對x和y進行加法
z = x + y
print(z)

#輸出如下
tensor([[1, 2, 3],
       [4, 5, 6]])
tensor([10, 20, 30])
tensor([[11, 22, 33],
       [14, 25, 36]])

在這個示例中,我們創(chuàng)建了一個2x3的張量x和一個1x3的張量y。兩個張量在第一維上的形狀不一致,但由于PyTorch支持廣播機制,系統(tǒng)會自動地將y進行擴展,使得它的形狀變?yōu)?x3,然后再和x進行加法運算。最終的結(jié)果是一個2x3的張量z,其中每個元素都是對應位置上x和y元素的和。在實際應用中,廣播機制可以大大簡化計算過程,避免了對數(shù)據(jù)進行顯式的擴展和復制。例如,在深度學習中,廣播機制可以使得模型對不同形狀的輸入數(shù)據(jù)進行處理,從而提高模型的通用性和適用性。同時,廣播機制還可以使得模型的參數(shù)共享,從而減少模型的參數(shù)量,提高模型的訓練效率。

3 自動求導和梯度

PyTorch中的自動求導機制是通過autograd模塊實現(xiàn)的,該模塊可以自動地對張量進行求導,同時還支持高階求導和自定義求導函數(shù)。在PyTorch中,每個張量都有一個requires_grad屬性,當設置為True時,表示需要對該張量進行求導。
下面是一個簡單的示例,說明如何使用PyTorch中的自動求導機制

import torch

# 創(chuàng)建一個張量,并設置requires_grad=True
x = torch.tensor([2.0], requires_grad=True)

# 定義一個函數(shù)y=x^2+2x+1
y = x ** 2 + 2 * x + 1

# 對y進行求導
y.backward()

# 打印x的梯度
print(x.grad)

在這個示例中,我們創(chuàng)建了一個張量x,并將requires_grad屬性設置為True,表示需要對它進行求導。然后,我們定義一個函數(shù)y=x^2+2x+1,并對它進行求導,即調(diào)用backward()函數(shù)。最后,我們打印x的梯度,即可得到y(tǒng)對x的導數(shù),即4。這里的梯度,需要重點總結(jié)一下,梯度是指函數(shù)在某一點處的變化率,它是一個向量,包含了函數(shù)在每個自變量維度上的偏導數(shù)。

我們可以看一個稍微更復雜的函數(shù),z= y^2 - x^2,那么z在自變量x上的倒數(shù)是-2x,在y自變量上的倒數(shù)是-2y。


image.png
import torch

# 創(chuàng)建一個張量,并設置requires_grad=True
x = torch.tensor([2.0], requires_grad=True)
y = torch.tensor([3.0], requires_grad=True)

# 定義一個函數(shù)z=y^2 - x^2
z = y ** 2 -  x ** 2;

# 對y進行求導
z.backward()

# 打印x的梯度
print (z)
print(y.grad)
print(x.grad)
print ('x.requires_grad=',x.requires_grad,'y.requires_grad=',y.requires_grad,'z.requires_grad=',z.requires_grad)


# 輸出
tensor([5.], grad_fn=<SubBackward0>)
tensor([6.])
tensor([-4.])
x.requires_grad= True y.requires_grad= True z.requires_grad= True


關于自動求導的”自動“怎么理解?z并沒有指定requires_grad = true, 但是由于x和y被設置了,z也被自動的設置為了requires_grad = true。

4 線性回歸模型

這段代碼定義了一個簡單的線性模型(LinearModel),并使用均方差損失函數(shù)(mean_squared_error)和梯度下降法(train)進行訓練。訓練數(shù)據(jù)是輸入x_train和輸出y_train。在訓練過程中,首先通過正向傳播(model.forward)計算模型的預測輸出(y_pred),然后計算損失(loss),接著通過反向傳播(計算梯度dW和db)更新模型的權(quán)重和偏置(model.W和model.b)。訓練過程會迭代num_epochs次,每10次輸出當前的損失值。最終訓練得到的模型可以用于預測新的輸入數(shù)據(jù)。

import torch
import numpy as np


# 模型定義
class LinearModel:
   def __init__(self, input_size, output_size):
       self.W = np.random.randn(input_size, output_size)  # 隨機初始化權(quán)重
       self.b = np.zeros((output_size, 1))  # 初始化偏置

   def forward(self, x):
       return np.dot(x, self.W) + self.b


# 損失函數(shù)
def mean_squared_error(y_true, y_pred):
   return np.mean((y_true - y_pred) ** 2)


# 訓練過程
def train(model, x_train, y_train, learning_rate, num_epochs):
   for epoch in range(num_epochs):
       # 正向傳播
       y_pred = model.forward(x_train)

       # 計算損失
       loss = mean_squared_error(y_train, y_pred)

       # 反向傳播(梯度下降法更新參數(shù))
       dW = np.dot(x_train.T, (y_pred - y_train)) / x_train.shape[0]  # 權(quán)重梯度
       db = np.mean(y_pred - y_train, axis=0, keepdims=True).T  # 偏置梯度

       model.W -= learning_rate * dW
       model.b -= learning_rate * db

       if epoch % 10 == 0:
           print(f"Epoch {epoch}, Loss: {loss}")


if __name__ == '__main__':
   x_train = np.array([[1, 2, 3], [4, 5, 6]])
   y_train = np.array([[3], [7]])

   model = LinearModel(input_size=3, output_size=1)
   train(model, x_train, y_train, learning_rate=0.01, num_epochs=100)


輸出:
Epoch 0, Loss: 153.96475781916735
Epoch 10, Loss: 0.5371193011886801
Epoch 20, Loss: 0.49120240483116584
Epoch 30, Loss: 0.4497690875642887
Epoch 40, Loss: 0.41183070630810104
Epoch 50, Loss: 0.3770924577692135
Epoch 60, Loss: 0.34528440820059597
Epoch 70, Loss: 0.3161593929820811
Epoch 80, Loss: 0.28949109602634426
Epoch 90, Loss: 0.2650722911885265

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容