EXAMPLES.md
July 3, 2018 ยท View on GitHub
Examples
The following examples can be found in PytorchRouting.Examples.Models, and can be tested on CIFAR100-MTL and MNIST-MTL with PytorchRouting.Examples.run_experiment.py.
Per-Task Agents
The most architectures introduced in the paper assign one agent exclusively to each task. Using Pytorch-Routing, these can be implemented as follows (here, using a WPL MARL agent):
class RoutedAllFC(nn.Module):
def __init__(self, in_channels, convnet_out_size, out_dim, num_modules, num_agents):
self.convolutions = nn.Sequential(
SimpleConvNetBlock(in_channels, 32, 3),
SimpleConvNetBlock(32, 32, 3),
SimpleConvNetBlock(32, 32, 3),
SimpleConvNetBlock(32, 32, 3),
nn.BatchNorm2d(32),
Flatten()
)
self._loss_func = Loss(torch.nn.MSELoss(), CorrectClassifiedReward(), discounting=1.)
self._initialization = Initialization()
self._per_task_assignment = PerTaskAssignment()
self._decision_1 = WPL(
num_modules, convnet_out_size, num_agents=num_agents, policy_storage_type='tabular',
additional_reward_func=CollaborationReward(reward_ratio=0.3, num_actions=num_modules))
self._decision_2 = WPL(
num_modules, convnet_out_size, num_agents=num_agents, policy_storage_type='tabular',
additional_reward_func=CollaborationReward(reward_ratio=0.3, num_actions=num_modules))
self._decision_3 = WPL(
num_modules, convnet_out_size, num_agents=num_agents, policy_storage_type='tabular',
additional_reward_func=CollaborationReward(reward_ratio=0.3, num_actions=num_modules))
self._selection_1 = Selection(*[LinearWithRelu(convnet_out_size, 48) for _ in range(num_modules)])
self._selection_2 = Selection(*[LinearWithRelu(48, 48) for _ in range(num_modules)])
self._selection_3 = Selection(*[nn.Linear(48, out_dim) for _ in range(num_modules)])
# self._selection_f = Selection(*[nn.Linear(48, out_dim) for _ in range(num_modules)])
def forward(self, x, tasks):
y = self.convolutions(x)
y, meta, actions = self._initialization(y, tasks=tasks)
y, meta, task_actions = self._per_task_assignment(y, meta, actions)
y, meta, routing_actions_1 = self._decision_1(y, meta, task_actions)
y, meta, _ = self._selection_1(y, meta, routing_actions_1)
y, meta, routing_actions_2 = self._decision_2(y, meta, task_actions)
y, meta, _ = self._selection_2(y, meta, routing_actions_2)
y, meta, routing_actions_3 = self._decision_3(y, meta, task_actions)
y, meta, _ = self._selection_3(y, meta, routing_actions_3)
return y, meta
def loss(self, yhat, ytrue, ym):
return self._lossfunc(yhat, ytrue, ym)
Again, the PerTaskAssignment layer is utilized to produce actions. However, these actions are not used to select a module, but to select an agent instead. Thus they cannot be overridden, but are explicitly passed to each of the decision making agents as dispatcher-actions.
Dispatched Routing Architectures
Extending this paradigm to dispatched architectures is straightforward:
class DispatchedRoutedAllFC(RoutedAllFC):
def __init__(self, dispatcher_decision_maker, decision_maker, in_channels, convnet_out_size,
out_dim, num_modules, num_agents):
RoutedAllFC.__init__(self, decision_maker, in_channels, convnet_out_size, out_dim, num_modules, num_agents)
self._per_task_assignment = dispatcher_decision_maker(
num_agents, convnet_out_size, num_agents=1, policy_storage_type='approx',
additional_reward_func=CollaborationReward(reward_ratio=0.0, num_actions=num_modules))
Here, the task-specific assignment "agent" simply got replaced by a separate dispatching agent.