| import torch |
| import torch.nn as nn |
| import torch.nn.functional as F |
| import numpy as np |
| from torch.nn import Sequential, Linear, ReLU |
| from torch_geometric.nn import GraphConv, GINConv, GATConv, SAGEConv, GPSConv, GINEConv, GATv2Conv |
| from torch_geometric.nn import global_mean_pool, global_add_pool, global_max_pool, GlobalAttention, Set2Set, MulAggregation |
| from torch_geometric.nn import aggr |
| from torch_geometric.nn import GraphNorm |
|
|
|
|
| import torch |
| import torch.nn as nn |
| import torch.nn.functional as F |
|
|
| class SimpleSelfAttention(nn.Module): |
| def __init__(self, embedding_dim, num_heads=1): |
| super(SimpleSelfAttention, self).__init__() |
| self.embedding_dim = embedding_dim |
| self.num_heads = num_heads |
|
|
| |
| self.key_channels = self.embedding_dim |
| self.value_channels = self.embedding_dim |
|
|
| |
| self.query = nn.Linear(embedding_dim, self.key_channels * num_heads) |
| self.key = nn.Linear(embedding_dim, self.key_channels * num_heads) |
| self.value = nn.Linear(embedding_dim, self.value_channels * num_heads) |
|
|
| |
| self.proj = nn.Linear(self.value_channels * num_heads, embedding_dim) |
|
|
| |
| self.scale = nn.Parameter(torch.sqrt(torch.FloatTensor([self.key_channels // num_heads]))) |
|
|
| def forward(self, x1, x2, x3): |
| |
| |
| batch_size = x1.shape[0] |
| x = torch.stack((x1, x2, x3), dim=1) |
|
|
| |
| Q = self.query(x) |
| K = self.key(x) |
| V = self.value(x) |
|
|
| |
| Q = Q.view(batch_size, -1, self.num_heads, self.embedding_dim).transpose(1, 2) |
| K = K.view(batch_size, -1, self.num_heads, self.embedding_dim).transpose(1, 2) |
| V = V.view(batch_size, -1, self.num_heads, self.embedding_dim).transpose(1, 2) |
|
|
| |
| attention_scores = torch.matmul(Q, K.transpose(-2, -1)) / self.scale |
| attention = F.softmax(attention_scores, dim=-1) |
|
|
| |
| x = torch.matmul(attention, V) |
|
|
| |
| x = x.transpose(1, 2).reshape(batch_size, -1, self.num_heads * self.embedding_dim) |
| x = self.proj(x) |
|
|
| |
| out = x.sum(dim=1) |
| return out |
|
|
| def cosine_similarity(x,y): |
| num = x.dot(y.T) |
| denom = np.linalg.norm(x) * np.linalg.norm(y) |
| return num / denom |
|
|
| class LogCoshLoss(nn.Module): |
| def __init__(self): |
| super().__init__() |
|
|
| def forward(self, y_t, y_prime_t): |
| ey_t = y_t - y_prime_t |
| return torch.mean(torch.log(torch.cosh(ey_t + 1e-12))) |
|
|
|
|
| class WeightedMSELoss(nn.Module): |
| def __init__(self): |
| super().__init__() |
|
|
| def forward(self, y, y_t, weights=None): |
| loss = (y - y_t) ** 2 |
| if weights is not None: |
| loss *= weights.expand_as(loss) |
| return torch.mean(loss) |
|
|
|
|
| class GNN(nn.Module): |
| def __init__(self, num_layer, input_dim, emb_dim, JK="last", drop_ratio=0, gnn_type="gin"): |
| super(GNN, self).__init__() |
| self.num_layer = num_layer |
| self.drop_ratio = drop_ratio |
| self.JK = JK |
| |
| self.gnns = torch.nn.ModuleList() |
| for layer in range(num_layer): |
| in_dim = input_dim if layer == 0 else emb_dim |
| if gnn_type == "gin": |
| |
| |
| self.gnns.append(GINConv(nn.Sequential(nn.Linear(in_dim, emb_dim), GraphNorm(emb_dim), nn.ReLU(), |
| nn.Linear(emb_dim, emb_dim), nn.ReLU()))) |
| elif gnn_type == "gps": |
| nn_ = Sequential( |
| Linear(in_dim, emb_dim), |
| ReLU(), |
| Linear(emb_dim, emb_dim), |
| ) |
| conv = GPSConv(emb_dim, GINEConv(nn_), heads=4) |
| self.gnns.append(conv) |
| elif gnn_type == "gcn": |
| self.gnns.append(GraphConv(in_dim, emb_dim)) |
| elif gnn_type == "gat": |
| self.gnns.append(GATConv(in_dim, emb_dim)) |
| elif gnn_type == "gatv2": |
| self.gnns.append(GATv2Conv(in_dim, emb_dim)) |
| elif gnn_type == "graphsage": |
| self.gnns.append(SAGEConv(in_dim, emb_dim)) |
| else: |
| raise ValueError("Invalid GNN type.") |
|
|
| def forward(self, x, edge_index, edge_attr=None): |
| h_list = [x] |
| mut_site = [] |
| for layer in range(self.num_layer): |
|
|
| h = self.gnns[layer](h_list[layer], edge_index, edge_attr) |
| |
| |
| |
| |
| |
| h_list.append(h) |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| |
| |
| |
| |
| if self.JK == "last": |
| node_representation = h_list[-1] |
| elif self.JK == "sum": |
| h_list = [h.unsqueeze_(0) for h in h_list] |
| node_representation = torch.sum(torch.cat(h_list[1:], dim=0), dim=0) |
| |
| return h_list[-1] |
|
|
|
|
| |
| def init_gru_orth(model, gain=1): |
| model.reset_parameters() |
| |
| for _, hh, _, _ in model.all_weights: |
| for i in range(0, hh.size(0), model.hidden_size): |
| torch.nn.init.orthogonal_(hh[i:i + model.hidden_size], gain=gain) |
|
|
|
|
| def init_lstm_orth(model, gain=1): |
| init_gru_orth(model, gain) |
|
|
| |
| for _, _, ih_b, hh_b in model.all_weights: |
| l = len(ih_b) |
| ih_b[l // 4: l // 2].data.fill_(1.0) |
| hh_b[l // 4: l // 2].data.fill_(1.0) |
|
|
|
|
| class GraphGNN(nn.Module): |
| def __init__(self, num_layer, input_dim, emb_dim, out_dim, JK="last", drop_ratio=0.5, graph_pooling="attention", |
| gnn_type="gat", concat_type=None, fds=False, feature_level='both', contrast_curri=False) -> object: |
| super(GraphGNN, self).__init__() |
| self.num_layer = num_layer |
| self.drop_ratio = drop_ratio |
| self.JK = JK |
| self.input_dim = input_dim |
| self.emb_dim = emb_dim |
| self.out_dim = out_dim |
| self.concat_type = concat_type |
| self.feature_level = feature_level |
| self.contrast_curri = contrast_curri |
|
|
| self.fc = nn.Sequential( |
| nn.Linear(self.emb_dim, self.emb_dim), nn.LeakyReLU(0.1), nn.Dropout(p=self.drop_ratio), nn.Linear(self.emb_dim, self.out_dim)) |
|
|
| self.gnn = GNN(num_layer, input_dim, emb_dim, JK, drop_ratio, gnn_type=gnn_type) |
|
|
| if graph_pooling == "sum": |
| self.pool = global_add_pool |
| elif graph_pooling == "mean": |
| self.pool = global_mean_pool |
| elif graph_pooling == "max": |
| self.pool = global_max_pool |
| elif graph_pooling == "mul": |
| self.pool = MulAggregation() |
| elif graph_pooling == "attention": |
| self.pool = GlobalAttention(gate_nn=torch.nn.Linear(emb_dim, 1)) |
| elif graph_pooling == "set2set": |
| self.pool = Set2Set(emb_dim, processing_steps=2) |
| elif graph_pooling == "lstm": |
| self.pool = aggr.LSTMAggregation(emb_dim, emb_dim) |
| else: |
| raise ValueError("Invalid graph pooling type.") |
|
|
| def forward_once(self, x, edge_index, batch): |
| node_representation = self.gnn(x, edge_index) |
| graph_rep = self.pool(node_representation, batch) |
| return graph_rep |
|
|
| def forward(self, data): |
| graph_rep_be = self.forward_once(data.x_s, data.edge_index_s, data.x_s_batch) |
| x = self.fc(graph_rep_be) |
| return x |
|
|
|
|
|
|
| class MMGraph(nn.Module): |
| def __init__(self, num_layer, input_dim, emb_dim, out_dim, JK="last", drop_ratio=0.5, graph_pooling="attention", |
| gnn_type="gat", concat_type=None, fds=False, feature_level='both', contrast_curri=False, max_length=50) -> object: |
| super(MMGraph, self).__init__() |
| self.num_layer = num_layer |
| self.drop_ratio = drop_ratio |
| self.JK = JK |
| self.input_dim = input_dim |
| self.emb_dim = emb_dim |
| self.out_dim = out_dim |
| self.concat_type = concat_type |
| self.feature_level = feature_level |
| self.contrast_curri = contrast_curri |
|
|
| self.graph_pool = nn.Linear(self.emb_dim, 1) |
|
|
| self.fc = nn.Sequential( |
| nn.Linear(self.emb_dim, self.emb_dim), nn.LeakyReLU(0.1), nn.Dropout(p=self.drop_ratio), |
| nn.Linear(self.emb_dim, self.out_dim)) |
|
|
| if fds: |
| self.dir = True |
| else: |
| self.dir = False |
| self.global_encoder = nn.Sequential(nn.Linear(10, self.emb_dim), nn.LeakyReLU(0.1), nn.Dropout(p=self.drop_ratio),) |
| self.seq_encoder = nn.Sequential( |
| nn.Linear(max_length, self.emb_dim), nn.LeakyReLU(0.1), nn.Dropout(p=self.drop_ratio), |
| ) |
| self.gnn = GNN(num_layer, input_dim, emb_dim, JK, drop_ratio, gnn_type=gnn_type) |
|
|
| if graph_pooling == "sum": |
| self.pool = global_add_pool |
| elif graph_pooling == "mean": |
| self.pool = global_mean_pool |
| elif graph_pooling == "max": |
| self.pool = global_max_pool |
| elif graph_pooling == "mul": |
| self.pool = MulAggregation() |
| elif graph_pooling == "attention": |
| self.pool = GlobalAttention(gate_nn=torch.nn.Linear(emb_dim, 1)) |
| elif graph_pooling == "set2set": |
| self.pool = Set2Set(emb_dim, processing_steps=2) |
| elif graph_pooling == "lstm": |
| self.pool = aggr.LSTMAggregation(emb_dim, emb_dim) |
| else: |
| raise ValueError("Invalid graph pooling type.") |
| self.att = SimpleSelfAttention(emb_dim, num_heads=4) |
|
|
| def forward_once(self, x, edge_index, batch): |
| node_representation = self.gnn(x, edge_index) |
| graph_rep = self.pool(node_representation, batch) |
| return graph_rep |
|
|
| def forward(self, data): |
| seq1, global_1 = data.seq, data.global_f |
| device = self.graph_pool.bias.device |
| seq1 = torch.tensor(seq1, dtype=torch.float, device=device) |
| global_1 = torch.tensor(global_1, dtype=torch.float, device=device) |
|
|
| graph_rep_be = self.forward_once(data.x_s, data.edge_index_s, data.x_s_batch) |
| seq1_rep_be = self.seq_encoder(seq1) |
| global1 = self.global_encoder(global_1) |
|
|
| a1 = self.att(graph_rep_be, seq1_rep_be, global1) |
| return self.fc(a1) |
|
|
|
|
|
|
| class PMMGraph(nn.Module): |
| def __init__(self, num_layer, input_dim, emb_dim, out_dim, JK="last", drop_ratio=0.5, graph_pooling="attention", |
| gnn_type="gat", concat_type=None, fds=False, feature_level='both', contrast_curri=False): |
| super(PMMGraph, self).__init__() |
| self.num_layer = num_layer |
| self.drop_ratio = drop_ratio |
| self.JK = JK |
| self.input_dim = input_dim |
| self.emb_dim = emb_dim |
| self.out_dim = out_dim |
| self.concat_type = concat_type |
| self.feature_level = feature_level |
| self.contrast_curri = contrast_curri |
|
|
| |
| self.prompt_token = nn.Parameter(torch.randn(1, 10)) |
|
|
| self.graph_pool = nn.Linear(self.emb_dim, 1) |
|
|
| self.fc = nn.Sequential( |
| nn.Linear(self.emb_dim + 10, self.emb_dim), |
| nn.LeakyReLU(0.1), nn.Dropout(p=self.drop_ratio), |
| nn.Linear(self.emb_dim, self.out_dim)) |
|
|
| self.dir = fds |
| self.global_encoder = nn.Sequential(nn.Linear(10, self.emb_dim), nn.LeakyReLU(0.1), nn.Dropout(p=self.drop_ratio)) |
| self.seq_encoder = nn.Sequential( |
| nn.Linear(30, self.emb_dim), nn.LeakyReLU(0.1), nn.Dropout(p=self.drop_ratio), |
| ) |
| self.gnn = GNN(num_layer, input_dim, emb_dim, JK, drop_ratio, gnn_type=gnn_type) |
|
|
| |
| if graph_pooling in ["sum", "mean", "max", "mul", "attention", "set2set", "lstm"]: |
| pooling_classes = { |
| "sum": global_add_pool, |
| "mean": global_mean_pool, |
| "max": global_max_pool, |
| "mul": aggr.MulAggregation(), |
| "attention": GlobalAttention(gate_nn=torch.nn.Linear(emb_dim, 1)), |
| "set2set": Set2Set(emb_dim, processing_steps=2), |
| "lstm": aggr.LSTMAggregation(emb_dim, emb_dim) |
| } |
| self.pool = pooling_classes[graph_pooling] |
| else: |
| raise ValueError("Invalid graph pooling type.") |
|
|
| self.att = SimpleSelfAttention(emb_dim + 10, num_heads=4) |
|
|
| def forward_once(self, x, edge_index, batch): |
| node_representation = self.gnn(x, edge_index) |
| graph_rep = self.pool(node_representation, batch) |
| |
| graph_rep = torch.cat([graph_rep, self.prompt_token.expand(graph_rep.size(0), -1)], dim=1) |
| return graph_rep |
|
|
| def forward(self, data): |
| seq1 = torch.tensor(np.array(data.seq, dtype=np.float32)).to(device='cuda') |
| global_1 = torch.tensor(np.array(data.global_f, dtype=np.float32)).to(device='cuda') |
|
|
| graph_rep_be = self.forward_once(data.x_s, data.edge_index_s, data.x_s_batch) |
| seq1_rep_be = self.seq_encoder(seq1) |
| global1_rep = self.global_encoder(global_1) |
| |
| seq1_rep_be = torch.cat([seq1_rep_be, self.prompt_token.expand(seq1_rep_be.size(0), -1)], dim=1) |
| global1_rep = torch.cat([global1_rep, self.prompt_token.expand(global1_rep.size(0), -1)], dim=1) |
|
|
| |
| a1 = self.att(graph_rep_be, seq1_rep_be, global1_rep) |
| return self.fc(a1) |
| |
|
|
|
|