最近大佬們重新對動手學習深度學習進行修改,加入了pytorch實現的方式,今天發佈了最新版,正在完善中,將自己今天的學習筆記記錄在此,由於全英文的內容,自己翻譯可能不太對,請多多指教!
#!H:\pytorch
# -*- coding:utf-8 -*-
#Author: Tangzhao
#content:pytorch
# 數據操作
# 導入pytorch
import torch
# 多維數組代表多維的數值,一維數組代表一個矢量,二維數組表示一個矩陣,超過兩位的數組我們稱爲張量(tensors)
# 首先我們創建一個以0開頭的行向量,包括12個元素,默認的數據類型爲float,一個新的數組存儲在主存中,並基於cpu的計算
x = torch.arange(12) # arange(x) 創建一個x以內的張量
print(x) # tensor([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])
# 獲取張量的形狀可以用x.shape
print(x.shape) # torch.Size([12])
# total number of elements in an ndarray
print(x.size())
# 改變張量的形狀
x1 = x.reshape((3,4)) # 括號內的數據爲需要得到的數據形狀,第二維可以不用寫,用-1表示,它會默認隨着第一維的變化而變化
print(x1)
"""
tensor([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
"""
x2 = x.reshape((3,-1))
print(x2)
"""
tensor([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
"""
# 空方法獲取一塊內存並返回一個矩陣,而不必費心更改其任何項的值。這非常高效,但我們必須小心,因爲條目可能取任意值,包括非常大的值!
x3 = torch.empty(2,3) # 得到的是一個任意的值,可能爲0,也可能爲很大的數
print(x3)
"""
tensor([[0., 0., 0.],
[0., 0., 0.]])
"""
# want our matrices initialized either with zeros, ones, some other constant
x4 = torch.zeros(2,3,4)
print(x4)
"""
tensor([[[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.]],
[[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.]]])
"""
x5 = torch.ones(2,3,4)
print(x5)
"""
tensor([[[1., 1., 1., 1.],
[1., 1., 1., 1.],
[1., 1., 1., 1.]],
[[1., 1., 1., 1.],
[1., 1., 1., 1.],
[1., 1., 1., 1.]]])
"""
# 當我們構造數組作爲神經網絡的參數時,我們通常會隨機初始化它們的值。下面的代碼片段創建了一個具有shape(3,4)的ndarray。
# 它的每個元素都從均值爲0、標準差爲1的標準高斯(正態)分佈中隨機採樣。
x6 = torch.randn(3, 4)
print(x6)
"""
tensor([[ 1.3997, 0.2624, 1.1852, 0.4023],
[-0.7597, 0.5661, 0.2412, 1.4060],
[ 0.7833, 0.9949, 0.3957, 0.8672]])
"""
# :我們還可以通過提供包含數值值的Python列表(或列表的列表)來爲所需的ndarray中的每個元素指定確切的值。
# 在這裏,最外層的列表對應於軸0,而內部列表對應於軸1。
x7 = torch.tensor([[2, 1, 4, 3], [1, 2, 3, 4], [4, 3, 2, 1]])
print(x7)
"""
ensor([[2, 1, 4, 3],
[1, 2, 3, 4],
[4, 3, 2, 1]])
"""
# 2、數據操作
# 2.1、加減乘除:對於相同形狀的數據進行四則運算
x = torch.tensor([1.0,2,4,8])
y = torch.tensor([2.0,2,2,2])
print(x + y)
print(x - y)
print(x * y)
print(x / y)
print(x ** y)
"""
tensor([ 3., 4., 6., 10.])
tensor([-1., 0., 2., 6.])
tensor([ 2., 4., 8., 16.])
tensor([0.5000, 1.0000, 2.0000, 4.0000])
tensor([ 1., 4., 16., 64.])
"""
# 同樣地可以用於其它計算
print(torch.exp(x)) # tensor([2.7183e+00, 7.3891e+00, 5.4598e+01, 2.9810e+03])
# 將數組疊加
x = torch.arange(12,dtype=torch.float32).reshape(3,4)
y = torch.tensor([[2.0,1,4,3],[1,2,3,4],[4,3,2,1]])
print(torch.cat((x,y),dim = 0)) # 在行上將兩個數組組合
"""
tensor([[ 0., 1., 2., 3.],
[ 4., 5., 6., 7.],
[ 8., 9., 10., 11.],
[ 2., 1., 4., 3.],
[ 1., 2., 3., 4.],
[ 4., 3., 2., 1.]])
"""
print(torch.cat((x,y),dim = 1)) # 在列上將兩個數組合並
"""
tensor([[ 0., 1., 2., 3., 2., 1., 4., 3.],
[ 4., 5., 6., 7., 1., 2., 3., 4.],
[ 8., 9., 10., 11., 4., 3., 2., 1.]])
"""
# 判斷兩個張量相等:對於每個元素的位置,如果x和y的元素值相等,則稱兩個張量相等,而且返回1或者True;否則返回0或者false
print(x == y)
"""
tensor([[False, True, False, True],
[False, False, False, False],
[False, False, False, False]])
"""
# 將張量所有元素相加得到一個輸出值
print(x.sum()) # tensor(66.)
# 2.1.3、廣播機制
# 上面我們講述對形狀相同的ndarray進行操作,當形狀不同時,可以利用廣播機制自動補全成形狀相同的ndarray(虛擬上)
a = torch.arange(3).reshape((3,1))
print(a)
"""
tensor([[0],
[1],
[2]])
"""
b = torch.arange(2).reshape((1,2))
print(b) # tensor([[0, 1]])
# a是3x1的ndarry,b是1x2的ndarry,採用廣播機制進行運算,a擴展列數,b擴展行數
print(a + b) # 得到的是一個3行2列
"""
tensor([[0, 1],
[1, 2],
[2, 3]])
"""
# 2.1.4、索引和切片:語法與python類似
print(x[-1]) # 取出x的最後一行元素
print(x[1:3]) # 取出最後兩行數據
"""
tensor([ 8., 9., 10., 11.])
tensor([[ 4., 5., 6., 7.],
[ 8., 9., 10., 11.]])
"""
# 修改x中的元素
x[1,2] = 9
print(x)
"""
tensor([[ 0., 1., 2., 3.],
[ 4., 5., 9., 7.],
[ 8., 9., 10., 11.]])
"""
x[0:2,:] = 12 # 前兩行所有列的元素值置爲12
print(x)
"""
tensor([[12., 12., 12., 12.],
[12., 12., 12., 12.],
[ 8., 9., 10., 11.]])
"""
# 2.1.5、節約存儲
"""
運行操作可能導致爲主機結果分配新內存。例如,如果我們寫入y = x + y,我們將取消引用y曾經指向的ndarray,而不是指向新分配的內存y。
在下面的示例中,我們使用Python的id()函數來演示這一點,該函數爲我們提供了被引用對象在內存中的確切地址。
運行y = y + x後,我們會發現id(y)指向一個不同的位置。這是因爲Python首先計算y + x,爲結果分配新的內存,然後讓y指向內存中的這個新位置。
"""
before = id(y)
y = y+x
print(id(y) == before) # False
"""
這可能是不可取的,原因有兩個。首先,我們不想總是分配不必要的內存。在機器學習中,我們可能有幾百兆字節的參數,並且每秒鐘更新一次。
通常,我們希望在適當的地方執行這些更新。其次,我們可能指向來自多個變量的相同參數。如果我們沒有及時更新,
其他引用仍然會指向舊的內存位置,這使得我們的部分代碼可能會無意中引用陳舊的參數
"""
# 如果想指定結果到原來的內存,我們可以使用之前的索引來進行替換操作
z = torch.zeros_like(y)
print('id(z):',id(z))
z[:] = x + y
print('id(z):',id(z))
"""
id(z): 2487647073120
id(z): 2487647073120
"""
# 我們可以使用索引和x+= y來實現上述的效果
before = id(x)
x += y
print(id(x) == before) # True
# 2.1.6、不同數據類型轉換
# numpy轉換爲tensor
a = x.numpy()
b = torch.tensor(a)
print(type(a),type(b)) # <class 'numpy.ndarray'> <class 'torch.Tensor'>
a = torch.tensor([3.5])
print(a, a.item(), float(a), int(a)) # tensor([3.5000]) 3.5 3.5 3