1.pytorch中的索引 index_select(x, dim, indices)
dim代表維度蔬螟,indices是篩選的索引序號,一般indices傳入的是torch.LongTensor([1,2])這種類型。見pytorch的切片
2..data是從Variable獲取底層Tensor的主要方式。
3.優(yōu)化器Optimizer都實現(xiàn)了step()方法來對所有的參數(shù)進行更新。
Loss.backward()反向傳播 #This call will compute the gradient of loss with respect to all Tensors with requires_grad=True.
Optimizer.step() 更新參數(shù)
4.torch.squeeze(input, dim=None, out=None)
將某一方向全部相同數(shù)據(jù)壓縮掉绸罗,想想一下,x、y聂儒、z是三維的,如果z全為0硫痰,則可轉化為二維衩婚。
torch.Tensor.view()會將原有數(shù)據(jù)重新分配為一個新的張量,同reshape()
如果有一個維度的大小用-1代替效斑,那么該函數(shù)就會根據(jù)張量總元素的個數(shù)和其他個維度的元素個數(shù)自動計算這個用-1指定的維度的大小非春。
x = torch.randn(2, 4)
#1.5600 -1.6180 -2.0366 2.7115
#0.8415 -1.0103 -0.4793 1.5734
#[torch.FloatTensor of size 2x4]
y = x.view(4,2)
print y
# 輸出如下
1.5600 -1.6180
-2.0366 2.7115
0.8415 -1.0103
-0.4793 1.5734
[torch.FloatTensor of size 4x2]
5.和numpy之間的轉換:from_numpy() numpy()
Pytorch變量類型轉換
6.torch.nn.Embedding
官方文檔說明:
參考:word_embeddings_tutorial.以下是筆記以下是筆記以下是筆記(重要的話說三遍)
word embeddings are a representation of the semantics of a word, efficiently encoding semantic information that might be relevant to the task at hand
Central to the idea of deep learning is that the neural network learns representations of the features, rather than requiring the programmer to design them herself. So why not just let the word embeddings be parameters in our model, and then be updated during training? This is exactly what we will do.
Similar to how we defined a unique index for each word when making one-hot vectors, we also need to define an index for each word when using embeddings. These will be keys into a lookup table.
To index into this table, you must use torch.LongTensor (since the indices are integers, not floats).
我們在使用它的時候,需要建立一個語料中所有詞的詞典鳍悠,使用one-hot形式表示所有的的詞税娜。
在實例化embedding類的對象時坐搔,需要傳入的參數(shù)為the vocabulary size, and the dimensionality of the embeddings.(詞典中的單詞個數(shù)藏研,嵌入的詞的維度,padding_idx)概行,其中蠢挡,如果給了padding_idx(int型),那么就是使用padding_idx的值進行嵌入。
使用時凳忙,傳入的input的值應該為 torch.LongTensor业踏,1??要么用torch.tensor()里指定dtype=torch.long2??要么torch.LongTensor([張量])3??要么可以使用data.long()轉換一下.
2019.1.23踩坑:
Traceback (most recent call last):
File "/Users/yumi/Documents/Code/pytorch_related/classifier/CNN+pooling/code/CNN.py", line 112, in <module>
pred = model(inputs)
File "/anaconda3/python.app/Contents/lib/python3.6/site-packages/torch/nn/modules/module.py", line 489, in __call__
result = self.forward(*input, **kwargs)
File "/Users/yumi/Documents/Code/pytorch_related/classifier/CNN+pooling/code/CNN.py", line 89, in forward
out = self.embedded(x)
File "/anaconda3/python.app/Contents/lib/python3.6/site-packages/torch/nn/modules/module.py", line 489, in __call__
result = self.forward(*input, **kwargs)
File "/anaconda3/python.app/Contents/lib/python3.6/site-packages/torch/nn/modules/sparse.py", line 118, in forward
self.norm_type, self.scale_grad_by_freq, self.sparse)
File "/anaconda3/python.app/Contents/lib/python3.6/site-packages/torch/nn/functional.py", line 1454, in embedding
return torch.embedding(weight, input, padding_idx, scale_grad_by_freq, sparse)
RuntimeError: index out of range at /Users/administrator/nightlies/pytorch-1.0.0/wheel_build_dirs/conda_3.6/conda/conda-bld/pytorch_1544137972173/work/aten/src/TH/generic/THTensorEvenMoreMath.cpp:191
出現(xiàn)這個的原因是我發(fā)現(xiàn)傳入的inputs里存在負數(shù),然后debug了一下以前正確的代碼涧卵,我猜想這個地方傳入的必須是非負數(shù)勤家,因為建詞典的時候肯定不存在indices為負數(shù)的情況。
(2019.01.26又出現(xiàn)了這個bug柳恐,原因是我詞匯表的維度設置的太小了)
p.s.這個地方傳入的inputs的維度是(batch_size,seq_len)
7.torch.nn.LSTM()
官方文檔說明:
參考:
LSTM:Pytorch實現(xiàn)
Pytorch的LSTM的理解
聊一聊PyTorch中LSTM的輸出格式
參數(shù):
- input_size:x的特征維度
- hidden_size:隱藏層的特征維度
- num_layers:lstm隱層的層數(shù)伐脖,默認為1
- bias:False則bih=0和bhh=0. 默認為True
- batch_first:True則輸入輸出的數(shù)據(jù)格式為 (batch, seq, feature)
- dropout:除最后一層热幔,每一層的輸出都進行dropout,默認為: 0
- bidirectional:True則為雙向lstm默認為False
輸入數(shù)據(jù)格式
- input(seq_len, batch, input_size)
seq_len體現(xiàn)序列的長度讼庇,也就是這串輸入中明確的單詞的個數(shù)绎巨。第二個維度表示如果希望一次在網(wǎng)絡中走完整個序列可以設置為1,第三個維度是輸入的向量的維度蠕啄,一般是詞嵌入的維度场勤。 - h0(num_layers * num_directions, batch, hidden_size)
- c0(num_layers * num_directions, batch, hidden_size)
輸出數(shù)據(jù)格式
- output(seq_len, batch, hidden_size * num_directions)
output保存了最后一層,每個time step的輸出h歼跟,如果是雙向LSTM和媳,每個time step的輸出h = [h正向, h逆向] (同一個time step的正向和逆向的h連接起來)。 - hn(num_layers * num_directions, batch, hidden_size)
h_n保存了每一層嘹承,最后一個time step的輸出h窗价,如果是雙向LSTM,單獨保存前向和后向的最后一個time step的輸出h叹卷。 - cn(num_layers * num_directions, batch, hidden_size)
output保存了最后一層每個time-step的輸出撼港,如果是雙向LSTM,
我們會看到lstm(i.view(1,1,-1),hidden)這種形式骤竹,其實就是輸入的數(shù)據(jù)形式應該為(seq_len, batch, input_size)這種三維的帝牡,hidden的輸入也會有人寫成(h0,c0),然后再去初始化他們的值在這里我們是直接在一開始就將它們初始化并進行了拼接蒙揣。
import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
torch.manual_seed(1)
lstm = nn.LSTM(3,3)
# 也就是seq_len是5,5個time-step
inputs = [torch.randn(1,3) for _ in range(5)]
# print(inputs)
# print(torch.randn(1,1,3))
# 也可以在類里自己定義初始化,維度是(num_layers * num_directions, batch, hidden_size)
hidden = (torch.randn(1,1,3),torch.randn(1,1,3))
# 逐個讀入序列的元素
for i in inputs:
# print(i.view(1,1,-1))
out,hidden = lstm(i.view(1,1,-1),hidden)
print("out\n",out)
print("hidden\n",hidden)
#以下是直接讀入整個序列,LSTM返回的第一個值表示所有時刻的隱狀態(tài)值靶溜,第二個表示最近的隱狀態(tài)值
# 所以下面的out_all和hidden_all是一樣的
#out_all是最后一層每個time-step的輸出值,這里我們只有一層LSTM。
# hidden_all的第一個張量h_n表示的是最后一個time_step的值
inputs = torch.cat(inputs).view(len(inputs),1,-1)
out_all,hidden_all = lstm(inputs,hidden)
print(out_all)
print(hidden_all)
8.產(chǎn)生隨機數(shù)https://zhuanlan.zhihu.com/p/31231210
9.NLLLoss 的 輸入 是一個對數(shù)概率向量和一個目標標簽. 它不會為我們計算對數(shù)概率. 適合網(wǎng)絡的最后一層是log_softmax. 損失函數(shù) nn.CrossEntropyLoss() 與 NLLLoss() 相同, 唯一的不同是它為我們?nèi)プ?softmax.
10.Pytorch數(shù)據(jù)讀取(Dataset, DataLoader, DataLoaderIter)
參考:
Pytorch數(shù)據(jù)讀取
PyTorch源碼解讀之torch.utils.data.DataLoader
Dataset
DataLoader
DataLoaderIter
從上往下裝入
當代碼運行到要從torch.utils.data.DataLoader類生成的對象中取數(shù)據(jù)的時候,就會調用DataLoader類的iter方法懒震,iter方法就一行代碼:return DataLoaderIter(self)罩息,輸入正是DataLoader類的屬性。因此當調用iter方法的時候就牽扯到另外一個類:DataLoaderIter个扰。
import torch
import torch.utils.data as Data
torch.manual_seed(1)
BATCH_SIZE = 5
x = torch.linspace(1,10,10)
y = torch.linspace(10,1,10)
torch_dataset = Data.TensorDataset(x,y)
loader = Data.DataLoader(
dataset=torch_dataset,
batch_size=BATCH_SIZE,
shuffle=True
)
# 將所有的數(shù)據(jù)訓練了3次
for epoch in range(3):
#總共有10條數(shù)據(jù),batch_size是5,每個epoch訓練兩次
for step,(batch_x,batch_y) in enumerate(loader):
print("Epoch:",epoch,"|step:",step,"|batch x:",batch_x.numpy(),"|batch y:",batch_y.numpy())
print("\n")
結果:
Epoch: 0 |step: 0 |batch x: [ 5. 7. 10. 3. 4.] |batch y: [6. 4. 1. 8. 7.]
Epoch: 0 |step: 1 |batch x: [2. 1. 8. 9. 6.] |batch y: [ 9. 10. 3. 2. 5.]
Epoch: 1 |step: 0 |batch x: [ 4. 6. 7. 10. 8.] |batch y: [7. 5. 4. 1. 3.]
Epoch: 1 |step: 1 |batch x: [5. 3. 2. 1. 9.] |batch y: [ 6. 8. 9. 10. 2.]
Epoch: 2 |step: 0 |batch x: [ 4. 2. 5. 6. 10.] |batch y: [7. 9. 6. 5. 1.]
Epoch: 2 |step: 1 |batch x: [3. 9. 1. 8. 7.] |batch y: [ 8. 2. 10. 3. 4.]
# 如果batch_size是8,不夠分成兩次的瓷炮,那第二次返回的就是剩下的數(shù)據(jù)
# eg.
torch_dataset2 = Data.TensorDataset(x,y)
loader2 = Data.DataLoader(
dataset=torch_dataset2,
batch_size= 8 ,
shuffle=True
)
for epoch in range(3):
# 總共有10條數(shù)據(jù),batch_size是5,so training for 2 times
for step, (batch_x, batch_y) in enumerate(loader2):
print("Epoch:", epoch, "|step:", step, "|batch x:", batch_x.numpy(), "|batch y:", batch_y.numpy())
結果:
Epoch: 0 |step: 0 |batch x: [ 4. 10. 9. 8. 7. 6. 1. 2.] |batch y: [ 7. 1. 2. 3. 4. 5. 10. 9.]
Epoch: 0 |step: 1 |batch x: [5. 3.] |batch y: [6. 8.]
Epoch: 1 |step: 0 |batch x: [9. 8. 4. 6. 5. 3. 7. 2.] |batch y: [2. 3. 7. 5. 6. 8. 4. 9.]
Epoch: 1 |step: 1 |batch x: [10. 1.] |batch y: [ 1. 10.]
Epoch: 2 |step: 0 |batch x: [ 5. 1. 3. 7. 6. 10. 9. 8.] |batch y: [ 6. 10. 8. 4. 5. 1. 2. 3.]
Epoch: 2 |step: 1 |batch x: [2. 4.] |batch y: [9. 7.]
11.Autograd
from torch.autograd import Variable
Tensor在被封裝為Variable后,可以調用.backward實現(xiàn)反向椽筆,自動計算所以梯度...Variable包含三個屬性:data,grad,grad_fn
y = x.detach()正如其名, 將返回一個不參與計算圖的Tensor y, Tensor y 一旦試圖改變修改自己的data, 會被語法檢查和python解釋器監(jiān)測到, 并拋出錯誤.
requires_grad直接掛在Tensor類下,也可以將requires_grad
作為一個參數(shù), 構造tensor
https://www.itency.com/topic/show.do?id=494122
# 可學習的參數(shù)可以通過net.parameters()查看
params = list(net.parameters())
# 同時返回可學習的參數(shù)和名稱
for name,parameters in net.named_parameters():
print(name,":",parameters.size())
Variable節(jié)點和Function節(jié)點,Variable記錄運算數(shù)據(jù)递宅,F(xiàn)unction記錄運算操作娘香。其中Variable節(jié)點又可以分為葉節(jié)點和非葉節(jié)點兩類。葉節(jié)點由用戶直接創(chuàng)建產(chǎn)生办龄,而非葉節(jié)點則由Variable節(jié)點之間的運算操作產(chǎn)生烘绽。
如果一個節(jié)點由用戶創(chuàng)建,則它為葉節(jié)點俐填,對應的grad_fn是None安接。
grad_fn可以查看這個variable的反向傳播函數(shù),grad_fn.next_functions[0][0]
12.pack_padded_sequence VS pad_packed_sequence
torch.nn.utils.rnn.pack_padded_sequence(input, lengths, batch_first=False)
輸入的input需要按長度降序排列英融,lengths需要從大到小排序盏檐。
input的維度:T x B x * 呀打,T表示一個最長的數(shù)據(jù)長度(the length of the longest sequence),B表示batch_size,如果batch_first=True,意味著維度是B x T x *
lengths:每個batch的數(shù)據(jù)長度(Expected len(lengths)
to be equal to batch_size)
返回的數(shù)據(jù)是一個PackedSequence 對象糯笙。包含data和batch_size贬丛,其中的data是對input按列算的值,batch_size是這一列去掉padding的0之后的數(shù)量给涕。
參考pytorch中如何處理RNN輸入變長序列padding
排序的思路的話豺憔,可以先對lengths進行sort,然后再使用index_select對input進行排序。
# 降序方法1
sort_index = np.argsort(-np.array(lengths))
# 降序方法2
lengths = torch.tensor(lengths)
_, idx_sort = torch.sort(lengths, dim=0, descending=True)
可以參考pytorch里的pack_padded_sequence和pad_packed_sequence解析
pytorch學習筆記(二十一): 使用 pack_padded_sequence
我的個人方法:
import numpy as np
import torch
data = [[1,1,1,1],[2,2,2,2,2],[3,3,3,3,3,3],[4,4,4,4,4,4,4]]
# print(type(data))
data_length = [len(item) for item in data]
max_len = np.max(data_length)
new_array = np.zeros((len(data), max_len))
for index, data in enumerate(data):
# print(index,data)
new_array[index][:len(data)] = data
data_tensor = torch.from_numpy(new_array)
_, indices = torch.sort(torch.tensor(data_length), descending=True)
# print(indices)
print(data_tensor[indices])
_, idx_sort = torch.sort(lengths, dim=0, descending=True)
x = torch.index_select(padding_tensor,0,idx_sort)
x_packed = nn.utils.rnn.pack_padded_sequence(input=x, lengths=lengths[idx_sort],batch_first=True)
把這個PackedSequence 對象送入網(wǎng)絡中够庙,生成出來的還是PackedSequence 對象恭应,這時候就需要pad_packed_sequence啦,pad_packed_sequence是pack_padded_sequence的一個逆操作耘眨。
torch.nn.utils.rnn.pad_packed_sequence(sequence, batch_first=False, padding_value=0.0, total_length=None)
T x B x * 在batch_first=True的情況下返回B x T x *
返回的是一個tuple,第一維是??
第二維是每條數(shù)據(jù)對應的長度昼榛。
13.eval即evaluation模式,train即訓練模式剔难。僅僅當模型中有Dropout和BatchNorm時才會有影響胆屿。因為訓練時dropout和BN都開啟,而一般而言測試時dropout被關閉偶宫,BN中的參數(shù)也是利用訓練時保留的參數(shù)非迹,所以測試時應進入評估模式
-
nn.Linear(in_features, out_features, bias=True)
參數(shù):in_features是輸入sample的維度,out_features是輸出sample的維度纯趋。
輸入:(N, *, in_features): where *? means any number of additional dimensions
- 在進行預測的時候憎兽,需要寫到with torch.no_grad()里面。
16.torch.transpose(input, dim0, dim1)
返回輸入矩陣input的轉置吵冒,交換維度dim0和dim1纯命。輸入張量與輸出張量共享內(nèi)存。
17.torch.nn.functional.max_pool1d
輸入維度:minibatch??in_channels??iT??iH??iW
根據(jù)torch.nn.MaxPool1d(kernel_size, stride=None, padding=0, dilation=1, return_indices=False, ceil_mode=False)
輸入的維度是(N,C,Lin)痹栖,輸出是(N,C,Lout)亿汞。
Lout的計算公式:
18.nn.CrossEntropyLoss()
input的第一項是y_pred,第二項是y_target结耀,今天踩的坑是把它倆位置放反了留夜,百思不得其解報錯信息匙铡。官方文檔是這么說的:
順便附上這張圖或許可以更好的理解輸出的維度代表的意思:
19.torch.max(input, dim, keepdim=False, out=None)
input是個tensor
dim為1图甜,表示按行選最大的
dim為0,表示按列選最大的鳖眼。
返回值是(Tensor, LongTensor)黑毅,第一個是max的值,第二個是max的索引值.
怎么用钦讳?可以用來計算預測準確的數(shù)量:
#####二分類的輸出#####
pred = torch.tensor([[0.1,-0.2],[0.3,0.5],[0.2,-0.1]])
label = torch.tensor([0,0,1])
#pred_label為預測的類別矿瘦,label為標注的類別
pred_label = torch.max(pred,1)[1]
print(pred_label)
print(float((pred_label == label).sum())/len(label)*100)
20.2019.01.16今日踩坑:
取tensor中的數(shù)枕面,忘記在哪里看過說如果用tensor.data獲取其中的值并進行疊加的話會加到動態(tài)圖中?缚去?潮秘?
如果一個tensor只有一個元素,那么可以使用tensor.item()方法取出這個元素作為普通的python數(shù)字易结。如果tensor有多個元素枕荞,用tensor.tolist()方法可以取出。
- nn.Conv1d & nn.Conv2d
nn.Conv1d:
主要參數(shù):input_channel(看一個博客里說這個是詞嵌入的維度), output_channel, kernel_size, stride, padding.
輸入:(batch_size, num of input channels搞动,文本長度)
輸出:(batch_size, num of output channels(我理解的是用多少個卷積核去卷積),Lout(這里是用那個卷積的公式計算出來的))
# 16表示input_channel,是詞嵌入的維度躏精,33是out_channel,是用幾個卷積核進行卷積鹦肿,3是表示卷積核的大小矗烛,這里是(3*詞嵌入的維度)
m = nn.Conv1d(16, 33, 3, stride=2)
# input2 = torch.randn()
# 輸入:N*C*L:batch_size為20,C為詞嵌入的維度箩溃,50為句子的length
# 輸出:N*Cout*Lout:Cout我理解的是out_channel的數(shù)量
#要注意輸入的維度是詞嵌入在第二維瞭吃,還是句子的length在第二維,不行就用permute()或者transpose()修改維度的順序涣旨。
input2 = torch.randn(20, 16, 50)
output2 = m(input2)
print(output2.size())
22.2019.01.25今日踩坑:
contiguous()一般與transpose虱而,permute,view搭配使用
即使用transpose或permute進行維度變換后,調用contiguous开泽,然后方可使用view對維度進行變形牡拇。