{ "cells": [ { "cell_type": "markdown", "id": "ea6d9c2b", "metadata": {}, "source": [ "Sascha Spors,\n", "Professorship Signal Theory and Digital Signal Processing,\n", "Institute of Communications Engineering (INT),\n", "Faculty of Computer Science and Electrical Engineering (IEF),\n", "University of Rostock,\n", "Germany\n", "\n", "# Data Driven Audio Signal Processing - A Tutorial with Computational Examples\n", "\n", "Winter Semester 2023/24 (Master Course #24512)\n", "\n", "- lecture: https://github.com/spatialaudio/data-driven-audio-signal-processing-lecture\n", "- tutorial: https://github.com/spatialaudio/data-driven-audio-signal-processing-exercise\n", "\n", "Feel free to contact lecturer frank.schultz@uni-rostock.de\n", "\n", "# Check the L-Curve for Ridge Regression\n", "with a matrix $\\textbf{X}$ - full column rank, but rather high condition number.\n", "\n", "Using toy data, we calculate and plot the L-curve and find an optimum regularization parameter $\\lambda_{opt}$, i.e. where L-curve has maximum curvature. For this $\\lambda_{opt}$ we get a suitable trade-off between prediction error and magnitude of model parameter vector. L-curve is typically plotted log-log because of rather large range of numbers." ] }, { "cell_type": "code", "execution_count": null, "id": "b9c24554", "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", "import matplotlib.pyplot as plt\n", "from numpy.linalg import inv, matrix_rank, cond\n", "from scipy.linalg import svd, diagsvd" ] }, { "cell_type": "code", "execution_count": null, "id": "e92f286e", "metadata": {}, "outputs": [], "source": [ "rng = np.random.default_rng(1234)" ] }, { "cell_type": "code", "execution_count": null, "id": "001db254", "metadata": {}, "outputs": [], "source": [ "mu = np.array([0, 0])\n", "tmp = 1 - 1e-4\n", "cov = [[1, tmp], [tmp, 1]]\n", "M, N = 2**7, mu.shape[0]\n", "\n", "X = rng.multivariate_normal(mu, cov, size=M, method='cholesky')\n", "[U, s, Vh] = svd(X)\n", "Uh = U.T.conj()\n", "V = Vh.T.conj()\n", "S = diagsvd(s, M, N)\n", "I = np.eye(N)\n", "\n", "n = rng.standard_normal(size=M)\n", "\n", "y = (2 * X[:, 0] + X[:, 1] + n)[:, None]" ] }, { "cell_type": "code", "execution_count": null, "id": "199f2ee6", "metadata": {}, "outputs": [], "source": [ "matrix_rank(X), s.shape[0], cond(X), s[0] / s[-1]" ] }, { "cell_type": "code", "execution_count": null, "id": "ee083563", "metadata": {}, "outputs": [], "source": [ "lmb = np.logspace(-2.2, 1.9, 2**7)\n", "lcurve = np.zeros([2, lmb.shape[0]])\n", "\n", "for cnt, val in enumerate(lmb):\n", " X_reg_left_inv = V @ inv(S.T @ S + val * I) @ S.T @ Uh\n", " theta_hat = X_reg_left_inv @ y\n", " tmp = y - X @ theta_hat\n", " lcurve[0, cnt] = tmp.T.conj() @ tmp\n", " lcurve[1, cnt] = theta_hat.T.conj() @ theta_hat\n", "\n", "curvature = np.gradient(np.gradient(lcurve[1, :]))\n", "lmb_opt_idx = np.argmin(np.abs(curvature))" ] }, { "cell_type": "code", "execution_count": null, "id": "e7a92ebe", "metadata": {}, "outputs": [], "source": [ "plt.loglog(lcurve[0, :], lcurve[1, :], 'o:', ms=2)\n", "plt.loglog(lcurve[0, lmb_opt_idx], lcurve[1, lmb_opt_idx], 'C3o')\n", "plt.text(lcurve[0, 0], lcurve[1, 0], r'$\\lambda\\rightarrow 0$')\n", "plt.text(lcurve[0, -1], lcurve[1, -1], r'$\\lambda\\rightarrow \\infty$')\n", "plt.text(lcurve[0, lmb_opt_idx], lcurve[1, lmb_opt_idx],\n", " r'$\\lambda_\\mathrm{opt}$')\n", "plt.xlabel(r'$||\\bf{y} - \\bf{X \\hat{\\theta}}||_2^2$')\n", "plt.ylabel(r'$||\\bf{\\hat{\\theta}}||_2^2$')\n", "plt.title(r'L-Curve for $\\hat{\\bf{\\theta}}(\\lambda)$')\n", "plt.xlim(100, 200)\n", "plt.ylim(1, 100)\n", "plt.grid(True, which='both', ls=':', lw=0.5)" ] }, { "cell_type": "code", "execution_count": null, "id": "29f17512", "metadata": {}, "outputs": [], "source": [ "# l-curve for tikzpicture in ddasp_exercise_slides.tex\n", "print('coordinates {', sep='', end='')\n", "for cnt, val in enumerate(lmb):\n", " print('(', np.log10(lcurve[0, cnt]), ',', np.log10(\n", " lcurve[1, cnt]), ')', sep='', end='')\n", "print('};', sep='', end='')" ] }, { "cell_type": "code", "execution_count": null, "id": "4c3277b7", "metadata": {}, "outputs": [], "source": [ "# l-curve values of opt lambda for tikzpicture in ddasp_exercise_slides.tex\n", "print('coordinates {', sep='', end='')\n", "print('(', np.log10(lcurve[0, lmb_opt_idx]), ',', np.log10(\n", " lcurve[1, lmb_opt_idx]), ')', sep='', end='')\n", "print('};', sep='', end='')" ] }, { "cell_type": "code", "execution_count": null, "id": "2470b8ea", "metadata": {}, "outputs": [], "source": [ "# l-curve values for small lambda for tikzpicture in ddasp_exercise_slides.tex\n", "print('coordinates {', sep='', end='')\n", "print('(', np.log10(lcurve[0, 0]), ',', np.log10(\n", " lcurve[1, 0]), ')', sep='', end='')\n", "print('};', sep='', end='')" ] }, { "cell_type": "code", "execution_count": null, "id": "e4c60168", "metadata": {}, "outputs": [], "source": [ "# l-curve values for large lambda for tikzpicture in ddasp_exercise_slides.tex\n", "print('coordinates {', sep='', end='')\n", "print('(', np.log10(lcurve[0, -1]), ',', np.log10(\n", " lcurve[1, -1]), ')', sep='', end='')\n", "print('};', sep='', end='')" ] }, { "cell_type": "markdown", "id": "0897f31e", "metadata": {}, "source": [ "## Copyright\n", "\n", "- the notebooks are provided as [Open Educational Resources](https://en.wikipedia.org/wiki/Open_educational_resources)\n", "- the text is licensed under [Creative Commons Attribution 4.0](https://creativecommons.org/licenses/by/4.0/)\n", "- the code of the IPython examples is licensed under the [MIT license](https://opensource.org/licenses/MIT)\n", "- feel free to use the notebooks for your own purposes\n", "- please attribute the work as follows: *Frank Schultz, Data Driven Audio Signal Processing - A Tutorial Featuring Computational Examples, University of Rostock* ideally with relevant file(s), github URL https://github.com/spatialaudio/data-driven-audio-signal-processing-exercise, commit number and/or version tag, year." ] } ], "metadata": { "kernelspec": { "display_name": "myddasp", "language": "python", "name": "myddasp" }, "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.6" } }, "nbformat": 4, "nbformat_minor": 5 }