def create_task(task_name, module_suffixes=("", "")): module1_name = f"linear1{module_suffixes[0]}" module2_name = f"linear2{module_suffixes[1]}" linear1 = nn.Linear(2, 2) linear1.weight.data.copy_(torch.eye(2)) linear1.bias.data.copy_(torch.zeros((2, ))) linear2 = nn.Linear(2, 2) linear2.weight.data.copy_(torch.eye(2)) linear2.bias.data.copy_(torch.zeros((2, ))) module_pool = nn.ModuleDict({ module1_name: nn.Sequential(linear1, nn.ReLU()), module2_name: linear2 }) op0 = Operation(module_name=module1_name, inputs=[("_input_", "data")], name="op0") op1 = Operation(module_name=module2_name, inputs=[op0.name], name="op1") op_sequence = [op0, op1] task = Task(name=task_name, module_pool=module_pool, op_sequence=op_sequence) return task
def test_task_creation(self): module_pool = nn.ModuleDict({ "linear1": nn.Sequential(nn.Linear(2, 10), nn.ReLU()), "linear2": nn.Linear(10, 1), }) op_sequence = [ Operation(name="the_first_layer", module_name="linear1", inputs=["_input_"]), Operation( name="the_second_layer", module_name="linear2", inputs=["the_first_layer"], ), ] task = Task(name=TASK_NAME, module_pool=module_pool, op_sequence=op_sequence) # Task has no functionality on its own # Here we only confirm that the object was initialized self.assertEqual(task.name, TASK_NAME)
def test_no_input_spec(self): # Confirm model doesn't break when a module does not specify specific inputs dataset = create_dataloader("task", shuffle=False).dataset task = Task( name="task", module_pool=nn.ModuleDict({"identity": nn.Identity()}), op_sequence=[Operation("identity", [])], ) model = MultitaskModel(tasks=[task], dataparallel=False) outputs = model.forward(dataset.X_dict, ["task"]) self.assertIn("_input_", outputs)
def create_task(task_name, module_suffixes=("", "")): module1_name = f"linear1{module_suffixes[0]}" module2_name = f"linear2{module_suffixes[1]}" module_pool = nn.ModuleDict({ module1_name: nn.Sequential(nn.Linear(2, 10), nn.ReLU()), module2_name: nn.Linear(10, 2), }) op1 = Operation(module_name=module1_name, inputs=[("_input_", "data")]) op2 = Operation(module_name=module2_name, inputs=[op1.name]) op_sequence = [op1, op2] task = Task(name=task_name, module_pool=module_pool, op_sequence=op_sequence) return task
def test_score_shuffled(self): # Test scoring with a shuffled dataset class SimpleVoter(nn.Module): def forward(self, x): """Set class 0 to -1 if x and 1 otherwise""" mask = x % 2 == 0 out = torch.zeros(x.shape[0], 2) out[mask, 0] = 1 # class 0 out[~mask, 1] = 1 # class 1 return out # Create model task_name = "VotingTask" module_name = "simple_voter" module_pool = nn.ModuleDict({module_name: SimpleVoter()}) op0 = Operation(module_name=module_name, inputs=[("_input_", "data")], name="op0") op_sequence = [op0] task = Task(name=task_name, module_pool=module_pool, op_sequence=op_sequence) model = MultitaskModel([task]) # Create dataset y_list = [0, 0, 0, 0, 0, 1, 1, 1, 1, 1] x_list = [i for i in range(len(y_list))] Y = torch.LongTensor(y_list * 100) X = torch.FloatTensor(x_list * 100) dataset = DictDataset(name="dataset", split="train", X_dict={"data": X}, Y_dict={task_name: Y}) # Create dataloaders dataloader = DictDataLoader(dataset, batch_size=2, shuffle=False) scores = model.score([dataloader]) self.assertEqual(scores["VotingTask/dataset/train/accuracy"], 0.6) dataloader_shuffled = DictDataLoader(dataset, batch_size=2, shuffle=True) scores_shuffled = model.score([dataloader_shuffled]) self.assertEqual(scores_shuffled["VotingTask/dataset/train/accuracy"], 0.6)
x = F.relu(self.fc2(x)) return x base_net = BaseNet() class_head_module = nn.Linear(84, 10) # The module pool contains all the modules this task uses module_pool = nn.ModuleDict({ "base_net": base_net, "class_head_module": class_head_module }) # Op1: pull data from "class_data" and send through base net op1 = Operation(name="base_net", module_name="base_net", inputs=[("_input_", "class_data")]) # Op2: pass output of Op1 to the class head module op2 = Operation(name="class_head", module_name="class_head_module", inputs=["base_net"]) op_sequence = [op1, op2] # - # The output of the final operation will then go into a loss function to calculate the loss (e.g., cross-entropy) during training or an output function (e.g., softmax) to convert the logits into a prediction. # # Each `Task` also specifies which metrics it supports, which are bundled together in a `Scorer` object. For this tutorial, we'll just look at accuracy. # +
from cerbero.core import Operation # Define a two-layer MLP module and a one-layer prediction "head" module base_mlp = nn.Sequential(nn.Linear(2, 8), nn.ReLU(), nn.Linear(8, 4), nn.ReLU()) head_module = nn.Linear(4, 2) # The module pool contains all the modules this task uses module_pool = nn.ModuleDict({ "base_mlp": base_mlp, "circle_head_module": head_module }) # "From the input dictionary, pull out 'circle_data' and send it through input_module" op1 = Operation(name="base_mlp", module_name="base_mlp", inputs=[("_input_", "circle_data")]) # "Pass the output of op1 (the MLP module) as input to the head_module" op2 = Operation(name="circle_head", module_name="circle_head_module", inputs=["base_mlp"]) op_sequence = [op1, op2] # - # The output of the final operation will then go into a loss function to calculate the loss (e.g., cross-entropy) during training or an output function (e.g., softmax) to convert the logits into a prediction. # # Each `Task` also specifies which metrics it supports, which are bundled together in a `Scorer` object. For this tutorial, we'll just look at accuracy. # Putting this all together, we define the circle task: