文章目錄
- 前言
- python與pytorch
- 1、型別對比
- 2、代碼實體
- pytorch的標量創建
- pytorch的張量創建
- 幾個名詞對應的概念
- 資料的匯入
- 資料的初始化問題
- 1、未初始化的分配
- 2、亂數初始化
- 3、指定值初始化
- 索引與切片
- 維度變化
- 1、不可逆變化
- 2、維度增加
- 3、維度減少
- 4、維度拓展
- 4、轉置操作
- 5、維度交換
前言
這個系列應該會有兩篇文章,主要記錄整理了一些pytorch的基本使用與實驗代碼,
python與pytorch
1、型別對比
| python | pytorch |
|---|---|
| int | inttensor of size() |
| float | floattensor of size() |
| int array | inttensor of size [d1,d2,d3…] |
| float array | floattensor of size [d1,d2,d3…] |
| string | – |
Quest1. 如何來表示string型別
one-hot就是:總共幾種型別就用幾維陣列來表示,但是會有兩個比較不好的地方,第一,當資料維度特別大的時候,資料稀疏(大部分位都是0);第二,對于比如說文本,轉化之后不能保留原有文本的語意相關性等等,Embedding:Word2vecglove
2、代碼實體
當然,僅僅是pytorch內部,就也存在著cpu變數與gpu變數的不同,結合下面的代碼來進一步了解吧,所有代碼的ipynb格式代碼都在整個專欄的github代碼庫中,歡迎star與下載使用
import torch
a = torch.randn(2,3) # 隨機初始化一個兩行三列的矩陣 randn表示N(0,1)來進行初始化
print(a)
print(a.type())
print(type(a)) # 不推薦使用python的type,不顯示其詳細型別
print(isinstance(a, torch.FloatTensor)) # isinstance 判斷是否是已知的這個型別
tensor([[-0.4170, -0.5086, 0.0340],
[-1.8330, 0.3811, -0.3105]])
torch.FloatTensor
<class 'torch.Tensor'>
True
torch.FloatTensor
# cpu型別與gpu型別的不同
print(isinstance(a, torch.cuda.FloatTensor))
a = a.cuda()
print(isinstance(a, torch.cuda.FloatTensor))
False
True
pytorch的標量創建
直接看下面的代碼吧,寫在備注里面了
# pytorch的標量表示
a = torch.tensor(1.1) # 標量0維矩陣
print(a.shape)
print(len(a.shape))
print(a.size())
torch.Size([])
0
torch.Size([])
pytorch的張量創建
三種創建方法:
# 第一種創建方法,直接賦值
torch.tensor([1,2,3])

# 第二種創建方法,指定初始化的元素個數
torch.Tensor(3) # 注意要大寫,區分上面的那個標量表示

# 第三種創建方法 使用numpy創建,之后引入
import numpy
data = numpy.ones(2)
data
torch.from_numpy(data)

幾個名詞對應的概念
例子:
[[1,1],[2,2]] # 2行2列矩陣
dim:全寫dimension,也就是維度,對應行或列size/shape:對應[2,2]表示對應資料時2行2列矩陣tensor變數名:就是具體指上面的這個資料
資料的匯入
資料匯入最常見的就是通過numpy進行匯入,
# 從numpy匯入資料
import numpy,torch
a = numpy.array([2,3,3])
print(a)
b = torch.from_numpy(a)
print(b)
# 從list中匯入
torch.tensor([1,2,3,4,5])

資料的初始化問題
1、未初始化的分配
雖然說大寫的T也是可以賦值的,但是為了避免某些時候的混淆,代碼可讀性,大寫為未賦值的初始化,小寫為賦值初始化(也可以理解為就是list轉變成tensor型別)
# 未初始化的api
torch.Tensor(2,2)
# 分配了記憶體空間之后一定要記得初始化賦值,否則可能會出現各種各樣的問題,比如下面的例子,數值非常大或者非常小

設定torch.set_default_tensor_type(torch.DoubleTensor)是為了提高精度,一般沒做任何改動的時候,默認的是torch.FloatTensor型別
2、亂數初始化
# 亂數初始化 rand / rand)like / randint
a = torch.rand(3, 3)
print(a)
b = torch.rand_like(a)
print(b)
c = torch.randint(1, 10, [3,3])
print(c)
d = 10*torch.rand(3, 3)
print(d)

兩個注意點:
_like這種型別的函式都是相當于,把指定tensor的shape提取出來,去丟給隨機初始化函式初始化;rand初始化的范圍是0,1,而randint必須是整數,所以必須通過乘法手段來獲取范圍內的float亂數初始化
# 正太分布亂數初始化 randn / normal
a = torch.randn(3,3) # N(0,1)
print(a)
b = torch.normal(mean=torch.full([10],1.0), std=torch.arange(1, 0, -0.1))
print(b)

注意:
normal生成的每個值是對應的N(mean,std)生成的亂數,我給了10個mean,是個std,所以最終生成10個亂數,不過是一維的,自己可以重新切分成多維tensor
3、指定值初始化
# 用指定值填充指定結構,dtype指定型別
print(torch.full([10],1, dtype=torch.int))
print(torch.full([2,3],1, dtype=torch.int))
print(torch.full([],1, dtype=torch.int))
torch.arange(100,90,-1)

# 等分
print(torch.linspace(0,10, steps=5))
print(torch.logspace(0,10, steps=5)) # 這個分出來還要變成10 x次方

Ps:最后補充,為了解決torch中沒有shuffle功能
# 產生隨機索引,主要是為了shuffle
torch.randperm(10)

索引與切片
a = torch.rand(4,3,28,28)
# 從最左邊開始索引
print(a[0].shape)
print(a[0,0].shape)
print(a[0,0,2,4])
# 冒號索引,和python中的串列的用法差不多
print(a.shape)
print(a[:2].shape)
print(a[:1,:1].shape)
print(a[:1,1:].shape)
print(a[:1,-1:].shape)
# 隔行采樣,和python也一樣 start:end:step
print(a[:1,:1,0:10:2].shape)
print(a[:1,:1,::2].shape)

# 在某個維度上面選給定的幾個
print(a.index_select(2, torch.arange(28)).shape)
print(a.index_select(2, torch.arange(1,8,1)).shape)
# ...的利用,其實也就是可以少寫幾個:
print(a[...].shape)
print(a[:,1,...].shape)
print(a[:,1,:,:].shape)

x = torch.randn(4,4)
print(x)
mark = x.ge(0.5) # 把所有大于0.5的選出來
print(mark)
print(torch.masked_select(x, mark))# 把對應標記矩陣中為true的選出來

維度變化
1、不可逆變化
a = torch.rand(4,1,28,28)
print(a.shape)
b = a.view(4,28*28)
print(b.shape)
b = a.reshape(4,28*28)
print(b.shape)

reshape和view函式完全是一致的作用,使用這兩個函式的時候,一定要注意三個問題:
- 和原先的資料總量一定要一樣多
- 不要做沒有實際意義(無法理解)的變化操作
- 做完操作之后,由于丟失了原先的資訊,沒有辦法
reshape回去,原來的維度/存盤順序非常重要
2、維度增加
a = torch.rand(4,32,28,28)
b = torch.rand(32)
c = b.unsqueeze(1).unsqueeze(2).unsqueeze(0)
print(a.shape)
print(b.shape)
print(c.shape)
b = torch.rand(32,2)
c = b.unsqueeze(1).unsqueeze(2).unsqueeze(0)
print(a.shape)
print(b.shape)
print(c.shape)
在某個維度新增維度,看上面兩個例子的對比,很容易理解

3、維度減少
這里的c是上一個代碼片的c
# squeeze與unsqueeze相反,將所有1的盡可能給壓縮
print(c.shape)
print(c.squeeze().shape)
print(c.squeeze(0).shape)

可以看到在不指定壓縮維度的時候,直接將能壓縮的(值為1)全部壓縮了,指定了則按照指定的來
4、維度拓展
注意區分下增加于拓展的區別,而且expand拓展需要有兩個前提:
- 維度一致
- 1拓展成n
結合代碼的例子來理解吧
a = torch.rand(3,3)
b = torch.rand(3,1)
print(a)
print(b)
print(a.shape)
print(b.shape)
c = b.expand(3,3)
print(c)
print(c.shape)

再來看下repeat拓展
print(b.shape)
d = b.repeat(3,3)
e = b.repeat(1,3)
print(d.shape)
print(d)
print(e.shape)
print(e)

repeat對應維度的復制次數,而不是最終維度
4、轉置操作
a = torch.rand(2,3)
a.t()

這里需要注意的是,轉置只適用于2維矩陣
5、維度交換
# transpose 只能兩兩交換
a = torch.rand(1,2,3,4)
print(a.shape)
b = a.transpose(1,3)
print(b.shape)
c = a.permute(0,3,1,2)# 這里的0,1,2,3指的是之前的tensor矩陣的維度位置
print(c.shape)
transpose 只能兩兩交換,permute則可以直接一次性搞定
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/34454.html
標籤:其他
