Source code for archai.supergraph.algos.random.random_model_desc_builder

# Copyright (c) Microsoft Corporation.
# Licensed under the MIT license.

import copy
import random
from typing import List, Optional, Tuple

from overrides import overrides

from archai.common.config import Config
from archai.supergraph.nas.model_desc import (
    AuxTowerDesc,
    CellDesc,
    CellType,
    ConvMacroParams,
    EdgeDesc,
    NodeDesc,
    OpDesc,
    TensorShape,
    TensorShapes,
    TensorShapesList,
)
from archai.supergraph.nas.model_desc_builder import ModelDescBuilder


[docs]class RandOps: """Container to store (op_names, to_states) for each nodes""" PRIMITIVES = [ 'max_pool_3x3', 'avg_pool_3x3', 'skip_connect', # identity 'sep_conv_3x3', 'sep_conv_5x5', 'dil_conv_3x3', 'dil_conv_5x5', # we don't allow none edge for random ops # 'none' # this must be at the end so top1 doesn't choose it ] def __init__(self, n_nodes:int, max_edges:int) -> None: self.ops_and_ins:List[Tuple[List[str], List[int]]] = [] for i in range(n_nodes): op_names = random.choices(RandOps.PRIMITIVES, k=max_edges) to_states = random.sample(list(range(i+2)), k=max_edges) self.ops_and_ins.append((op_names, to_states))
[docs]class RandomModelDescBuilder(ModelDescBuilder):
[docs] @overrides def build_cells(self, in_shapes:TensorShapesList, conf_model_desc:Config)\ ->Tuple[List[CellDesc], List[Optional[AuxTowerDesc]]]: max_edges = conf_model_desc['num_edges_to_sample'] node_count = self.get_node_count(0) # create two sets of random ops, one for each cell type self._normal_ops = RandOps(node_count, max_edges) self._reduction_ops = RandOps(node_count, max_edges) return super().build_cells(in_shapes, conf_model_desc)
[docs] @overrides def build_nodes(self, stem_shapes:TensorShapes, conf_cell:Config, cell_index:int, cell_type:CellType, node_count:int, in_shape:TensorShape, out_shape:TensorShape) \ ->Tuple[TensorShapes, List[NodeDesc]]: assert in_shape[0]==out_shape[0] reduction = (cell_type==CellType.Reduction) ops = self._reduction_ops if reduction else self._normal_ops assert node_count == len(ops.ops_and_ins) nodes:List[NodeDesc] = [] conv_params = ConvMacroParams(in_shape[0], out_shape[0]) for op_names, to_states in ops.ops_and_ins: edges=[] # add random edges for op_name, to_state in zip(op_names, to_states): op_desc = OpDesc(op_name, params={ 'conv': conv_params, 'stride': 2 if reduction and to_state < 2 else 1 }, in_len=1, trainables=None, children=None) edge = EdgeDesc(op_desc, input_ids=[to_state]) edges.append(edge) nodes.append(NodeDesc(edges=edges, conv_params=conv_params)) out_shapes = [copy.deepcopy(out_shape) for _ in range(node_count)] return out_shapes, nodes