运行项目的一些感受:
很多时候,一个整体的深度学习项目的程序的执行流程是需要理一理的,往往是多个模块层层包含嵌套,然后执行的顺序也是在多个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对象
#该对象可以用于后续的预测或其他操作
模型的定义
在下面常见代码中,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 = []
........
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,
)
模型的训练
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表示将训练好的模型对象作为方法的返回值。
关于模型的训练和评估方法
self.model.train()和self.model.eval()是深度学习模型中常用的方法,用于设置模型的训练和评估状态。
需要注意的是,train()和eval()方法通常用于PyTorch等深度学习框架中的模型对象。调用这些方法是为了设置模型的内部状态,以便根据当前的训练或评估阶段执行不同的操作。这样可以确保在不同的阶段下模型的行为一致,提高模型的稳定性和可复现性。