{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "[](https://colab.research.google.com/github/bgoujaud/PEPit/blob/master/ressources/demo/PEPit_demo.ipynb)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# PEPit : numerical examples of worst-case analyses" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This notebook provides:\n", "- a simple example illustrating how to obtain a worst-case guarantee for **gradient descent** using the PEPit package,\n", "- worst-case analyses for 4 more advanced examples, for which we compare analytical and numerical worst-case guarantees, respectively obtained in the literature and by PEPit. \n", "\n", "In short, PEPit is a package enabling **computer-assisted worst-case analyses** of first-order optimization methods. The key underlying idea is to cast the problem of performing a worst-case analysis, often referred to as a performance estimation problem (PEP), as a semidefinite program (SDP) which can be solved numerically. For doing that, the package users are only required to write first-order methods nearly as they would have implemented them. The package then takes care of the SDP modelling parts, and the worst-case analysis is performed numerically via a standard solver.\n", "\n", "\n", "PEPit can be installed following these [instructions](https://pypi.org/project/PEPit/), and a quickstart is available in its [documentation](https://pepit.readthedocs.io/en/latest/). More information can be found in the [PEPit reference paper](https://arxiv.org/pdf/2201.04040.pdf). \n", "\n", "We refer to [this blog post](https://francisbach.com/computer-aided-analyses/) and the references therein for a more mathematical introduction to performance estimation problems." ] }, { "cell_type": "markdown", "metadata": { "toc": true }, "source": [ "\n", "## Table of Contents\n", "- [1 Installing PEPit](#1-Installing-PEPit)\n", "- [2 How to obtain a worst-case guarantee for GD using PEPit](#2-How-to-obtain-a-worst-case-guarantee-for-GD-using-PEPit)\n", " - [2.1 Imports](#2.1-Imports)\n", " - [2.2 Initialization of PEPit](#2.2-Initialization-of-PEPit)\n", " - [2.3 Choose parameters values](#2.3-Choose-parameters-values)\n", " - [2.4 Specifying the problem class](#2.4-Specifying-the-problem-class)\n", " - [2.5 Algorithm initialization](#2.5-Algorithm-initialization)\n", " - [2.6 Algorithm implementation](#2.6-Algorithm-implementation)\n", " - [2.7 Setting up a performance measure](#2.7-Setting-up-a-performance-measure)\n", " - [2.8 Solving the PEP](#2.8-Solving-the-PEP)\n", " - [2.9 Analytical upper bound comparison](#2.9-Comparing-to-the-an-(established)-analytical-upper-bound-(worst-case-guarantee)-provided-by-the-literature)\n", " - [2.10 Conclusion](#2.10-Conclusion)\n", "- [3 Comparison of analytical and numerical worst-case guarantees](#3-Comparison-of-analytical-(obtained-in-the-literature)-and-numerical-(obtained-by-PEPit)-worst-case-guarantees-on-4-more-advanced-methods)\n", " - [3.1 Example 1: GD with fixed step size](#3.1-Example-1-:-Gradient-descent-with-fixed-step-size-in-contraction)\n", " - [3.1.1 Worst-case guarantees as functions of the iteration count](#3.1.1-Worst-case-guarantees-as-functions-of-the-iteration-count)\n", " - [3.1.2 Worst-case guarantees as functions of the step size](#3.1.2-Worst-case-guarantees-as-functions-of-the-step-size)\n", " - [3.2 Example 2: Accelerated gradient method](#3.2-Example-2-:-An-accelerated-gradient-method-for-strongly-convex-objectives)\n", " - [3.3 Example 3: Accelerated Douglas-Rachford splitting](#3.3-Example-3-:-An-accelerated-Douglas-Rachford-splitting)\n", " - [3.4 Example 4: point-SAGA](#3.4-Example-4-:-point-SAGA)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 1 Installing PEPit" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [] }, "outputs": [], "source": [ "# If PEPit is not installed yet, you can run this cell.\n", "!pip3 install pepit;" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "
" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 2 How to obtain a worst-case guarantee for GD using PEPit" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In this section, we provide a step-by-step tutorial on how to use PEPit to compute a worst-case guarantee for gradient descent.\n", "\n", "That is, we consider the minimization problem\n", "\n", "$$\\min_{x} f(x),$$\n", "\n", "where $f$ os an $L$-smooth convex function which is minimized at $x_*$. We denote by $x_n$ the output of gradient descent with step-size $\\gamma$ after $n\\in\\mathbb{N}$ iterations, starting from $x_0$. We perform a worst-case analysis in the following sense: we compute the smallest possible value of $\\tau(L,\\gamma,n)$ such that\n", "\n", "$$ f(x_{n})-f(x_*) \\leqslant\\ \\tau(L,\\gamma,n)\\ \\ \\|x_0-x_*\\|^2_2$$\n", "\n", "is valid for all $L$-smooth convex function $f$ and initial iterate $x_0$. Computing the smallest possible such $\\tau(L,\\gamma,n)$ is equivalent to computing the worst-case value of $f(x_{n})-f(x_*)$ under the constraint $\\| x_{0}-x_*\\|_2^2\\leqslant 1$.\n", "\n", "PEPit formulates the problem of computing $\\tau(L,\\gamma,n)$ as an SDP which can be solved numerically. In what follows, we describe the few lines that a user has to provide for generating the numerical worst-case analysis of GD using PEPit.\n", "\n", "In general, performing a worst-case analysis of a first-order method usually relies on **four main ingredients**: \n", "- a class of problems (containing the assumptions on the function to be minimized),\n", "- a first-order method (to be analyzed), \n", "- a performance measure (measuring the quality of the output of the algorithm under consideration),\n", "- an initial condition (measuring the quality of the initial iterate). \n", "\n", "PEPit requires the user to specify a choice for each of those four elements." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 2.1 Imports\n", "Before anything else, we have to import the PEP and the classes of functions of interest." ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "scrolled": true, "tags": [] }, "outputs": [], "source": [ "from PEPit import PEP\n", "from PEPit.functions import SmoothStronglyConvexFunction" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 2.2 Initialization of PEPit\n", "Then, we initialize a PEP object. This object allows manipulating the forthcoming ingredients of the PEP, such as functions and iterates." ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "scrolled": true, "tags": [] }, "outputs": [], "source": [ "# Instantiate PEP\n", "problem = PEP()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 2.3 Choose parameters values\n", "\n", "For the sake of the example, we pick some simple values for the problem class and algorithmic parameters, for which we perform the worst-case analysis below. " ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "scrolled": true, "tags": [] }, "outputs": [], "source": [ "# Specify values for the smoothness parameter L, number of iterations n, and the step size gamma.\n", "L = 3\n", "n = 4\n", "gamma = 1 / L" ] }, { "cell_type": "markdown", "metadata": { "tags": [] }, "source": [ "### 2.4 Specifying the problem class\n", "Next, we specify our assumptions on the **class of functions** containing the function to be optimized, and instantiate a corresponding object. Here, we consider an $L$-smooth convex function. \n", "\n", "