def fit(<EOL>self,<EOL>peptides,<EOL>affinities,<EOL>allele_encoding=None,<EOL>inequalities=None,<EOL>sample_weights=None,<EOL>shuffle_permutation=None,<EOL>verbose=<NUM_LIT:1>,<EOL>progress_preamble="<STR_LIT>",<EOL>progress_print_interval=<NUM_LIT>):
encodable_peptides = EncodableSequences.create(peptides)<EOL>peptide_encoding = self.peptides_to_network_input(encodable_peptides)<EOL>length_counts = (<EOL>pandas.Series(encodable_peptides.sequences)<EOL>.str.len().value_counts().to_dict())<EOL>num_random_negative = {}<EOL>for length in range(<NUM_LIT:8>, <NUM_LIT:16>):<EOL><INDENT>num_random_negative[length] = int(<EOL>length_counts.get(length, <NUM_LIT:0>) *<EOL>self.hyperparameters['<STR_LIT>'] +<EOL>self.hyperparameters['<STR_LIT>'])<EOL><DEDENT>num_random_negative = pandas.Series(num_random_negative)<EOL>logging.info("<STR_LIT>" % (<EOL>str(num_random_negative.to_dict())))<EOL>aa_distribution = None<EOL>if self.hyperparameters['<STR_LIT>']:<EOL><INDENT>aa_distribution = amino_acid_distribution(<EOL>encodable_peptides.sequences,<EOL>smoothing=self.hyperparameters[<EOL>'<STR_LIT>'])<EOL>logging.info(<EOL>"<STR_LIT>" % (<EOL>str(aa_distribution.to_dict())))<EOL><DEDENT>y_values = from_ic50(affinities)<EOL>assert numpy.isnan(y_values).sum() == <NUM_LIT:0>, numpy.isnan(y_values).sum()<EOL>if inequalities is not None:<EOL><INDENT>adjusted_inequalities = pandas.Series(inequalities).map({<EOL>"<STR_LIT:=>": "<STR_LIT:=>",<EOL>"<STR_LIT:>>": "<STR_LIT:<>",<EOL>"<STR_LIT:<>": "<STR_LIT:>>",<EOL>}).values<EOL><DEDENT>else:<EOL><INDENT>adjusted_inequalities = numpy.tile("<STR_LIT:=>", len(y_values))<EOL><DEDENT>if len(adjusted_inequalities) != len(y_values):<EOL><INDENT>raise ValueError("<STR_LIT>")<EOL><DEDENT>x_dict_without_random_negatives = {<EOL>'<STR_LIT>': peptide_encoding,<EOL>}<EOL>allele_encoding_dims = None<EOL>if allele_encoding is not None:<EOL><INDENT>allele_encoding_input = self.allele_encoding_to_network_input(<EOL>allele_encoding)<EOL>allele_encoding_dims = allele_encoding_input.shape[<NUM_LIT:1>:]<EOL>x_dict_without_random_negatives['<STR_LIT>'] = allele_encoding_input<EOL><DEDENT>if shuffle_permutation is None:<EOL><INDENT>shuffle_permutation = numpy.random.permutation(len(y_values))<EOL><DEDENT>y_values = y_values[shuffle_permutation]<EOL>peptide_encoding = peptide_encoding[shuffle_permutation]<EOL>adjusted_inequalities = adjusted_inequalities[shuffle_permutation]<EOL>for key in x_dict_without_random_negatives:<EOL><INDENT>x_dict_without_random_negatives[key] = (<EOL>x_dict_without_random_negatives[key][shuffle_permutation])<EOL><DEDENT>if sample_weights is not None:<EOL><INDENT>sample_weights = sample_weights[shuffle_permutation]<EOL><DEDENT>if self.hyperparameters['<STR_LIT>'].startswith("<STR_LIT>"):<EOL><INDENT>try:<EOL><INDENT>custom_loss = CUSTOM_LOSSES[<EOL>self.hyperparameters['<STR_LIT>'].replace("<STR_LIT>", "<STR_LIT>")<EOL>]<EOL><DEDENT>except KeyError:<EOL><INDENT>raise ValueError(<EOL>"<STR_LIT>" % (<EOL>self.hyperparameters['<STR_LIT>'],<EOL>"<STR_LIT:U+002CU+0020>".join([<EOL>"<STR_LIT>" + loss_name for loss_name in CUSTOM_LOSSES<EOL>])))<EOL><DEDENT>loss_name_or_function = custom_loss.loss<EOL>loss_supports_inequalities = custom_loss.supports_inequalities<EOL>loss_encode_y_function = custom_loss.encode_y<EOL><DEDENT>else:<EOL><INDENT>loss_name_or_function = self.hyperparameters['<STR_LIT>']<EOL>loss_supports_inequalities = False<EOL>loss_encode_y_function = None<EOL><DEDENT>if not loss_supports_inequalities and (<EOL>any(inequality != "<STR_LIT:=>" for inequality in adjusted_inequalities)):<EOL><INDENT>raise ValueError("<STR_LIT>" % (<EOL>loss_name_or_function))<EOL><DEDENT>if self.network() is None:<EOL><INDENT>self._network = self.make_network(<EOL>allele_encoding_dims=allele_encoding_dims,<EOL>**self.network_hyperparameter_defaults.subselect(<EOL>self.hyperparameters))<EOL>self.network().compile(<EOL>loss=loss_name_or_function,<EOL>optimizer=self.hyperparameters['<STR_LIT>'])<EOL><DEDENT>if self.hyperparameters['<STR_LIT>'] is not None:<EOL><INDENT>from keras import backend as K<EOL>K.set_value(<EOL>self.network().optimizer.lr,<EOL>self.hyperparameters['<STR_LIT>'])<EOL><DEDENT>if loss_supports_inequalities:<EOL><INDENT>random_negative_ic50 = self.hyperparameters['<STR_LIT>']<EOL>random_negative_target = from_ic50(random_negative_ic50)<EOL>y_dict_with_random_negatives = {<EOL>"<STR_LIT>": numpy.concatenate([<EOL>numpy.tile(<EOL>random_negative_target, int(num_random_negative.sum())),<EOL>y_values,<EOL>]),<EOL>}<EOL>adjusted_inequalities_with_random_negatives = (<EOL>["<STR_LIT:<>"] * int(num_random_negative.sum()) +<EOL>list(adjusted_inequalities))<EOL><DEDENT>else:<EOL><INDENT>y_dict_with_random_negatives = {<EOL>"<STR_LIT>": numpy.concatenate([<EOL>from_ic50(<EOL>numpy.random.uniform(<EOL>self.hyperparameters[<EOL>'<STR_LIT>'],<EOL>self.hyperparameters[<EOL>'<STR_LIT>'],<EOL>int(num_random_negative.sum()))),<EOL>y_values,<EOL>]),<EOL>}<EOL><DEDENT>if sample_weights is not None:<EOL><INDENT>sample_weights_with_random_negatives = numpy.concatenate([<EOL>numpy.ones(int(num_random_negative.sum())),<EOL>sample_weights])<EOL><DEDENT>else:<EOL><INDENT>sample_weights_with_random_negatives = None<EOL><DEDENT>if loss_encode_y_function is not None:<EOL><INDENT>y_dict_with_random_negatives['<STR_LIT>'] = loss_encode_y_function(<EOL>y_dict_with_random_negatives['<STR_LIT>'],<EOL>adjusted_inequalities_with_random_negatives)<EOL><DEDENT>val_losses = []<EOL>min_val_loss_iteration = None<EOL>min_val_loss = None<EOL>fit_info = collections.defaultdict(list)<EOL>start = time.time()<EOL>last_progress_print = None<EOL>x_dict_with_random_negatives = {}<EOL>for i in range(self.hyperparameters['<STR_LIT>']):<EOL><INDENT>random_negative_peptides_list = []<EOL>for (length, count) in num_random_negative.iteritems():<EOL><INDENT>random_negative_peptides_list.extend(<EOL>random_peptides(<EOL>count,<EOL>length=length,<EOL>distribution=aa_distribution))<EOL><DEDENT>random_negative_peptides = EncodableSequences.create(<EOL>random_negative_peptides_list)<EOL>random_negative_peptides_encoding = (<EOL>self.peptides_to_network_input(random_negative_peptides))<EOL>if not x_dict_with_random_negatives:<EOL><INDENT>if len(random_negative_peptides) > <NUM_LIT:0>:<EOL><INDENT>x_dict_with_random_negatives["<STR_LIT>"] = numpy.concatenate([<EOL>random_negative_peptides_encoding,<EOL>peptide_encoding,<EOL>])<EOL>if '<STR_LIT>' in x_dict_without_random_negatives:<EOL><INDENT>x_dict_with_random_negatives['<STR_LIT>'] = numpy.concatenate([<EOL>x_dict_without_random_negatives['<STR_LIT>'][<EOL>numpy.random.choice(<EOL>x_dict_without_random_negatives[<EOL>'<STR_LIT>'].shape[<NUM_LIT:0>],<EOL>size=len(random_negative_peptides_list))],<EOL>x_dict_without_random_negatives['<STR_LIT>']<EOL>])<EOL><DEDENT><DEDENT>else:<EOL><INDENT>x_dict_with_random_negatives = (<EOL>x_dict_without_random_negatives)<EOL><DEDENT><DEDENT>else:<EOL><INDENT>if len(random_negative_peptides) > <NUM_LIT:0>:<EOL><INDENT>x_dict_with_random_negatives["<STR_LIT>"][:len(random_negative_peptides)] = (<EOL>random_negative_peptides_encoding<EOL>)<EOL>if '<STR_LIT>' in x_dict_with_random_negatives:<EOL><INDENT>x_dict_with_random_negatives['<STR_LIT>'][:len(random_negative_peptides)] = (<EOL>x_dict_with_random_negatives['<STR_LIT>'][<EOL>len(random_negative_peptides) + numpy.random.choice(<EOL>x_dict_with_random_negatives['<STR_LIT>'].shape[<NUM_LIT:0>] -<EOL>len(random_negative_peptides),<EOL>size=len(random_negative_peptides))<EOL>]<EOL>)<EOL><DEDENT><DEDENT><DEDENT>fit_history = self.network().fit(<EOL>x_dict_with_random_negatives,<EOL>y_dict_with_random_negatives,<EOL>shuffle=True,<EOL>batch_size=self.hyperparameters['<STR_LIT>'],<EOL>verbose=verbose,<EOL>epochs=<NUM_LIT:1>,<EOL>validation_split=self.hyperparameters['<STR_LIT>'],<EOL>sample_weight=sample_weights_with_random_negatives)<EOL>for (key, value) in fit_history.history.items():<EOL><INDENT>fit_info[key].extend(value)<EOL><DEDENT>if progress_print_interval is not None and (<EOL>not last_progress_print or (<EOL>time.time() - last_progress_print<EOL>> progress_print_interval)):<EOL><INDENT>print((progress_preamble + "<STR_LIT:U+0020>" +<EOL>"<STR_LIT>"<EOL>"<STR_LIT>" % (<EOL>i,<EOL>self.hyperparameters['<STR_LIT>'],<EOL>fit_info['<STR_LIT>'][-<NUM_LIT:1>],<EOL>str(min_val_loss),<EOL>min_val_loss_iteration)).strip())<EOL>last_progress_print = time.time()<EOL><DEDENT>if self.hyperparameters['<STR_LIT>']:<EOL><INDENT>val_loss = fit_info['<STR_LIT>'][-<NUM_LIT:1>]<EOL>val_losses.append(val_loss)<EOL>if min_val_loss is None or val_loss <= min_val_loss:<EOL><INDENT>min_val_loss = val_loss<EOL>min_val_loss_iteration = i<EOL><DEDENT>if self.hyperparameters['<STR_LIT>']:<EOL><INDENT>threshold = (<EOL>min_val_loss_iteration +<EOL>self.hyperparameters['<STR_LIT>'])<EOL>if i > threshold:<EOL><INDENT>if progress_print_interval is not None:<EOL><INDENT>print((progress_preamble + "<STR_LIT:U+0020>" +<EOL>"<STR_LIT>"<EOL>"<STR_LIT>" % (<EOL>i,<EOL>self.hyperparameters['<STR_LIT>'],<EOL>fit_info['<STR_LIT>'][-<NUM_LIT:1>],<EOL>str(min_val_loss),<EOL>min_val_loss_iteration)).strip())<EOL><DEDENT>break<EOL><DEDENT><DEDENT><DEDENT><DEDENT>fit_info["<STR_LIT:time>"] = time.time() - start<EOL>fit_info["<STR_LIT>"] = len(peptides)<EOL>self.fit_info.append(dict(fit_info))<EOL>
Fit the neural network.

Parameters
----------
peptides : EncodableSequences or list of string

affinities : list of float
    nM affinities. Must be same length of as peptides.

allele_encoding : AlleleEncoding, optional
    If not specified, the model will be a single-allele predictor.

inequalities : list of string, each element one of ">", "<", or "=".
    Inequalities to use for fitting. Same length as affinities.
    Each element must be one of ">", "<", or "=". For example, a ">"
    will train on y_pred > y_true for that element in the training set.
    Requires using a custom losses that support inequalities (e.g.
    mse_with_ineqalities).
    If None all inequalities are taken to be "=".

sample_weights : list of float, optional
    If not specified, all samples (including random negatives added
    during training) will have equal weight. If specified, the random
    negatives will be assigned weight=1.0.

shuffle_permutation : list of int, optional
    Permutation (integer list) of same length as peptides and affinities
    If None, then a random permutation will be generated.

verbose : int
    Keras verbosity level

progress_preamble : string
    Optional string of information to include in each progress update

progress_print_interval : float
    How often (in seconds) to print progress update. Set to None to
    disable.