def model_configuration(self): """ Constructs the dictionary containing the priors for the weight vectors for the model according to the regularization function. The parameters are: * **weights** : Weights to evaluates the utility of the objects For ``l1`` regularization the priors are: .. math:: \\text{mu}_w \sim \\text{Normal}(\\text{mu}=0, \\text{sd}=5.0) \\\\ \\text{b}_w \sim \\text{HalfCauchy}(\\beta=1.0) \\\\ \\text{weights} \sim \\text{Laplace}(\\text{mu}=\\text{mu}_w, \\text{b}=\\text{b}_w) For ``l2`` regularization the priors are: .. math:: \\text{mu}_w \sim \\text{Normal}(\\text{mu}=0, \\text{sd}=5.0) \\\\ \\text{sd}_w \sim \\text{HalfCauchy}(\\beta=1.0) \\\\ \\text{weights} \sim \\text{Normal}(\\text{mu}=\\text{mu}_w, \\text{sd}=\\text{sd}_w) """ if self._config is None: if self.regularization == 'l2': weight = pm.Normal prior = 'sd' elif self.regularization == 'l1': weight = pm.Laplace prior = 'b' self._config = { 'weights': [weight, {'mu': (pm.Normal, {'mu': 0, 'sd': 5}), prior: (pm.HalfCauchy, {'beta': 1})}]} self.logger.info('Creating model with config {}'.format(print_dictionary(self._config))) return self._config
def set_tunable_parameters(self, alpha=5e-2, loss_function='', regularization='l2', **point): """ Set tunable parameters of the Paired Combinatorial logit model to the values provided. Parameters ---------- alpha: float (range : [0,1]) The lower bound of the correlations between the objects in a nest loss_function : string , {‘categorical_crossentropy’, ‘binary_crossentropy’, ’categorical_hinge’} Loss function to be used for the discrete choice decision from the query set regularization : string, {‘l1’, ‘l2’}, string Regularizer function (L1 or L2) applied to the `kernel` weights matrix point: dict Dictionary containing parameter values which are not tuned for the network """ if alpha is not None: self.alpha = alpha if loss_function in likelihood_dict.keys(): self.loss_function = likelihood_dict.get(loss_function, None) self.regularization = regularization self.model = None self.trace = None self.trace_vi = None self.Xt = None self.Yt = None self.p = None self._config = None if len(point) > 0: self.logger.warning( 'This ranking algorithm does not support tunable parameters' ' called: {}'.format(print_dictionary(point)))
def set_tunable_parameters(self, n_mixtures=4, loss_function="", regularization="l1", **point): """ Set tunable parameters of the Mixed Logit model to the values provided. Parameters ---------- n_mixtures: int (range : [2, inf]) The number of logit models (:math:`R`) which are used to estimate the choice probability loss_function : string , {‘categorical_crossentropy’, ‘binary_crossentropy’, ’categorical_hinge’} Loss function to be used for the discrete choice decision from the query set regularization : string, {‘l1’, ‘l2’}, string Regularizer function (L1 or L2) applied to the `kernel` weights matrix point: dict Dictionary containing parameter values which are not tuned for the network """ if loss_function in likelihood_dict.keys(): self.loss_function = likelihood_dict.get(loss_function, None) self.n_mixtures = n_mixtures self.regularization = regularization self.model = None self.trace = None self.trace_vi = None self.Xt = None self.Yt = None self.p = None self._config = None if len(point) > 0: self.logger.warning("This ranking algorithm does not support" " tunable parameters called: {}".format( print_dictionary(point)))
def set_tunable_parameters(self, alpha=None, n_nests=None, loss_function='', regularization='l2', **point): if alpha is not None: self.alpha = alpha if n_nests is None: self.n_nests = self.n_objects + int(self.n_objects / 2) else: self.n_nests = n_nests if loss_function in likelihood_dict.keys(): self.loss_function = likelihood_dict.get(loss_function, None) self.regularization = regularization self.model = None self.trace = None self.trace_vi = None self.Xt = None self.Yt = None self.p = None self._config = None if len(point) > 0: self.logger.warning( 'This ranking algorithm does not support tunable parameters' ' called: {}'.format(print_dictionary(point)))
def create_rankings_dataset(self, dataset, hdf5file_path): logger.info("Writing in hd5 {}".format(hdf5file_path)) X, Y, scores = self.create_instances(dataset) result, freq = self._build_training_buckets(X, Y, scores) h5f = h5py.File(hdf5file_path, "w") logger.info("Frequencies of rankings: {}".format( print_dictionary(freq))) for key, value in result.items(): x, y, s = value h5f.create_dataset("X_" + str(key), data=x, compression="gzip", compression_opts=9) h5f.create_dataset("Y_" + str(key), data=y, compression="gzip", compression_opts=9) h5f.create_dataset("score_" + str(key), data=s, compression="gzip", compression_opts=9) lengths = np.array(list(result.keys())) h5f.create_dataset("lengths", data=lengths, compression="gzip", compression_opts=9) h5f.close()
def set_tunable_parameters(self, n_hidden=32, n_units=2, reg_strength=1e-4, learning_rate=1e-3, batch_size=128, **point): """ Set tunable parameters of the CmpNet network to the values provided. Parameters ---------- n_hidden: int Number of hidden layers used in the scoring network n_units: int Number of hidden units in each layer of the scoring network reg_strength: float Regularization strength of the regularizer function applied to the `kernel` weights matrix learning_rate: float Learning rate of the stochastic gradient descent algorithm used by the network batch_size: int Batch size to use during training point: dict Dictionary containing parameter values which are not tuned for the network """ self.n_hidden = n_hidden self.n_units = n_units self.kernel_regularizer = l2(reg_strength) self.batch_size = batch_size self.optimizer = self.optimizer.from_config(self._optimizer_config) K.set_value(self.optimizer.lr, learning_rate) self._construct_layers(kernel_regularizer=self.kernel_regularizer, kernel_initializer=self.kernel_initializer, activation=self.activation, **self.kwargs) if len(point) > 0: self.logger.warning('This ranking algorithm does not support' ' tunable parameters called: {}'.format(print_dictionary(point)))
def set_tunable_parameters(self, loss_function='', regularization="l1", **point): """ Set tunable parameters of the Multinomial Logit model to the values provided. Parameters ---------- loss_function : string , {‘categorical_crossentropy’, ‘binary_crossentropy’, ’categorical_hinge’} Loss function to be used for the discrete choice decision from the query set regularization : string, {‘l1’, ‘l2’}, string Regularizer function (L1 or L2) applied to the `kernel` weights matrix point: dict Dictionary containing parameter values which are not tuned for the network """ if loss_function in likelihood_dict.keys(): self.loss_function = likelihood_dict.get(loss_function, None) self.regularization = regularization self.model = None self.trace = None self.trace_vi = None self.Xt = None self.Yt = None self.p = None self._config = None if len(point) > 0: self.logger.warning('This ranking algorithm does not support' ' tunable parameters called: {}'.format( print_dictionary(point)))
def model_priors(self): if self._config is None: if self.regularization == 'l2': weight = pm.Normal prior = 'sd' elif self.regularization == 'l1': weight = pm.Laplace prior = 'b' self._config = { 'weights': [ weight, { 'mu': (pm.Normal, { 'mu': 0, 'sd': 5 }), prior: (pm.HalfCauchy, { 'beta': 1 }) } ], 'weights_ik': [ weight, { 'mu': (pm.Normal, { 'mu': 0, 'sd': 5 }), prior: (pm.HalfCauchy, { 'beta': 1 }) } ] } self.logger.info('Creating model with config {}'.format( print_dictionary(self._config))) return self._config
def set_tunable_parameters(self, learning_rate=1e-3, batch_size=128, epochs_drop=300, drop=0.1, **point): """ Set tunable parameters of the FETA-network to the values provided. Parameters ---------- learning_rate: float Learning rate of the stochastic gradient descent algorithm used by the network batch_size: int Batch size to use during training epochs_drop: int The epochs after which the learning rate is decreased drop: float The percentage with which the learning rate is decreased point: dict Dictionary containing parameter values which are not tuned for the network """ self.batch_size = batch_size self.learning_rate = learning_rate self._construct_model_(self.n_objects) self.epochs_drop = epochs_drop self.drop = drop if len(point) > 0: self.logger.warning( "This ranking algorithm does not support tunable parameters" " called: {}".format(print_dictionary(point)))
def set_tunable_parameters(self, C=1, tol=1e-4, **point): self.tol = tol self.C = C if len(point) > 0: self.logger.warning('This ranking algorithm does not support' ' tunable parameters' ' called: {}'.format(print_dictionary(point)))
def set_tunable_parameters(self, alpha=0.0, l1_ratio=0.5, tol=1e-4, **point): """ Set tunable parameters of the PairwiseSVM model to the values provided. Parameters ---------- alpha : float Regularization strength l1_ratio : float in [0,1] Ratio between pure L2 (=0) or pure L1 (=1) regularization tol : float Optimization tolerance for regression model point: dict Dictionary containing parameter values which are not tuned for the network """ self.tol = tol self.alpha = alpha self.l1_ratio = l1_ratio if len(point) > 0: self.logger.warning('This ranking algorithm does not support' ' tunable parameters' ' called: {}'.format(print_dictionary(point)))
def set_tunable_parameters(self, patience=300, min_delta=2, **point): self.patience = patience self.min_delta = min_delta if len(point) > 0: self.logger.warning('This callback does not support' ' tunable parameters' ' called: {}'.format(print_dictionary(point)))
def set_tunable_parameters(self, epochs_drop=300, drop=0.1, **point): self.epochs_drop = epochs_drop self.drop = drop if len(point) > 0: self.logger.warning('This callback does not support' ' tunable parameters' ' called: {}'.format(print_dictionary(point)))
def insert_results(self, experiment_schema, experiment_table, results, **kwargs): self.init_connection(cursor_factory=None) results_table = "{}.{}".format(experiment_schema, experiment_table) columns = ', '.join(list(results.keys())) values_str = ', '.join(list(results.values())) self.cursor_db.execute("select to_regclass(%s)", [results_table]) is_table_exist = bool(self.cursor_db.fetchone()[0]) if not is_table_exist: self.logger.info( "Table {} does not exist creating with columns {}".format( results_table, columns)) create_command = "CREATE TABLE {} (job_id INTEGER PRIMARY KEY, cluster_id INTEGER NOT NULL)".format( results_table) self.cursor_db.execute(create_command) for column in results.keys(): if column not in ["job_id", "cluster_id"]: alter_table_command = 'ALTER TABLE %s ADD COLUMN %s double precision' % ( results_table, column) self.cursor_db.execute(alter_table_command) self.close_connection() self.init_connection(cursor_factory=None) try: insert_result = "INSERT INTO {0} ({1}) VALUES ({2})".format( results_table, columns, values_str) self.logger.info("Inserting results: {}".format(insert_result)) self.cursor_db.execute(insert_result) if self.cursor_db.rowcount == 1: self.logger.info("Results inserted for the job {}".format( results['job_id'])) except psycopg2.IntegrityError as e: self.logger.info(print_dictionary(results)) self.logger.info( "IntegrityError for the job {0}, results already inserted to another node error {1}" .format(results["job_id"], str(e))) self.connection.rollback() update_str = '' values_tuples = [] for i, col in enumerate(results.keys()): if col != 'job_id': if (i + 1) == len(results): update_str = update_str + col + " = %s " else: update_str = update_str + col + " = %s, " if 'Infinity' in results[col]: results[col] = 'Infinity' values_tuples.append(results[col]) update_result = "UPDATE {0} set {1} where job_id= %s ".format( results_table, update_str) self.logger.info(update_result) values_tuples.append(results['job_id']) self.logger.info('values {}'.format(tuple(values_tuples))) self.cursor_db.execute(update_result, tuple(values_tuples)) if self.cursor_db.rowcount == 1: self.logger.info("The job {} is updated".format( results['job_id'])) self.close_connection()
def set_tunable_parameters(self, alpha=1.0, l1_ratio=0.5, tol=1e-4, **point): self.tol = tol self.alpha = alpha self.l1_ratio = l1_ratio if len(point) > 0: self.logger.warning('This ranking algorithm does not support' ' tunable parameters' ' called: {}'.format(print_dictionary(point)))
def set_tunable_parameters(self, point): keys = self._tunable.copy().keys() named = dict(zip(keys, point)) self.logger.info("Setting Tunable Parameters: " + print_dictionary(named)) return named
def set_tunable_parameters(self, neighbours=20, algorithm="ball_tree", **point): self.neighbours = neighbours self.algorithm = algorithm if len(point) > 0: self.logger.warning('This ranking algorithm does not support' ' tunable parameters' ' called: {}'.format(print_dictionary(point)))
def model_configuration(self): """ Constructs the dictionary containing the priors for the weight vectors for the model according to the regularization function. The parameters are: * **weights** : Weights to evaluates the utility of the objects * **weights_k** : Weights to evaluates the fractional allocation of each object in :math:'Q' to each nest For ``l1`` regularization the priors are: .. math:: \\text{mu}_w \\sim \\text{Normal}(\\text{mu}=0, \\text{sd}=5.0) \\\\ \\text{b}_w \\sim \\text{HalfCauchy}(\\beta=1.0) \\\\ \\text{weights} \\sim \\text{Laplace}(\\text{mu}=\\text{mu}_w, \\text{b}=\\text{b}_w) For ``l2`` regularization the priors are: .. math:: \\text{mu}_w \\sim \\text{Normal}(\\text{mu}=0, \\text{sd}=5.0) \\\\ \\text{sd}_w \\sim \\text{HalfCauchy}(\\beta=1.0) \\\\ \\text{weights} \\sim \\text{Normal}(\\text{mu}=\\text{mu}_w, \\text{sd}=\\text{sd}_w) Returns ------- configuration : dict Dictionary containing the priors applies on the weights """ if not hasattr(self, "config_"): if self.regularization == "l2": weight = pm.Normal prior = "sd" elif self.regularization == "l1": weight = pm.Laplace prior = "b" self.config_ = { "weights": [ weight, { "mu": (pm.Normal, {"mu": 0, "sd": 5}), prior: (pm.HalfCauchy, {"beta": 1}), }, ], "weights_ik": [ weight, { "mu": (pm.Normal, {"mu": 0, "sd": 5}), prior: (pm.HalfCauchy, {"beta": 1}), }, ], } logger.info( "Creating model with config {}".format(print_dictionary(self.config_)) ) return self.config_
def set_tunable_parameters(self, regularization="l1", **point): self.regularization = regularization self.model = None self.trace = None self.trace_vi = None self.Xt = None self.Yt = None self.p = None if len(point) > 0: self.logger.warning('This ranking algorithm does not support' ' tunable parameters called: {}'.format( print_dictionary(point)))
def create_choices_dataset(self, dataset, hdf5file_path): self.logger.info("Writing in hd5 {}".format(hdf5file_path)) X, scores = self.create_instances(dataset) result, freq = self._build_training_buckets(X, scores) h5f = h5py.File(hdf5file_path, 'w') self.logger.info("Frequencies of rankings: {}".format(print_dictionary(freq))) for key, value in result.items(): x, s = value h5f.create_dataset('X_' + str(key), data=x, compression='gzip', compression_opts=9) h5f.create_dataset('score_' + str(key), data=s, compression='gzip', compression_opts=9) lengths = np.array(list(result.keys())) h5f.create_dataset('lengths', data=lengths, compression='gzip', compression_opts=9) h5f.close()
def construct_model(self, X, Y): self.logger.info('Creating model_args config {}'.format( print_dictionary(self.default_configuration))) with pm.Model() as self.model: self.Xt = theano.shared(X) self.Yt = theano.shared(Y) shapes = {'weights': self.n_object_features} # shapes = {'weights': (self.n_object_features, 3)} weights_dict = create_weight_dictionary(self.model_args, shapes) intercept = pm.Normal('intercept', mu=0, sd=10) utility = tt.dot(self.Xt, weights_dict['weights']) + intercept self.p = ttu.sigmoid(utility) yl = BinaryCrossEntropyLikelihood('yl', p=self.p, observed=self.Yt) self.logger.info("Model construction completed")
def tunable_parameters(cls): logger = logging.getLogger(GENERAL_RANKING_CORE) logger.info("Tunable parameters") if cls._tunable is None: logger.info("tunable is None") cls._tunable = dict([ (N_HIDDEN_JOINT_UNITS, JOINT_HIDDEN_UNITS_DEFAULT_RANGE), (N_HIDDEN_JOINT_LAYERS, JOINT_HIDDEN_LAYERS_DEFAULT_RANGE), (LEARNING_RATE, LR_DEFAULT_RANGE), (REGULARIZATION_FACTOR, REGULARIZATION_FACTOR_DEFAULT_RANGE), (BATCH_SIZE, BATCH_SIZE_DEFAULT_RANGE), ]) logger.info("Core ranking params {}".format( print_dictionary(cls._tunable)))
def set_tunable_parameters(self, n_hidden=32, n_units=2, reg_strength=1e-4, learning_rate=1e-3, batch_size=128, **point): self.n_hidden = n_hidden self.n_units = n_units self.kernel_regularizer = l2(reg_strength) self.batch_size = batch_size K.set_value(self.optimizer.lr, learning_rate) self._construct_layers() if len(point) > 0: self.logger.warning('This ranking algorithm does not support' ' tunable parameters' ' called: {}'.format(print_dictionary(point)))
def model_configuration(self): """ Constructs the dictionary containing the priors for the weight vectors for the model according to the regularization function. The parameters are: * **weights** : Weights to evaluates the utility of the objects For ``l1`` regularization the priors are: .. math:: \\text{mu}_w \\sim \\text{Normal}(\\text{mu}=0, \\text{sd}=5.0) \\\\ \\text{b}_w \\sim \\text{HalfCauchy}(\\beta=1.0) \\\\ \\text{weights} \\sim \\text{Laplace}(\\text{mu}=\\text{mu}_w, \\text{b}=\\text{b}_w) For ``l2`` regularization the priors are: .. math:: \\text{mu}_w \\sim \\text{Normal}(\\text{mu}=0, \\text{sd}=5.0) \\\\ \\text{sd}_w \\sim \\text{HalfCauchy}(\\beta=1.0) \\\\ \\text{weights} \\sim \\text{Normal}(\\text{mu}=\\text{mu}_w, \\text{sd}=\\text{sd}_w) """ if self._config is None: if self.regularization == "l2": weight = pm.Normal prior = "sd" elif self.regularization == "l1": weight = pm.Laplace prior = "b" self._config = { "weights": [ weight, { "mu": (pm.Normal, { "mu": 0, "sd": 5 }), prior: (pm.HalfCauchy, { "beta": 1 }), }, ] } self.logger.info("Creating model with config {}".format( print_dictionary(self._config))) return self._config
def get_job_for_id(self, cluster_id, job_id): self.init_connection() avail_jobs = "{}.avail_jobs".format(self.schema) running_jobs = "{}.running_jobs".format(self.schema) select_job = """SELECT * FROM {0} WHERE {0}.job_id={1}""".format( avail_jobs, job_id) self.cursor_db.execute(select_job) if self.cursor_db.rowcount == 1: try: self.job_description = self.cursor_db.fetchall()[0] print('Jobs found {}'.format( print_dictionary(self.job_description))) start = datetime.now() update_job = """UPDATE {} set job_allocated_time = %s WHERE job_id = %s""".format( avail_jobs) self.cursor_db.execute(update_job, (start, job_id)) select_job = """SELECT * FROM {0} WHERE {0}.job_id = {1} AND {0}.interrupted = {2} AND {0}.finished = {3} FOR UPDATE""".format( running_jobs, job_id, False, True) self.cursor_db.execute(select_job) running_job = self.cursor_db.fetchall() if len(running_job) == 0: self.job_description = None print("The job is not evaluated yet") else: print( "Job with job_id {} present in the updating and row locked" .format(job_id)) update_job = """UPDATE {} set cluster_id = %s, interrupted = %s, finished = %s WHERE job_id = %s""".format(running_jobs) self.cursor_db.execute( update_job, (cluster_id, 'FALSE', 'FALSE', job_id)) if self.cursor_db.rowcount == 1: print("The job {} is updated".format(job_id)) self.close_connection() except psycopg2.IntegrityError as e: print( "IntegrityError for the job {}, already assigned to another node error {}" .format(job_id, str(e))) self.job_description = None self.connection.rollback() except (ValueError, IndexError) as e: print( "Error as the all jobs are already assigned to another nodes {}" .format(str(e)))
def tunable_parameters(cls): logger = logging.getLogger(GENERAL_OBJECT_RANKING_CORE) if cls._tunable is None: FATERankingCore.tunable_parameters() logger.info("Use Early Stopping {}".format(cls._use_early_stopping)) if cls._use_early_stopping: cls._tunable[ EARLY_STOPPING_PATIENCE] = EARLY_STOPPING_PATIENCE_DEFAULT_RANGE dict_params = dict([ (N_HIDDEN_SET_UNITS, SET_HIDDEN_UNITS_DEFAULT_RANGE), (N_HIDDEN_SET_LAYERS, SET_LAYERS_DEFAULT_RANGES), (REGULARIZATION_FACTOR, REGULARIZATION_FACTOR_DEFAULT_RANGE) ]) logger.info("Set params {}".format(print_dictionary(dict_params))) for k, v in dict_params.items(): cls._tunable[k] = v cls._tunable = OrderedDict(sorted(cls._tunable.items()))
def set_tunable_parameters(self, alpha=None, n_nests=None, loss_function="", regularization="l1", **point): """ Set tunable parameters of the Nested Logit model to the values provided. Parameters ---------- alpha: float (range : [0,1]) The lower bound of the correlations between the objects in a nest n_nests: int (range : [2,n_objects]) The number of nests in which the objects are divided loss_function : string , {‘categorical_crossentropy’, ‘binary_crossentropy’, ’categorical_hinge’} Loss function to be used for the discrete choice decision from the query set regularization : string, {‘l1’, ‘l2’}, string Regularizer function (L1 or L2) applied to the `kernel` weights matrix point: dict Dictionary containing parameter values which are not tuned for the network """ if alpha is not None: self.alpha = alpha if n_nests is None: self.n_nests = int(self.n_objects / 2) else: self.n_nests = n_nests self.regularization = regularization if loss_function in likelihood_dict.keys(): self.loss_function = likelihood_dict.get(loss_function, None) self.cluster_model = None self.features_nests = None self.model = None self.trace = None self.trace_vi = None self.Xt = None self.Yt = None self.p = None self.y_nests = None self._config = None if len(point) > 0: self.logger.warning( "This ranking algorithm does not support tunable parameters" " called: {}".format(print_dictionary(point)))
def insert_new_jobs_with_different_fold(self, dataset="synthetic_dc", learner="fate_choice", folds=4): self.init_connection() avail_jobs = "{}.avail_jobs".format(self.schema) select_job = "SELECT * FROM {0} WHERE {0}.dataset=\'{1}\' AND {0}.learner =\'{2}\' ORDER BY {0}.job_id".format( avail_jobs, dataset, learner) self.cursor_db.execute(select_job) jobs_all = self.cursor_db.fetchall() for job in jobs_all: job = dict(job) fold_id = job['fold_id'] del job['job_id'] del job['job_allocated_time'] self.logger.info( '###########################################################') self.logger.info(print_dictionary(job)) for f_id in range(folds): job['fold_id'] = fold_id + f_id + 1 columns = ', '.join(list(job.keys())) values_str = [] for i, val in enumerate(job.values()): if isinstance(val, dict): val = json.dumps(val) # elif isinstance(val, str): # val = "\'{}\'".format(str(val)) else: val = str(val) values_str.append(val) if i == 0: values = '%s' else: values = values + ', %s' insert_result = "INSERT INTO {0} ({1}) VALUES ({2})".format( avail_jobs, columns, values) self.logger.info("Inserting results: {} {}".format( insert_result, values_str)) self.cursor_db.execute(insert_result, tuple(values_str)) if self.cursor_db.rowcount == 1: self.logger.info("Results inserted for the job {}".format( job['fold_id'])) self.close_connection()
def construct_model(self, X, Y): self.logger.info('Creating model_args config {}'.format( print_dictionary(self.model_priors))) with pm.Model() as self.model: self.Xt = theano.shared(X) self.Yt = theano.shared(Y) shapes = {'weights': self.n_object_features} # shapes = {'weights': (self.n_object_features, 3)} weights_dict = create_weight_dictionary(self.model_args, shapes) intercept = pm.Normal('intercept', mu=0, sd=10) utility = tt.dot(self.Xt, weights_dict['weights']) + intercept self.p = ttu.softmax(utility, axis=1) yl = LogLikelihood('yl', loss_func=self.loss_function, p=self.p, observed=self.Yt) self.logger.info("Model construction completed")
def set_tunable_parameters(self, loss_function='', regularization="l1", **point): if loss_function in likelihood_dict.keys(): self.loss_function = likelihood_dict.get(loss_function, None) self.regularization = regularization self.model = None self.trace = None self.trace_vi = None self.Xt = None self.Yt = None self.p = None self._config = None if len(point) > 0: self.logger.warning('This ranking algorithm does not support' ' tunable parameters called: {}'.format( print_dictionary(point)))