{ "cells": [ { "cell_type": "markdown", "source": [ "### Author: Fatemeh yaghoobi\n", "#### September 2022\n", "\n", "#### The aim of this notebook is to provide the basic and fundemental linear algebra operations in numPy which will be useful to know for \"Basics of sensor fusion\" course.\n", "\n", "#### REFERECES:\n", "\n", "NumPy for MATLAB users: the NumPy documentation which help MATLAB users get started with NumPy [here](https://numpy.org/devdocs/user/numpy-for-matlab-users.html).\n", "\n", "Python basics [notebook](https://colab.research.google.com/github/data-psl/lectures2020/blob/master/notebooks/01_python_basics.ipynb) prepared by [Mathieu Blonde](https://mblondel.org/).\n", "\n", "Matlab vs. Python -- A rebuttal [here](https://johnfoster.pge.utexas.edu/blog/posts/matlab-vs-python/#disqus_thread).\n", "\n", "Matrix Operations in NumPy vs. Matlab [here](https://mccormickml.com/2019/10/28/matrix-operations-in-numpy-vs-matlab/)." ], "metadata": { "collapsed": false, "pycharm": { "name": "#%% md\n" } } }, { "cell_type": "markdown", "source": [ "#### To use NumPy in your program, you need to import it as follows (remember to pip install numpy first)" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%% md\n" } } }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [ "import numpy as np" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%%\n" } } }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [ "# Vectors and vector operations\n" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%%\n" } } }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [ "# A vector that has 4 elements\n", "v1 = np.array([3, 4, 5])\n", "v1" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%%\n" } } }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [ "# multipying vector with a scalar\n", "# When a vector is multiplied by a scalar, \n", "#each element of the vector is multiplied with the scalar\n", "\n", "v1*2\n" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%%\n" } } }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [ "# add (subtract) 2 vectors: Element-wise summation\n", "#and subtraction on vectors are done with standard math operations.\n", "v1 = np.array([3, 4, 5])\n", "v2 = np.array([2, 0, -2])\n", "print(\"v1+v2 = \", v1 + v2)\n", "print(\"v1-v2 = \", v1 - v2)\n" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%%\n" } } }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [ "# dot product: The dot product of two vectors \n", "#is the sum of the products of elements with regards to position\n", "v1 = np.array([3, 4, 5])\n", "v2 = np.array([2, 0, -2])\n", "\n", "np.dot(v1, v2)\n" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%%\n" } } }, { "cell_type": "markdown", "source": [ "# Matrix and matrix operations" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%% md\n" } } }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [ "# A matrix is a 2-dimensional array.\n", "my_matrix = np.array([[1, 2, 3], [4, 5, 6]])\n", "\n", "print(my_matrix)\n" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%%\n" } } }, { "cell_type": "markdown", "source": [ "### Arrays of all zeros" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%% md\n" } } }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [ "#zero matrix\n", "zero_matrix = np.zeros((2, 3))\n", "zero_matrix" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%%\n" } } }, { "cell_type": "markdown", "source": [ "### Arrays of ones" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%% md\n" } } }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [ "# ones matrix\n", "ones_matrix = np.ones((3,4))\n", "ones_matrix" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%%\n" } } }, { "cell_type": "markdown", "source": [ "### Shape of matices:\n", "We define the shape of a matrix in terms of the number of rows and columns" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%% md\n" } } }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [ "print(\"shape of my_matrix:\", my_matrix.shape)\n", "print(\"shape of ones_matrix:\", ones_matrix.shape)\n" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%%\n" } } }, { "cell_type": "markdown", "source": [ "### Accessing specific elements, rows, columns" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%% md\n" } } }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [ "a = np.array([[1,2,3],[4,5,6], [7,8,9]])\n", "a" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%%\n" } } }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [ "a.shape" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%%\n" } } }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [ "# We can access individual elements of a 2d-array using two indices\n", "a[3,1]" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%%\n" } } }, { "cell_type": "markdown", "source": [ "#### Note: NumPy numbers indices from 0. When we have 3 rows, the indices are 0, 1 and 2" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%% md\n" } } }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [ "# We can also access rows\n", "a_row = a[0] # or a[0, :] # First row\n", "a_row\n" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%%\n" } } }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [ "# and columns\n", "a_column = a[:, 2] # Last column\n", "a_column\n" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%%\n" } } }, { "cell_type": "markdown", "source": [ "## matrix-matrix multiplication" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%% md\n" } } }, { "cell_type": "markdown", "source": [ "### `numpy.dot`" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%% md\n" } } }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [ "M1 = np.array([[1, 2], [3, 4]])\n", "M2 = np.array([[5, 7], [6, 8]])\n", "print(M1)\n", "print()\n", "print(M2)" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%%\n" } } }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [ "np.dot(M1, M2)\n", "\n" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%%\n" } } }, { "cell_type": "markdown", "source": [ "Each element of the product matrix is a dot product of a row in first matrix and a column in the second matrix. " ], "metadata": { "collapsed": false, "pycharm": { "name": "#%% md\n" } } }, { "cell_type": "markdown", "source": [ "## `@`: The built-in operator to do matrix-vector or matrix-matrix multiplication" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%% md\n" } } }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [ "M1 @ M2" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%%\n" } } }, { "cell_type": "markdown", "source": [ "# Transpose" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%% md\n" } } }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [ "print(M1)\n", "print(M1.T)\n" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%%\n" } } }, { "cell_type": "markdown", "source": [ " ## Let's once again look at vectors in numpy" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%% md\n" } } }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [ "# ndarray treats vectors as 1-dimensional\n", "v1\n" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%%\n" } } }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [ "v1.shape" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%%\n" } } }, { "cell_type": "markdown", "source": [ "#### In Matlab, a vector is a 2-dimensional object – it is either a column vector (e.g., [3 x 1]) or a row vector (e.g., [1 x 3])." ], "metadata": { "collapsed": false, "pycharm": { "name": "#%% md\n" } } }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [ "# transpose\n", "print(v1.T)\n" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%%\n" } } }, { "cell_type": "markdown", "source": [ "#### Numpy doesn’t naturally distinguish between a row vector and a column vector.\n" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%% md\n" } } }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [ "M3 = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])\n", "M3" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%%\n" } } }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [ "# Multiply v1 with M3." ], "metadata": { "collapsed": false, "pycharm": { "name": "#%%\n" } } }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [ "np.dot(M3, v1)" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%%\n" } } }, { "cell_type": "markdown", "source": [ "In above operation, numPy assumes that you know what you're doing and that \n", "`v1` is a column vector with shape [3 x 1]\n" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%% md\n" } } }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [ "np.dot(v1, M3)" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%%\n" } } }, { "cell_type": "markdown", "source": [ "In above operation, numPy assumes that you know what you're doing and that \n", "`v1` is a row vector with shape [1 x 3]" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%% md\n" } } }, { "cell_type": "markdown", "source": [ "### Safe method: force vectors to have two dimensions \n", " \n", " \n", " " ], "metadata": { "collapsed": false, "pycharm": { "name": "#%% md\n" } } }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [ "# call the reshape function on the 1d vectors in NumPy \n", "print(v1.shape)\n", "print(np.reshape(v1, (3,1)).shape)\n", "print(np.reshape(v1, (1,3)).shape)\n" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%%\n" } } }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [ "# put the vector’s index inside square brackets\n", "print(v1.shape)\n", "print(v1[:, None].shape)\n", "print(v1[None, :].shape)" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%%\n" } } }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [ "#adding a second set of brackets to explicitly add the second dimension to the row vector. \n", "v1_new = np.array([[1, 2, 3]])\n", "print(v1_new.shape)\n", "print(v1_new.T.shape)\n" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%%\n" } } }, { "cell_type": "markdown", "source": [ "### Other useful functions for creating arrays:\n", "\n", "We saw `np.zeros`, `np.ones`" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%% md\n" } } }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [ "# create a range of values using\n", "np.arange(5)" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%%\n" } } }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [ "# or specifying the starting point\n", "np.arange(3, 5)" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%%\n" } } }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [ "# creating linearly spaced values in an interval. \n", "np.linspace(0, 1, 10)" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%%\n" } } }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [ "# creating random integres\n", "np.random.randint(low = 1, high = 6, size = (2,3))" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%%\n" } } }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [ "# creating random samples from a uniform distribution over [0,1)\n", "np.random.rand(2,4)\n" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%%\n" } } }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [ "np.dot(np.array([2, 2, -1]), np.array([-1,2,2]))" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%%\n" } } }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [ "np.linalg.norm(np.array([3, 4]))" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%%\n" } } }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [ "# create a range of values using\n", "np.arange(5)" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%%\n" } } }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [ "# or specifying the starting point\n", "np.arange(3, 5)" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%%\n" } } }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [ "# creating linearly spaced values in an interval. \n", "np.linspace(0, 1, 10)" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%%\n" } } }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [ "# creating random integres\n", "np.random.randint(low = 1, high = 6, size = (2,3))" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%%\n" } } }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [ "# creating random samples from a uniform distribution over [0,1)\n", "np.random.rand(2,4)\n" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%%\n" } } } ], "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.8.8" }, "rise": { "theme": "sky" } }, "nbformat": 4, "nbformat_minor": 1 }