理解
訓練完之后也需要做測試
為什么要做test?
上圖藍色代表train的accuracy
下圖藍色代表train的loss
基本上符合預期,隨著epoch增大,train的accuracy也會上升,loss也會一直下降,下降到一個較小的程度
但是如果只看train的情況的話,就會被欺騙,雖然accuracy高并且loss很低,你會以為這個算法就很好了,但是做其他的事情就不是特別好,這就是過擬合(overfitting)
deep learning表達能力非常強表達效果很好,在模型在訓練數據上表現非常好,但在新的、未見過的數據上表現不佳的情況。這是因為模型學習到了訓練數據中的特定噪聲和細節,而不是更通用的特征。
如何緩解這種情況?
在train的時候做一個test,這個test使用validation set 驗證集做的,在剛開始的階段,藍色的線在上升的時候,驗證集的accuracy也會上升loss也與train基本一致,只不過是在訓練集上面train在驗證集上測試不一定完全符合,所以波動會有點大,很明顯train會的更好,validation的表現(包括accuracy和loss)也會變的更好
說明在剛開始的階段確實學到了一些通用的特征,隨著時間的推移,就開始over fitting了,開始去記住一些噪聲和細節,這樣的話泛化能力會變差,所以在訓練集上訓練后,在驗證集上測試的時候,accuracy會保持不變或者可能下降同樣的loss也會巨幅的波動
深度學習所以并不是越訓練越好,數據量和架構是核心問題,有一個好的結構再加上足夠的數據才能取得一個好的結果
logits是一個是十個節點的向量,經過cross entropy loss(包含softmax和log和nll_loss)訓練,得到loss和accuracy(經過softmax之后就變成了Y=i,i代表第i號節點的概率,只需要argmax之后就能得到概率最大所在的位置),這里對softmax之前和之后都做了一下argmax,其實是一樣的效果,因為softmax不會改變單調性,即原來大的數據在softmax之后也會大
這是計算accuracy的基本流程
什么時候計算test的accuracy和loss
不能夠每做一個batch就訓練一次,這樣就會花大量的時間做測試,不合理,尤其是對于大型數據集
一般情況:
- 訓練若干個batch做一次測試
- 訓練一個epoch做一次測試
如何做測試
import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
from torchvision import datasets, transformsdef load_data(batch_size):train_loader = torch.utils.data.DataLoader(datasets.MNIST('mnist_data', train=True, download=True,transform=transforms.Compose([transforms.ToTensor(),transforms.Normalize((0.1307,), (0.3081,))])),batch_size=batch_size, shuffle=True)test_loader = torch.utils.data.DataLoader(datasets.MNIST('mnist_data', train=False, transform=transforms.Compose([transforms.ToTensor(),transforms.Normalize((0.1307,), (0.3081,))])),batch_size=batch_size, shuffle=True)return train_loader, test_loaderclass MLP(nn.Module):def __init__(self):super(MLP, self).__init__()self.model = nn.Sequential(nn.Linear(784, 200),nn.LeakyReLU(inplace=True),nn.Linear(200, 200),nn.LeakyReLU(inplace=True),nn.Linear(200, 10),nn.LeakyReLU(inplace=True),)def forward(self, x):x = self.model(x)return xdef training(train_loader, net, device):for batch_idx, (data, target) in enumerate(train_loader):data = data.view(-1, 28 * 28)data, target = data.to(device), target.cuda()logits = net(data)loss = criteon(logits, target)optimizer.zero_grad()loss.backward()# print(w1.grad.norm(), w2.grad.norm())optimizer.step()if batch_idx % 100 == 0:print('Train Epoch: {} [{}/{} ({:.0f}%)]\tLoss: {:.6f}'.format(epoch, batch_idx * len(data), len(train_loader.dataset), 100. * batch_idx / len(train_loader),loss.item()))def testing(test_loader, net, device):test_loss = 0correct = 0for data, target in test_loader:data = data.view(-1, 28 * 28)data, target = data.to(device), target.cuda()logits = net(data)test_loss += criteon(logits, target).item()pred = logits.argmax(dim=1)correct += pred.eq(target).float().sum().item()test_loss /= len(test_loader.dataset)print('\nTest set: Average loss: {:.4f}, Accuracy: {}/{} ({:.0f}%)\n'.format(test_loss, correct, len(test_loader.dataset),100. * correct / len(test_loader.dataset)))global netif __name__ == '__main__':batch_size = 200learning_rate = 0.01epochs = 10train_loader, test_loader = load_data(batch_size)device = torch.device('cuda:0')net = MLP().to(device)optimizer = optim.SGD(net.parameters(), lr=learning_rate)criteon = nn.CrossEntropyLoss().to(device)for epoch in range(epochs):training(train_loader, net, device)testing(test_loader, net, device)