《動手學深度學習》(pytorch版本)Chapter 3.7 SOFTMAX回歸的簡潔實現(xiàn) 部分少了把模型和數(shù)據(jù)加載到GPU上的程序闯参,如果只按照書上的代碼運行咪奖,則會報錯霉涨。這里參考機器之心pro的文章刀崖,把代碼補全仅财,用jupyter notebook 可以運行,記錄一下属韧。
import torch
from torch import nn
from torch.nn import init # initializer
import numpy as np
# import sys # 可以用來添加包安拟,把包的地址添加到系統(tǒng)的環(huán)境變量中,便于搜索
# sys. path.append('..')
import d2lzh_pytorch as d2l
##################################
# gpu運算優(yōu)先函數(shù)
def get_default_device():
"""Pick GPU if availbale, else CPU"""
return torch.device('cuda:0' if torch.cuda.is_available() else 'cpu')
device = get_default_device()
print(device)
##################################
# 移動數(shù)據(jù)到目標設(shè)備的函數(shù)
def to_device(data, device):
"""Move tensors to chonsen device"""
if isinstance(data, (list, tuple)):
return [to_device(x, device) for x in data]
return data.to(device, non_blocking = True)
##################################
# 數(shù)據(jù)封裝與加載到設(shè)備類
class DeviceDataLoader():
"""Wrap a dataloader to move data to a device"""
def __init__(self, dl, device):
self.dl = dl
self.device = device
def __iter__(self):
"""Yield a batch of data after moving it to device"""
for batch in self.dl:
yield to_device(batch, self.device)
def __len__(self):
"""Number of batches"""
return len(self.dl)
##################################
# 獲取數(shù)據(jù)
batch_size = 256
train_iter, test_iter = d2l.load_data_fashion_mnist(batch_size)
# 封裝數(shù)據(jù)加載器
train_iter = DeviceDataLoader(train_iter, device)
test_iter = DeviceDataLoader(test_iter, device)
# 讀取一個批次試試
for X, y in train_iter:
print('X.device', X.device) # 不用看這個宵喂,這個數(shù)據(jù)太多
print('y', y) #看標簽
break
##################################
# 定義和初始化模型
num_inputs = 784
num_outputs = 10
class LinearNet(nn.Module):
def __init__(self, num_inputs, num_outputs):
super(LinnearNet, self).__init__()
self.linear = nn.Linear(num_inputs, num_outputs) # 定義輸入輸出個數(shù)糠赦,全連接層自動確定參數(shù)
def forwad(self, x): # x.shape: (batch, 1, 28, 28)
y = self.linear(x.view(x.shape[0], -1)) # 轉(zhuǎn)換為batch_size, 784 才能放入全連接層
return y
##################################
# 將 x形狀的改變定義為一個FlattenLayer
class FlattenLayer(nn.Module):
def __init__(self):
super(FlattenLayer, self).__init__()
def forward(self, x): # x shape-> ( batch, *, *, ...)
return x.view(x.shape[0], -1)
##################################
from collections import OrderedDict
net = nn.Sequential(
# FlattenLayer(),
# nn.Linear(num_inputs, num_outputs)
OrderedDict([
('flatten', FlattenLayer()),
('linear', nn.Linear(num_inputs, num_outputs))
]
)
)
net = net.to(device) # 模型也加載到gpu上
##################################
# 初始化
init.normal_(net.linear.weight, mean = 0, std = 0.01)
init.constant_(net.linear.bias, val = 0)
##################################
# softmax運算和交叉熵損失函數(shù)直接整合在一起
loss = nn.CrossEntropyLoss()
##################################
#優(yōu)化算法定義,隨機梯度下降法
optimizer = torch.optim.SGD(net.parameters(), lr = 0.1)
##################################
num_epochs = 5
d2l.train_ch3(net, train_iter, test_iter, loss, num_epochs, batch_size, None, None, optimizer)
訓練與預(yù)測輸出如下:
epoch 1, loss 0.0031, train acc 0.751, test acc 0.791
epoch 2, loss 0.0022, train acc 0.813, test acc 0.790
epoch 3, loss 0.0021, train acc 0.825, test acc 0.792
epoch 4, loss 0.0020, train acc 0.832, test acc 0.823
epoch 5, loss 0.0019, train acc 0.837, test acc 0.827