I set up a simple CNN network, trained through the MNIST data set.But accuracy varies from 99 percent to 10 percent.I don’t know what went wrong.
deepconvnet.py
import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.utils.data as Data
import torch.optim as optim
import numpy as np
import matplotlib.pyplot as plt
import os
from torchvision import datasets, transforms


class DeepConvNet(nn.Module):
    def __init__(self, train_set_x, train_set_y, test_set_x, test_set_y,
                DROPOUT = 0.5, BATH_SIZE = 1000, EPOCH = 20, LEARNING_RATE = 0.01):
        super(DeepConvNet, self).__init__()
        self.conv = nn.Sequential(
            # nn.Conv2d(in_channels = 1, out_channels = 16, kernel_size = 3, padding = 1, padding_mode = 'zeros'),
            nn.Conv2d(in_channels = 1, out_channels = 16, kernel_size = 3, padding = 1),
            nn.ReLU(),
            # nn.Conv2d(in_channels = 16, out_channels = 16, kernel_size = 3, padding = 1, padding_mode = 'zeros'),
            nn.Conv2d(in_channels = 16, out_channels = 16, kernel_size = 3, padding = 1),
            nn.ReLU(),
            nn.MaxPool2d(kernel_size = 2, stride = 2),
            nn.Conv2d(in_channels = 16, out_channels = 32, kernel_size = 3, padding = 1, padding_mode = 'zeros'),
            nn.ReLU(),
            nn.Conv2d(in_channels = 32, out_channels = 32, kernel_size = 3, padding = 2, padding_mode = 'zeros'),
            nn.ReLU(),
            nn.MaxPool2d(kernel_size = 2, stride = 2),
            nn.Conv2d(in_channels = 32, out_channels = 64, kernel_size = 3, padding = 1, padding_mode = 'zeros'),
            nn.ReLU(),
            nn.Conv2d(in_channels = 64, out_channels = 64, kernel_size = 3, padding = 1, padding_mode = 'zeros'),
            nn.ReLU(),
            nn.MaxPool2d(kernel_size = 2, stride = 2),
        )
        for m in self.conv:
            if(isinstance(m, nn.Conv2d)):
                nn.init.kaiming_normal_(m.weight, mode='fan_in')
        self.fc = nn.Sequential(
            nn.Linear(in_features = 1024, out_features = 50),
            nn.ReLU(),
            # nn.Dropout(DROPOUT),
            nn.Linear(in_features = 50, out_features = 10),
            nn.ReLU(),
            # nn.Dropout(DROPOUT)
        )
        for m in self.conv:
            if(isinstance(m, nn.Linear)):
                nn.init.kaiming_normal_(m.weight, mode='fan_in')
                m.parameters = m.parameters / 10
        self.train_dataset = Data.TensorDataset(train_set_x, train_set_y)
        self.test_dataset = Data.TensorDataset(test_set_x, test_set_y)
        self.BATH_SIZE = BATH_SIZE
        self.loader_train = Data.DataLoader(
            dataset = self.train_dataset,
            batch_size = BATH_SIZE,
            shuffle = True,
        )
        self.loader_test = Data.DataLoader(
            dataset = self.test_dataset,
            batch_size = len(test_set_y),
            shuffle = True
        )
        self.optimizer = optim.Adam(self.parameters(), lr = LEARNING_RATE, betas = (0.9, 0.999), eps = 1e-8)
        # self.optimizer = optim.SGD(self.parameters(), lr = LEARNING_RATE)
        # self.optimizer = optim.RMSprop(self.parameters(),lr = LEARNING_RATE)
        self.EPOCH = EPOCH

    def forward(self, x):
        conv_out = self.conv(x)
        conv_out = conv_out.view(conv_out.size()[0], -1)
        out = self.fc(conv_out)
        return out
        
    def loss(self, pre_y, label_y):
        # loss = nn.CrossEntropyLoss()
        # Loss = loss(pre_y, label_y)
        # return Loss
        loss = F.log_softmax(pre_y)
        loss = -torch.mean((loss[range(pre_y.shape[0]), label_y]))
        return loss
        
    def train_net(self):
        for eporch in range(self.EPOCH):
            running_loss = 0.0
            for i, data in enumerate(self.loader_train):
                x, y = data
                # print(x.view(1000,-1)[1])
                # print(y.shape)
                # print(i)
                # img = np.transpose(np.array(x[0].numpy()), (1, 2, 0))
                # print(img.shape)
                # plt.imshow(img)
                # plt.show()
                
                self.optimizer.zero_grad()
                # params = list(self.named_parameters())
                # print(params)
                # (name, param) = params[0]
                # print(name)
                # print(param.shape)
                # print(y)
                # os.system("pause")
                outputs = self.forward(x)
                # print(outputs.shape)
                Loss = self.loss(outputs, y)
                Loss.backward()
                # print(param.grad)
                self.optimizer.step()
                running_loss += Loss.item()
                # if (i+1) % self.BATH_SIZE == 0:
                prediction = torch.argmax(outputs, 1)
                correct = (prediction == y).sum().float()
                total = float(len(prediction))
                acc = correct / total
                print(acc)
                print('Epoch: %d, iter: %5d, Loss: %3f Acc: %3f' %(eporch+1, (i+1)*self.BATH_SIZE, running_loss, acc))
                # print(outputs.shape)
                # print(y)


                running_loss = 0.0
                
        torch.save(self.state_dict(),'parameters.pth')            
        print('Finish Train')

    def test(self):
        self.eval()
        for data in self.loader_test:
            # print(data)
            x, y = data
        outputs = self.forward(x)
        # print(outputs)
        Loss = self.loss(outputs, y)
        prediction = torch.argmax(outputs, 1)
        # print(prediction)
        correct = (prediction == y).sum().float()
        total = float(len(prediction))
        acc = correct / total
        print("On test set, the loss is %.3f, Acc is %.3f" %(Loss, acc))            

traindeepnet.py
import sys, os
sys.path.append(os.pardir)
import numpy as np
import matplotlib.pyplot as plt
from mnist import load_mnist
import torch
from deepconvnet import DeepConvNet

(x_train,t_train), (x_test,t_test) = load_mnist(flatten=False)

x_train = torch.Tensor(x_train)
t_train = torch.Tensor(t_train).long()
# x_train = torch.Tensor(x_train)[:10000]
# t_train = torch.Tensor(t_train).long()[:10000]
x_test = torch.Tensor(x_test)
t_test = torch.Tensor(t_test).long()


print(x_train.shape)
print(t_train.shape)                                            


Net = DeepConvNet(x_train, t_train, x_test, t_test)
Net.test()
Net.train_net()
Net.test()

mnist.py
# coding: utf-8
try:
    import urllib.request
except ImportError:
    raise ImportError('You should use Python 3.x')
import os.path
import gzip
import pickle
import os
import numpy as np


url_base = 'http://yann.lecun.com/exdb/mnist/'
key_file = {
    'train_img':'train-images-idx3-ubyte.gz',
    'train_label':'train-labels-idx1-ubyte.gz',
    'test_img':'t10k-images-idx3-ubyte.gz',
    'test_label':'t10k-labels-idx1-ubyte.gz'
}

dataset_dir = os.path.dirname(os.path.abspath(__file__))
save_file = dataset_dir + "/mnist.pkl"

train_num = 60000
test_num = 10000
img_dim = (1, 28, 28)
img_size = 784


def _download(file_name):
    file_path = dataset_dir + "/" + file_name
    
    if os.path.exists(file_path):
        return

    print("Downloading " + file_name + " ... ")
    urllib.request.urlretrieve(url_base + file_name, file_path)
    print("Done")
    
def download_mnist():
    for v in key_file.values():
       _download(v)
        
def _load_label(file_name):
    file_path = dataset_dir + "/" + file_name
    
    print("Converting " + file_name + " to NumPy Array ...")
    with gzip.open(file_path, 'rb') as f:
            labels = np.frombuffer(f.read(), np.uint8, offset=8)
    print("Done")
    
    return labels

def _load_img(file_name):
    file_path = dataset_dir + "/" + file_name
    
    print("Converting " + file_name + " to NumPy Array ...")    
    with gzip.open(file_path, 'rb') as f:
            data = np.frombuffer(f.read(), np.uint8, offset=16)
    data = data.reshape(-1, img_size)
    print("Done")
    
    return data
    
def _convert_numpy():
    dataset = {}
    dataset['train_img'] =  _load_img(key_file['train_img'])
    dataset['train_label'] = _load_label(key_file['train_label'])    
    dataset['test_img'] = _load_img(key_file['test_img'])
    dataset['test_label'] = _load_label(key_file['test_label'])
    
    return dataset

def init_mnist():
    download_mnist()
    dataset = _convert_numpy()
    print("Creating pickle file ...")
    with open(save_file, 'wb') as f:
        pickle.dump(dataset, f, -1)
    print("Done!")

def _change_one_hot_label(X):
    T = np.zeros((X.size, 10))
    for idx, row in enumerate(T):
        row[X[idx]] = 1
        
    return T
    

def load_mnist(normalize=True, flatten=True, one_hot_label=False):
    """读入MNIST数据集
    
    Parameters
    ----------
    normalize : 将图像的像素值正规化为0.0~1.0
    one_hot_label : 
        one_hot_label为True的情况下，标签作为one-hot数组返回
        one-hot数组是指[0,0,1,0,0,0,0,0,0,0]这样的数组
    flatten : 是否将图像展开为一维数组
    
    Returns
    -------
    (训练图像, 训练标签), (测试图像, 测试标签)
    """
    if not os.path.exists(save_file):
        init_mnist()
        
    with open(save_file, 'rb') as f:
        dataset = pickle.load(f)
    
    if normalize:
        for key in ('train_img', 'test_img'):
            dataset[key] = dataset[key].astype(np.float32)
            dataset[key] /= 255.0
            
    if one_hot_label:
        dataset['train_label'] = _change_one_hot_label(dataset['train_label'])
        dataset['test_label'] = _change_one_hot_label(dataset['test_label'])
    
    if not flatten:
         for key in ('train_img', 'test_img'):
            dataset[key] = dataset[key].reshape(-1, 1, 28, 28)

    return (dataset['train_img'], dataset['train_label']), (dataset['test_img'], dataset['test_label']) 


if __name__ == '__main__':
    init_mnist()