{ "cells": [ { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "Objective functions can optionally take in step, budget, and generations.\n", "\n", "step - The same objective function will be run for #evaluation_early_stop_steps, the current step will be passed into the function as an interger. (This is useful for getting a single fold of cross validation for example).\n", "\n", "budget - A parameter that varies over the course of the generations. Gets passed into the objective function as a float between 0 and 1. If the budget of the previous evaluation is less than the current budget, it will get re-evaluated. Useful for using smaller datasets earlier in training.\n", "\n", "generations - an int corresponding to the current generation number.\n" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "/opt/anaconda3/envs/tpotenv/lib/python3.10/site-packages/tqdm/auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html\n", " from .autonotebook import tqdm as notebook_tqdm\n", "Generation: 100%|██████████| 100/100 [01:43<00:00, 1.03s/it]\n" ] } ], "source": [ "#knapsack problem\n", "import numpy as np\n", "import tpot\n", "import random\n", "import matplotlib.pyplot as plt\n", "from dask.distributed import Client, LocalCluster\n", "\n", "class SubsetSelector(tpot.individual.BaseIndividual):\n", " def __init__( self,\n", " values,\n", " initial_set = None,\n", " k=1, #step size for shuffling\n", " ):\n", "\n", " if isinstance(values, int):\n", " self.values = set(range(0,values))\n", " else:\n", " self.values = set(values)\n", "\n", "\n", " if initial_set is None:\n", " self.subsets = set(random.choices(values, k=k))\n", " else:\n", " self.subsets = set(initial_set)\n", "\n", " self.k = k\n", "\n", " self.mutation_list = [self._mutate_add, self._mutate_remove]\n", " self.crossover_list = [self._crossover_swap]\n", " \n", "\n", " def mutate(self, rng=None):\n", " mutation_list_copy = self.mutation_list.copy()\n", " random.shuffle(mutation_list_copy)\n", " for func in mutation_list_copy:\n", " if func():\n", " return True\n", " return False\n", "\n", " def crossover(self, ind2, rng=None):\n", " crossover_list_copy = self.crossover_list.copy()\n", " random.shuffle(crossover_list_copy)\n", " for func in crossover_list_copy:\n", " if func(ind2):\n", " return True\n", " return False\n", "\n", " def _mutate_add(self,):\n", " not_included = list(self.values.difference(self.subsets))\n", " if len(not_included) > 1:\n", " self.subsets.update(random.sample(not_included, k=min(self.k, len(not_included))))\n", " return True\n", " else:\n", " return False\n", "\n", " def _mutate_remove(self,):\n", " if len(self.subsets) > 1:\n", " self.subsets = self.subsets - set(random.sample(list(self.subsets), k=min(self.k, len(self.subsets)-1) ))\n", "\n", " def _crossover_swap(self, ss2):\n", " diffs = self.subsets.symmetric_difference(ss2.subsets)\n", "\n", " if len(diffs) == 0:\n", " return False\n", " for v in diffs:\n", " self.subsets.discard(v)\n", " ss2.subsets.discard(v)\n", " random.choice([self.subsets, ss2.subsets]).add(v)\n", " \n", " return True\n", "\n", " def unique_id(self):\n", " return str(tuple(sorted(self.subsets)))\n", "\n", "def individual_generator():\n", " while True:\n", " yield SubsetSelector(values=np.arange(len(values)))\n", "\n", "\n", "values = np.random.randint(200,size=100)\n", "weights = np.random.random(200)*10\n", "max_weight = 50\n", "\n", "def simple_objective(ind, **kwargs):\n", " subset = np.array(list(ind.subsets))\n", " if len(subset) == 0:\n", " return 0, 0\n", "\n", " total_weight = np.sum(weights[subset])\n", " total_value = np.sum(values[subset])\n", "\n", " if total_weight > max_weight:\n", " total_value = 0\n", "\n", " return total_value, total_weight\n", "\n", "objective_names = [\"Value\", \"Weight\"]\n", "objective_function_weights = [1,-1]\n", "\n", "\n", "\n", "evolver = tpot.evolvers.BaseEvolver( individual_generator=individual_generator(), \n", " objective_functions=[simple_objective],\n", " objective_function_weights = objective_function_weights,\n", " bigger_is_better = True,\n", " population_size= 100,\n", " objective_names = objective_names,\n", " generations= 100,\n", " n_jobs=32,\n", " verbose = 1,\n", "\n", ")\n", "\n", "evolver.optimize()" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "best subset {1, 8, 9, 16, 17, 22, 23, 24, 28, 29, 31, 42, 43, 48, 50, 61, 62, 68, 80, 89, 91, 97, 98}\n", "Best value 3070.0, weight 49.01985602703945\n", "\n", "All results\n" ] }, { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Selected IndexValueWeightParentsVariation_FunctionIndividualGenerationSubmitted TimestampCompleted TimestampEval ErrorPareto_Front
0(40,)89.09.883465NaNNaN<__main__.SubsetSelector object at 0x32aa80eb0>0.01.740209e+091.740209e+09NoneNaN
1(45,)116.06.643557NaNNaN<__main__.SubsetSelector object at 0x32aa83b50>0.01.740209e+091.740209e+09NoneNaN
2(52,)172.09.273163NaNNaN<__main__.SubsetSelector object at 0x32aa81210>0.01.740209e+091.740209e+09NoneNaN
3(33,)112.01.594347NaNNaN<__main__.SubsetSelector object at 0x32aa838e0>0.01.740209e+091.740209e+09NoneNaN
4(37,)90.03.273826NaNNaN<__main__.SubsetSelector object at 0x32aa83e50>0.01.740209e+091.740209e+09NoneNaN
....................................
9995(1, 9, 16, 23, 24, 31, 77, 79)998.011.622582((1, 9, 16, 17, 23, 24, 31, 77), (1, 9, 16, 17...ind_mutate<__main__.SubsetSelector object at 0x3a739b010>99.01.740209e+091.740209e+09NoneNaN
9996(1, 8, 9, 16, 22, 23, 24, 28, 29, 31, 48, 49, ...0.051.400433((1, 8, 9, 16, 17, 22, 23, 24, 28, 29, 31, 48,...ind_mutate<__main__.SubsetSelector object at 0x3af9a4460>99.01.740209e+091.740209e+09NoneNaN
9997(1, 4, 8, 9, 16, 17, 23, 24, 31, 49, 68, 77, 8...1728.015.997430((1, 4, 8, 9, 16, 17, 23, 24, 31, 68, 77, 88, ...ind_mutate<__main__.SubsetSelector object at 0x3aa303430>99.01.740209e+091.740209e+09None1.0
9998(8, 9, 17, 23, 24, 25, 31, 51, 77)972.011.991547((8, 9, 17, 23, 24, 31, 77, 88), (8, 9, 17, 23...ind_mutate<__main__.SubsetSelector object at 0x3a7399600>99.01.740209e+091.740209e+09NoneNaN
9999(8, 23, 24, 73, 79)648.012.109013((8, 16, 17, 23, 24), (8, 16, 17, 23, 24))ind_mutate<__main__.SubsetSelector object at 0x3a88d4430>99.01.740209e+091.740209e+09NoneNaN
\n", "

10000 rows × 11 columns

\n", "
" ], "text/plain": [ " Selected Index Value Weight \\\n", "0 (40,) 89.0 9.883465 \n", "1 (45,) 116.0 6.643557 \n", "2 (52,) 172.0 9.273163 \n", "3 (33,) 112.0 1.594347 \n", "4 (37,) 90.0 3.273826 \n", "... ... ... ... \n", "9995 (1, 9, 16, 23, 24, 31, 77, 79) 998.0 11.622582 \n", "9996 (1, 8, 9, 16, 22, 23, 24, 28, 29, 31, 48, 49, ... 0.0 51.400433 \n", "9997 (1, 4, 8, 9, 16, 17, 23, 24, 31, 49, 68, 77, 8... 1728.0 15.997430 \n", "9998 (8, 9, 17, 23, 24, 25, 31, 51, 77) 972.0 11.991547 \n", "9999 (8, 23, 24, 73, 79) 648.0 12.109013 \n", "\n", " Parents Variation_Function \\\n", "0 NaN NaN \n", "1 NaN NaN \n", "2 NaN NaN \n", "3 NaN NaN \n", "4 NaN NaN \n", "... ... ... \n", "9995 ((1, 9, 16, 17, 23, 24, 31, 77), (1, 9, 16, 17... ind_mutate \n", "9996 ((1, 8, 9, 16, 17, 22, 23, 24, 28, 29, 31, 48,... ind_mutate \n", "9997 ((1, 4, 8, 9, 16, 17, 23, 24, 31, 68, 77, 88, ... ind_mutate \n", "9998 ((8, 9, 17, 23, 24, 31, 77, 88), (8, 9, 17, 23... ind_mutate \n", "9999 ((8, 16, 17, 23, 24), (8, 16, 17, 23, 24)) ind_mutate \n", "\n", " Individual Generation \\\n", "0 <__main__.SubsetSelector object at 0x32aa80eb0> 0.0 \n", "1 <__main__.SubsetSelector object at 0x32aa83b50> 0.0 \n", "2 <__main__.SubsetSelector object at 0x32aa81210> 0.0 \n", "3 <__main__.SubsetSelector object at 0x32aa838e0> 0.0 \n", "4 <__main__.SubsetSelector object at 0x32aa83e50> 0.0 \n", "... ... ... \n", "9995 <__main__.SubsetSelector object at 0x3a739b010> 99.0 \n", "9996 <__main__.SubsetSelector object at 0x3af9a4460> 99.0 \n", "9997 <__main__.SubsetSelector object at 0x3aa303430> 99.0 \n", "9998 <__main__.SubsetSelector object at 0x3a7399600> 99.0 \n", "9999 <__main__.SubsetSelector object at 0x3a88d4430> 99.0 \n", "\n", " Submitted Timestamp Completed Timestamp Eval Error Pareto_Front \n", "0 1.740209e+09 1.740209e+09 None NaN \n", "1 1.740209e+09 1.740209e+09 None NaN \n", "2 1.740209e+09 1.740209e+09 None NaN \n", "3 1.740209e+09 1.740209e+09 None NaN \n", "4 1.740209e+09 1.740209e+09 None NaN \n", "... ... ... ... ... \n", "9995 1.740209e+09 1.740209e+09 None NaN \n", "9996 1.740209e+09 1.740209e+09 None NaN \n", "9997 1.740209e+09 1.740209e+09 None 1.0 \n", "9998 1.740209e+09 1.740209e+09 None NaN \n", "9999 1.740209e+09 1.740209e+09 None NaN \n", "\n", "[10000 rows x 11 columns]" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "final_population_results = evolver.population.evaluated_individuals\n", "final_population_results.reset_index(inplace=True)\n", "final_population_results = final_population_results.rename(columns = {'index':'Selected Index'})\n", "\n", "best_idx = final_population_results[\"Value\"].idxmax()\n", "best_individual = final_population_results.loc[best_idx]['Individual']\n", "print(\"best subset\", best_individual.subsets)\n", "print(\"Best value {0}, weight {1}\".format(final_population_results.loc[best_idx, \"Value\"],final_population_results.loc[best_idx, \"Weight\"]))\n", "print()\n", "\n", "print(\"All results\")\n", "final_population_results" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "data": { "image/png": "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", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "from scipy.stats import binned_statistic_2d\n", "\n", "y = final_population_results[\"Value\"]\n", "x = final_population_results[\"Weight\"]\n", "c = final_population_results[\"Generation\"]\n", "\n", "x_bins = np.linspace(0, 100, 100)\n", "y_bins = np.linspace(0, 3000, 100)\n", "\n", "ret = binned_statistic_2d(x, y, c, statistic=np.mean, bins=[x_bins, y_bins])\n", "\n", "fig, ax1 = plt.subplots(1, 1, figsize=(12, 4))\n", "\n", "im = ax1.imshow(ret.statistic.T, origin='lower', extent=(0,100,0,3000), vmin=0, vmax=100, aspect=.03)\n", "ax1.set_xlabel(\"Weight\")\n", "ax1.set_ylabel(\"Value\")\n", "ax1.set_title(\"Binned Average Generation\")\n", "\n", "cbar = fig.colorbar(im,)\n", "cbar.set_label('Generation')\n", "plt.tight_layout()" ] } ], "metadata": { "kernelspec": { "display_name": "tpotenv", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.10.16" }, "orig_nbformat": 4 }, "nbformat": 4, "nbformat_minor": 2 }