MNIST数据集大家应该已经很熟悉了。
之前这个pytorch版本的是全连接层,现在换个net,重写一下。
废话不多说直接上代码,这次研究了一下pytorch中的二维卷积的函数,所以人为的改了一下代码,毕竟一直模仿是行不通的,就和修车一样,你得拆了之后再组装起来才能说明你good at修车。
第一个版本:
使用了两个卷积层,两个dropout层最后是全连接层,这模型是一个教程给的实例,我跑了一遍准确率大概是97%徘徊,已经很高了,但是我试图拉升这个准确率,
import torch
import torch.nn as nn
import torch.nn.functional as f
import torchvision
import torchvision.transforms as transforms
import matplotlib.pyplot as plt
class MyNet(nn.Module):
def __init__(self):
super(MyNet,self).__init__()
self.conv1 = nn.Conv2d(1,32,3,1)
self.conv2 = nn.Conv2d(32,64,3,1)
self.pool = nn.MaxPool2d(2,2)
self.dropout1 = nn.Dropout2d(0.25)
self.dropout2 = nn.Dropout2d(0.5)
self.fc1 = nn.Linear(12*12*64,128)
self.fc2 = nn.Linear(128,10)
def forward(self,x):
x = self.conv1(x)
x = f.relu(x)
x = self.conv2(x)
x = f.relu(x)
x = self.pool(x)
x = self.dropout1(x)
x = x.view(-1,12*12*64)
x = self.fc1(x)
x = f.relu(x)
x = self.dropout2(x)
x = self.fc2(x)
return f.log_softmax(x, dim=1)
def load_MNIST(batch=128):
transform = transforms.Compose([transforms.ToTensor(),
transforms.Normalize((0.1307,), (0.3081,))])
train_set = torchvision.datasets.MNIST(root="./data",
train=True,
download=True,
transform=transform)
train_loader = torch.utils.data.DataLoader(train_set,
batch_size=batch,
shuffle=True,
num_workers=2)
val_set = torchvision.datasets.MNIST(root="./data",
train=False,
download=True,
transform=transform)
val_loader =torch.utils.data.DataLoader(val_set,
batch_size=batch,
shuffle=True,
num_workers=2)
return {"train":train_loader, "validation":val_loader}
def main():
epoch = 20
batch_size = 64
history = {
"train_loss": [],
"validation_loss": [],
"validation_acc": []
}
data_loder = load_MNIST(batch=batch_size)
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
print(device)
net = MyNet().to(device)
print(net)
optimizer = torch.optim.Adam(params=net.parameters(), lr=0.001)
for e in range(epoch):
""" 学習部分 """
loss = None
train_loss = 0.0
net.train()
print("\nTrain start")
for i,(data,target) in enumerate(data_loder["train"]):
data,target = data.to(device),target.to(device)
optimizer.zero_grad()
output = net(data)
loss = f.nll_loss(output,target)
train_loss += loss.item()
loss.backward()
optimizer.step()
if i % 100 == 99:
print("Training: {} epoch. {} iteration. Loss: {}".format(e+1,i+1,loss.item()))
train_loss /= len(data_loder["train"])
print("Training loss (ave.): {}".format(train_loss))
history["train_loss"].append(train_loss)
"""検証部分"""
print("\nValidation start")
net.eval()
val_loss = 0.0
accuracy = 0.0
with torch.no_grad():
for data,target in data_loder["validation"]:
data,target = data.to(device),target.to(device)
output = net(data)
loss = f.nll_loss(output,target).item()
val_loss += f.nll_loss(output,target,reduction='sum').item()
predict = output.argmax(dim=1,keepdim=True)
accuracy += predict.eq(target.view_as(predict)).sum().item()
val_loss /= len(data_loder["validation"].dataset)
accuracy /= len(data_loder["validation"].dataset)
print("Validation loss: {}, Accuracy: {}\n".format(val_loss,accuracy))
history["validation_loss"].append(val_loss)
history["validation_acc"].append(accuracy)
PATH = "./my_mnist_model.pt"
torch.save(net.state_dict(), PATH)
#結果
print(history)
plt.figure()
plt.plot(range(1, epoch+1), history["train_loss"], label="train_loss")
plt.plot(range(1, epoch+1), history["validation_loss"], label="validation_loss")
plt.xlabel("epoch")
plt.legend()
plt.savefig("loss.png")
plt.figure()
plt.plot(range(1, epoch+1), history["validation_acc"])
plt.title("test accuracy")
plt.xlabel("epoch")
plt.savefig("test_acc.png")
if __name__ == "__main__":
main()
第二个版本:
我多加了一个卷积层,也就是代码中的conv3,卷积核没变还是3*3,stride还是1,这样做了之后需要重新计算卷积之后输出的参数个数。不过惊喜的是这样做成功的把准确率拉升到了98%
class MyNet(nn.Module):
def __init__(self):
super(MyNet,self).__init__()
self.conv1 = nn.Conv2d(1,32,3,1)
self.conv2 = nn.Conv2d(32,128,3,1)
self.conv3 = nn.Conv2d(128,256,3,1)
self.pool = nn.MaxPool2d(2,2)
self.dropout1 = nn.Dropout2d(0.25)
self.dropout2 = nn.Dropout2d(0.5)
self.fc1 = nn.Linear(11*11*256,128)
self.fc2 = nn.Linear(128,10)
def forward(self,x):
x = self.conv1(x)
x = f.relu(x)
x = self.conv2(x)
x = f.relu(x)
x=self.conv3(x)
x = f.relu(x)
x = self.pool(x)
x = self.dropout1(x)
x = x.view(-1,11*11*256)
x = self.fc1(x)
x = f.relu(x)
x = self.dropout2(x)
x = self.fc2(x)
return f.log_softmax(x, dim=1)
import torch
import torch.nn as nn
import torch.nn.functional as f
import torchvision
import torchvision.transforms as transforms
import matplotlib.pyplot as plt
from torchsummary import summary
model = MyNet().to('cuda')
print(model)
print(summary(model, (1, 28, 28)))
def load_MNIST(batch=128):
transform = transforms.Compose([transforms.ToTensor(),
transforms.Normalize((0.1307,), (0.3081,))])
train_set = torchvision.datasets.MNIST(root="./data",
train=True,
download=True,
transform=transform)
train_loader = torch.utils.data.DataLoader(train_set,
batch_size=batch,
shuffle=True,
num_workers=2)
val_set = torchvision.datasets.MNIST(root="./data",
train=False,
download=True,
transform=transform)
val_loader =torch.utils.data.DataLoader(val_set,
batch_size=batch,
shuffle=True,
num_workers=2)
return {"train":train_loader, "validation":val_loader}
# In[29]:
epoch = 5
batch_size = 64
history = {
"train_loss": [],
"validation_loss": [],
"validation_acc": []
}
data_loder = load_MNIST(batch=batch_size)
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
print(device)
net = MyNet().to(device)
print(net)
optimizer = torch.optim.Adam(params=net.parameters(), lr=0.001)
for e in range(epoch):
""" 学習部分 """
loss = None
train_loss = 0.0
net.train()
print("\nTrain start")
for i,(data,target) in enumerate(data_loder["train"]):
data,target = data.to(device),target.to(device)
optimizer.zero_grad()
output = net(data)
loss = f.nll_loss(output,target)
train_loss += loss.item()
loss.backward()
optimizer.step()
if i % 100 == 99:
print("Training: {} epoch. {} iteration. Loss:{}".format(e+1,i+1,loss.item()))
train_loss /= len(data_loder["train"])
print("Training loss (ave.): {}".format(train_loss))
history["train_loss"].append(train_loss)
"""検証部分"""
print("\nValidation start")
net.eval()
val_loss = 0.0
accuracy = 0.0
with torch.no_grad():
for data,target in data_loder["validation"]:
data,target = data.to(device),target.to(device)
output = net(data)
loss = f.nll_loss(output,target).item()
val_loss += f.nll_loss(output,target,reduction='sum').item()
predict = output.argmax(dim=1,keepdim=True)
accuracy += predict.eq(target.view_as(predict)).sum().item()
val_loss /= len(data_loder["validation"].dataset)
accuracy /= len(data_loder["validation"].dataset)
print("Validation loss: {}, Accuracy: {}\n".format(val_loss,accuracy))
history["validation_loss"].append(val_loss)
history["validation_acc"].append(accuracy)
plt.plot(history["validation_loss"],label="validation_loss")
plt.plot(history["validation_acc"],label="validation_acc")
plt.legend()
plt.show()
PATH = "./my_mnist_model.pt"
torch.save(net.state_dict(), PATH)
。