• transformer模型训练结构解析(加深理解)


    运行项目的一些感受:
    很多时候,一个整体的深度学习项目的程序的执行流程是需要理一理的,往往是多个模块层层包含嵌套,然后执行的顺序也是在多个python功能模块间跳转,有时候在某个程序文件里的短短一行代码(比如self._train_model(training_loader) )背后可能是运行了上百行另一个类下的某个函数的功能代码,主要需要体会模型中层层嵌套,模块化的思维,然后掌握举一反三的能力。

    深度学习里经常使用到的python基础:

    class BaseImputer(BaseModel):
        """Abstract class for all imputation models."""
    
        def __init__(self, device):
            super().__init__(device)
    
        @abstractmethod
        def fit(self, train_X, val_X=None):
            """Train the imputer.
    
            Parameters
            ----------
            train_X : array-like, shape: [n_samples, sequence length (time steps), n_features],
                Time-series data for training, can contain missing values.
            val_X : array-like, optional, shape [n_samples, sequence length (time steps), n_features],
                Time-series data for validating, can contain missing values.
    
            Returns
            -------
            self : object,
                Trained imputer.
            """
            return self   # self代表类的实例对象,
            #代码最后的return self语句表示将训练好的模型对象返回。
            #也就是说,当调用fit方法进行训练后,方法会返回一个已经训练好的BaseImputer对象
            #该对象可以用于后续的预测或其他操作
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    模型的定义
    在下面常见代码中,self.model是所在类BaseNNImputer的一个成员变量,表示一个机器学习模型(例如神经网络模型、回归模型等)的实例对象。

    class BaseNNImputer(BaseNNModel, BaseImputer):
        def __init__(
            self, learning_rate, epochs, patience, batch_size, weight_decay, device
        ):
            super().__init__(
                learning_rate, epochs, patience, batch_size, weight_decay, device
            )
    
        @abstractmethod
        def assemble_input_data(self, data):
            pass
    
        def _train_model(
            self,
            training_loader,#text_emb,
            val_loader=None,
            val_X_intact=None,
            val_indicating_mask=None,
        ):
            self.optimizer = torch.optim.Adam(
                self.model.parameters(), lr=self.lr, weight_decay=self.weight_decay
            )
    
            # each training starts from the very beginning, so reset the loss and model dict here
            self.best_loss = float("inf")
            self.best_model_dict = None
    
            try:
                for epoch in range(self.epochs):
                    self.model.train() #self.model是所在类BaseNNImputer的一个成员变量
                    epoch_train_loss_collector = []
                    ........
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    如何具体定义一个深度学习模型?
    self.model = _TransformerEncoder(
    
                self.n_layers,
    
                self.n_steps,
    
                self.n_features,
    
                self.d_model,
    
                self.d_inner,
    
                self.n_head,
    
                self.d_k,
    
                self.d_v,
    
                self.dropout,
    
                self.ORT_weight,
    
                self.MIT_weight,
    
            )
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    模型的训练

    class Transformer(BaseNNImputer):
    
        def __init__(
    
            self,
    
            n_steps,
    
            n_features,
    
            n_layers,
    
            d_model,
    
            d_inner,
    
            n_head,
    
            d_k,
    
            d_v,
    
            dropout,
    
            ORT_weight=1, 
    
            MIT_weight=1,
    
            learning_rate=3e-4,#3e-4, # 1e-3
    
            epochs=100,
    
            patience=10, 
    
            batch_size=32,
    
            weight_decay=1e-5,#1e-5,  #1e-5 best: 1e-4 
    
            device=None,
    
        ):
    
            super().__init__(
    
                learning_rate, epochs, patience, batch_size, weight_decay, device
    
            )
    
    
    
            self.n_steps = n_steps
    
            self.n_features = n_features
    
            # model hype-parameters
    
            self.n_layers = n_layers
    
            self.d_model = d_model
    
            self.d_inner = d_inner
    
            self.n_head = n_head
    
            self.d_k = d_k
    
            self.d_v = d_v
    
            self.dropout = dropout
    
            self.ORT_weight = ORT_weight
    
            self.MIT_weight = MIT_weight
    
    
    
            self.model = _TransformerEncoder(
    
                self.n_layers,
    
                self.n_steps,
    
                self.n_features,
    
                self.d_model,
    
                self.d_inner,
    
                self.n_head,
    
                self.d_k,
    
                self.d_v,
    
                self.dropout,
    
                self.ORT_weight,
    
                self.MIT_weight,
    
            )
    
            self.model = self.model.to(self.device)
    
            self._print_model_size()
    
    
    
        def fit(self, train_X,x_vectors,text_emb,labels, val_X=None):
    
            train_X = self.check_input(self.n_steps, self.n_features, train_X)
    
            if val_X is not None:
    
                val_X = self.check_input(self.n_steps, self.n_features, val_X)
    
    
    
            training_set = DatasetForMIT(train_X,x_vectors,text_emb,labels)
    
            training_loader = DataLoader(
    
                training_set, batch_size=self.batch_size, shuffle=True
    
            )
    
            if val_X is None:
    
                self._train_model(training_loader)
    
            else:
    
                val_X_intact, val_X, val_X_missing_mask, val_X_indicating_mask = mcar(
    
                    val_X, 0.2
    
                )
    
                val_X = masked_fill(val_X, 1 - val_X_missing_mask, np.nan)
    
                val_set = DatasetForMIT(val_X)
    
                val_loader = DataLoader(val_set, batch_size=self.batch_size, shuffle=False)
    
                self._train_model(
    
                    training_loader, val_loader, val_X_intact, val_X_indicating_mask
    
                ) #这行代码调用了一个名为_train_model的方法,并传入了training_loader作为参数
                #根据代码片段的上下文,可以推测_train_model方法是用来执行模型的训练操作的。
                #它接收一个数据加载器training_loader作为输入,该加载器提供了训练数据的批量样本。
                #具体的训练操作会在_train_model方法的实现中定义。
                
    
    
    
            self.model.load_state_dict(self.best_model_dict)  #这行代码使用load_state_dict方法加载了一个名为best_model_dict的状态字典到self.model中
            #状态字典包含了模型的参数和权重信息,通过加载状态字典,可以将模型的参数设置为保存的最佳模型的参数。
            #这样做的目的是恢复模型到训练过程中表现最好的状态,以便进行后续的评估或推理。
    
            self.model.eval()  # set the model as eval status to freeze it.
            #这行代码将模型的状态设置为评估状态,即执行eval()方法。
            #在评估状态下,模型的行为会发生变化,主要是为了冻结一些层和特定操作,以确保在推理或评估阶段不会影响模型的结果。例如,一些具有随机性的操作(如Dropout)可能会被关闭,以保持一致的输出。
    
            return self #返回self表示将训练好的模型对象作为方法的返回值。
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165

    关于模型的训练和评估方法

    self.model.train()和self.model.eval()是深度学习模型中常用的方法,用于设置模型的训练和评估状态。

    • train()方法:调用train()方法将模型设置为训练状态。在训练状态下,模型会启用一些具有随机性的操作,如Dropout和Batch Normalization的更新。这些随机性操作有助于模型学习更好的泛化能力和防止过拟合。此外,训练状态下还会计算并更新模型的梯度,以进行参数的优化。
    • eval()方法:调用eval()方法将模型设置为评估状态。在评估状态下,模型会禁用一些具有随机性的操作,以确保模型的输出稳定和可重复。例如,Dropout操作会被关闭,Batch Normalization层会使用训练时的统计信息而不是实时计算的统计信息。这样可以保持一致的输出结果,在模型的推理、验证或测试阶段使用。

    需要注意的是,train()和eval()方法通常用于PyTorch等深度学习框架中的模型对象。调用这些方法是为了设置模型的内部状态,以便根据当前的训练或评估阶段执行不同的操作。这样可以确保在不同的阶段下模型的行为一致,提高模型的稳定性和可复现性。

  • 相关阅读:
    基于微信小程序的高校宿舍管理系统设计与实现(亮点:选择宿舍、宿舍评分、宿舍报修)
    [Angular 基础] - 表单:响应式表单
    Java多线程
    java乱码问题一次性解决
    【从零开始学习 SystemVerilog】3.1.3、SystemVerilog 控制流—— for 循环
    HVIDB!人类病毒蛋白互作数据库介绍
    php操作服务器中json文件 进行读写操作用ajax交互
    2024华数杯数学建模竞赛选题建议+初步分析
    基于ffmpeg开发的多音频文件音量均衡程序
    基于JAVA三合国际影城计算机毕业设计源码+数据库+lw文档+系统+部署
  • 原文地址:https://blog.csdn.net/weixin_44064434/article/details/134091564