第一階段知識點查漏補缺
d2l
1.d2l官方也沒有過多解釋這個包的信息,但是卻給出了用法:
DESCRIPTION
Please import d2l by one of the following ways:
from d2l import mxnet as d2l # Use MXNet as the backend
from d2l import torch as d2l # Use PyTorch as the backend
from d2l import tensorflow as d2l # Use TensorFlow as the backend
PACKAGE CONTENTS
mxnet
tensorflow
torch
點擊這里可以下載查看d2l支持的包,或者直接在cmd環境中鍵入pip install -U d2l -i https://mirrors.aliyun.com/pypi/simple/查看已經安裝過的包。
2.查看d2l調用的包的地址 ,發現這個包是來自於我們本地已經編譯過的函數,在jupyter中鍵入(在一個空的程序執行框內,不能有任何注釋): d2l.synthetic_data??
Signature: d2l.synthetic_data(w, b, num_examples)
Source:
def synthetic_data(w, b, num_examples):
"""Generate y = Xw + b + noise.
Defined in :numref:`sec_linear_scratch`"""
X = d2l.normal(0, 1, (num_examples, len(w)))
y = d2l.matmul(X, w) + b
y += d2l.normal(0, 0.01, y.shape)
return X, d2l.reshape(y, (-1, 1))
File: d:\miniconda\lib\site-packages\d2l\torch.py
Type: function
我們用代碼測試下
from d2l import torch as d2l
import torch
# 用法一,可以讀取本地的函數
ture_w = torch.tensor([1,3.2],requires_grad=True)
true_b = torch.zeros(1,requires_grad=True)
features,labels = d2l.synthetic_data(ture_w,true_b,1000)
-->據此初步給出結論: d2l 就是一個容器,或者說一個整合怪。將所有冗雜的東西都塞進d2l里面,如果要再次調用的話,就可以直接調用d2l里面的函數了。
-------------2021/12/21更正知識點:d2l就是我們下載的李沐老師推行的一個包😂,里面有李沐大佬編寫的synthetic_data()這個方法,只是我們照着他的來寫,以為要是我們自己編寫的函數,用d2l.synthetic_data??查看到的是存在d:\miniconda\lib\site-packages\d2l\torch.py下----------
torch.utils.data
Pytorch 的數據處理: imoprt torch.utils.data實現數據的自由讀取
torch.utils.data主要包括以下三個類:
-
class torch.utils.data.Dataset
表示Dataset的抽象類。
所有其他數據集都應該進行子類化。所有子類應該override__len__和__getitem__,前者提供了數據集的大小,后者支持整數索引,范圍從0到len(self)。 -
class torch.utils.data.TensorDataset(data_tensor, target_tensor)
包裝數據和目標張量的數據集。通過沿着第一個維度索引兩個張量來恢復每個樣本。
data_tensor (Tensor) - 包含樣本數據
target_tensor (Tensor) - 包含樣本目標(標簽)
class torch.utils.data.DataLoader(dataset, batch_size=1, shuffle=False, sampler=None, num_workers=0, collate_fn=<function default_collate>, pin_memory=False, drop_last=False)
數據加載器。組合數據集和采樣器,並在數據集上提供單進程或多進程迭代器。
dataset:輸入的 TensorDataset包裝好的樣本
batch_size:小批量梯度的批量大小
shuffle:洗牌,隨機化我們的數據
class torch.utils.data.sampler.Sampler(data_source)
所有采樣器的基礎類。
每個采樣器子類必須提供一個__iter__方法,提供一種迭代數據集元素的索引的方法,以及返回迭代器長度的__len__方法。
同樣的,我們使用代碼來驗證下官方的解釋:官網解釋,源碼
# class torch.utils.data.TensorDataset(data_tensor, target_tensor) 包裝數據
import torch
from d2l import torch as d2l
from torch.utils import data
features = torch.arange(1,21).reshape(10,2)
labels = torch.randn(10,1)
train_data = data.TensorDataset(features,labels) # <torch.utils.data.dataset.TensorDataset at 0x2b82714edf0>
#data.TensorDataset(features,labels)返回的是一個 tuple 的地址
train_loader = data.DataLoader(dataset=train_data,batch_size=10,shuffle=True)
next(iter(train_loader)) # train_loader <torch.utils.data.dataloader.DataLoader at 0x2b827082100> 返回的是一個地址
為了簡便起見,我們截取前面三條數據進行輸出:
[tensor([[ 5, 6],
[13, 14],
[ 1, 2]),
tensor([[-0.5224],
[-0.2214],
[-0.2276]])]
TensorDataset()方法傳入特征和標簽包裝成一個數據,其中每個樣本和標簽一一對應,返回該數據的地址
DataLoader()方法傳入梯度的批量,是否洗牌等參數,獲得批量大小的數據,方便用於SGD (Small batch gradient descent)
torch.nn
class torch.nn.Sequential(* args) torch.nn.Sequential() 是torch.nn模塊中的一個方法,用更加嚴謹的話來說就是一個時序容器。Modules 會以他們傳入的順序被添加到容器中。當然,也可以傳入一個OrderedDict
我們最開始實現的是LinearRegression,只有一個模型,我們並不需要Sequential這個時序容器,Sequential實例將數據傳入到第一層,然后將第一層的輸出作為第二層的輸入,依此類推。在下面的例子中,我們的模型只包含一個層,因此實際上不需要Sequential。但是由於以后幾乎所有的模型都是多層的,在這里使用Sequential會讓你熟悉標准的流水線。
import torch.nn as nn
# Example of using Sequential
model = nn.Sequential(
nn.Conv2d(1,20,5),
nn.ReLU(),
nn.Conv2d(20,64,5),
nn.ReLU()
)
# model[0]調用第一個模型,model[1]調用第二個函數等等
Linear layers
class torch.nn.Linear(in_features, out_features, bias=True)對輸入數據做線性變換:\(y=Ax+b\)
in_features - 每個輸入樣本的大小
out_features - 每個輸出樣本的大小
bias - 若設置為False,這層不會學習偏置。默認值:True
weight -形狀為(out_features x in_features)的模塊中可學習的權值
bias -形狀為(out_features)的模塊中可學習的偏置
李沐d2l里面是這樣描述的:正如我們在構造nn.Linear時指定輸入和輸出尺寸一樣。現在我們直接訪問參數以設定初始值。我們通過net[0]選擇網絡中的第一個圖層,然后使用weight.data和bias.data方法訪問參數。然后使用替換方法normal_和fill_來重寫參數值。
# Example of using Sequential2
net = nn.Sequential(nn.Linear(in_features=2, out_features=1)) # 一個線性回歸的模型
net[0].weight.data.normal_(mean=0, std=0.01) # 時序容器,我們選擇第一個線性回歸模型
net[0].bias.data.fill_(0)
'''normal_(mean=0, std=1, , gengerator=None*)
將tensor用均值為mean和標准差為std的正態分布填充。'''
class torch.nn.MSELoss(size_average=True)
\(loss(x,y)=1/n∑(xi−yi)2\)
- x 和 y 可以是任意形狀,每個包含n個元素。
- 對n個元素對應的差值的絕對值求和,得出來的結果除以n。
- 如果在創建MSELoss實例的時候在構造函數中傳入size_average=False,那么求出來的平方和將不會除以n
torch.optim
torch.optim是一個實現了各種優化算法的庫。大部分常用的方法得到支持,並且接口具備足夠的通用性,使得未來能夠集成更加復雜的方法。
為了使用torch.optim,你需要構建一個optimizer對象。這個對象能夠保持當前參數狀態並基於計算得到的梯度進行參數更新。
為了構建一個Optimizer,你需要給它一個包含了需要優化的參數(必須都是Variable對象)的iterable。然后,你可以設置optimizer的參 數選項,比如學習率,權重衰減,等等。
提示一下,我在pytorch找到的內容如下:
- The Variable API has been deprecated(棄用): Variables are no longer necessary to use autograd with tensors. Autograd automatically supports Tensors with requires_grad set to True. Below please find a quick guide on what has changed:
- Variable(tensor) and Variable(tensor, requires_grad) still work as expected, but they return Tensors instead of Variables.
- Methods such as var.backward(), var.detach(), var.register_hook() now work on tensors with the same method names. 這段話也就是說,以前的
Variable類創建出來的對象var調用var.backward()等方法才能夠進行反向傳播,而現在直接調用tensor.backward()就可以了(前提是tensor是requires_grad)
所以我也有點不知所以...
optimizer = optim.SGD(model.parameters(), lr = 0.01, momentum=0.9)
optimizer = optim.Adam([var1, var2], lr = 0.0001)
像上面這種直接調用model.parameters()的就包含了所有的參數,當然我們也可以單獨為每一個超參數進行設置
給算法傳入的是dict類型的數據,SGD包括學習率,w和b,我么在字典里面單獨設置,字典外共享設置。
from torch import optim,nn
model = nn.Sequential(
nn.Linear(2,1),
nn.Linear(3,1)
)
optimizer_1 = optim.SGD([
{'params': model[0].parameters()},
{'params': model[1].parameters(), 'lr': 1e-3}
], lr=1e-2, momentum=0.9)
# 這意味着model[0]的參數將會使用1e-2的學習率,model[1]的參數將會使用1e-3的學習率,並且0.9的momentum將會被用於所 有的參數。
# 等價於
optimizer_2 = optim.SGD([
{'params': model[0].parameters(), 'lr': 1e-2},
{'params': model[1].parameters(), 'lr': 1e-3}
], momentum=0.9)
所有的optimizer都實現了step()方法,這個方法會更新所有的參數。它能按兩種方式來使用:就好像我們之前用的:
.....
for X, y in data_iter:
l = loss(net(X) ,y) # 我們之前定義的在optim模塊中的MSEloss()算法
trainer.zero_grad() # 每次調用SGD之后都要清空 ,因為我們進行的是小批量梯度下降
l.backward() # 在前面我們進行了前向傳播,現在進行反向傳播更新我們的參數
trainer.step()
l = loss(net(features), labels) # 完成一次迭代之后查看我們的損失函數的值
.... #(偽代碼)
optimizer.step() 只要optimizer進行了反向傳播之后,我們就可以用.step()來更新我我們所有參數
