我的代码如下所示，我想在其中加入inner_loop_optimizers模块，使其在进行元学习的时候能够自适应地调节学习率和模型参数权重
import time
import os
import sys
import argparse
import shutil
import numpy as np
import torch.utils
from tqdm import tqdm
import torch
import torch.nn as nn
import torchvision.transforms as transforms
from torch.optim import lr_scheduler
from tensorboardX import SummaryWriter
from easydict import EasyDict
from network import model_selection_meta as model_selection
from torch.utils.data.sampler import SubsetRandomSampler, RandomSampler
import random
# from network import FNet
from utils.loss import CompactLoss
from torch.utils.data.dataset import Dataset
from torch.nn import functional as F
import copy
from utils.config import *
from utils.roc import cal_metric
from utils import *
import pdb
from PIL import Image

from inner_loop_optimizers import LSLRGradientDescentLearningRule
import higher

def worker_init_fn(x):
    seed = RNG_SEED
    np.random.seed(seed)
    random.seed(seed)
    torch.manual_seed(seed)
    return

def model_forward(image, model, post_function=nn.Sigmoid(),feat = False, params=None):
    """
    Predicts the label of an input image. Preprocesses the input image and
    casts it to cuda if required

    :param image: numpy image
    :param model: torch model with linear layer at the end
    :param post_function: e.g., softmax
    :return: prediction (1 = fake, 0 = real)
    """

    # Model prediction
    output,feature = model(image, params=params)
    output = post_function(output)
    output = output.squeeze()
    
    prediction = (output >= 0.5).float()
    if feat==False:
        return prediction, output
    else:
        return prediction, output,feature

class RegularizerNetwork(nn.Module):
    def __init__(self, embedding_size, num_layers):
        super(RegularizerNetwork, self).__init__()
        self.fc = nn.Sequential(
            nn.Linear(embedding_size, embedding_size),
            nn.ReLU(inplace=True),
            nn.Linear(embedding_size, num_layers * 2)  # 输出 alpha 和 beta
        )
    
    def forward(self, embeddings):
        output = self.fc(embeddings)
        num_layers = output.size(-1) // 2
        alphas = output[:, :num_layers]
        betas = output[:, num_layers:]
        return alphas, betas

def train(model,optimizer,train_dataloader,meta_dataloader,criterion_oc,epoch,epoch_size,device,inner_loop_optimizer, regularizer_network):
    '''
    Train the model with inner loop optimization and meta-learning.

    Args:
        model: The model to train.
        optimizer: The optimizer for the outer loop (meta-optimizer).
        train_dataloader: Dataloader for the training data.
        meta_dataloader: Dataloader for the meta (support) data.
        criterion_oc: The compact loss criterion.
        epoch: Current epoch number.
        epoch_size: Total number of iterations per epoch.
        device: Device to run on ('cuda' or 'cpu').
        inner_loop_optimizer: The inner loop optimizer (e.g., LSLRGradientDescentLearningRule).
        regularizer_network: The regularizer network that generates alpha and beta parameters.
    '''
    model.train()
    regularizer_network.train()
    inner_loop_optimizer.train()

    if meta_dataloader!=None:
        meta_dataloader_iter = iter(meta_dataloader)
    losses = AverageMeter()
    acces = AverageMeter()
    meta_losses = AverageMeter()
    meta_acces = AverageMeter()
    post_function=nn.Sigmoid()
    criterion = torch.nn.BCELoss(reduce = False).to(device)
    # meta_lr = metalr * ((gamma ** int(epoch >= step_size)) * (gamma ** int(epoch >= step_size*2)) * (gamma ** int(epoch >= step_size*3)) * (gamma ** int(epoch >= step_size*4)))         
    num_inner_steps = inner_loop_optimizer.total_num_inner_loop_steps
    # print(f"meta lr = {meta_lr}")  
    print_interval = 10  # 可以根据需要调整打印间隔

    for i, datas in enumerate(train_dataloader):
        images = datas[0].to(device)
        targets = datas[1].float().to(device)

        # 创建模型的初始参数副本，并设置 requires_grad=True
        names_weights_copy = {name: param.clone().detach().to(device).requires_grad_(True)
                              for name, param in model.named_parameters()}

        # 初始化内循环优化器的参数
        inner_loop_optimizer.initialise(names_weights_dict=names_weights_copy)

        # 内循环：多步更新
        for inner_step in range(num_inner_steps):
            # 前向传播
            prediction, output, feature = model_forward(images, model, feat=True, params=names_weights_copy)
            compact_loss = criterion_oc(output, targets)
            cost = criterion(output, targets)
            support_loss = cost + lamda * compact_loss

            # 计算任务嵌入
            task_embedding = feature.mean(dim=0, keepdim=True)

            # 生成 alpha 和 beta
            alphas, betas = regularizer_network(task_embedding)
            alphas = alphas.squeeze()
            betas = betas.squeeze()
            generated_alpha_params = dict(zip(names_weights_copy.keys(), alphas))
            generated_beta_params = dict(zip(names_weights_copy.keys(), betas))

            # 计算损失对参数的梯度
            grads = torch.autograd.grad(support_loss, names_weights_copy.values(), create_graph=True)
            names_grads_wrt_params_dict = dict(zip(names_weights_copy.keys(), grads))

            # 使用内循环优化器更新参数
            names_weights_copy = inner_loop_optimizer.update_params(
                names_weights_dict=names_weights_copy,
                names_grads_wrt_params_dict=names_grads_wrt_params_dict,
                generated_alpha_params=generated_alpha_params,
                generated_beta_params=generated_beta_params,
                num_step=inner_step
            )

        # 使用元集计算元损失
        if meta_dataloader is not None:
            try:
                meta_datas = next(meta_dataloader_iter)
            except StopIteration:
                meta_dataloader_iter = iter(meta_dataloader)
                meta_datas = next(meta_dataloader_iter)
            meta_images = meta_datas[0].to(device)
            meta_targets = meta_datas[1].float().to(device)
        else:
            meta_images = images
            meta_targets = targets

        # 使用更新后的参数进行前向传播
        prediction_meta, output_meta = model_forward(meta_images, model, params=names_weights_copy)
        meta_loss = criterion(output_meta, meta_targets)

        # 计算元梯度并更新外循环参数
        optimizer.zero_grad()
        meta_loss.backward()
        optimizer.step()

        # 计算当前批次的训练损失和准确率
        acc = (prediction == targets).float().mean()
        loss = support_loss.item()
        meta_acc = (prediction_meta == meta_targets).float().mean()

        # 更新损失和准确率的记录
        meta_acces.update(meta_acc.item(), meta_targets.size(0))
        acces.update(acc.item(), targets.size(0))
        losses.update(loss, targets.size(0))
        meta_losses.update(meta_loss.item(), meta_targets.size(0))

        if i % print_interval == 0:
            print(f'{time.ctime()} || Epoch:{epoch} || Iter:{i}/{epoch_size} || '
                  f'Loss:{losses.val:.4f}({losses.avg:.4f}) || '
                  f'Accuracy:{acces.val:.4f}({acces.avg:.4f}) || '
                  f'MetaAccuracy:{meta_acces.val:.4f}({meta_acces.avg:.4f}) || '
                  f'MetaLoss:{meta_losses.val:.4f}({meta_losses.avg:.4f})')

    # 清除计算图，防止内存泄漏
    del names_weights_copy

def test(data_loader, model, device):
    model.eval()
    acces = []
    losses = 0.0
    label_list = []
    output_list = []
    criterion = torch.nn.BCELoss().to(device)
    wrongimg = []
    for i, datas in enumerate(tqdm(data_loader)):
        images = datas[0].to(device)#3,3,224,224
        targets = datas[1].float().to(device)
        
        with torch.no_grad():
            prediction, output = model_forward(images, model)
        label_list.extend(targets.cpu().numpy().tolist())
        output_list.extend(output.cpu().numpy().tolist())

        # acces.append((targets == prediction).cpu().numpy())
        batch_accuracy = (targets == prediction).float().mean().cpu().numpy()
        acces.append(batch_accuracy)
        loss = criterion(output, targets).item()
        losses += loss
    metrics = EasyDict()
    metrics.acc = np.mean(acces)
    eer,TPRs, auc,scaler = cal_metric(label_list,output_list,False)

    metrics.loss = losses / len(data_loader)
    metrics.auc = auc
    metrics.tpr = TPRs
    metrics.eer = eer
    model.train()
    
    return metrics

def updatebest(metrics,best_acc,best_loss,name,model,pnet=None):
    if metrics.acc>best_acc:
        best_acc = metrics.acc
        if model!=None:
            save_checkpoint(model.state_dict(), fpath=f'{save_dir}/{model_name}_best{name}acc.pth')
        if pnet!=None:
            save_checkpoint(pnet.state_dict(), fpath=f'{save_dir}/{model_name}_pnet_best{name}acc.pth')
        print(f'best_{name}_acc:{best_acc:.5f} (updated)', end=' ')
    else:
        print(f'best_{name}_acc:{best_acc:.5f} ')

    if metrics.loss<best_loss:
        best_loss = metrics.loss
        if model!=None:
            save_checkpoint(model.state_dict(), fpath=f'{save_dir}/{model_name}_best{name}loss.pth')
        if pnet!=None:
            save_checkpoint(pnet.state_dict(), fpath=f'{save_dir}/{model_name}_pnet_best{name}loss.pth')
        print(f'best_{name}_loss:{best_loss:.5f} (updated)')
    else:
        print(f'best_{name}_loss:{best_loss:.5f} ')

    return best_acc,best_loss

class FFDIDataset(Dataset):
    def __init__(self, img_path, img_label, transform=None):
        self.img_path = img_path
        self.img_label = img_label
        
        if transform is not None:
            self.transform = transform
        else:
            self.transform = None
    
    def __getitem__(self, index):
        img = Image.open(self.img_path[index]).convert('RGB')
        
        if self.transform is not None:
            img = self.transform(img)
        
        return img, torch.from_numpy(np.array(self.img_label[index]))
    
    def __len__(self):
        return len(self.img_path)

def main():
    if os.path.exists(save_dir):
        shutil.rmtree(save_dir)
    print(f'save dir :{save_dir}')
    sys.stdout = Logger(os.path.join(save_dir, 'train.log'))

    device = 'cuda' if torch.cuda.is_available else 'cpu'

    model = model_selection(model_name=model_name, num_classes=1)

    # fnet = FNet(model.num_ftrs).to(device)


    if model_path is not None:    
        state_dict = torch.load(model_path)
        model.load_state_dict(state_dict)
        print(f'resume model from {model_path}')
    else:
        print('No model found, initializing random model.')
    if fnet_path is not None:    
        state_dict = torch.load(fnet_path)
        # fnet.load_state_dict(state_dict)
        print(f'resume model from {fnet_path}')
    else:
        print('No fnet_model found, initializing random model.')

    
    model = model.to(device)
    if parallel:
        model = nn.DataParallel(model)
    # 初始化正则化器网络
    embedding_size = model.module.num_ftrs if parallel else model.num_ftrs
    num_layers = len(list(model.named_parameters()))
    # 初始化内循环优化器
    init_inner_loop_learning_rate = 1e-3  
    init_weight_decay = 1e-4  
    num_inner_steps = 5
    inner_loop_optimizer = LSLRGradientDescentLearningRule(
        device=device,
        total_num_inner_loop_steps=num_inner_steps,
        use_learnable_learning_rates=True,
        use_learnable_weight_decay=True,
        alfa=True,
        random_init=False,
        init_learning_rate=init_inner_loop_learning_rate,
        init_weight_decay=init_weight_decay
    )
    regularizer_network = RegularizerNetwork(embedding_size, num_layers).to(device)
    # 将正则化器网络和内循环优化器的参数添加到优化器中
    optimizer = torch.optim.Adam(
        list(model.parameters()) + list(regularizer_network.parameters()) + list(inner_loop_optimizer.parameters()),
        lr=learning_rate, betas=(beta1, beta2)
    )

    scheduler = lr_scheduler.StepLR(optimizer, step_size=step_size, gamma=gamma)

    criterion = torch.nn.BCELoss().to(device)
    criterion_oc = CompactLoss().to(device)



    train_label = pd.read_csv('/root/autodl-tmp/FaceForensics++/c23/train.txt', sep=' ', header=None, names=['img_name', 'target'])
    val_label = pd.read_csv('/root/autodl-tmp/FaceForensics++/c23/val.txt', sep=' ', header=None, names=['img_name', 'target'])
    train_label['path'] = train_label['img_name']
    val_label['path'] = val_label['img_name']
    
    support_label = pd.read_csv('/root/autodl-tmp/Celeb-DF-v2/test.txt', sep=' ', header=None, names=['img_name', 'target'])
    support_label['path'] = support_label['img_name']
    FFval_dataset = FFDIDataset(val_label['path'], val_label['target'], 
            transforms.Compose([
                        transforms.Resize((224, 224)),
                        transforms.ToTensor(),
                        transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
                        ])
            )

    FF_test_dataloader = torch.utils.data.DataLoader(FFval_dataset, batch_size=batch_size, shuffle=False, num_workers=4)


    model.train()
    
    best_acc = 0.
    best_loss = 1000.

    for epoch in range(epochs):
        '''
        random shuffile all the source domain and split it into training domain and meta domain
        '''
        # copydatalist = copy.deepcopy(datasetlist)
        # random.seed(epoch)
        # random.shuffle(copydatalist)
        # meta_dataset = copydatalist[2].cat(copydatalist[2],randomseed = epoch)

        # copydatalist[0].set_meta_type(copydatalist[2].type)
        # copydatalist[1].set_meta_type(copydatalist[2].type)

        # train_dataset = copydatalist[0].cat(copydatalist[1])
        sampled_data = train_label.sample(n=10000).reset_index(drop=True)
        support_data = support_label.sample(n=16).reset_index(drop=True)
        # train_dataset = FFDIDataset(train_label['path'], train_label['target'],     
        train_dataset = FFDIDataset(sampled_data['path'], sampled_data['target'],        
            transforms.Compose([
                        transforms.Resize((224, 224)),
                        transforms.ToTensor(),
                        transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
                        ])
        )
        support_dataset = FFDIDataset(support_data['path'], support_label['target'], 
            transforms.Compose([
                        transforms.Resize((224, 224)),
                        transforms.ToTensor(),
                        transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
                        ])
            )
        epoch_size = len(train_dataset) //batch_size
        # print(f"train dataset is:{copydatalist[0].type},{copydatalist[1].type},meta dataset is:{meta_dataset.type}")
        train_dataloader = torch.utils.data.DataLoader(train_dataset, batch_size=batch_size, shuffle=True, num_workers=4,worker_init_fn=worker_init_fn)
        support_dataloader = torch.utils.data.DataLoader(support_dataset, batch_size=batch_size, shuffle=True, num_workers=4)
        train(model, optimizer, train_dataloader, support_dataloader, criterion_oc,epoch, epoch_size,device, inner_loop_optimizer, regularizer_network)

        scheduler.step()
        # scheduler_fnet.step()

        if (epoch + 1) % test_interval == 0:
            '''
            Testing model on serval test-set.
            '''
            FF_metrics = test(FF_test_dataloader, model, device)
            metrics_list = [FF_metrics]
            avg_metrics = EasyDict()
            all_avg_metrics = EasyDict()
            avg_metrics.acc = (FF_metrics.acc)
            avg_metrics.loss = (FF_metrics.loss)
            avg_metrics.auc = (FF_metrics.auc)
            avg_metrics.eer = (FF_metrics.eer)

            print(f"avg acc:{avg_metrics.acc:.3f},loss:{avg_metrics.loss:.3f},auc:{avg_metrics.auc:.3f},eer:{avg_metrics.eer:.3f}")
            best_acc,best_loss = updatebest(avg_metrics,best_acc,best_loss,"avg",model)

            save_checkpoint(model.state_dict(), fpath=f'{save_dir}/{model_name}_lastepoch.pth')
            # save_checkpoint(fnet.state_dict(), fpath=f'{save_dir}/{model_name}_pnet_lastepoch.pth')
            
    print(f'save dir :{save_dir} done!!!')

if __name__ == '__main__':
    if DETERMINSTIC:
        np.random.seed(RNG_SEED)         
        torch.manual_seed(RNG_SEED)
        torch.cuda.manual_seed(RNG_SEED)           
        torch.cuda.manual_seed_all(RNG_SEED)         
        random.seed(RNG_SEED)         
        torch.backends.cudnn.benchmark = False         
        torch.backends.cudnn.deterministic = True         
        torch.backends.cudnn.enabled = True   
    main()
其中inner_loop_optimizers如下所示import logging
import os
from collections import OrderedDict

import numpy as np
import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim

class LSLRGradientDescentLearningRule(nn.Module):
    """Simple (stochastic) gradient descent learning rule.
    For a scalar error function `E(p[0], p_[1] ... )` of some set of
    potentially multidimensional parameters this attempts to find a local
    minimum of the loss function by applying updates to each parameter of the
    form
        p[i] := p[i] - learning_rate * dE/dp[i]
    With `learning_rate` a positive scaling parameter.
    The error function used in successive applications of these updates may be
    a stochastic estimator of the true error function (e.g. when the error with
    respect to only a subset of data-points is calculated) in which case this
    will correspond to a stochastic gradient descent learning rule.
    """

    def __init__(self, device, total_num_inner_loop_steps, use_learnable_learning_rates, use_learnable_weight_decay, alfa, random_init, init_learning_rate=1e-3, init_weight_decay=5e-4):
        """Creates a new learning rule object.
        Args:
            init_learning_rate: A postive scalar to scale gradient updates to the
                parameters by. This needs to be carefully set - if too large
                the learning dynamic will be unstable and may diverge, while
                if set too small learning will proceed very slowly.
        """
        super(LSLRGradientDescentLearningRule, self).__init__()
        print(init_learning_rate)
        assert init_learning_rate > 0., 'learning_rate should be positive.'

        self.alfa = alfa
        self.random_init = random_init

        self.init_lr_val = init_learning_rate
        self.init_wd_val = init_weight_decay

        self.init_pspl_weight_decay = torch.ones(1)
        self.init_pspl_weight_decay.to(device)

        self.init_learning_rate = torch.ones(1) * init_learning_rate
        self.init_learning_rate.to(device)
        self.total_num_inner_loop_steps = total_num_inner_loop_steps
        self.use_learnable_learning_rates = use_learnable_learning_rates
        self.use_learnable_weight_decay = use_learnable_weight_decay
        self.init_weight_decay = torch.ones(1) * init_weight_decay
        self.init_bias_decay = torch.ones(1) 

    def initialise(self, names_weights_dict):
        if self.alfa:
            if self.random_init:
                self.names_beta_dict_per_param = nn.ParameterDict()

            self.names_alpha_dict = nn.ParameterDict()
            self.names_beta_dict = nn.ParameterDict()

            for idx, (key, param) in enumerate(names_weights_dict.items()):

                if self.random_init:
                # per-param weight decay for random init
                    self.names_beta_dict_per_param[key.replace(".", "-")] = nn.Parameter(
                        data=torch.ones(param.shape) * self.init_weight_decay * self.init_learning_rate,
                        requires_grad=self.use_learnable_learning_rates)

                    self.names_beta_dict[key.replace(".", "-")] = nn.Parameter(
                        data=torch.ones(self.total_num_inner_loop_steps + 1),
                        requires_grad=self.use_learnable_learning_rates)
                else:
                    # per-step per-layer meta-learnable weight decay bias term (for more stable training and better performance by 2~3%)
                    self.names_beta_dict[key.replace(".", "-")] = nn.Parameter(
                        data=torch.ones(self.total_num_inner_loop_steps + 1) * self.init_weight_decay * self.init_learning_rate,
                        requires_grad=self.use_learnable_learning_rates)

                # per-step per-layer meta-learnable learning rate bias term (for more stable training and better performance by 2~3%)
                self.names_alpha_dict[key.replace(".", "-")] = nn.Parameter(
                    data=torch.ones(self.total_num_inner_loop_steps + 1) * self.init_learning_rate,
                    requires_grad=self.use_learnable_learning_rates)
 
    def update_params(self, names_weights_dict, names_grads_wrt_params_dict, generated_alpha_params, generated_beta_params, num_step, tau=0.1):
        """Applies a single gradient descent update to all parameters.
        All parameter updates are performed using in-place operations and so
        nothing is returned.
        Args:
            grads_wrt_params: A list of gradients of the scalar loss function
                with respect to each of the parameters passed to `initialise`
                previously, with this list expected to be in the same order.
        """
        updated_names_weights_dict = dict()

        for key in names_grads_wrt_params_dict.keys():
            # beta = (1 - generated_beta * meta-learned per-step-per-layer bias term)
            # alpha = generated_alpha * meta-learned per-step-per-layer bias term)
            if self.alfa:
                if self.random_init:
                    updated_names_weights_dict[key] = (1 - self.names_beta_dict_per_param[key.replace(".", "-")] * generated_beta_params[key] * self.names_beta_dict[key.replace(".", "-")][num_step]) * names_weights_dict[key] - generated_alpha_params[key] * self.names_alpha_dict[key.replace(".", "-")][num_step] * names_grads_wrt_params_dict[key]
                else:
                    updated_names_weights_dict[key] = (1 - generated_beta_params[key] * self.names_beta_dict[key.replace(".", "-")][num_step]) * names_weights_dict[key] - generated_alpha_params[key] * self.names_alpha_dict[key.replace(".", "-")][num_step] * names_grads_wrt_params_dict[key]
            else:
                updated_names_weights_dict[key] = names_weights_dict[key] - self.init_lr_val * names_grads_wrt_params_dict[key]

        return updated_names_weights_dict

我使用的骨干网络是efficientnet_b4，帮我分析一下还有哪里需要进行更改，以完成我所需要的功能