寫在前面
由於MLP的實現框架已經非常完善,網上搜到的代碼大都大同小異,而且MLP的實現是deeplearning學習過程中較為基礎的一個實驗。因此完全可以找一份源碼以參考,重點在於照着源碼手敲一遍,以熟悉pytorch的基本操作。
實驗要求
熟悉pytorch的基本操作:用pytorch實現MLP,並在MNIST數據集上進行訓練
環境配置
實驗環境如下:
- Win10
- python3.8
- Anaconda3
- Cuda10.2 + cudnn v7
- GPU : NVIDIA GeForce MX250
配置環境的過程中遇到了一些問題,解決方案如下:
-
anaconda下載過慢
使用清華鏡像源,直接百度搜索即可
-
pytorch安裝失敗
這里我首先使用的是pip的安裝方法,失敗多次后嘗試了使用anaconda,然后配置了清華鏡像源,最后成功。參考的教程如下:
win10快速安裝pytorch,清華鏡像源當然也可以直接去pytorch官網下載所需版本的whl文件,然后手動pip安裝。由於這種方式我已經學會了,為了學習anaconda,所以沒有采用這種方式。具體方式可以百度如何使用whl。順便貼下pytorch的whl的下載頁面
注意:pytorch的版本是要嚴格對應是否使用GPU、python版本、cuda版本的,如需手動下載pytorch的安裝包,需搞懂其whl文件的命名格式
另外還學習了anaconda的一些基本操作與原理,參考如下:
Anaconda完全入門指南
實驗過程
最終代碼見github:hit-deeplearning-1
首先設置一些全局變量,加載數據。batch_size決定了每次向網絡中輸入的樣本數,epoch決定了整個數據集的迭代次數,具體作用與大小如何調整可參考附錄中的博客。
將數據讀入,如果數據不存在於本地,則可以自動從網上下載,並保存在本地的data文件夾下。
#一次取出的訓練樣本數
batch_size = 16
# epoch 的數目
n_epochs = 10
#讀取數據
train_data = datasets.MNIST(root="./data", train=True, download=True,transform=transforms.ToTensor())
test_data = datasets.MNIST(root="./data", train=False, download=True, transform=transforms.ToTensor())
#創建數據加載器
train_loader = torch.utils.data.DataLoader(train_data, batch_size = batch_size, num_workers = 0)
test_loader = torch.utils.data.DataLoader(test_data, batch_size = batch_size, num_workers = 0)
接下來是創建MLP模型,關於如何創建一個模型,可以參考附錄中的博客,總之創建模型模板,訓練模板都是固定的。
其中Linear
、view
、CrossEntropyLoss
、SGD
的用法需重點關注。查看官方文檔或博客解決。
這兩條語句將數據放到了GPU上,同理測試的時候也要這樣做。
data = data.cuda()
target = target.cuda()
class MLP(nn.Module):
def __init__(self):
#繼承自父類
super(MLP, self).__init__()
#創建一個三層的網絡
#輸入的28*28為圖片大小,輸出的10為數字的類別數
hidden_first = 512
hidden_second = 512
self.first = nn.Linear(in_features=28*28, out_features=hidden_first)
self.second = nn.Linear(in_features=hidden_first, out_features=hidden_second)
self.third = nn.Linear(in_features=hidden_second, out_features=10)
def forward(self, data):
#先將圖片數據轉化為1*784的張量
data = data.view(-1, 28*28)
data = F.relu(self.first(data))
data = F.relu((self.second(data)))
data = F.log_softmax(self.third(data), dim = 1)
return data
def train():
# 定義損失函數和優化器
lossfunc = torch.nn.CrossEntropyLoss().cuda()
#lossfunc = torch.nn.CrossEntropyLoss()
optimizer = torch.optim.SGD(params=model.parameters(), lr=0.01)
# 開始訓練
for epoch in range(n_epochs):
train_loss = 0.0
for data, target in train_loader:
optimizer.zero_grad()
#將數據放至GPU並計算輸出
data = data.cuda()
target = target.cuda()
output = model(data)
#計算誤差
loss = lossfunc(output, target)
#反向傳播
loss.backward()
#將參數更新至網絡中
optimizer.step()
#計算誤差
train_loss += loss.item() * data.size(0)
train_loss = train_loss / len(train_loader.dataset)
print('Epoch: {} \tTraining Loss: {:.6f}'.format(epoch + 1, train_loss))
# 每遍歷一遍數據集,測試一下准確率
test()
#最后將模型保存
path = "model.pt"
torch.save(model, path)
test程序不再貼出,直接調用了一個很常用的test程序。
最后是主程序,在這里將模型放到GPU上。
model = MLP()
#將模型放到GPU上
model = model.cuda()
train()
實驗結果
實驗結果如下,可以看到,當對數據迭代訓練十次時,准確率已經可以達到97%
分別運行了兩次,第一次沒有使用cuda加速,第二次使用了cuda加速,任務管理器分別顯示如下:
可以看到,未使用cuda加速時,cpu占用率達到了100%,而GPU的使用率為0;而使用cuda加速時,cpu占用率只有49%,而GPU使用率為1%。這里GPU使用率較低的原因很多,比如我程序中batch_size設置的較小,另外只將數據和模型放到了GPU上,cpu上仍有部分代碼與數據。經簡單測試,使用cuda的訓練時間在2:30左右,不使用cuda的訓練時間在3:40左右。
參考博客
如何創建自定義模型
pytorch教程之nn.Module類詳解——使用Module類來自定義網絡層
epoch和batch是什么
深度學習 | 三個概念:Epoch, Batch, Iteration
如何用GPU加速
PyTorch如何使用GPU加速(CPU與GPU數據的相互轉換)
保存模型