When I classify digital images for identification (sample distribution is not balanced)，why is the validation set highly accurate , and the test set is only 2%, and the weighted loss is about 30% (accuracy is low)?
Is there any other way to improve the accuracy of the test set?
The distribution of my training set is:

all code is here:
# -*- coding: utf-8 -*-
"""
Created on Fri May 10 09:03:47 2019
测试加权损失函数的有效性，matlab代码的复现版
# https://ww2.mathworks.cn/matlabcentral/answers/461076-why-is-the-validation-set-highly-accurate-99-and-the-test-set-is-only-21-and-the-weighted-loss
@author: cuixingxing
"""

import torch
import torch.nn as nn
from torch.utils.data import DataLoader
import torchvision
import torchvision.transforms as transforms
import torch.nn.functional as F
import time
import os
import numpy as np

input_size = (1,28,28)

#%% 网络结构
class testNet(nn.Module):
    def __init__(self,input_size=input_size):
        super(testNet, self).__init__()
        self.conv1 = torch.nn.Sequential(
            torch.nn.Conv2d(1, 32, 3, 1, 1),
            torch.nn.BatchNorm2d(32),
            torch.nn.ReLU(),
            torch.nn.MaxPool2d(2))
        self.conv2 = torch.nn.Sequential(
            torch.nn.Conv2d(32, 64, 3, 1, 1),
            torch.nn.ReLU(),
            torch.nn.MaxPool2d(2))
        self.conv3 = torch.nn.Sequential(
            torch.nn.Conv2d(64, 64, 3, 1, 1),
            torch.nn.ReLU(),
            torch.nn.MaxPool2d(2))
        
        n_size = self._get_linear_inNums(input_size)#根据输入图像大小自动推断fc层输入
        print('linear input number:{:}'.format(n_size))
        self.dense = torch.nn.Sequential(
            torch.nn.Linear(n_size , 10)
            )
        
    def _get_linear_inNums(self,shape):
        batch_x = 1
        temp = torch.rand(batch_x,*shape)
        single_feature = self._forward_features(temp)
        n_size = single_feature.view(batch_x,-1).size(1)
        return n_size
    
    def _forward_features(self,x):
        x = self.conv1(x)
#        x = self.conv2(x)
#        x = self.conv3(x)
        return x

    def forward(self, x):
        out = self._forward_features(x)
#        print('out.size():',out.size())
        res = out.view(out.size(0),-1)
        out = self.dense(res)
        out =  F.softmax(out,dim = 1)
        
        return out


def trainNetWork(train_loader,val_loader,lossFcn,log_file):
    net = testNet()
    net.cuda() #把网络推送到GPU
    net.train()
    
    #print(net)
    optimizer = torch.optim.SGD(net.parameters(),lr= 0.05)
    #torch.cuda.set_device(0)
    #loss_func.cuda() # 损失函数推送到GPU
    times = 0
    train_loss = 0.
    train_corr_all =0
    numSamples = 0
    valFrequencePerIters = 30 # 每30次迭代就验证一次准确度，防止过拟合
    fid = open(log_file,"w")
    for epoch in range(10):
        print('epoch {}'.format(epoch + 1))
        # training-----------------------------
        for batch_x, batch_y in train_loader:
            times+=1
            batch_x  = batch_x.cuda() # 推送到GPU
            batch_y  = batch_y.cuda() # 推送到GPU
            out = net(batch_x)
            loss = lossFcn(out, batch_y)
            train_loss += loss.item()
            pred = torch.max(out, 1)[1]
            train_correct = (pred == batch_y).sum()
            train_corr_all += train_correct.item()
            optimizer.zero_grad()
            loss.backward()
            optimizer.step()
            if times%valFrequencePerIters==0: # val
                numsCorrect = 0
                for val_x,val_y in val_loader:
                    val_x = val_x.cuda()
                    val_y = val_y.cuda()
                    val_out = net(val_x)
                    pred_val = torch.max(val_out,dim=1)[1]
                    numC = (pred_val==val_y).sum()
                    numsCorrect += numC.item()
                strings_val = "val acc:{}".format(numsCorrect/len(val_db))
                print(strings_val)
                fid.write(strings_val+'\n')
                
            numSamples+=len(batch_x)
            strings = "iter:{:d},train average acc:{:.6f},average loss:{:.6f}".format(times,train_corr_all/(numSamples),
                  train_loss / numSamples)
            print(strings)
            fid.write(strings+'\n')
            
                # 保存模型 checkpoint
            if times % 100 == 0: 
                    print('saving ....')
                    timestr = time.strftime('%Y-%m-%d_%H-%M-%S',time.localtime(time.time()))
                    save_file_path = os.path.join('./save/', '{0}_{1}_{2}.pth'.format(times,timestr,epoch))
                    states = {
                        'epoch': epoch + 1,
                        'state_dict': net.state_dict(),
                        'optimizer' : optimizer.state_dict(),
                    }
                    torch.save(states, save_file_path)
    fid.close()
    return net
    
def test_accuracy(net,test_loader):
    """
    测试集准确度
    """
    net.eval()
    numsTestCorr = 0
    for batch_testX,batch_testY in test_loader:
        batch_testX = batch_testX.cuda()
        batch_testY = batch_testY.cuda()
        out = net(batch_testX)
        pred = torch.max(out,dim=1)[1]
        
        numsC= (pred==batch_testY).sum()
        numsTestCorr+=numsC.item()
    return numsTestCorr/len(test_sets)
    
# %% main
if __name__ == '__main__':
    
    train_sets = torchvision.datasets.ImageFolder(r'D:\test_video\digitRec\train',
                                                  transform = transforms.Compose([
                                                          transforms.Grayscale(input_size[0]),
                                                          transforms.Resize(input_size[1:]),
                                                          transforms.ToTensor()]))
    test_sets = torchvision.datasets.ImageFolder(r'D:\test_video\digitRec\test',
                                                  transform = transforms.Compose([
                                                          transforms.Grayscale(input_size[0]),
                                                          transforms.Resize(input_size[1:]),
                                                          transforms.ToTensor()]))
        
    trainNums = int(torch.floor(0.8*torch.Tensor([len(train_sets)])).item()) # 80%的数据用于训练，剩下20%用于验证
    train_db, val_db = torch.utils.data.random_split(train_sets, [trainNums, len(train_sets)-trainNums])
    loss_func = torch.nn.CrossEntropyLoss() # no add weighted CrossEntropyLoss
    
    train_indexs = train_db.indices
    labels = [ str(train_sets.samples[i][1]) for i in train_indexs]
    weights = [1./labels.count(name) for name in train_sets.classes]
    weights = torch.FloatTensor(weights).cuda()
    loss_func_weight = torch.nn.CrossEntropyLoss(weight = weights)  #  add weighted CrossEntropyLoss

    train_loader = DataLoader(train_db,batch_size = 25,shuffle = True) # ,drop_last = True
    val_loader = DataLoader(val_db,batch_size = 25,shuffle = True) # ,drop_last = True
    test_loader = DataLoader(test_sets,batch_size = 25,shuffle = True) # ,drop_last = True
    
    # %%  train
    net = trainNetWork(train_loader,val_loader,loss_func,"trainInfor.txt")
    net_weighted = trainNetWork(train_loader,val_loader,loss_func_weight,"trainInfor_weighted.txt")

    # %% test accuracy
    acc = test_accuracy(net,test_loader)
    strings_test = "no add weighted, all test data acc:{}".format(acc)
    print(strings_test) # low acc ?
    
    # %% after weighted ,test accuracy
    acc = test_accuracy(net_weighted,test_loader)
    strings_test = "after add weighted ,all test data acc:{}".format(acc) # also low acc?
    print(strings_test)

The data and recurring version of the matlab version is here 1.