基于pytorch的DeepLearning學習筆記
最近開始學深度學習架構pytorch,從最簡單的卷積神經網絡開始了解pytorch的架構。以下涉及到的代碼完整版請檢視https://github.com/XieHanS/CPSC_ECGHbClassify_demo.git
基于pytorch的DL主要分為三個子產品,資料塊,模型塊,和訓練塊。具體如下:
1、 資料集
pytorch提供有專門的資料下載下傳,資料處理包,使用這些包可以極大地提高開發效率
torch.utils.data工具包
該包中有兩個常用的類,分别為Dataset和DataLoader
Dataset 一個抽象類,抽象類隻能作為基類派生新類使用,不能建立抽象類對象。其他資料集需要繼承這個類,并覆寫其中的兩個方法:
__getitem__ 和 __len__
from torch.utils.data import Dataset, DataLoaderclass MyDataset(Dataset):def __init__(self, data, label):self.data = dataself.label = labeldef __getitem__(self, index):return (torch.tensor(self.data[index], dtype=torch.float), torch.tensor(self.label[index], dtype=torch.long))def __len__(self):return len(self.data)
調用__getitem__隻傳回一個樣本,是以需要一個批量讀取的工具,pytorch為我們提供了另外一個類DataLoader。DataLoader 定義一個新的疊代器,實作批量讀取,打亂資料并提供并行加速等功能
loader = torch.utils.data.DataLoader(dataset = datasets, #加載的資料集batch_size = BATCH_SIZE, #批大小shuffle = True, #是否将資料打亂,預設為falsenum_workers=2,#使用多程序加載的程序數,0代表不使用多程序
使用的時候隻需要調用這兩個類即可
#繼承Dataset類,自定義資料集以及對應的标簽dataset = MyDataset(X_train, Y_train)dataset_test = MyDataset(X_test, Y_test)#裝載資料,實作批量讀取dataloader = DataLoader(dataset, batch_size=batch_size)dataloader_test = DataLoader(dataset_test, batch_size=batch_size, drop_last=False)
#訓練模型時候的資料循環for epoch in range(n_epoch):model.train()for batch_idx, batch in enumerate(dataloader):input_x, input_y = tuple(batch)pred = model(input_x)[0]
2、 定義模型
pytorch中自定義的模型往往繼承自nn.Model,包括兩個函數,初始化函數__init__()和forward()。__init__()定義了卷積層和其他層的參數,forward()規定了網絡執行的順序。例如下面的網絡:
__init__()定義了兩個卷積層conv1和conv2,和一個全連接配接層out層,兩個卷積層裡面分别包含了一維卷積,DropOut,ReLU激活和最大池化層。
forward()定義了執行順序。首先conv1,接着conv2,最後out層。由于上下層連接配接的問題,往往init裡面會按照順序撰寫,而真正的執行順序是forward裡面的順序。
class CNN(nn.Module): def __init__(self): super(CNN, self).__init__() self.conv1 = nn.Sequential( # input shape (1, 1, 2000) nn.Conv1d( in_channels=1, # input height out_channels=16, # n_filters kernel_size=5, # filter size stride=1, # filter movement/step padding=2, ), # output shape (16, 1, 2000) nn.Dropout(0.2),#扔到0.2 nn.ReLU(), nn.MaxPool1d(kernel_size=5), # choose max value in 1x5 area, output shape (16, 1, 400)2000/5 ) self.conv2 = nn.Sequential( # input shape (16, 1, 400) nn.Conv1d(16, 32, 5, 1, 2),# output shape (32, 1, 400) nn.Dropout(0.2),#扔掉0.2 nn.ReLU(), nn.MaxPool1d(kernel_size=5),# output shape (32, 1, 400/5=80) ) self.out = nn.Linear(32 * 80, 3) # fully connected layer, output 3 classes def forward(self, x): x = self.conv1(x) x = self.conv2(x) x = x.view(x.size(0), -1) output = self.out(x) return output, x
我們列印出模型如下:
3、訓練模型
1) 讀資料,裝載資料,随機批量配置設定
2) 初始化自定義的模型類
3) 定義優化器【SGD,自适應優化算法(RMSProp,Adam,Adadelta)】和損失函數【MSE(回歸),crossEntropy(分類)】
4) 定義epoch數量,for循環訓練模型
# 初始化自定義的模型類 model = CNN() model.verbose = False#運作的時候不顯示詳細資訊 # 定義優化器和損失函數 LR = 0.001 optimizer = torch.optim.Adam(model.parameters(), lr=LR) loss_func = torch.nn.CrossEntropyLoss()
for epoch in range(n_epoch): model.train() for batch_idx, batch in enumerate(dataloader): input_x, input_y = tuple(batch) pred = model(input_x)[0] loss = loss_func(pred, input_y) optimizer.zero_grad()#梯度置零 loss.backward() #optimizer.step()是大多數optimizer所支援的簡化版本。一旦梯度被如backward()之類的函數計算好後,就可以調用這個函數更新所有的參數。 optimizer.step() step += 1 # test model.eval()#為了固定BN和dropout層,使得偏置參數不随着發生變化
訓練需要注意的幾點:
1) 反向傳播之前,優化器的梯度需要置零
2) optimizer.step()是大多數optimizer所支援的簡化版本。一旦梯度被如backward()之類的函數計算好後,就可以調用這個函數更新所有的參數
3) model.eval()#訓練完train_datasets之後,model要用來測試樣本,model.eval()為了固定BN和dropout層,使得偏置參數不随着發生變化
完整的代碼https://github.com/XieHanS/CPSC_ECGHbClassify_demo.git