| 781 | |
| 782 | |
| 783 | class Meta_Graph1(nn.Module): |
| 784 | def __init__(self, hidden_dim, device=torch.cuda.device('cuda')): |
| 785 | super().__init__() |
| 786 | |
| 787 | |
| 788 | self.device = device |
| 789 | self.gcn = GraphConvolution(device=device, |
| 790 | hidden_dim=hidden_dim, |
| 791 | sparse_inputs=False, |
| 792 | act=nn.Tanh(), |
| 793 | bias=True, dropout=0.6).to(device=device) |
| 794 | |
| 795 | torch.cuda.empty_cache() |
| 796 | self.apply(self._init_weights) |
| 797 | |
| 798 | def _init_weights(self, m): |
| 799 | if isinstance(m, nn.Linear): |
| 800 | trunc_normal_(m.weight, std=.02) |
| 801 | if isinstance(m, nn.Linear) and m.bias is not None: |
| 802 | nn.init.constant_(m.bias, 0) |
| 803 | |
| 804 | def forward(self, x, attribute_feat=None, attribute_label=None): |
| 805 | if attribute_label is not None: |
| 806 | x_out = [] |
| 807 | adj = self.create_compositional_graph(attribute_label) |
| 808 | attribute_feat_tensor = torch.stack(attribute_feat, dim=1) |
| 809 | for _x, _att_f, _adj in zip(x, attribute_feat_tensor, adj): |
| 810 | _vertex = torch.cat((_att_f, _x.unsqueeze(0)), dim=0) |
| 811 | after_vertex = self.gcn(_vertex, _adj) |
| 812 | x_out.append(after_vertex[-1]) |
| 813 | x_out = torch.stack(x_out, dim=0) |
| 814 | return x_out |
| 815 | else: |
| 816 | l2norm_head_embedding_list = [] |
| 817 | for _att_f in attribute_feat: |
| 818 | l2norm_head_embedding_list.append(F.normalize(_att_f)) |
| 819 | a = torch.stack(l2norm_head_embedding_list, dim=1) # 64*28*384 |
| 820 | l2_x = F.normalize(x) |
| 821 | b = torch.unsqueeze(l2_x, dim=2) # 64*384*1 |
| 822 | ab = F.softmax(torch.bmm(a, b), dim=1) # 64*28*1 |
| 823 | a_t = torch.transpose(a, dim0=1, dim1=2) # 64*384*28 |
| 824 | a_t_ab = torch.bmm(a_t, ab) |
| 825 | a_t_ab = a_t_ab.squeeze() |
| 826 | return a_t_ab |
| 827 | |
| 828 | def create_compositional_graph(self, attribute_label): |
| 829 | att_num = attribute_label.size(1) |
| 830 | copy_attribute_label = attribute_label.detach() |
| 831 | adj_list = [] |
| 832 | for row in copy_attribute_label: |
| 833 | adj = torch.zeros((att_num + 1, att_num + 1)) |
| 834 | non_zero_positions = torch.nonzero(row) |
| 835 | for p in non_zero_positions: |
| 836 | adj[p, att_num] = 1 |
| 837 | adj[att_num, p] = 1 |
| 838 | adj_list.append(adj) |
| 839 | adj_matrix = torch.stack(adj_list, dim=0).to(device=self.device) |
| 840 | |