深大的夏令營已經結束,篩選入營的保研er就篩選了1/3,280多的入營總人數里面雙非只有30左右。
最終雖然憑借機試拿到offer了,但是我感受到了自己的明顯短板,比如夏令營的舍友就都有一篇核心論文,甚至還有SCI一區(qū)一作的。
既然,學歷和沒過六級這件事在9月份之前都沒辦法彌補,現在也只有狂肝科研了,希望9月份預推免之前能夠趕出來一點點成果也好。
首先把機器學習&&深度學習入門一下,里面包含了一些數學、線性代數、概率論的知識,這剛好也是將來9月預推免的面試中容易被問到的,所以就堅持著全復習完。
1 數據操作
無非就是兩件事:
(1)獲取數據
(2)處理并存儲數據
1.1 入門
張量表示一個由數組組成的數組,可能有多個維度。一維的叫向量,二維的叫矩陣。
下列直接給出代碼和注釋查看pytorch對張量的操作:
import torch
# 使用arrange創(chuàng)建一個行向量
x = torch.arange(12)
print(x)
# 可以通過張量的shape屬性來訪問張量(沿每個軸的長度)的形狀
print(x.shape)
# 張量中的元素總數
print(x.numel())
# 改變形狀而不改變元素的數量和元素值
X = x.reshape(3, 4)
print(X)
# 輸出全0、全1矩陣
print(torch.zeros(2, 3, 4))
print(torch.ones(2, 3, 4))
# 創(chuàng)建一個形狀為(3,4)的張量,每個元素都是從均值為0,標準差為1的正態(tài)分布中隨機采樣
print(torch.randn(3, 4))
# 還可以直接創(chuàng)建Python列表
print(torch.tensor([[2, 1, 4, 3], [1, 2, 3, 4], [4, 3, 2, 1]]))
運行結果:
tensor([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])
torch.Size([12])
12
tensor([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
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.]]])
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.]]])
tensor([[ 1.5651, -0.2855, -0.4439, 0.5795],
[-1.3375, -1.3290, -0.1183, -1.0676],
[ 0.0334, -2.0030, -1.0172, 0.7654]])
tensor([[2, 1, 4, 3],
[1, 2, 3, 4],
[4, 3, 2, 1]])
1.2 運算符
代碼:
import torch
# 對于相同形狀的張量,常見的標準算術運算符:加減乘除和指數
x = torch.tensor([1.0, 2, 4, 8])
y = torch.tensor([2, 2, 2, 2])
ans = (x + y, x - y, x * y, x / y, x ** y)
print(ans)
# 也可以實現求冪,如e^x
print(torch.exp(x))
# 張量也可以端對端的連接起來,只需要提供張量列表并給出沿哪個軸連結
# 下面給出的兩個張量:
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]])
# 可以發(fā)現這是二維的,軸就有兩個。軸0表示行,軸1表示列
# 按照軸0來連接,也就是連接行
print(torch.cat((X, Y), dim=0))
# 按照軸1來連接,也就是連接列
print(torch.cat((X, Y), dim=1))
# 通過邏輯運算符構建二元張量:
print(X == Y)
# 若對張量中的所有元素求和,會產生單元素張量
print(X.sum())
運行結果:
(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.]))
tensor([2.7183e+00, 7.3891e+00, 5.4598e+01, 2.9810e+03])
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.]])
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.]])
tensor([[False, True, False, True],
[False, False, False, False],
[False, False, False, False]])
tensor(66.)
1.3 廣播機制
如果兩個張量的形狀不同,可以通過調用廣播機制來執(zhí)行按元素操作:
1、通過適當復制元素來擴展一個或兩個數組,以便在轉換之后,兩個張量具有相同的形狀;
2、對生成的數組執(zhí)行按元素操作。
代碼:
import torch
# a為3×1,b為1×2,那么就將a復制列,b復制行
a = torch.arange(3).reshape((3, 1))
b = torch.arange(2).reshape((1, 2))
print(a + b)
運行結果:
tensor([[0, 1],
[1, 2],
[2, 3]])
1.4 索引和切片
第一個元素的索引是0,最后一個元素索引是-1。這個沒什么好說的
1.5 節(jié)省內存
運行一些操作可能會導致為新結果分配內存。 例如,如果我們用Y = X + Y,我們將取消引用Y指向的張量,而是指向新分配的內存處的張量。
用Python的id()函數演示了這一點, 它給我們提供了內存中引用對象的確切地址。 運行Y = Y + X后,我們會發(fā)現id(Y)指向另一個位置。 這是因為Python首先計算Y + X,為結果分配新的內存,然后使Y指向內存中的這個新位置。
before = id(Y)
Y = Y + X
print(id(Y) == before)
最終輸出False
但是這并不可取,原因有二:
1、我們不想總是不必要地分配內存。通常情況下,我們希望原地執(zhí)行這些更新;
2、如果我們不原地更新,其他引用仍然會指向舊的內存位置,這樣我們的某些代碼可能會無意中引用舊的參數。
執(zhí)行原地操作代碼:
# 使用切片表示法將操作的結果分配給先前分配的數組
Z = torch.zeros_like(Y)
print('id(Z):', id(Z))
Z[:] = X + Y
print('id(Z):', id(Z))
結果:
id(Z): 139931132035296
id(Z): 139931132035296
如果在后續(xù)計算中沒有重復使用X, 我們也可以使用X[:] = X + Y或X += Y來減少操作的內存開銷:
before = id(X)
X += Y
print(id(X) == before)
輸出True
2 數據預處理
為了用深度學習解決現實問題,常要從預處理原始數據開始,而不是從準備好的張量格式數據開始。
2.1 讀取數據集
代碼如下:
import os
import pandas as pd
os.makedirs(os.path.join('D:/Pytorch', 'data'), exist_ok=True)
data_file = os.path.join('D:/Pytorch', 'data', 'house_tiny.csv')
with open(data_file, 'w') as f:
f.write('NumRooms,Alley,Price\n') # 定義列(房間數量、巷子類型、房屋價格)
f.write('NA,Pave,127500\n') # 每行表示一個數據樣本
f.write('2,NA,106000\n')
f.write('4,NA,178100\n')
f.write('NA,NA,140000\n')
# 從創(chuàng)建的CSV文件中加載數據集,需要導入pandas包并調入read_csv函數。
data = pd.read_csv(data_file)
print(data)
運行結果:
NumRooms Alley Price
0 NaN Pave 127500
1 2.0 NaN 106000
2 4.0 NaN 178100
3 NaN NaN 140000
2.2 處理缺失值
”NaN“項代表缺失值,可使用插值法解決,用一個替代之彌補缺失值。
通過位置索引iloc,將data分成inputs和outputs,其中前者為data的前兩列,后者為最后一列。對于inputs中缺少的數值,用同一列的值替換“NaN”項。
代碼:
inputs, outputs = data.iloc[:, 0:2], data.iloc[:, 2]
inputs = inputs.fillna(inputs.mean())
print(inputs)
輸出:
NumRooms Alley
0 3.0 Pave
1 2.0 NaN
2 4.0 NaN
3 3.0 NaN
對于inputs中的類別值或離散值,我們將“NaN”視為一個類別。 由于“巷子類型”(“Alley”)列只接受兩種類型的類別值“Pave”和“NaN”, pandas可以自動將此列轉換為兩列“Alley_Pave”和“Alley_nan”。 巷子類型為“Pave”的行會將“Alley_Pave”的值設置為1,“Alley_nan”的值設置為0。 缺少巷子類型的行會將“Alley_Pave”和“Alley_nan”分別設置為0和1。
代碼:
inputs = pd.get_dummies(inputs, dummy_na=True)
print(inputs)
結果:
NumRooms Alley_Pave Alley_nan
0 NaN True False
1 2.0 False True
2 4.0 False True
3 NaN False True
3 線性代數
3.1 標量
import torch
x = torch.tensor(3.0)
y = torch.tensor(2.0)
print(x + y, x * y, x / y, x ** y)
最終輸出:
tensor(5.) tensor(6.) tensor(1.5000) tensor(9.)
3.2 向量
可以視為標量值組成的列表,具有一定現實意義。如:一個預測貸款風險的模型,可能會將每個申請人與一個向量相關聯,其分量與其收入、工作年限、過往違約次數和其他因素相對應。
生成向量:
x = torch.arrange(4)
可以直接通過索引來訪問任一元素:
x[3]
3.3 矩陣
import torch
# 輸出矩陣A
A = torch.arange(20).reshape(5, 4)
print(A)
# 矩陣轉置:若B為A的轉置,則對于任意i,j都有B(i,j)=A(j,i)
# 輸出A的轉置
print(A.T)
# 如果是方陣,那么其轉置與其相同
B = torch.tensor([[1, 2, 3], [2, 0, 4], [3, 4, 5]])
print(B == B.T)
結果:
tensor([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11],
[12, 13, 14, 15],
[16, 17, 18, 19]])
tensor([[ 0, 4, 8, 12, 16],
[ 1, 5, 9, 13, 17],
[ 2, 6, 10, 14, 18],
[ 3, 7, 11, 15, 19]])
tensor([[True, True, True],
[True, True, True],
[True, True, True]])
3.4 張量算法的基本性質
任何按元素的一元運算都不會改變其操作數的形狀。
1、兩個矩陣按元素乘法稱為Hadamard積;
2、將張量乘以或加上一個標量不會改變張量的形狀,其中張量的每個元素都將與標量相加或相乘。
3.5 降維
import torch
A = torch.arange(20, dtype=torch.float32).reshape(5, 4)
# 直接得到矩陣A的和:
print(A.sum())
# 可以通過指定張量沿哪個軸來降維,如果通過求和所有的行元素來降維,則指定軸0
A_sum_axis0 = A.sum(axis=0)
print(A_sum_axis0, A_sum_axis0.shape)
# 匯總所有列的元素降維
A_sum_axis1 = A.sum(axis=1)
print(A_sum_axis1, A_sum_axis1.shape)
# 沿著行和列對矩陣求和,等價于對所有元素求和
print(A.sum(axis=[0, 1]))
# 求平均值,使用A.mean()或A.sum()/A.numer()
print(A.mean())
# 求平均值也可以沿指定軸降低張量維度
print(A.mean(axis=0))
結果
tensor(190.)
tensor([40., 45., 50., 55.]) torch.Size([4])
tensor([ 6., 22., 38., 54., 70.]) torch.Size([5])
tensor(190.)
tensor(9.5000)
tensor([ 8., 9., 10., 11.])
3.6 點積
對于兩個向量x,y,其點積為x的轉置乘y,是相同位置的按元素乘積的和。
import torch
x = torch.arange(4, dtype=torch.float32)
y = torch.ones(4, dtype=torch.float32)
print(x, y, torch.dot(x, y))
# 也可以先按元素乘法,然后進行求和來表示兩個向量的點積
print(torch.sum(x * y))
結果:
tensor([0., 1., 2., 3.]) tensor([1., 1., 1., 1.]) tensor(6.)
tensor(6.)
3.7 矩陣-向量積
其實就是一種特殊的矩陣乘法,使用函數torch.mv(A,x)即可實現矩陣A和向量x的積
3.8 矩陣-矩陣乘法
使用torch.mm(A,B)即可實現矩陣A和B的相乘。3.7和3.8的矩陣乘法學過線代都知道,不講解了。
3.9 范數
非正式的說,向量的范數表示一個向量多大。這里的大小不涉及維度,而是分量的大小。
現代中,向量范數是將向量映射到標量的函數f。給定任意向量x,向量范數要滿足一些屬性:
深度學習中常用L1、L2范數,都是Lp范數的特例。
函數:文章來源:http://www.zghlxwxcb.cn/news/detail-604945.html
L1范數:torch.abs(u).sum()
L2范數:torch.norm(u)文章來源地址http://www.zghlxwxcb.cn/news/detail-604945.html
到了這里,關于機器學習&&深度學習——預備知識(上)的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網!