How to improve accuracy in my image model?

I am trying to improve my accuracy in the model. I want to improve the accuracy. The image data is 34400 image samples. I think it is enough to train.
Now I am trying the data augmentation method and adding more hidden layers. And then, the validation accuracy stuck. I have already tried the dropout method and L2 regularization(weight decay). I have already tried the 2/3 and 1/3 training and validation set, different batch sizes, and different learning rates. Adam and SGD optimizer have already tried. It doesn’t work for my model. The training loss does not decrease after the first epochs. Please suggest and advise me. Thanks.

“”"
class Denoising(nn.Module):

def __init__(self, input_features, middle_features, num_conv_layers):
    super(Denoising, self).__init__()
    self.kernel_size = 3
    self.padding = 1
    self.input_features = input_features
    self.num_conv_layers = num_conv_layers
    self.middle_features = middle_features
    if self.input_features == 5:
        self.output_features = 4  # Grayscale image
    else:
        raise Exception('Invalid number of input features')

    layers = [nn.Conv2d(in_channels=self.input_features,
                        out_channels=self.middle_features,
                        kernel_size=self.kernel_size,
                        padding=self.padding,
                        bias=False), nn.ReLU(inplace=False)]
    for _ in range(self.num_conv_layers - 2):
        layers.append(nn.Conv2d(in_channels=self.middle_features,
                                out_channels=self.middle_features,
                                kernel_size=self.kernel_size,
                                padding=self.padding,
                                bias=False))
        layers.append(nn.BatchNorm2d(self.middle_features))
        layers.append(nn.ReLU(inplace=True))
    layers.append(nn.Conv2d(in_channels=self.middle_features,
                            out_channels=self.output_features,
                            kernel_size=self.kernel_size,
                            padding=self.padding,
                            bias=False))
    self.Denoising= nn.Sequential(*layers)

def forward(self, x):
    out = self.Denoising(x)
    return out

“”"
This is the feature map and some parameters.
“”"

def __init__(self, num_input_channels):
    self.num_input_channels = num_input_channels
    if self.num_input_channels == 1:
        # Grayscale image
        self.num_feature_maps = 64  # number of channel
        self.num_conv_layers = 15  # convolution layer
        self.downsampled_channels = 5  # downsampled channel
        self.output_features = 4
    elif self.num_input_channels == 3:
        # RGB image
        self.num_feature_maps = 96
        self.num_conv_layers = 12
        self.downsampled_channels = 15
        self.output_features = 12
    else:
        raise Exception('Invalid number of input features')

    self.intermediate_dncnn = IntermediateDnCNN(
        input_features=self.downsampled_channels,
        middle_features=self.num_feature_maps,
        num_conv_layers=self.num_conv_layers)
    self.upsamplefeatures = UpSampleFeatures()

def forward(self, x, noise_sigma):
    concat_noise_x = functions.concatenate_input_noise_map(
        x.data, noise_sigma.data)
    concat_noise_x = Variable(concat_noise_x)
    h_dncnn = self.intermediate_dncnn(concat_noise_x)
    return pred_noise

“”"
And this is a training model.
“”"
for epoch in range(start_epoch, args.epochs):
# Learning rate value scheduling according to args.milestone
if epoch > args.milestone[1]:
current_lr = args.lr / 1000.
training_params[‘no_orthog’] = True
elif epoch > args.milestone[0]:
current_lr = args.lr / 10.
else:
current_lr = args.lr
# set learning rate in optimizer
for param_group in optimizer.param_groups:
param_group[“lr”] = current_lr
print(‘learning rate %f’ % current_lr)

    # train
    for i, data in enumerate(loader_train, 0):
        # Pre-training step
        model.train()
        model.zero_grad()
        optimizer.zero_grad()

        # inputs: noise and noisy image
        img_train = data
        noise = torch.zeros(img_train.size())
        stdn = np.random.uniform(args.noiseIntL[0], args.noiseIntL[1],
                                 size=noise.size()[0])
        for nx in range(noise.size()[0]):
            sizen = noise[0, :, :, :].size()
            noise[nx, :, :, :] = torch.FloatTensor(sizen).normal_(mean=0, std=stdn[nx])
        imgn_train = img_train + noise  # Create image with AWGN noise

        # # # Create input Variables to cuda
        img_train = img_train.to('cuda')
        stdn_var = Variable(torch.cuda.FloatTensor(stdn))
        # Convert Frequency Domain Images
        imgn_train_fft = mix_data(imgn_train)

        # Evaluate model and optimize it
        out_train = model(imgn_train_fft.to('cuda'), stdn_var.to('cuda'))
        loss = criterion(out_train.to('cuda'), noise.to('cuda')) / (imgn_train_fft.size()[0] * 2)
        loss.backward()
        optimizer.step()

        # Results
        model.eval()
        out_train = torch.clamp(imgn_train_fft.to('cuda') - model(imgn_train_fft.to('cuda'), stdn_var.to('cuda')),
                                0., 1.)
        psnr_train = batch_psnr(out_train, img_train, 1.)

        # Print results
        if training_params['step'] % args.save_every == 0:
            # Apply regularization by orthogonalizing filters
            if not training_params['no_orthog']:
                model.apply(svd_orthogonalization)

            print("[epoch %d][%d/%d] loss: %.4f PSNR_train: %.4f" % \
                  (epoch + 1, i + 1, len(loader_train), loss.item(), psnr_train))
        training_params['step'] += 1
        # The end of each epoch
    model.eval()

    psnrt.append(psnr_train)
    losst.append(loss.item())

    # Validation
    psnr_val = 0
    for valimg in dataset_val:
        img_val = torch.unsqueeze(valimg, 0)
        vnoise = torch.FloatTensor(img_val.size()).normal_(mean=0, std=args.val_noiseL)
        imgn_val = img_val + vnoise
        with torch.no_grad():
            img_val, imgn_val = img_val.to('cuda'), imgn_val.to('cuda')
            sigma_noise = torch.FloatTensor([args.val_noiseL]).to('cuda')
            out_val = torch.clamp(imgn_val - model(imgn_val, sigma_noise), 0., 1.)
            psnr_val += batch_psnr(out_val, img_val, 1.)
    psnr_val /= len(dataset_val)
    print("\n[epoch %d] PSNR_val: %.4f" % (epoch + 1, psnr_val))

    # save model and checkpoint
    training_params['start_epoch'] = epoch + 1

    torch.save(model.state_dict(), os.path.join(args.log_dir, 'net.pth'))

    # save model and checkpoint
    if psnr_val > best_psnr_val:
        best_psnr_val = psnr_val
        torch.save(model.state_dict(), os.path.join(args.log_dir, 'best_model.pth'))

    save_dict = {
        'state_dict': model.state_dict(),
        'optimizer': optimizer.state_dict(),
        'training_params': training_params,
        'args': args
    }

    torch.save(save_dict, os.path.join(args.log_dir, 'ckpt.pth'))
    if epoch % args.save_every_epochs == 0:
        torch.save(save_dict, os.path.join(args.log_dir,
                                           'ckpt_e{}.pth'.format(epoch + 1)))
    del save_dict

“”"

Have you tried skip connections and self attention? That’s a lot of conv layers to pass through, and you may be getting vanishing gradients.

Try reducing the number of conv layers. No more than six. In addition, you can add skip connections, to allow the model to make use of the additional complexity only when necessary, and self attention to help the model filter out some of the kernels.