Pytorch深度學習指南 卷I --編程基礎(A Beginner‘s Guide) 第1章 一個簡單的回歸

本章正式開始使用pytorch的接口來實現對應的numpy的學習的過程,來學習模型的實現,我們會介紹numpy是如何學習的,以及我們如何一步步的通過torch的接口來實現簡單化的過程,優雅的展示我們的代碼,已經我們的代碼完成的事情

numpy的線性回歸

在此之前,先看看現在的numpy實現的學習的過程是什么樣的

#引入計算模塊
import numpy as np
from sklearn.linear_model import LinearRegressionimport torch
import torch.optim as optim
import torch.nn as nn
from torchviz import make_dot用真實的數據來生成對應的分布點的數據
true_b = 1
true_w = 2
N = 100# Data Generation
np.random.seed(42)
x = np.random.rand(N, 1)
epsilon = (.1 * np.random.randn(N, 1))
y = true_b + true_w * x + epsilon
np.rand# Shuffles the indices
idx = np.arange(N)
np.random.shuffle(idx)# Uses first 80 random indices for train
train_idx = idx[:int(N*.8)]
# Uses the remaining indices for validation
val_idx = idx[int(N*.8):]# Generates train and validation sets
x_train, y_train = x[train_idx], y[train_idx]
x_val, y_val = x[val_idx], y[val_idx]np.random.seed(42)
b = np.random.randn(1)
w = np.random.randn(1)for _ in range(1000):# Step 1 - Computes our model's predicted output - forward passyhat = b + w * x_train# Step 2 - Computing the loss# We are using ALL data points, so this is BATCH gradient# descent. How wrong is our model? That's the error!error = (yhat - y_train)# It is a regression, so it computes mean squared error (MSE)loss = (error ** 2).mean()# Step 3 - Computes gradients for both "b" and "w" parametersb_grad = 2 * error.mean()w_grad = 2 * (x_train * error).mean()# Sets learning rate - this is "eta" ~ the "n" like Greek letterlr = 0.1# Step 4 - Updates parameters using gradients and # the learning rateb = b - lr * b_gradw = w - lr * w_grad#驗證,通過線性的模型直接學習
linr = LinearRegression()
linr.fit(x_train, y_train)

如上一章所說,我們的5個步驟,就是準備數據,前向傳遞,計算損失,計算梯度,更新參數,循環往復

pytorch的取代

張量(通常指3維)但是這里除了標量全部都是張量,為了簡化。

#如下是創建張量的例子
scalar = torch.tensor(3.14159)	#張量
vector = torch.tensor([1, 2, 3]) #一維
matrix = torch.ones((2, 3), dtype=torch.float) #二維
tensor = torch.randn((2, 3, 4), dtype=torch.float)	#三維

獲取到張量的shape

shape將會是我們以后將會長期用到的東西

print(tensor.size(), tensor.shape)
torch.Size([2, 3, 4]) torch.Size([2, 3, 4])

view

我們可以使用view的接口來改變一個張量的shape,注意view并不會創建新的張量。

# We get a tensor with a different shape but it still is the SAME tensor
same_matrix = matrix.view(1, 6)
# If we change one of its elements...
same_matrix[0, 1] = 2.

創建新的tensor

使用這個可以使用new_tensor和clone

# We can use "new_tensor" method to REALLY copy it into a new one
different_matrix = matrix.new_tensor(matrix.view(1, 6))
# Now, if we change one of its elements...
different_matrix[0, 1] = 3.

使用clone.detach,為什么要用detach(涉及到后面的數據存放和計算的內容)

another_matrix = matrix.view(1, 6).clone().detach()

加載數據、設備、CUDA

我們需要從numpy的數據轉成tensor張量

x_train_tensor = torch.as_tensor(x_train)
x_train.dtype, x_train_tensor.dtype

注意,這里變成了torch的張量,但是這里是還是共享的原始的內存,換句話說,改了還是會一起改

(dtype('float64'), torch.float64)

cuda的數據

cuda就是要使用GPU來存儲和運算的數據,我們需要手動的將其放到GPU的內存中,用于加速計算的過程

#判斷是否有GPU的數據可以使用的接口,如果存在那么設置device為GPU,否則CPU
device = 'cuda' if torch.cuda.is_available() else 'cpu'
#可以獲取GPU的數量
n_cudas = torch.cudsa.device_count()
for i in range(n_cuda):print(torch.cuda.get_device_naem(i))

我的機器上的輸出的結果

NVIDIA GeForce RTX 2060

將數據發送到GPU上

gpu_tensor = torch.as_tensor(x_train).to(device)
gpu_tensor[0]

輸出

torch.cuda.FloatTensor

如果發送到了GPU上的數據,需要重新變成numpy的數組,需要使用CPU的變量

back_to_numpy = x_train_tensor.cpu().numpy()

創建參數,并且需要梯度計算

為什么要使用torch,很多的時候在于可以自行進行梯度計算,也可以使用到很多pytorch的使用的接口和用法

# 創建一個隨機1以內的參數,并且需要梯度,類型是float
b = torch.randn(1, requires_grad=True, dtype=torch.float)
w = torch.randn(1, requires_grad=True, dtype=torch.float)
print(b, w)

創建數據并且發送到GPU,但是需要注意的是,這樣會丟失梯度,因為這個是CPU的數據需要梯度,發送到GPU后又是新的數據,

b = torch.randn(1, requires_grad=True, dtype=torch.float).to(device)
w = torch.randn(1, requires_grad=True, dtype=torch.float).to(device)

好的方法是直接在GPU上創建變量

b = torch.randn(1, requires_grad=True, dtype=torch.float,device = device)
w = torch.randn(1, requires_grad=True, dtype=torch.float),device = device)

Autograd

自動求解梯度

backward

我們可以通過backward直接計算和進行backward的實現,注意b,w是我們創建的參數(需要梯度的那種)

# Step 1 - Computes our model's predicted output - forward pass
yhat = b + w * x_train_tensor# Step 2 - Computes the loss
# We are using ALL data points, so this is BATCH gradient descent
# How wrong is our model? That's the error! 
error = (yhat - y_train_tensor)
# It is a regression, so it computes mean squared error (MSE)
loss = (error ** 2).mean()# Step 3 - Computes gradients for both "b" and "w" parameters
# No more manual computation of gradients! 
# b_grad = 2 * error.mean()
# w_grad = 2 * (x_tensor * error).mean()
loss.backward()

需要說明的是,所有的參與到b,w的計算的都是需要梯度的參數,例如這里面的yhat,error,loss,都是通過w,b的計算得來的,我們都認為是傳遞了梯度的計算特性

需要特別注意的是,這里的梯度是累計的,因為為了后續的小批量的情況,所以每次更新完畢以后需要手動設置gard_zero_()函數

b.grad.zero_(), w.grad.zero_()

還需要特別注意的是,我們更新參數的時候,是不能直接更新的,需要使用

    with torch.no_grad():b -= lr * b.gradw -= lr * w.grad

這在停一下,除了前面的變量的配置不一樣的地方,我們這里已經在改造我們的numpy代碼了

	# 原來的numpy的梯度的計算需要手動計算# Step 3 - Computes gradients for both "b" and "w" parametersb_grad = 2 * error.mean()w_grad = 2 * (x_train * error).mean()#但是這里已經可以使用自動計算的方法loss.backward()#可以直接讀取當前的梯度的值b.gradw.grad

動態計算圖

可以使用動態計算圖,直接看到當前的所有的梯度的變量的相互之間的關系,這里大家可以自己看,我就不放出來了

優化器

我們之前都要手動的執行backward,然后獲取b,w的grad,然后手動的進行更新使用了learning rate,最后還需要zero_grad。我們可以通過優化器的方式將變量一開始就加入到優化器中

	optimizer = optim.SGD([b,w],lr = lr)#	....執行學習的步驟loss.backward()optimizer.step()#一次性更新所有的參數的變量optimizer.zero_grad()#一次性zero所有的變量的值

損失函數

實際上,我們的損失函數也有torch的封裝,可以直接使用已經配置好的損失函數
loss_fn = nn.MSELoss(reduction = ‘mean’)

損失函數直接得到我們的yhat的結果和y_lable之間的損失的值

	#原文中的損失函數的部分error = (yhat - y_train_tensor)loss = (error**2).mean()#取代后loss_fn = nn.MSELoss(reduction='mean')loss = loss_fn(y_hat,y_train_tensor)此時的loss計算出來的結果和之前的是一模一樣的

需要注意的是,如果此時需要回歸的numpy,需要執行detach()操作,表示Loss函數不再參與grad的計算

模型

我們已經有了優化器(用于更新參數),損失函數(用于生成損失值),我們還可以定義自己的module模型(顯然嗎,我們還需要構建很多的我們自己的東西)

我們使用model函數來用現有的模型針對輸入得到我們的輸出函數,model函數對比forward函數,還會 前向和反向的鉤子函數
我們聲明一個繼承與Module的自己的類

class ManualLinearRegression(nn.Module):def __init__(self):super().__init__()# To make "b" and "w" real parameters of the model,# we need to wrap them with nn.Parameterself.b = nn.Parameter(torch.randn(1,requires_grad=True, dtype=torch.float))self.w = nn.Parameter(torch.randn(1, requires_grad=True,dtype=torch.float))def forward(self, x):# Computes the outputs / predictionsreturn self.b + self.w * x

通過parameters的函數,我們可以得到一個module類的目前包含的參數

dummpy = ManualLinearRegression()
list(dummy.parameters)
[Parameter containing:tensor([0.3367], requires_grad=True), Parameter containing:tensor([0.1288], requires_grad=True)]

也可以state_dict來獲取所有的參數的當前值,和parameters的區別在于state_dict通常用于加載和保存模型,而前面的通常用于展示優化器的包含的變量
注意,數據和模型需要在同一個設備

dummy = ManualLinearRegression().to(device)

階段代碼

經過我們的使用自己的類以后的代碼可以優化如下

# Greek letter
lr = 0.1# Step 0 - Initializes parameters "b" and "w" randomly
torch.manual_seed(42)
# Now we can create a model and send it at once to the device
model = ManualLinearRegression().to(device)# Defines a SGD optimizer to update the parameters 
# (now retrieved directly from the model)
optimizer = optim.SGD(model.parameters(), lr=lr)# Defines a MSE loss function
loss_fn = nn.MSELoss(reduction='mean')# Defines number of epochs
n_epochs = 1000for epoch in range(n_epochs):model.train() # What is this?!?# Step 1 - Computes model's predicted output - forward pass# No more manual prediction,直接使yhat = model(x_train_tensor)# 一定注意這里使用的是model而不是forward# Step 2 - Computes the lossloss = loss_fn(yhat, y_train_tensor)# Step 3 - Computes gradients for both "b" and "w" parametersloss.backward()# Step 4 - Updates parameters using gradients and# the learning rateoptimizer.step()optimizer.zero_grad()# We can also inspect its parameters using its state_dict
print(model.state_dict())

model.train()

這個是配置了訓練模式,訓練模式可以有很多內容,例如我們常見的dropout的優化模式來減少過擬合的問題

嵌套模型

我們可以使用了已經有的模型來作為嵌套的模型

首先我們使用nn自帶的Linear來取代我們手寫的線性的Module,如下是一個具有一個權重w,和一個bias的線性模型,我們完全可以用這個來取代我們之前的手寫的類

linear = nn.Linear(1,1)

當然我們可以嵌套這個到我們自己的類,這個和之前的基本上是完全等價的

class MyLinearRegression(nn.Module):def __init__(self):super().__init__()# Instead of our custom parameters, we use a Linear model# with single input and single outputself.linear = nn.Linear(1, 1)def forward(self, x):# Now it only takes a callself.linear(x)

序列模型

一個好的深度學習的模型,顯然不只有一層,通常都會有很多隱藏層,將所有的封裝子在一起,我們可以認為是一個序列模型

# Building the model from the figure above
model = nn.Sequential(nn.Linear(3, 5), nn.Linear(5, 1)).to(device)model.state_dict()

注意這里創建了一個序列類,序列類里面有兩層,第一層是一個35的輸出,第二層是一個51的模型,或者我們可以通過添加層的方式來增加帶名字的層

# Building the model from the figure above
model = nn.Sequential()
model.add_module('layer1', nn.Linear(3, 5))
model.add_module('layer2', nn.Linear(5, 1))
model.to(device)

這里其實已經涉及到了深度學習的部分,pytorch的層只是很多例如
卷積層、池化層、填充層、非線性激活層、歸一化層、循環層、transformer層、線性層、丟棄層、稀疏層、視覺層、數據平移(多GPU),展平層

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

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

相關文章

String.join()

String.join() 方法是 Java 8 及其以上版本中的一個方法,用于將多個字符串用指定的分隔符連接成一個字符串。 其語法為: java復制 String joinedString String.join(CharSequence delimiter, CharSequence... elements); 在這個方法中:…

FastAPI 數據庫配置最佳實踐

FastAPI 數據庫配置最佳實踐 1. 基礎配置 1.1 數據庫連接配置 from sqlalchemy import create_engine, event from sqlalchemy.orm import sessionmaker, declarative_base from sqlalchemy.pool import QueuePool from sqlalchemy.exc import SQLAlchemyError import loggi…

深度解析 Java 的幻讀現象與應對策略

目錄 一、幻讀現象的本質 二、幻讀在 Java 數據庫編程中的體現 三、幻讀帶來的問題 四、應對幻讀的策略 1. 數據庫隔離級別 2. 應用層解決方案 五、總結 在 Java 的數據庫編程領域,幻讀是一個不容忽視的概念。它涉及到數據庫事務處理過程中數據一致性的關鍵問…

Glary Utilities Pro 多語便攜版系統優化工具 v6.21.0.25

Glary Utilities是一款功能強大的系統優化工具軟件,旨在幫助用戶清理計算機垃圾文件、修復系統錯誤、優化系統性能等。 軟件功能 清理和修復:可以清理系統垃圾文件、無效注冊表項、無效快捷方式等,修復系統錯誤和藍屏問題。 優化和加速&…

【貪心算法】洛谷P1106 - 刪數問題

2025 - 12 - 26 - 第 46 篇 【洛谷】貪心算法題單 - 【貪心算法】 - 【學習筆記】 作者(Author): 鄭龍浩 / 仟濹(CSND賬號名) 目錄 文章目錄 目錄P1106 刪數問題題目描述輸入格式輸出格式樣例 #1樣例輸入 #1樣例輸出 #1 提示思路代碼 P1106 刪數問題 題目描述 鍵盤輸入一個高…

Oracle 創建并使用外部表

目錄 一. 什么是外部表二. 創建外部表所在的文件夾對象三. 授予訪問外部表文件夾的權限3.1 DBA用戶授予普通用戶訪問外部表文件夾的權限3.2 授予Win10上的Oracle用戶訪問桌面文件夾的權限 四. 普通用戶創建外部表五. 查詢六. 刪除 一. 什么是外部表 在 Oracle 數據庫中&#x…

基于FPGA的BPSK+costas環實現,包含testbench,分析不同信噪比對costas環性能影響

目錄 1.算法仿真效果 2.算法涉及理論知識概要 3.Verilog核心程序 4.完整算法代碼文件獲得 1.算法仿真效果 本作品是之前作品的改進和擴展: 1.m基于FPGA的BPSK調制解調通信系統verilog實現,包含testbench,包含載波同步_csdn基于fpga的bpsk-CSDN博客 2.m基于FP…

Linux 目錄操作詳解

Linux目錄操作詳解 1. 獲取當前工作目錄1.1 getcwd()1.2 get_current_dir_name() 2. 切換工作目錄2.1 chdir() 3. 創建和刪除目錄3.1 mkdir()3.2 rmdir() 4. 獲取目錄中的文件列表4.1 opendir() 打開目錄4.2 readdir() 讀取目錄內容4.3 closedir() 關閉目錄 5. dirent 結構體6.…

Spring 依賴注入詳解:創建 Bean 和注入依賴是一回事嗎?

1. 什么是依賴注入(Dependency Injection,DI)? 依賴注入 是 Spring IoC(控制反轉)容器的核心功能。它的目標是將對象的依賴(如其他對象或配置)從對象本身中剝離,由容器負…

AI時代的網絡安全:傳統技術的落寞與新機遇

AI時代的網絡安全:傳統技術的落寞與新機遇 在AI技術飛速發展的浪潮中,網絡安全領域正經歷著前所未有的變革。一方面,傳統網絡安全技術在面對新型攻擊手段時逐漸顯露出局限性;另一方面,AI為網絡安全帶來了新的機遇&…

后端開發Web

Maven Maven是apache旗下的一個開源項目,是一款用于管理和構建java項目的工具 Maven的作用 依賴管理 方便快捷的管理項目依賴的資源(jar包),避免版本沖突問題 統一項目結構 提供標準、統一的項目結構 項目構建 標準跨平臺(…

前沿技術趨勢洞察:2024年技術的嶄新篇章與未來走向!

引言 時光飛逝,2024年已經來臨,回顧過去一年,科技的迅猛進步簡直讓人目不暇接。 在人工智能(AI)越來越強大的今天,我們不再停留在幻想階段,量子計算的雛形開始展示它的無窮潛力,Web …

【10.2】隊列-設計循環隊列

一、題目 設計你的循環隊列實現。 循環隊列是一種線性數據結構,其操作表現基于 FIFO(先進先出)原則并且隊尾被連接在隊首之后以形成一個循環。它也被稱為“環形緩沖器”。 循環隊列的一個好處是我們可以利用這個隊列之前用過的空間。在一個普…

博客之星2024年度總評選——我的年度創作回顧與總結

2024年,是我在CSDN博客上持續耕耘、不斷成長的一年。在此,與大家分享一下我的年度創作回顧與總結。 一、創作成長與突破 在人工智能領域,技術迭代迅速,知識更新頻繁。為了保持自己的競爭力,在今年,我始終…

IDEA運行Java項目總會報程序包xxx不存在

我的在另外一臺電腦上跑是沒有問題的,在新的電腦上跑的時候,又出現了這個惡心的問題...... 思來想去,唯一的問題就是我的mavn環境沒的配置好 如何在本地部署mavn環境,這里推薦一篇很好的文章: Maven安裝與配置&…

java 根據前端傳回的png圖片數組,后端加水印加密碼生成pdf,返回給前端

前端傳回的png圖片數組,后端加水印加密碼生成pdf,返回給前端 場景:重點:maven依賴controllerservice 場景: 當前需求,前端通過html2canvas將頁面報表生成圖片下載,可以仍然不滿意。 需要java后…

數據分庫分表和遷移方案

在我們業務快速發展的過程中,數據量必然也會迎來突飛猛漲。那么當我們的數據量百倍、千倍、萬倍、億倍增長后,原有的單表性能就不能滿足我們日常的查詢和寫入了,此時數據架構就不得不進行拆分,比如單表拆分成10張表、100張表、單個…

線上突發:MySQL 自增 ID 用完,怎么辦?

線上突發:MySQL 自增 ID 用完,怎么辦? 1. 問題背景2. 場景復現3. 自增id用完怎么辦?4. 總結 1. 問題背景 最近,我們在數據庫巡檢的時候發現了一個問題:線上的地址表自增主鍵用的是int類型。隨著業務越做越…

[Java] Solon 框架的三大核心組件之一插件擴展體系

1、Solon 的三大核心組件 核心組件說明Plugin 插件擴展機制提供“編碼風格”的擴展體系Ioc/Aop 應用容器提供基于注入依賴的自動裝配體系ContextHandler 通用上下文處理接口提供“開放式處理”適配體系(俗稱,三元合一) 2、Solon Plugin 插件…

TRELLIS微軟的圖生3D

TRELLIS 教程目錄: Youtube:https://www.youtube.com/watch?vJqFHZ-dRMhI 官網地址:https://trellis3d.github.io/ GitHub:https://github.com/Microsoft/TRELLIS 部署目錄: 克隆項目 git clone --recurse-submodul…