Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save eblancoh/2fcb60c0412a064500d30c8eca732de5 to your computer and use it in GitHub Desktop.
Save eblancoh/2fcb60c0412a064500d30c8eca732de5 to your computer and use it in GitHub Desktop.
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Optimización de Hiperparámetros (Hyperparameter Tuning)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Comenzamos por crear un estimador de **Random Forest** para observar los valores predeterminados de los hiperparámetros disponibles.\n",
"\n",
"Procedemos a imprimir los parámetros sobre los que vamos a hacer una búsqueda más adelante."
]
},
{
"cell_type": "code",
"execution_count": 26,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"{'bootstrap': True,\n",
" 'class_weight': None,\n",
" 'criterion': 'gini',\n",
" 'max_depth': None,\n",
" 'max_features': 'auto',\n",
" 'max_leaf_nodes': None,\n",
" 'min_impurity_decrease': 0.0,\n",
" 'min_impurity_split': None,\n",
" 'min_samples_leaf': 1,\n",
" 'min_samples_split': 2,\n",
" 'min_weight_fraction_leaf': 0.0,\n",
" 'n_estimators': 'warn',\n",
" 'n_jobs': None,\n",
" 'oob_score': False,\n",
" 'random_state': None,\n",
" 'verbose': 0,\n",
" 'warm_start': False}\n"
]
}
],
"source": [
"from pprint import pprint\n",
"pprint(clf.get_params())"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Tuning usando Random Search"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Antes de buscar qué combinación de valores de parámetros conduce al modelo más preciso, debemos especificar los diferentes valores candidatos que queremos probar mediante un simple diccionario. En el siguiente código tenemos una serie de valores de parámetros candidatos, que incluyen varias posibilidades para los siguientes hiperparámetros:\n",
"The hyperparameters which I decided to focus on are:\n",
"\n",
"1. n_estimators: número de estimadores en el Random Forest)\n",
"2. max_features: número máximo de atributos para la partición de nodos; generalmente < número de características en el dataset)\n",
"3. max_depth: número de niveles en cada Decision Tree)\n",
"4. min_samples_split: número mínimo de datos en un nodo antes de que este se parta hacia el siguiente nivel \n",
"5. min_samples_leaf: número mínimo de datos en un único nodo \n",
"5. criterion: métrica usada para fijar el `stopping criteria` de los árboles de decisión"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Importamos `RandomizedSearchCV()` para, definidos los hiperparámetros, crear el estimador que iterará por todas las posibilidades facilitadas:"
]
},
{
"cell_type": "code",
"execution_count": 27,
"metadata": {},
"outputs": [],
"source": [
"from sklearn.model_selection import RandomizedSearchCV"
]
},
{
"cell_type": "code",
"execution_count": 28,
"metadata": {},
"outputs": [],
"source": [
"hyperparameters = {'max_features':[None, 'auto', 'sqrt', 'log2'],\n",
" 'max_depth':[None, 1, 5, 10, 15, 20],\n",
" 'min_samples_leaf': [1, 2, 4],\n",
" 'min_samples_split': [2, 5, 10],\n",
" 'n_estimators': [int(x) for x in np.linspace(start = 10, stop = 100, num = 10)],\n",
" 'criterion': ['gini', 'entropy']}"
]
},
{
"cell_type": "code",
"execution_count": 29,
"metadata": {},
"outputs": [],
"source": [
"rf_random = RandomizedSearchCV(clf, hyperparameters, \n",
" n_iter = 100, \n",
" cv = 10, \n",
" verbose=2, \n",
" random_state=123, \n",
" n_jobs = -1)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Para limitar la búsqueda, primero se ejecuta una validación cruzada de búsqueda aleatoria. Se realiza una búsqueda aleatoria de parámetros usando $k = 10$ veces la validación cruzada (`cv = 10`), en 100 combinaciones diferentes (n_iter = 100) y con todos los núcleos disponibles al mismo tiempo (n_jobs = -1). \n",
"La Random Search selecciona una combinación de características al azar en lugar de iterar en cada combinación posible. Una mayor n_iter y cv dan como resultado más combinaciones y menos posibilidad de overfitting respectivamente."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Ejecutamos la búsqueda aleatoria mediante el entrenamiento de múltiples Random Forest con los parámetros anteriormente definidos permutados. En nuestro caso, la ejecución de esta línea de código tardó unos 9 minutos aproximadamente."
]
},
{
"cell_type": "code",
"execution_count": 30,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Fitting 10 folds for each of 100 candidates, totalling 1000 fits\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"[Parallel(n_jobs=-1)]: Using backend LokyBackend with 4 concurrent workers.\n",
"[Parallel(n_jobs=-1)]: Done 33 tasks | elapsed: 9.4s\n",
"[Parallel(n_jobs=-1)]: Done 154 tasks | elapsed: 1.1min\n",
"[Parallel(n_jobs=-1)]: Done 357 tasks | elapsed: 2.4min\n",
"[Parallel(n_jobs=-1)]: Done 640 tasks | elapsed: 4.1min\n",
"[Parallel(n_jobs=-1)]: Done 1000 out of 1000 | elapsed: 6.4min finished\n"
]
},
{
"data": {
"text/plain": [
"RandomizedSearchCV(cv=10, error_score='raise-deprecating',\n",
" estimator=RandomForestClassifier(bootstrap=True, class_weight=None, criterion='gini',\n",
" max_depth=None, max_features='auto', max_leaf_nodes=None,\n",
" min_impurity_decrease=0.0, min_impurity_split=None,\n",
" min_samples_leaf=1, min_samples_split=2,\n",
" min_weight_fraction_leaf=0.0, n_estimators='warn', n_jobs=None,\n",
" oob_score=False, random_state=None, verbose=0,\n",
" warm_start=False),\n",
" fit_params=None, iid='warn', n_iter=100, n_jobs=-1,\n",
" param_distributions={'max_features': [None, 'auto', 'sqrt', 'log2'], 'max_depth': [None, 1, 5, 10, 15, 20], 'min_samples_leaf': [1, 2, 4], 'min_samples_split': [2, 5, 10], 'n_estimators': [10, 20, 30, 40, 50, 60, 70, 80, 90, 100], 'criterion': ['gini', 'entropy']},\n",
" pre_dispatch='2*n_jobs', random_state=123, refit=True,\n",
" return_train_score='warn', scoring=None, verbose=2)"
]
},
"execution_count": 30,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"rf_random.fit(x_train, y_train)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Mediante el siguiente comando podemos visualizar los mejores parámetros tras este proceso combinado de validación cruzada y finetuning de parámetros:"
]
},
{
"cell_type": "code",
"execution_count": 31,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{'criterion': 'entropy',\n",
" 'max_depth': None,\n",
" 'max_features': None,\n",
" 'min_samples_leaf': 1,\n",
" 'min_samples_split': 2,\n",
" 'n_estimators': 80}"
]
},
"execution_count": 31,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"rf_random.best_params_"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"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.6.7"
},
"latex_envs": {
"LaTeX_envs_menu_present": true,
"autoclose": false,
"autocomplete": true,
"bibliofile": "biblio.bib",
"cite_by": "apalike",
"current_citInitial": 1,
"eqLabelWithNumbers": true,
"eqNumInitial": 1,
"hotkeys": {
"equation": "Ctrl-E",
"itemize": "Ctrl-I"
},
"labels_anchors": false,
"latex_user_defs": false,
"report_style_numbering": false,
"user_envs_cfg": false
},
"toc": {
"base_numbering": 1,
"nav_menu": {},
"number_sections": true,
"sideBar": true,
"skip_h1_title": false,
"title_cell": "Table of Contents",
"title_sidebar": "Contents",
"toc_cell": true,
"toc_position": {},
"toc_section_display": true,
"toc_window_display": false
}
},
"nbformat": 4,
"nbformat_minor": 2
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment