def possible_output_shapes(cls, input_ntss: Dict[str, TypeShape], target_output: TypeShape, is_reachable, max_possibilities: int = 10, **kwargs) -> \ List[Tuple[Dict[str, TypeShape], Dict[str, TypeShape], Dict[str, str]]]: target_shape = target_output.shape for label, nts in input_ntss.items(): if nts.dtype not in cls.allowedTypes: continue possible_sizes = [] names = [] invalid_dim = False for _dim in nts.shape.dim: target_size = target_shape[_dim.name] if _dim.name == DimNames.UNITS: lower_border = max(math.floor(_dim.size * cls.__min_f), (min(2, target_size) if target_size is not None else 2)) upper_border = math.ceil(_dim.size * cls.__max_f) pool = list(range(lower_border + 1, upper_border)) border_pool = list({lower_border, upper_border}) if target_size is None or not (lower_border < target_size < upper_border): pool = sample(pool, k=min(max(max_possibilities - len(border_pool), 0), len(pool))) else: pool.remove(target_size) pool = sample(pool, k=min(max(max_possibilities - len(border_pool) - 1, 0), len(pool))) + [target_size] pool = pool + border_pool elif _dim.name == DimNames.BATCH: pool = [_dim.size] else: invalid_dim = True break possible_sizes.append(pool) names.append(_dim.name) if invalid_dim: continue for dim_combination in Shape.random_dimension_product(possible_sizes): out_nts = TypeShape(nts.dtype, Shape(*zip(names, dim_combination))) if is_reachable(out_nts, target_output): yield ({}, {IOLabel.DENSE_OUT: out_nts}, {IOLabel.DENSE_IN: label})
def possible_output_shapes(cls, input_ntss: Dict[str, TypeShape], target_output: TypeShape, is_reachable, max_possibilities: int = 10, max_inputs: int = None, **kwargs) -> \ List[Tuple[Dict[str, TypeShape], Dict[str, TypeShape], Dict[str, str]]]: for label, nts in input_ntss.items(): if nts.dtype not in cls.allowedTypes: continue possible_sizes = [] names = [] invalid_dim = False for _dim in nts.shape.dim: if _dim.name == DimNames.UNITS and _dim.size == 1: pool = [1] elif _dim.name == DimNames.BATCH: pool = [_dim.size] else: invalid_dim = True break possible_sizes.append(pool) names.append(_dim.name) if invalid_dim: continue for comb in Shape.random_dimension_product(possible_sizes): out_nts = TypeShape(nts.dtype, Shape(*zip(names, comb))) if is_reachable(out_nts, target_output): yield ({ cls.get_in_label(i + 1): nts.__copy__() for i in range( round( np.random.beta(2, 5) * (10 if not isinstance(max_inputs, int) else max_inputs - 1))) }, { IOLabel.PERCEPTRON_OUT: out_nts }, { cls.get_in_label(0): label }) break
def possible_output_shapes(cls, input_ntss: Dict[str, TypeShape], target_output: TypeShape, is_reachable, max_possibilities: int = 20, **kwargs) -> \ List[Tuple[Dict[str, TypeShape], Dict[str, TypeShape], Dict[str, str]]]: def valid_config(h_i, h_o, w_i, w_o): def stride_range(in_, out_): if out_ == 1: return [in_] else: lower_limit = math.ceil(in_ / out_) upper_limit = math.ceil(in_ / (out_ - 1)) - 1 if lower_limit == 0 or \ math.ceil(in_ / lower_limit) < out_ or \ upper_limit == 0 or \ math.ceil(in_ / upper_limit) > out_: return [] return list(range(lower_limit, upper_limit + 1)) def filter_range(in_, out_): lower_limit = 1 upper_limit = in_ - out_ + 1 return list(range(lower_limit, upper_limit + 1)) for s_h in stride_range(h_i, h_o): for s_w in stride_range(w_i, w_o): if s_h != s_w: continue return True for k_w in filter_range(w_i, w_o): for k_h in filter_range(h_i, h_o): if k_w != k_h: continue for s_h in stride_range(h_i - k_h + 1, h_o): for s_w in stride_range(w_i - k_w + 1, w_o): if s_h != s_w: continue return True return False target_shape = target_output.shape for label, nts in input_ntss.items(): _prev = time.time() if nts.dtype not in cls.allowedTypes: continue possible_sizes = [] names = [] invalid_dim = False for _dim in nts.shape.dim: target_size = target_shape[_dim.name] if _dim.name == DimNames.WIDTH or \ _dim.name == DimNames.HEIGHT: lower_border = max(math.floor(_dim.size * cls.__min_f_hw), (min(2, target_size) if target_size is not None else 2)) upper_border = math.ceil(_dim.size * cls.__max_f_hw) pool = list(range(lower_border + 1, upper_border)) border_pool = list({lower_border, upper_border}) if target_size is None or not (lower_border < target_size < upper_border): pool = sample( pool, k=min(max(max_possibilities - len(border_pool), 0), len(pool))) else: pool.remove(target_size) pool = sample( pool, k=min( max(max_possibilities - len(border_pool) - 1, 0), len(pool))) + [target_size] pool = pool + border_pool elif _dim.name == DimNames.CHANNEL: lower_border = max(math.floor(_dim.size * cls.__min_f_c), (min(2, target_size) if target_size is not None else 2)) upper_border = math.ceil(_dim.size * cls.__max_f_c) pool = list(range(lower_border + 1, upper_border)) border_pool = list({lower_border, upper_border}) if target_size is None or not (lower_border < target_size < upper_border): pool = sample( pool, k=min(max(max_possibilities - len(border_pool), 0), len(pool))) else: pool.remove(target_size) pool = sample( pool, k=min( max(max_possibilities - len(border_pool) - 1, 0), len(pool))) + [target_size] pool = pool + border_pool elif _dim.name == DimNames.BATCH: pool = [_dim.size] else: invalid_dim = True break possible_sizes.append(pool) names.append(_dim.name) if invalid_dim: continue in_w, in_h = nts.shape[DimNames.WIDTH], nts.shape[DimNames.HEIGHT] for comb in Shape.random_dimension_product(possible_sizes): out_nts = TypeShape(nts.dtype, Shape(*zip(names, comb))) out_w, out_h = out_nts.shape[DimNames.WIDTH], out_nts.shape[ DimNames.HEIGHT] if valid_config(in_h, out_h, in_w, out_w) and is_reachable( out_nts, target_output): yield ({}, { IOLabel.CONV2D_OUT: out_nts }, { IOLabel.CONV2D_IN: label })