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.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({upper_border, lower_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 or \ _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 ({}, { IOLabel.POOLING2D_OUT: out_nts }, { IOLabel.POOLING2D_IN: label })
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 or \ nts.dtype != target_output.dtype: 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 or \ _dim.name == DimNames.BATCH or \ _dim.name == DimNames.TIME: pool = [_dim.size] elif _dim.name == DimNames.CHANNEL or \ _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 - _dim.size) < upper_border): pool = sample(pool, k=min(max(max_possibilities - len(border_pool), 0), len(pool))) else: pool.remove(target_size - _dim.size) pool = sample(pool, k=min(max(max_possibilities - len(border_pool) - 1, 0), len(pool))) + [ target_size - _dim.size] pool = pool + border_pool 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): remaining_shape = Shape(*zip(names, dim_combination)) out_nts = TypeShape(nts.dtype, Shape(*zip(names, [ d_.size + _d.size if _d.name == DimNames.CHANNEL or _d.name == DimNames.UNITS else _d.size for d_, _d in zip(remaining_shape.dim, nts.shape.dim)]))) if is_reachable(out_nts, target_output): yield ({IOLabel.MERGE_OTHER: TypeShape(nts.dtype, remaining_shape)}, {IOLabel.MERGE_OUT: out_nts}, {IOLabel.MERGE_IN: label})
def possible_output_shapes(cls, input_ntss: Dict[str, TypeShape], target_output: TypeShape, is_reachable, max_possibilities: int = 15, **kwargs) -> \ List[Tuple[Dict[str, TypeShape], Dict[str, TypeShape], Dict[str, str]]]: def valid_config(h_i, h_o, w_i, w_o): configurations = list() 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 pooling_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 p_w in pooling_range(w_i, w_o): for p_h in pooling_range(h_i, h_o): if p_w != p_h: continue for s_w in stride_range(w_i - p_w + 1, w_o): for s_h in stride_range(h_i - p_h + 1, h_o): if s_w != s_h: continue return True return False 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.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({upper_border, lower_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 or \ _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.POOLING2D_OUT: out_nts }, { IOLabel.POOLING2D_IN: label })