def __init__(self, preprocessor=None, convergence=None, personalization_transform: Postprocessor = None, preserve_norm: bool = True, **kwargs): """ Args: preprocessor: Optional. Method to extract a scipy sparse matrix from a networkx graph. If None (default), pygrank.algorithms.utils.preprocessor is used with keyword arguments automatically extracted from the ones passed to this constructor. convergence: Optional. The ConvergenceManager that determines when iterations stop. If None (default), a ConvergenceManager is used with keyword arguments automatically extracted from the ones passed to this constructor. personalization_transform: Optional. A Postprocessor whose `transform` method is used to transform the personalization before applying the graph filter. If None (default) a Tautology is used. preserve_norm: Optional. If True (default) the input's norm is used to scale the output. For example, if *convergence* is L1, this effectively means that the sum of output values is equal to the sum of input values. """ self.preprocessor = call( default_preprocessor, kwargs) if preprocessor is None else preprocessor self.convergence = call(ConvergenceManager, kwargs) if convergence is None else convergence self.personalization_transform = Tautology( ) if personalization_transform is None else personalization_transform self.preserve_norm = preserve_norm ensure_used_args(kwargs, [default_preprocessor, ConvergenceManager])
def _transform(self, ranks: GraphSignal, **kwargs): ensure_used_args(kwargs) return { v: order + 1 for order, v in enumerate( sorted(ranks, key=ranks.get, reverse=True)) }
def __init__(self, ranker_generator: Callable[[list], NodeRanking] = None, measure: Callable[[GraphSignal, GraphSignal], Supervised] = Cos, basis: Optional[str] = "Krylov", tuning_backend: Optional[str] = None, autoregression: int = 0, num_parameters: int = 20, tunable_offset: Optional[Callable[[GraphSignal, GraphSignal], Supervised]] = None, pre_diffuse: Optional[NodeRanking] = None, **kwargs): """ Instantiates the tuning mechanism. Args: ranker_generator: A callable that constructs a ranker based on a list of parameters. If None (default) then a pygrank.algorithms.learnable.GenericGraphFilter is constructed with automatic normalization and assuming immutability (this is the most common setting). These parameters can be overriden and other ones can be passed to the algorithm'personalization constructor simply by including them in kwargs. measure: Callable to constuct a supervised measure with given known node scores. basis: Can use either the "Krylov" or the "Arnoldi" orthonormal basis of the krylov space. The latter does not produce a ranking algorithm. tuning_backend: Specifically switches to a designted backend for the tuning process before restoring the previous one to perform the actual ranking. If None (default), this functionality is ignored. tunable_offset: If None, no offset is added to estimated parameters. Otherwise, a supervised measure generator (e.g. a supervised measure class) can be passed. Default is `pygrank.AUC`. kwargs: Additional arguments are passed to the automatically instantiated GenericGraphFilter. Example: >>> import pygrank as pg >>> graph, personalization = ... >>> tuner = pg.HopTuner(measure=AUC) >>> ranks = tuner.rank(graph, personalization) """ if ranker_generator is None: if "optimization_dict" not in kwargs: kwargs["optimization_dict"] = SelfClearDict() from pygrank.algorithms import GenericGraphFilter def ranker_generator(params): return GenericGraphFilter(params, **kwargs) else: ensure_used_args(kwargs, []) self.ranker_generator = ranker_generator self.measure = measure self.tuning_backend = tuning_backend self.autoregression = autoregression self.num_parameters = num_parameters self.tunable_offset = tunable_offset self.pre_diffuse = pre_diffuse self.basis = basis.lower()
def _transform(self, ranks: GraphSignal, **kwargs): ensure_used_args(kwargs) threshold = 0 fraction_of_training = self.fraction_of_training*backend.length(ranks) if self.fraction_of_training < 1 else self.fraction_of_training fraction_of_training = int(fraction_of_training) for v in sorted(ranks, key=ranks.get, reverse=True): fraction_of_training -= 1 if fraction_of_training == 0: threshold = ranks[v] break return {v: 1. if ranks[v] >= threshold else 0. for v in ranks.keys()}
def _transform(self, ranks: GraphSignal, **kwargs): ensure_used_args(kwargs) threshold = self.threshold if threshold == "gap": # TODO maybe enable ranks = {v: ranks[v] / ranks.graph.degree(v) for v in ranks} with a postprocessor max_diff = 0 threshold = 0 prev_rank = 0 for v in sorted(ranks, key=ranks.get, reverse=True): if prev_rank > 0: diff = (prev_rank - ranks[v]) / prev_rank if diff > max_diff: max_diff = diff threshold = ranks[v] prev_rank = ranks[v] return {v: 1 if ranks[v] >= threshold else 0 for v in ranks.keys()}
def _transform(self, ranks: GraphSignal, **kwargs): ensure_used_args(kwargs) min_rank = 0 if self.method == "range": max_rank = float(backend.max(ranks.np)) min_rank = float(backend.min(ranks.np)) elif self.method == "max": max_rank = float(backend.max(ranks.np)) elif self.method == "sum": max_rank = float(backend.sum(ranks.np)) else: raise Exception("Can only normalize towards max or sum") if min_rank == max_rank: return ranks ret = (ranks.np - min_rank) / (max_rank - min_rank) return ret
def __init__(self, preprocessor=None, convergence=None, personalization_transform: Postprocessor = None, **kwargs): """ Args: preprocessor: Optional. Method to extract a scipy sparse matrix from a networkx graph. If None (default), pygrank.algorithms.utils.preprocessor is used with keyword arguments automatically extracted from the ones passed to this constructor. convergence: Optional. The ConvergenceManager that determines when iterations stop. If None (default), a ConvergenceManager is used with keyword arguments automatically extracted from the ones passed to this constructor. personalization_transform: Optional. A Postprocessor whose `transform` method is used to transform the personalization before applying the graph filter. If None (default) a Tautology is used. """ self.preprocessor = call( default_preprocessor, kwargs) if preprocessor is None else preprocessor self.convergence = call(ConvergenceManager, kwargs) if convergence is None else convergence self.personalization_transform = Tautology( ) if personalization_transform is None else personalization_transform ensure_used_args(kwargs, [default_preprocessor, ConvergenceManager])
def __init__(self, ranker_generator: Callable[[list], NodeRanking] = None, measure: Callable[[GraphSignal, GraphSignal], Measure] = AUC, fraction_of_training: float = 0.8, combined_prediction: bool = True, tuning_backend: str = None, **kwargs): """ Instantiates the tuning mechanism. Args: ranker_generator: A callable that constructs a ranker based on a list of parameters. If None (default) then a pygrank.algorithms.learnable.GenericGraphFilter is constructed with automatic normalization and assuming immutability (this is the most common setting). These parameters can be overriden and other ones can be passed to the algorithm'personalization constructor by including them in kwargs. measure: Callable to constuct a supervised measure with given known node scores and an iterable of excluded scores. fraction_of_training: A number in (0,1) indicating how to split provided graph signals into training and validaton ones by randomly sampling training nodes to meet the required fraction of all graph nodes. Numbers outside this range can also be used (not recommended without specific reason) per the conventions of `pygrank.split(...)`. Default is 0.8. combined_prediction: If True (default), after the best version of algorithms is determined, the whole personalization is used to produce the end-result. Otherwise, only the training portion of the training-validation split is used. tuning_backend: Specifically switches to a designted backend for the tuning process before restoring the previous one to perform the actual ranking. If None (default), this functionality is ignored. kwargs: Additional arguments can be passed to pygrank.algorithms.autotune.optimization.optimize. Otherwise, the respective arguments are retrieved from the variable *default_tuning_optimization*, which is crafted for fast convergence of the default ranker_generator. Arguments passable to the ranker_generator are also passed to it. Make sure to declare both the upper **and** the lower bounds of parameter values. Example: >>> import pygrank as pg >>> graph, personalization = ... >>> tuner = pg.ParameterTuner(measure=AUC, deviation_tol=0.01) >>> ranks = tuner.rank(graph, personalization) Example to tune pagerank'personalization float parameter alpha in the range [0.5, 0.99]: >>> import pygrank as pg >>> graph, personalization = ... >>> tuner = pg.ParameterTuner(lambda params: pg.PageRank(alpha=params[0]), >>> measure=AUC, deviation_tol=0.01, max_vals=[0.99], min_vals=[0.5]) >>> ranks = tuner.rank(graph, personalization) """ if ranker_generator is None: from pygrank.algorithms import GenericGraphFilter if 'preprocessor' not in kwargs and 'assume_immutability' not in kwargs and 'normalization' not in kwargs: kwargs['preprocessor'] = preprocessor(assume_immutability=True) if "optimization_dict" not in kwargs: kwargs["optimization_dict"] = SelfClearDict() def ranker_generator(params): return GenericGraphFilter(params, **remove_used_args(optimize, kwargs)) else: ensure_used_args(kwargs, [optimize]) self.ranker_generator = ranker_generator self.measure = measure self.fraction_of_training = fraction_of_training self.optimize_args = { kwarg: kwargs.get(kwarg, val) for kwarg, val in default_tuning_optimization.items() } self.combined_prediction = combined_prediction self.tuning_backend = tuning_backend
def _transform(self, ranks: GraphSignal, **kwargs): ensure_used_args(kwargs) uniforms = self.centrality(ranks.graph).np return ranks.np - uniforms
def _transform(self, ranks: GraphSignal, **kwargs): ensure_used_args(kwargs) try: return self.expr(ranks.np) except: return {v: self.expr(ranks[v]) for v in ranks}