def model_select(<EOL>self,<EOL>score_function,<EOL>alleles=None,<EOL>min_models=<NUM_LIT:1>,<EOL>max_models=<NUM_LIT>):
if alleles is None:<EOL><INDENT>alleles = self.supported_alleles<EOL><DEDENT>dfs = []<EOL>allele_to_allele_specific_models = {}<EOL>for allele in alleles:<EOL><INDENT>df = pandas.DataFrame({<EOL>'<STR_LIT>': self.allele_to_allele_specific_models[allele]<EOL>})<EOL>df["<STR_LIT>"] = df.index<EOL>df["<STR_LIT>"] = allele<EOL>df["<STR_LIT>"] = False<EOL>round_num = <NUM_LIT:1><EOL>while not df.selected.all() and sum(df.selected) < max_models:<EOL><INDENT>score_col = "<STR_LIT>" % round_num<EOL>prev_score_col = "<STR_LIT>" % (round_num - <NUM_LIT:1>)<EOL>existing_selected = list(df[df.selected].model)<EOL>df[score_col] = [<EOL>numpy.nan if row.selected else<EOL>score_function(<EOL>Class1AffinityPredictor(<EOL>allele_to_allele_specific_models={<EOL>allele: [row.model] + existing_selected<EOL>}<EOL>)<EOL>)<EOL>for (_, row) in df.iterrows()<EOL>]<EOL>if round_num > min_models and (<EOL>df[score_col].max() < df[prev_score_col].max()):<EOL><INDENT>break<EOL><DEDENT>(best_model_index,) = df.loc[<EOL>(df[score_col] == df[score_col].max())<EOL>].sample(<NUM_LIT:1>).index<EOL>df.loc[best_model_index, "<STR_LIT>"] = True<EOL>round_num += <NUM_LIT:1><EOL><DEDENT>dfs.append(df)<EOL>allele_to_allele_specific_models[allele] = list(<EOL>df.loc[df.selected].model)<EOL><DEDENT>df = pandas.concat(dfs, ignore_index=True)<EOL>new_predictor = Class1AffinityPredictor(<EOL>allele_to_allele_specific_models,<EOL>metadata_dataframes={<EOL>"<STR_LIT>": df,<EOL>})<EOL>return new_predictor<EOL>
Perform model selection using a user-specified scoring function.

Model selection is done using a "step up" variable selection procedure,
in which models are repeatedly added to an ensemble until the score
stops improving.

Parameters
----------
score_function : Class1AffinityPredictor -> float function
    Scoring function

alleles : list of string, optional
    If not specified, model selection is performed for all alleles.

min_models : int, optional
    Min models to select per allele

max_models : int, optional
    Max models to select per allele

Returns
-------
Class1AffinityPredictor : predictor containing the selected models