aboutsummaryrefslogtreecommitdiff
path: root/model/nn/percept_gate_controller.py
blob: a548c20f8a2061c053d945ac8f23c1d6c31d2a8c (plain) (blame)
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
import torch.nn as nn
import torch as th
from model.utils.nn_utils import LambdaModule
from einops import rearrange, repeat, reduce
from model.nn.eprop_gate_l0rd import ReTanh

class PerceptGateController(nn.Module):
    def __init__(
        self,
        num_inputs: int,
        num_hidden: list,
        bias: bool,
        num_objects: int,
        gate_noise_level: float = 0.1,
        reg_lambda: float = 0.000005
    ):
        super(PerceptGateController, self).__init__()

        self.to_batch  = LambdaModule(lambda x: rearrange(x, 'b (o c) -> (b o) c', o=num_objects))
        self.to_shared = LambdaModule(lambda x: rearrange(x, '(b o) c -> b o c', o=num_objects))

        self.layers = nn.Sequential(
            nn.Linear(num_inputs, num_hidden[0], bias = bias),
            nn.Tanh(),
            nn.Linear(num_hidden[0], num_hidden[1], bias = bias),
            nn.Tanh(),
            nn.Linear(num_hidden[1], 2, bias = bias)
        )
        self.output_function = ReTanh(reg_lambda)
        self.register_buffer("noise", th.tensor(gate_noise_level), persistent=False)
        self.init_weights()

    def init_weights(self):
        for layer in self.layers:
            if isinstance(layer, nn.Linear):
                nn.init.xavier_uniform(layer.weight)
                layer.bias.data.fill_(3.00)

    def forward(self, position_cur, gestalt_cur, priority_cur, slots_occlusionfactor_cur, position_last, gestalt_last, priority_last, slots_occlusionfactor_last, position_last2, evaluate=False):

        position_cur = self.to_batch(position_cur)
        gestalt_cur  = self.to_batch(gestalt_cur)
        priority_cur = self.to_batch(priority_cur)
        position_last = self.to_batch(position_last)
        gestalt_last  = self.to_batch(gestalt_last)
        priority_last = self.to_batch(priority_last)
        slots_occlusionfactor_cur = self.to_batch(slots_occlusionfactor_cur).detach()
        slots_occlusionfactor_last = self.to_batch(slots_occlusionfactor_last).detach()
        position_last2 = self.to_batch(position_last2).detach()

        input  = th.cat((position_cur, gestalt_cur, priority_cur, slots_occlusionfactor_cur, position_last, gestalt_last, priority_last, slots_occlusionfactor_last, position_last2), dim=1)
        output = self.layers(input)
        if evaluate:
            output = self.output_function(output)
        else:
            noise  = th.normal(mean=0, std=self.noise, size=output.shape, device=output.device)    
            output = self.output_function(output + noise)

        return self.to_shared(output)