MCPcopy Create free account
hub / github.com/DeepGraphLearning/S3F / GVP

Class GVP

s3f/gvp_layer.py:90–153  ·  view source on GitHub ↗

Geometric Vector Perceptron. See manuscript and README.md for more details. :param in_dims: tuple (n_scalar, n_vector) :param out_dims: tuple (n_scalar, n_vector) :param h_dim: intermediate number of vector channels, optional :param activations: tuple of functions (scal

Source from the content-addressed store, hash-verified

88
89
90class GVP(nn.Module):
91 '''
92 Geometric Vector Perceptron. See manuscript and README.md
93 for more details.
94
95 :param in_dims: tuple (n_scalar, n_vector)
96 :param out_dims: tuple (n_scalar, n_vector)
97 :param h_dim: intermediate number of vector channels, optional
98 :param activations: tuple of functions (scalar_act, vector_act)
99 :param vector_gate: whether to use vector gating.
100 (vector_act will be used as sigma^+ in vector gating if `True`)
101 '''
102 def __init__(self, in_dims, out_dims, h_dim=None,
103 activations=(F.relu, torch.sigmoid), vector_gate=False):
104 super().__init__()
105 self.input_dim_s, self.input_dim_v = in_dims
106 self.output_dim_s, self.output_dim_v = out_dims
107 self.vector_gate = vector_gate
108 if self.input_dim_v:
109 self.h_dim = h_dim or max(self.input_dim_v, self.output_dim_v)
110 self.wh = nn.Linear(self.input_dim_v, self.h_dim, bias=False)
111 self.ws = nn.Linear(self.h_dim + self.input_dim_s, self.output_dim_s)
112 if self.output_dim_v:
113 self.wv = nn.Linear(self.h_dim, self.output_dim_v, bias=False)
114 if self.vector_gate: self.wsv = nn.Linear(self.output_dim_s, self.output_dim_v)
115 else:
116 self.ws = nn.Linear(self.input_dim_s, self.output_dim_s)
117
118 self.scalar_act, self.vector_act = activations
119
120 def forward(self, x):
121 '''
122 :param x: tuple (s, V) of `torch.Tensor`,
123 or (if vectors_in is 0), a single `torch.Tensor`
124 :return: tuple (s, V) of `torch.Tensor`,
125 or (if vectors_out is 0), a single `torch.Tensor`
126 '''
127 if self.input_dim_v:
128 s, v = x
129 v = torch.transpose(v, -1, -2)
130 vh = self.wh(v)
131 vn = _norm_no_nan(vh, axis=-2)
132 s = self.ws(torch.cat([s, vn], -1))
133 if self.output_dim_v:
134 v = self.wv(vh)
135 v = torch.transpose(v, -1, -2)
136 if self.vector_gate:
137 if self.vector_act:
138 gate = self.wsv(self.vector_act(s))
139 else:
140 gate = self.wsv(s)
141 v = v * torch.sigmoid(gate).unsqueeze(-1)
142 elif self.vector_act:
143 v = v * self.vector_act(
144 _norm_no_nan(v, axis=-1, keepdims=True))
145 else:
146 s = self.ws(x)
147 if self.output_dim_v:

Callers

nothing calls this directly

Calls

no outgoing calls

Tested by

no test coverage detected