【Kaggle-MNIST之路】CNN+改进过的损失函数+多次的epoch(四)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/a19990412/article/details/84095610

简述

在看完很多版本的代码,看了下,发现一个问题,随着epoch的次数逐渐上升,精度会一定程度上上升。(有时候也不一定)

所以,怀疑自己的这个代码还有改进的空间,所以,在提高了一下epoch的次数。但是要稍微降低一下Learning Rate。

逻辑解释

  • 稍微降低一下Learning Rate的原因:
    假设是一个简单的优化问题,担心LR太大,就直接滑动过去了。。

目前成绩

  • 分数:0.9790
  • 排名:1500+

代码

import pandas as pd
import torch.utils.data as data
import torch
import torch.nn as nn

file = './all/train.csv'
LR = 0.0008


class MNISTCSVDataset(data.Dataset):

    def __init__(self, csv_file, Train=True):
        self.dataframe = pd.read_csv(csv_file, iterator=True)
        self.Train = Train

    def __len__(self):
        if self.Train:
            return 42000
        else:
            return 28000

    def __getitem__(self, idx):
        data = self.dataframe.get_chunk(100)
        ylabel = data['label'].as_matrix().astype('float')
        xdata = data.ix[:, 1:].as_matrix().astype('float')
        return ylabel, xdata


class CNN(nn.Module):
    def __init__(self):
        super(CNN, self).__init__()
        self.layer1 = nn.Sequential(
            # (1, 28, 28)
            nn.Conv2d(
                in_channels=1,
                out_channels=16,
                kernel_size=5,  # 卷积filter, 移动块长
                stride=1,  # filter的每次移动步长
                padding=2,
                groups=1
            ),
            # nn.BatchNorm2d(16),
            # (16, 28, 38)
            nn.ReLU(),
            nn.MaxPool2d(kernel_size=2)
            # (16, 14, 14)
        )
        self.layer2 = nn.Sequential(
            nn.Conv2d(
                in_channels=16,
                out_channels=32,
                kernel_size=5,
                stride=1,
                padding=2
            ),
            # nn.BatchNorm2d(32),
            nn.ReLU(),
            nn.MaxPool2d(kernel_size=2)
        )
        self.layer3 = nn.Linear(32 * 7 * 7, 10)

    def forward(self, x):
        # print(x.shape)
        x = self.layer1(x)
        # print(x.shape)
        x = self.layer2(x)
        # print(x.shape)
        x = x.view(x.size(0), -1)
        # print(x.shape)
        x = self.layer3(x)
        # print(x.shape)
        return x


net = CNN()

loss_function = nn.MultiMarginLoss()
optimizer = torch.optim.Adam(net.parameters(), lr=LR)
EPOCH = 5
for epo in range(EPOCH):
    mydataset = MNISTCSVDataset(file)
    train_loader = torch.utils.data.DataLoader(mydataset, batch_size=1, shuffle=True)
    for step, (yl, xd) in enumerate(train_loader):
        xd = xd.reshape(100, 1, 28, 28).float()
        output = net(xd)
        yl = yl.long()
        loss = loss_function(output, yl.squeeze())
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()

        if step % 20 == 0:
            print('step %d-%d' % (step, epo), loss)

torch.save(net, 'divided-net.pkl')

总结

到这里,就很容易搞懂了,为什么大家都喜欢单独把模型的放在一个固定的文件夹中。现在也是理解了。
因为如果要改那个生成数据的py文件的话,重新加载是需要有复制这个类到另外生成数据的py文件下的。

这样就很麻烦了,所以大家就会提出搞一个模型文件夹。然后只需要加载的时候的模型参数就好了。

此外,提高一下epoch的次数,可以提高精度。但是理论上这个是有限的。
接下来只能改模型,改损失函数,改读取数据方式来提高了。

猜你喜欢

转载自blog.csdn.net/a19990412/article/details/84095610