File size: 2,772 Bytes
ff0fadf
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
import torch
import torch.nn as nn
import torch_geometric.nn as nng
from onescience.modules.mlp.MLP import StandardMLP

class Model(nn.Module):
    """
    GraphSAGE 模型。

    使用 SAGEConv 进行邻居聚合,并结合 MLP 进行特征编码和解码。
    """
    def __init__(self, args, device):
        super(Model, self).__init__()
        self.__name__ = "GraphSAGE"

        self.nb_hidden_layers = args.n_layers
        self.size_hidden_layers = args.n_hidden
        self.bn_bool = True
        self.activation = nn.ReLU()

        self.encoder = StandardMLP(
            input_dim=args.fun_dim + args.space_dim,
            output_dim=args.n_hidden,
            hidden_dims=[args.n_hidden * 2],
            activation=args.act,
            use_bias=True
        )
        
        self.decoder = StandardMLP(
            input_dim=args.n_hidden,
            output_dim=args.out_dim,
            hidden_dims=[args.n_hidden * 2],
            activation=args.act,
            use_bias=True
        )

        # Graph Layers (Keep PyG implementation for consistency)
        self.in_layer = nng.SAGEConv(
            in_channels=args.n_hidden, out_channels=self.size_hidden_layers
        )

        self.hidden_layers = nn.ModuleList()
        for n in range(self.nb_hidden_layers - 1):
            self.hidden_layers.append(
                nng.SAGEConv(
                    in_channels=self.size_hidden_layers,
                    out_channels=self.size_hidden_layers,
                )
            )

        self.out_layer = nng.SAGEConv(
            in_channels=self.size_hidden_layers, out_channels=self.size_hidden_layers
        )

        if self.bn_bool:
            self.bn = nn.ModuleList()
            for n in range(self.nb_hidden_layers):
                self.bn.append(
                    nn.BatchNorm1d(self.size_hidden_layers, track_running_stats=False)
                )

    def forward(self, x, fx, T=None, geo=None):
        if x.dim() == 3:
            x = x.squeeze(0)  # [1, N, C] → [N, C]
        if fx is not None and fx.dim() == 3:
            fx = fx.squeeze(0)  # [1, N, C] → [N, C]
        if geo.dim() == 3:
            edge_index = geo.squeeze(0)  # [1, 2, E] → [2, E]
        else:
            edge_index = geo

        z = torch.cat((x, fx), dim=-1)
        z = self.encoder(z)
        z = self.in_layer(z, edge_index)
        if self.bn_bool:
            z = self.bn[0](z)
        z = self.activation(z)

        for n in range(self.nb_hidden_layers - 1):
            z = self.hidden_layers[n](z, edge_index)
            if self.bn_bool:
                z = self.bn[n + 1](z)
            z = self.activation(z)

        z = self.out_layer(z, edge_index)
        z = self.decoder(z)
        return z.unsqueeze(0)