代碼里的注釋一定要看?。?!里面包括了一些基本知識和原因
可以依次把下面的代碼段合在一起運行,也可以通過jupyter notebook分次運行
第一步:一些庫的導(dǎo)入
import torch#深度學(xué)習(xí)的pytoch平臺
import torch.nn as nn
import numpy as np
import random
import time#可以用來簡單地記錄時間
import matplotlib.pyplot as plt#畫圖
#隨機種子
random.seed(1234)
np.random.seed(1234)
torch.manual_seed(1234)
torch.cuda.manual_seed(1234)
torch.cuda.manual_seed_all(1234)
第二步:構(gòu)建簡單的數(shù)據(jù)集,這里利用sinx函數(shù)作為例子
x = np.linspace(-np.pi,np.pi).astype(np.float32)
y = np.sin(x)
#隨機取25個點
x_train = random.sample(x.tolist(),25) #x_train 就相當(dāng)于網(wǎng)絡(luò)的輸入
y_train = np.sin(x_train) #y_train 就相當(dāng)于輸入對應(yīng)的標(biāo)簽,每一個輸入都會對應(yīng)一個標(biāo)簽
plt.scatter(x_train,y_train,c="r")
plt.plot(x,y)
?紅色的點就是我在sinx函數(shù)上取的已知點作為網(wǎng)絡(luò)的訓(xùn)練點。
第三步:用pytorch搭建簡單的全連接網(wǎng)絡(luò)
class DNN(nn.Module):
def __init__(self):
super().__init__()
layers = [1,20,1] #網(wǎng)絡(luò)每一層的神經(jīng)元個數(shù),[1,10,1]說明只有一個隱含層,輸入的變量是一個,也對應(yīng)一個輸出。如果是兩個變量對應(yīng)一個輸出,那就是[2,10,1]
self.layer1 = nn.Linear(layers[0],layers[1]) #用torh.nn.Linear構(gòu)建線性層,本質(zhì)上相當(dāng)于構(gòu)建了一個維度為[layers[0],layers[1]]的矩陣,這里面所有的元素都是權(quán)重
self.layer2 = nn.Linear(layers[1],layers[2])
self.elu = nn.ELU() #非線性的激活函數(shù)。如果只有線性層,那么相當(dāng)于輸出只是輸入做了了線性變換的結(jié)果,對于線性回歸沒有問題。但是非線性回歸我們需要加入激活函數(shù)使輸出的結(jié)果具有非線性的特征
def forward(self,d):#d就是整個網(wǎng)絡(luò)的輸入
d1 = self.layer1(d)
d1 = self.elu(d1)#每一個線性層之后都需要加入一個激活函數(shù)使其非線性化。
d2 = self.layer2(d1)#但是在網(wǎng)絡(luò)的最后一層可以不用激活函數(shù),因為有些激活函數(shù)會使得輸出結(jié)果限定在一定的值域里。
return d2
第四步:一些基本參數(shù)變量的確定以及數(shù)據(jù)格式的轉(zhuǎn)換
device = torch.device("cuda") #在跑深度學(xué)習(xí)的時候最好使用GPU,這樣速度會很快。不要的話默認(rèn)用cpu跑
epochs = 10000 #這是迭代次數(shù),把所有的訓(xùn)練數(shù)據(jù)輸入到網(wǎng)絡(luò)里去就叫完成了一次epoch。
learningrate = 1e-4 #學(xué)習(xí)率,相當(dāng)于優(yōu)化算法里的步長,學(xué)習(xí)率越大,網(wǎng)絡(luò)參數(shù)更新地更加激進(jìn)。學(xué)習(xí)率越小,網(wǎng)絡(luò)學(xué)習(xí)地更加穩(wěn)定。
net = DNN().to(device=device) #網(wǎng)絡(luò)的初始化
optimizer = torch.optim.Adam(net.parameters(), lr=learningrate)#優(yōu)化器,不同的優(yōu)化器選擇的優(yōu)化方式不同,這里用的是隨機梯度下降SGD的一種類型,Adam自適應(yīng)優(yōu)化器。需要輸入網(wǎng)絡(luò)的參數(shù)以及學(xué)習(xí)率,當(dāng)然還可以設(shè)置其他的參數(shù)
mseloss = nn.MSELoss() #損失函數(shù),這里選用的是MSE。損失函數(shù)也就是用來計算網(wǎng)絡(luò)輸出的結(jié)果與對應(yīng)的標(biāo)簽之間的差距,差距越大,說明網(wǎng)絡(luò)訓(xùn)練不夠好,還需要繼續(xù)迭代。
MinTrainLoss = 1e10
train_loss =[] #用一個空列表來存儲訓(xùn)練時的損失,便于畫圖
pt_x_train = torch.from_numpy(np.array(x_train)).to(device=device,dtype = torch.float32).reshape(-1,1) #這里需要把我們的訓(xùn)練數(shù)據(jù)轉(zhuǎn)換為pytorch tensor的類型,并且把它變成gpu能運算的形式。
pt_y_train = torch.from_numpy(np.array(y_train)).to(device=device,dtype = torch.float32).reshape(-1,1) #reshap的目的是把維度變成(25,1),這樣25相當(dāng)于是batch,我們就可以一次性把所有的點都輸入到網(wǎng)絡(luò)里去,最后網(wǎng)絡(luò)輸出的結(jié)果也不是(1,1)而是(25,1),我們就能直接計算所有點的損失
print(pt_x_train.dtype)
print(pt_x_train.shape)
第五步:網(wǎng)絡(luò)訓(xùn)練過程
start = time.time()
start0=time.time()
for epoch in range(1,epochs+1):
net.train() #net.train():在這個模式下,網(wǎng)絡(luò)的參數(shù)會得到更新。對應(yīng)的還有net.eval(),這就是在驗證集上的時候,我們只評價模型,并不對網(wǎng)絡(luò)參數(shù)進(jìn)行更新。
pt_y_pred = net(pt_x_train) #將tensor放入網(wǎng)絡(luò)中得到預(yù)測值
loss = mseloss(pt_y_pred,pt_y_train) #用mseloss計算預(yù)測值和對應(yīng)標(biāo)簽的差別
optimizer.zero_grad() #在每一次迭代梯度反傳更新網(wǎng)絡(luò)參數(shù)時,需要把之前的梯度清0,不然上一次的梯度會累積到這一次。
loss.backward() # 反向傳播
optimizer.step() #優(yōu)化器進(jìn)行下一次迭代
if epoch % 10 == 0:#每10個epoch保存一次loss
end = time.time()
print("epoch:[%5d/%5d] time:%.2fs current_loss:%.5f"
%(epoch,epochs,(end-start),loss.item()))
start = time.time()
train_loss.append(loss.item())
if train_loss[-1] < MinTrainLoss:
torch.save(net.state_dict(),"model.pth") #保存每一次loss下降的模型
MinTrainLoss = train_loss[-1]
end0 = time.time()
print("訓(xùn)練總用時: %.2fmin"%((end0-start0)/60))
?訓(xùn)練過程如上,時間我這里設(shè)置的比較簡單,除了分鐘,之后的時間沒有按照60進(jìn)制規(guī)定。
第六步:查看loss下降情況
plt.plot(range(epochs),train_loss)
plt.xlabel("epoch")
plt.ylabel("loss")
可以看到收斂的還是比較好的。
第七步:導(dǎo)入網(wǎng)絡(luò)模型,輸入驗證數(shù)據(jù),預(yù)測結(jié)果?
x_test = np.linspace(-np.pi,np.pi).astype(np.float32)
pt_x_test = torch.from_numpy(x_test).to(device=device,dtype=torch.float32).reshape(-1,1)
Dnn = DNN().to(device)
Dnn.load_state_dict(torch.load("model.pth",map_location=device))#pytoch 導(dǎo)入模型
Dnn.eval()#這里指評價模型,不反傳,所以用eval模式
pt_y_test = Dnn(pt_x_test)
y_test = pt_y_test.detach().cpu().numpy()#輸出結(jié)果torch tensor,需要轉(zhuǎn)化為numpy類型來進(jìn)行可視化
plt.scatter(x_train,y_train,c="r")
plt.plot(x_test,y_test)
這里紅色的點為訓(xùn)練用的數(shù)據(jù),藍(lán)色為我們的預(yù)測曲線,可以看到整體上擬合的是比較好的。文章來源:http://www.zghlxwxcb.cn/news/detail-465859.html
以上就是用pytorch搭建的簡單全連接網(wǎng)絡(luò)的基本步驟,希望可以給到初學(xué)者一些幫助!文章來源地址http://www.zghlxwxcb.cn/news/detail-465859.html
實驗室網(wǎng)址:CIG | zhixiang
Github網(wǎng)址:ProgrammerZXG (Zhixiang Guo) · GitHub
到了這里,關(guān)于Pytorch:手把手教你搭建簡單的全連接網(wǎng)絡(luò)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!