{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# MNIST classification using Extreme Learning Machines\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", "import time\n", "from scipy.stats import uniform\n", "from sklearn.base import clone\n", "from sklearn.datasets import fetch_openml\n", "from sklearn.linear_model import Ridge\n", "from sklearn.preprocessing import MinMaxScaler\n", "from sklearn.model_selection import RandomizedSearchCV, GridSearchCV, StratifiedKFold, ParameterGrid, cross_validate\n", "from sklearn.utils.fixes import loguniform\n", "from sklearn.metrics import accuracy_score\n", "\n", "from pyrcn.model_selection import SequentialSearchCV\n", "from pyrcn.extreme_learning_machine import ELMClassifier" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Load the dataset" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "X, y = fetch_openml('mnist_784', version=1, return_X_y=True, as_frame=False)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Train test split. \n", "Normalize to a range between [-1, 1]." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "X = MinMaxScaler(feature_range=(-1,1)).fit_transform(X=X)\n", "X_train, X_test = X[:60000], X[60000:]\n", "y_train, y_test = y[:60000].astype(int), y[60000:].astype(int)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Prepare sequential hyperparameter tuning" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "initially_fixed_params = {'hidden_layer_size': 500,\n", " 'input_activation': 'tanh',\n", " 'k_in': 10,\n", " 'bias_scaling': 0.0,\n", " 'alpha': 1e-5,\n", " 'random_state': 42}\n", "\n", "step1_params = {'input_scaling': loguniform(1e-5, 1e1)}\n", "kwargs1 = {'random_state': 42,\n", " 'verbose': 1,\n", " 'n_jobs': -1,\n", " 'n_iter': 50,\n", " 'scoring': 'accuracy'}\n", "step2_params = {'bias_scaling': np.linspace(0.0, 1.6, 16)}\n", "kwargs2 = {'verbose': 5,\n", " 'n_jobs': -1,\n", " 'scoring': 'accuracy'}\n", "\n", "elm = ELMClassifier(regressor=Ridge(), **initially_fixed_params)\n", "\n", "# The searches are defined similarly to the steps of a sklearn.pipeline.Pipeline:\n", "searches = [('step1', RandomizedSearchCV, step1_params, kwargs1),\n", " ('step2', GridSearchCV, step2_params, kwargs2)]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Perform the sequential search" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "sequential_search = SequentialSearchCV(elm, searches=searches).fit(X_train, y_train)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "best_params = sequential_search.best_estimator_.get_params()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Test\n", "Increase reservoir size and compare different regression methods. Make sure that you have enough RAM for that, because all regression types without chunk size require a lot of memory. This is the reason why, especially for large datasets, the incremental regression is recommeded." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "base_elm_ridge = ELMClassifier(regressor=Ridge(), **best_params)\n", "base_elm_inc = ELMClassifier(**best_params)\n", "base_elm_inc_chunk = clone(base_elm_inc).set_params(chunk_size=6000)\n", "\n", "param_grid = {'hidden_layer_size': [500, 1000, 2000, 4000, 8000, 16000]}\n", "\n", "print(\"CV results\\tFit time\\tInference time\\tAccuracy score\\tSize[Bytes]\")\n", "for params in ParameterGrid(param_grid):\n", " elm_ridge_cv = cross_validate(clone(base_elm_ridge).set_params(**params), X=X_train, y=y_train)\n", " t1 = time.time()\n", " elm_ridge = clone(base_elm_ridge).set_params(**params).fit(X_train, y_train)\n", " t_fit = time.time() - t1\n", " mem_size = elm_ridge.__sizeof__()\n", " t1 = time.time()\n", " acc_score = accuracy_score(y_test, elm_ridge.predict(X_test))\n", " t_inference = time.time() - t1\n", " print(\"{0}\\t{1}\\t{2}\\t{3}\\t{4}\".format(elm_ridge_cv, t_fit, t_inference, acc_score, mem_size))\n", " elm_inc_cv = cross_validate(clone(base_elm_inc).set_params(**params), X=X_train, y=y_train)\n", " t1 = time.time()\n", " elm_inc = clone(base_elm_inc).set_params(**params).fit(X_train, y_train)\n", " t_fit = time.time() - t1\n", " mem_size = elm_inc.__sizeof__()\n", " t1 = time.time()\n", " acc_score = accuracy_score(y_test, elm_inc.predict(X_test))\n", " t_inference = time.time() - t1\n", " print(\"{0}\\t{1}\\t{2}\\t{3}\\t{4}\".format(elm_inc_cv, t_fit, t_inference, acc_score, mem_size))\n", " elm_inc_chunk_cv = cross_validate(clone(base_elm_inc_chunk).set_params(**params), X=X_train, y=y_train)\n", " t1 = time.time()\n", " elm_inc_chunk = clone(base_elm_inc_chunk).set_params(**params).fit(X_train, y_train)\n", " t_fit = time.time() - t1\n", " mem_size = elm_inc_chunk.__sizeof__()\n", " t1 = time.time()\n", " acc_score = accuracy_score(y_test, elm_inc_chunk.predict(X_test))\n", " t_inference = time.time() - t1\n", " print(\"{0}\\t{1}\\t{2}\\t{3}\\t{4}\".format(elm_inc_chunk_cv, t_fit, t_inference, acc_score, mem_size))" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "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.4" } }, "nbformat": 4, "nbformat_minor": 4 }