这个notebook也同时发表在Kaggle上
Fashion MNIST数据集
Label | Class |
---|---|
0 | T-shirt/top |
1 | Trouser |
2 | Pullover |
3 | Dress |
4 | Coat |
5 | Sandal |
6 | Shirt |
7 | Sneaker |
8 | Bag |
9 | Ankle boot |
准备工作
import os
import torch
import torch.nn.functional as F
import torch.nn as nn
import torch.optim as optim
import numpy as np
import pandas as pd
from PIL import Image
import matplotlib.pyplot as plt
from torchvision import transforms, datasets
from torch.utils.data import Dataset, DataLoader
EPOCHS = 20
BATCH_SIZE = 512
DEVICE = ("cuda" if torch.cuda.is_available() else "cpu")
class_names = ['T-shirt/top', 'Trouser', 'Pullover', 'Dress', 'Coat',
'Sandal', 'Shirt', 'Sneaker', 'Bag', 'Ankle boot']
print(torch.__version__)
print(DEVICE)
1.4.0
cuda
加载数据
有两种方式来加载 Fashion-MNIST dataset:
- 使用官方在
datasets.FashionMNIST
给出的数据集 - 使用下载的原始csv数据集
在这里我们选择第二种,因此需要建立我们自己的 dataset
首先 ,用pd.read_csv
导入'.csv' 文件
train_csv = pd.read_csv('/content/fashion-mnist_train.csv')
test_csv = pd.read_csv('/content/fashion-mnist_test.csv')
print(train_csv.shape)
print(test_csv.shape)
(60000, 785)
(10000, 785)
print(train_csv.info())
print(train_csv.head())
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 60000 entries, 0 to 59999
Columns: 785 entries, label to pixel784
dtypes: int64(785)
memory usage: 359.3 MB
None
label pixel1 pixel2 pixel3 ... pixel781 pixel782 pixel783 pixel784
0 2 0 0 0 ... 0 0 0 0
1 9 0 0 0 ... 0 0 0 0
2 6 0 0 0 ... 0 0 0 0
3 0 0 0 0 ... 0 0 0 0
4 3 0 0 0 ... 0 0 0 0
[5 rows x 785 columns]
根据输出可知,第一列是每个图像的label,而每个图像由784个像素组成
建立Dataset
关于Dataset的有关内容在这里提到过
我们需要建立一个继承自Dataset
的类,其中必须定义函数get_item()
& len()
get_item()
返回指定图像和labellen()
返回数据集中数据数量
# 创建自己的Dataset
class FashionDataset(Dataset):
def __init__(self, data, transform=None):
self.fashion_MNIST = list(data.values)
self.transform = transform
label, image = [], []
for i in self.fashion_MNIST:
label.append(i[0])
image.append(i[1:])
self.labels = np.asarray(label)
self.images = np.asarray(image).reshape(-1, 28, 28).astype('float32')
def __len__(self):
return len(self.images)
def __getitem__(self, idx):
# 返回指定行数据
label = self.labels[idx]
image = self.images[idx]
if self.transform is not None:
# 转换成PIL
pil_image = Image.fromarray(np.uint8(image))
image = self.transform(pil_image)
return image, label
Transform
Transform有关的内容也在之前的blog中介绍过:blog:PYTORCH_TORCHVISION
我们打算使用AlexNet进行训练,AlexNet输入size为227*227
,而Fashion-MNIST默认为28*28
,故我们需要在transform
中对image进行resize
AlexTransform = transforms.Compose([
transforms.Resize((227, 227)),
transforms.ToTensor(),
transforms.Normalize((0.1307,), (0.3081,))
])
DataLoader
train_loader = DataLoader(
FashionDataset(train_csv, transform=AlexTransform),
batch_size=BATCH_SIZE, shuffle=True)
test_loader = DataLoader(
FashionDataset(test_csv, transform=AlexTransform),
batch_size=BATCH_SIZE, shuffle=True)
查看图像
这一步阔以略过,只是看看我们数据集中的图像罢了
def matplotlib_imshow(img):
img = img.mean(dim=0)
img = img / 2 + 0.5 # unnormalize
npimg = img.numpy()
plt.imshow(npimg, cmap="Greys")
dataiter = iter(train_loader)
images, labels = dataiter.next()
img_grid = torchvision.utils.make_grid(images[0])
matplotlib_imshow(img_grid)
print(class_names[labels[0]])
T-shirt/top
定义Net
AlexNet网络的相关介绍可以在这篇文章:卷积神经网络CNN以及几种经典模型中找到
class fasion_mnist_alexnet(nn.Module): # 选用AlexNet网络
def __init__(self):
super().__init__()
self.conv1 = nn.Sequential(
nn.Conv2d(in_channels=1, out_channels=96, kernel_size=11, stride=4, padding=0),
nn.ReLU(),
nn.MaxPool2d(kernel_size=3, stride=2)
)
self.conv2 = nn.Sequential(
nn.Conv2d(96, 256, 5, 1, 2),
nn.ReLU(),
nn.MaxPool2d(3, 2)
)
self.conv3 = nn.Sequential(
nn.Conv2d(256, 384, 3, 1, 1),
nn.ReLU()
)
self.conv4 = nn.Sequential(
nn.Conv2d(384, 384, 3, 1, 1),
nn.ReLU()
)
self.conv5 = nn.Sequential(
nn.Conv2d(384, 256, 3, 1, 1),
nn.ReLU(),
nn.MaxPool2d(3, 2)
)
self.fc1 = nn.Linear(256 * 6 * 6, 4096)
self.fc2 = nn.Linear(4096, 4096)
self.fc3 = nn.Linear(4096, 10)
def forward(self, x):
out = self.conv1(x)
out = self.conv2(out)
out = self.conv3(out)
out = self.conv4(out)
out = self.conv5(out)
out = out.view(out.size(0), -1)
out = F.relu(self.fc1(out)) # 256*6*6 -> 4096
out = F.dropout(out, 0.5)
out = F.relu(self.fc2(out))
out = F.dropout(out, 0.5)
out = self.fc3(out)
out = F.log_softmax(out, dim=1)
return out
实例化Model
model = fasion_mnist_alexnet().to(DEVICE)
criterion = F.nll_loss
optimizer = optim.Adam(model.parameters())
训练函数
def train(model, device, train_loader, optimer, epoch):
model.train()
for batch_idx, (data, target) in enumerate(train_loader):
target = target.type(torch.LongTensor)
data, target = data.to(device), target.to(device)
optimizer.zero_grad()
output = model(data)
loss = criterion(output, target)
loss.backward()
optimizer.step()
if (batch_idx + 1) % 30 == 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 test(model, device, test_loader):
model.eval()
test_loss = 0
correct = 0
with torch.no_grad():
for data, target in test_loader:
data, target = data.to(device), target.to(device)
output = model(data)
test_loss += criterion(output, target, reduction='sum').item()
pred = output.max(1, keepdim=True)[1]
correct += pred.eq(target.view_as(pred)).sum().item()
test_loss /= len(test_loader.dataset) # loss之和除以data数量 -> mean
print("\nTest set: Average loss: {:.4f}, Accuracy: {}/{} ({:.0f}%)\n".format(
test_loss, correct, len(test_loader.dataset), 100. * correct / len(test_loader.dataset)))
print('='*50)
开始训练
for epoch in range(1, EPOCHS+1):
train(model, DEVICE, train_loader, optimizer, epoch)
test(model, DEVICE, test_loader)
Train Epoch:1 [14848/60000 (25%)] Loss: 0.877214
Train Epoch:1 [30208/60000 (50%)] Loss: 0.644841
Train Epoch:1 [45568/60000 (75%)] Loss: 0.532848
Test set: Average loss: 0.4413, Accuracy: 8316/10000 (83%)
==================================================
Train Epoch:2 [14848/60000 (25%)] Loss: 0.433440
Train Epoch:2 [30208/60000 (50%)] Loss: 0.360927
Train Epoch:2 [45568/60000 (75%)] Loss: 0.368575
Test set: Average loss: 0.3194, Accuracy: 8838/10000 (88%)
==================================================
Train Epoch:3 [14848/60000 (25%)] Loss: 0.308415
Train Epoch:3 [30208/60000 (50%)] Loss: 0.224128
Train Epoch:3 [45568/60000 (75%)] Loss: 0.245119
Test set: Average loss: 0.2992, Accuracy: 8995/10000 (90%)
==================================================
Train Epoch:4 [14848/60000 (25%)] Loss: 0.272408
Train Epoch:4 [30208/60000 (50%)] Loss: 0.226366
Train Epoch:4 [45568/60000 (75%)] Loss: 0.274030
Test set: Average loss: 0.2753, Accuracy: 8973/10000 (90%)
==================================================
Train Epoch:5 [14848/60000 (25%)] Loss: 0.224429
Train Epoch:5 [30208/60000 (50%)] Loss: 0.237268
Train Epoch:5 [45568/60000 (75%)] Loss: 0.280958
Test set: Average loss: 0.2686, Accuracy: 9082/10000 (91%)
==================================================
Train Epoch:6 [14848/60000 (25%)] Loss: 0.217329
Train Epoch:6 [30208/60000 (50%)] Loss: 0.258806
Train Epoch:6 [45568/60000 (75%)] Loss: 0.179489
Test set: Average loss: 0.2273, Accuracy: 9180/10000 (92%)
==================================================
Train Epoch:7 [14848/60000 (25%)] Loss: 0.232198
Train Epoch:7 [30208/60000 (50%)] Loss: 0.193284
Train Epoch:7 [45568/60000 (75%)] Loss: 0.180621
Test set: Average loss: 0.2556, Accuracy: 9073/10000 (91%)
==================================================
Train Epoch:8 [14848/60000 (25%)] Loss: 0.202838
Train Epoch:8 [30208/60000 (50%)] Loss: 0.177613
Train Epoch:8 [45568/60000 (75%)] Loss: 0.166227
Test set: Average loss: 0.2537, Accuracy: 9090/10000 (91%)
==================================================
Train Epoch:9 [14848/60000 (25%)] Loss: 0.191794
Train Epoch:9 [30208/60000 (50%)] Loss: 0.179932
Train Epoch:9 [45568/60000 (75%)] Loss: 0.157028
Test set: Average loss: 0.2236, Accuracy: 9181/10000 (92%)
==================================================
Train Epoch:10 [14848/60000 (25%)] Loss: 0.201635
Train Epoch:10 [30208/60000 (50%)] Loss: 0.193036
Train Epoch:10 [45568/60000 (75%)] Loss: 0.133806
Test set: Average loss: 0.2228, Accuracy: 9207/10000 (92%)
==================================================
Train Epoch:11 [14848/60000 (25%)] Loss: 0.140554
Train Epoch:11 [30208/60000 (50%)] Loss: 0.195291
Train Epoch:11 [45568/60000 (75%)] Loss: 0.167740
Test set: Average loss: 0.2298, Accuracy: 9169/10000 (92%)
==================================================
Train Epoch:12 [14848/60000 (25%)] Loss: 0.145187
Train Epoch:12 [30208/60000 (50%)] Loss: 0.136410
Train Epoch:12 [45568/60000 (75%)] Loss: 0.148455
Test set: Average loss: 0.2208, Accuracy: 9244/10000 (92%)
==================================================
Train Epoch:13 [14848/60000 (25%)] Loss: 0.102129
Train Epoch:13 [30208/60000 (50%)] Loss: 0.119473
Train Epoch:13 [45568/60000 (75%)] Loss: 0.151384
Test set: Average loss: 0.2176, Accuracy: 9245/10000 (92%)
==================================================
Train Epoch:14 [14848/60000 (25%)] Loss: 0.085864
Train Epoch:14 [30208/60000 (50%)] Loss: 0.161960
Train Epoch:14 [45568/60000 (75%)] Loss: 0.173307
Test set: Average loss: 0.2276, Accuracy: 9210/10000 (92%)
==================================================
Train Epoch:15 [14848/60000 (25%)] Loss: 0.158055
Train Epoch:15 [30208/60000 (50%)] Loss: 0.164117
Train Epoch:15 [45568/60000 (75%)] Loss: 0.119916
Test set: Average loss: 0.2236, Accuracy: 9236/10000 (92%)
==================================================
Train Epoch:16 [14848/60000 (25%)] Loss: 0.120705
Train Epoch:16 [30208/60000 (50%)] Loss: 0.138526
Train Epoch:16 [45568/60000 (75%)] Loss: 0.132989
Test set: Average loss: 0.2330, Accuracy: 9241/10000 (92%)
==================================================
Train Epoch:17 [14848/60000 (25%)] Loss: 0.082980
Train Epoch:17 [30208/60000 (50%)] Loss: 0.142380
Train Epoch:17 [45568/60000 (75%)] Loss: 0.088001
Test set: Average loss: 0.2495, Accuracy: 9213/10000 (92%)
==================================================
Train Epoch:18 [14848/60000 (25%)] Loss: 0.106110
Train Epoch:18 [30208/60000 (50%)] Loss: 0.121420
Train Epoch:18 [45568/60000 (75%)] Loss: 0.102312
Test set: Average loss: 0.2547, Accuracy: 9251/10000 (93%)
==================================================
Train Epoch:19 [14848/60000 (25%)] Loss: 0.118317
Train Epoch:19 [30208/60000 (50%)] Loss: 0.113046
Train Epoch:19 [45568/60000 (75%)] Loss: 0.085053
Test set: Average loss: 0.2661, Accuracy: 9213/10000 (92%)
==================================================
Train Epoch:20 [14848/60000 (25%)] Loss: 0.103729
Train Epoch:20 [30208/60000 (50%)] Loss: 0.049429
Train Epoch:20 [45568/60000 (75%)] Loss: 0.109371
Test set: Average loss: 0.2729, Accuracy: 9230/10000 (92%)
==================================================
可见当进行10次训练后,我们模型的准确率就稳定在了92%,所以想要继续提升准确率就需要对模型进行改进