FedR代码的学习--客户机的训练

发布时间 2023-07-20 22:18:44作者: csjywu1
        opt = torch.optim.Adam(self.kge_model.parameters(), lr=self.args.learning_rate)

这段代码用于初始化一个Adam优化器,用于优化知识图谱嵌入(Knowledge Graph Embedding,KGE)模型的参数。

逐步解释:

  1. self.kge_model: 这是指向KGE模型的引用。kge_model是一个自定义的PyTorch模型实例,包含了模型的所有可学习参数(权重)。

  2. self.kge_model.parameters(): 这个函数返回一个迭代器,用于访问kge_model的所有可学习参数。在PyTorch中,模型的参数被存储在torch.nn.Parameter对象中,这个函数允许访问这些参数以便进行优化。

  3. self.args.learning_rate: 这是学习率,是一个超参数,用于控制在优化过程中每次迭代时更新模型参数的步长。学习率通常在训练过程中设置,并决定了在优化过程中模型权重更新的大小。

  4. torch.optim.Adam(...): 这里初始化了一个Adam优化器。Adam(自适应矩估计)是一种自适应学习率的优化算法,它为每个参数计算自适应学习率。它适用于各种优化问题,包括KGE等深度学习任务。

总之,这段代码设置了一个Adam优化器,用于在训练过程中更新知识图谱嵌入(KGE)模型的参数,并且使用指定的学习率self.args.learning_rate进行优化。

        # Create a list of indexes from 0 to (number of entities + number of relations - 1)
        lst_indexes = []
        for i in range(self.ent_embed.shape[0] + self.nrelation):
            lst_indexes.append(i)
        lst_indexes = torch.LongTensor(lst_indexes).to(self.args.gpu)

        # Get entity-relation (ER) vocab from train data indexes
        er_vocab = self.get_er_vocab(train_data_idxs)

        # Create a list of ER vocab pairs
        er_vocab_pairs = []
        for pair in er_vocab.keys():
            er_vocab_pairs.append(pair)

构建embedding vector与词汇的关系。这段代码的作用是创建实体和关系的索引列表,并获取从训练数据索引中构建的实体-关系(ER)词汇表。

让我们逐步解释每一步:

  1. 创建索引列表:lst_indexes 是一个列表,entities加relation总数 (0,1,2...,总数)

  2. 创建 torch.LongTensor 张量:lst_indexes 列表中的索引列表现在被转换为一个 PyTorch 的 torch.LongTensor 张量,并通过 .to(self.args.gpu) 将其放置到指定的 GPU 上(如果可用)。这个张量将用于后续的操作。

  3. 获取实体-关系(ER)词汇表:通过调用 self.get_er_vocab(train_data_idxs),从训练数据索引中获取实体-关系(ER)词汇表。er_vocab 是一个字典,三元组键值对的表格。实体-关系-实体(对应的列表)

  4. 创建 ER 词汇表对列表:er_vocab_pairs 是一个列表,用于存储 ER 词汇表中的实体-关系对。通过一个简单的循环,遍历 er_vocab 字典的键,将每个实体-关系对添加到 er_vocab_pairs 列表中。实体-关系

综上所述,这段代码用于创建实体和关系的索引列表,并获取实体-关系(ER)词汇表对的列表。索引列表 lst_indexes 将用于后续操作,例如在嵌入矩阵中选择对应的实体和关系的嵌入。er_vocab_pairs 列表将包含 ER 词汇表中的所有实体-关系对,用于在训练数据中构建对应的图谱表示。

losses = []
        for it in range(1, self.args.local_epoch + 1):#单个客户机的训练回合
            self.kge_model.train()
            np.random.shuffle(er_vocab_pairs)
            for j in range(0, len(er_vocab_pairs), self.args.batch_size):
                data_batch, targets = self.get_batch(er_vocab, er_vocab_pairs, j)
                opt.zero_grad()
                e1_idx = torch.tensor(data_batch[:, 0]).to(self.args.gpu)
                r_idx = torch.tensor(data_batch[:, 1]).to(self.args.gpu)

                predictions = self.kge_model.forward(e1_idx, r_idx, lst_indexes)
                if self.args.label_smoothing:
                    targets = ((1.0 - self.args.label_smoothing) * targets) + (1.0 / targets.size(1))
                loss = self.kge_model.loss(predictions, targets)
                loss.backward()
                torch.nn.utils.clip_grad_norm_(self.kge_model.parameters(), 0.5)  # prevent the exploding gradient problem
                opt.step()
                losses.append(loss.item())

1.self.kge_model.train(): 设置 KGE 模型为训练模式,这个步骤是为了开启模型中的一些特定操作,例如 Dropout 和 Batch Normalization,在训练过程中启用这些操作有助于模型的泛化能力。
2.假设 len(er_vocab_pairs) 等于100,而 self.args.batch_size 等于10,那么在每次循环中,j 从0开始递增,每次递增的步长为 self.args.batch_size(即10)。循环将遍历以下值:0, 10, 20, 30, 40, 50, 60, 70, 80, 90。
3.opt.zero_grad(): 清空优化器 opt 中之前保存的梯度信息,以便在当前小批量上计算新的梯度。
4.e1_idx 是传递头实体,r_idx 是传递关系,targets是一个矩阵用行表示头实体的index,列表示在relation限制的情况下,联通的尾实体
5.predictions = self.kge_model.forward(e1_idx, r_idx, lst_indexes): 使用 KGE 模型 self.kge_model 对当前小批量进行前向传播,得到预测结果 predictions。

for j in range(0, len(er_vocab_pairs), self.args.batch_size):
    def get_batch(self, er_vocab, er_vocab_pairs, idx):
        batch = er_vocab_pairs[idx:idx + self.args.batch_size]
        targets = np.zeros((len(batch), self.ent_embed.shape[0]))
        for idx, pair in enumerate(batch):
            targets[idx, er_vocab[pair]] = 1.
        targets = torch.FloatTensor(targets)
        return np.array(batch), targets.to(self.args.gpu)

1.batch = er_vocab_pairs[idx:idx + self.args.batch_size]: 从 er_vocab_pairs 中截取一个大小为 self.args.batch_size 的小批量数据,并将其存储在 batch 变量中。

2.targets = np.zeros((len(batch), self.ent_embed.shape[0])): 创建一个大小为 (len(batch), self.ent_embed.shape[0]) 的零数组 targets,其中 len(batch) 表示小批量数据的大小,self.ent_embed.shape[0] 表示实体嵌入矩阵的大小(即实体的数量)。

3.for idx, pair in enumerate(batch): ...: 遍历小批量数据 batch 中的每个实体-关系对 pair。

4.targets[idx, er_vocab[pair]] = 1.: 将目标标签中对应于当前实体-关系对的位置设置为 1,表示这是正样本。er_vocab[pair] 表示当前实体-关系对在 ER 词汇表中的索引,这个索引对应于 targets 数组中的特定位置。

5.targets = torch.FloatTensor(targets): 将 targets 数组转换为 PyTorch 的 torch.FloatTensor 张量。

return np.array(batch), targets.to(self.args.gpu): 将小批量数据 batch 转换为 NumPy 数组,并将目标标签张量 targets 放置在指定的 GPU 上(如果可用)。最后,函数返回这个小批量的数据和目标标签。

    def forward(self, e1_idx, r_idx, lst_indexes):
        X = self.embeddings(lst_indexes)
        #print(1, self.adj.get_device())
        for _layer in range(self.num_layers):
            X = self.lst_gcn[_layer](X, self.adj)
        # change
        # h = X[e1_idx]
        # r = X[r_idx + self.n_entities]
        #for system out
        # print(e1_idx)
        # print(self.n_relations)
        # print(e1_idx + self.n_relations)
        h = X[(e1_idx + self.n_relations).long()]
        r = X[r_idx.long()]
        # h = X[e1_idx + self.n_relations]
        # r = X[r_idx]
        normalized_r = normalization(r)
        hr = vec_vec_wise_multiplication(h, normalized_r) # following the 1-N scoring strategy
        hr = self.hidden_dropout2(hr)
        #change
        #hrt = torch.mm(hr, X[:self.n_entities].t())
        hrt = torch.mm(hr, X[self.n_relations:].t())
        pred = torch.sigmoid(hrt)
        return pred