{ "cells": [ { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# Linear algebra\n", "Linear algebra is the branch of mathematics that deals with **vector spaces**. " ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "ExecuteTime": { "end_time": "2018-09-12T02:56:32.691859Z", "start_time": "2018-09-12T02:56:32.437287Z" }, "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "import re, math, random # regexes, math functions, random numbers\n", "import matplotlib.pyplot as plt # pyplot\n", "from collections import defaultdict, Counter\n", "from functools import partial, reduce" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# Vectors\n", "\n", "Vectors are points in some finite-dimensional space. " ] }, { "cell_type": "code", "execution_count": 19, "metadata": { "ExecuteTime": { "end_time": "2018-09-12T02:05:07.953664Z", "start_time": "2018-09-12T02:05:07.950046Z" }, "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "v = [1, 2]\n", "w = [2, 1]\n", "vectors = [v, w]" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "ExecuteTime": { "end_time": "2018-09-12T01:59:29.991620Z", "start_time": "2018-09-12T01:59:29.987741Z" }, "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "def vector_add(v, w):\n", " \"\"\"adds two vectors componentwise\"\"\"\n", " return [v_i + w_i for v_i, w_i in zip(v,w)]" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "ExecuteTime": { "end_time": "2018-09-12T02:00:08.880719Z", "start_time": "2018-09-12T02:00:08.873616Z" }, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/plain": [ "[3, 3]" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "vector_add(v, w)" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "ExecuteTime": { "end_time": "2018-09-12T02:00:48.559535Z", "start_time": "2018-09-12T02:00:48.552722Z" }, "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "data": { "text/plain": [ "[-1, 1]" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "def vector_subtract(v, w):\n", " \"\"\"subtracts two vectors componentwise\"\"\"\n", " return [v_i - w_i for v_i, w_i in zip(v,w)]\n", "\n", "vector_subtract(v, w)" ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "ExecuteTime": { "end_time": "2018-09-12T02:01:22.749575Z", "start_time": "2018-09-12T02:01:22.746421Z" }, "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "def vector_sum(vectors):\n", " return reduce(vector_add, vectors)" ] }, { "cell_type": "code", "execution_count": 20, "metadata": { "ExecuteTime": { "end_time": "2018-09-12T02:05:16.459169Z", "start_time": "2018-09-12T02:05:16.454550Z" }, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/plain": [ "[3, 3]" ] }, "execution_count": 20, "metadata": {}, "output_type": "execute_result" } ], "source": [ "vector_sum(vectors)" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "ExecuteTime": { "end_time": "2018-09-12T02:56:37.552577Z", "start_time": "2018-09-12T02:56:37.548815Z" }, "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "def scalar_multiply(c, v):\n", " # c is a number, v is a vector\n", " return [c * v_i for v_i in v]" ] }, { "cell_type": "code", "execution_count": 13, "metadata": { "ExecuteTime": { "end_time": "2018-09-12T02:02:59.938350Z", "start_time": "2018-09-12T02:02:59.934107Z" }, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/plain": [ "[2.5, 5.0]" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "scalar_multiply(2.5, v)" ] }, { "cell_type": "code", "execution_count": 14, "metadata": { "ExecuteTime": { "end_time": "2018-09-12T02:03:15.086122Z", "start_time": "2018-09-12T02:03:15.082201Z" }, "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "def vector_mean(vectors):\n", " \"\"\"compute the vector whose i-th element is the mean of the\n", " i-th elements of the input vectors\"\"\"\n", " n = len(vectors)\n", " return scalar_multiply(1/n, vector_sum(vectors))\n" ] }, { "cell_type": "code", "execution_count": 21, "metadata": { "ExecuteTime": { "end_time": "2018-09-12T02:05:25.854562Z", "start_time": "2018-09-12T02:05:25.850482Z" }, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/plain": [ "[1.5, 1.5]" ] }, "execution_count": 21, "metadata": {}, "output_type": "execute_result" } ], "source": [ "vector_mean(vectors)" ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "ExecuteTime": { "end_time": "2018-09-12T02:56:56.631003Z", "start_time": "2018-09-12T02:56:56.627206Z" }, "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "def dot(v, w):\n", " \"\"\"v_1 * w_1 + ... + v_n * w_n\"\"\"\n", " return sum(v_i * w_i for v_i, w_i in zip(v, w))\n" ] }, { "cell_type": "code", "execution_count": 18, "metadata": { "ExecuteTime": { "end_time": "2018-09-12T02:04:55.369415Z", "start_time": "2018-09-12T02:04:55.365183Z" }, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/plain": [ "4" ] }, "execution_count": 18, "metadata": {}, "output_type": "execute_result" } ], "source": [ "dot(v, w)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "The dot product measures how far the vector v extends in the w direction. \n", "- For example, if w = [1, 0] then dot(v, w) is just the first component of v. \n", "\n", "The dot product measures the length of the vector you’d get if you projected v onto w." ] }, { "cell_type": "code", "execution_count": 22, "metadata": { "ExecuteTime": { "end_time": "2018-09-12T02:07:35.950195Z", "start_time": "2018-09-12T02:07:35.946818Z" }, "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "def sum_of_squares(v):\n", " \"\"\"v_1 * v_1 + ... + v_n * v_n\"\"\"\n", " return dot(v, v)" ] }, { "cell_type": "code", "execution_count": 23, "metadata": { "ExecuteTime": { "end_time": "2018-09-12T02:07:36.983243Z", "start_time": "2018-09-12T02:07:36.978652Z" }, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/plain": [ "5" ] }, "execution_count": 23, "metadata": {}, "output_type": "execute_result" } ], "source": [ "sum_of_squares(v)" ] }, { "cell_type": "code", "execution_count": 24, "metadata": { "ExecuteTime": { "end_time": "2018-09-12T02:07:57.941211Z", "start_time": "2018-09-12T02:07:57.937912Z" }, "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "def magnitude(v):\n", " return math.sqrt(sum_of_squares(v))" ] }, { "cell_type": "code", "execution_count": 25, "metadata": { "ExecuteTime": { "end_time": "2018-09-12T02:08:06.030797Z", "start_time": "2018-09-12T02:08:06.026317Z" }, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/plain": [ "2.23606797749979" ] }, "execution_count": 25, "metadata": {}, "output_type": "execute_result" } ], "source": [ "magnitude(v)" ] }, { "cell_type": "code", "execution_count": 26, "metadata": { "ExecuteTime": { "end_time": "2018-09-12T02:08:55.689307Z", "start_time": "2018-09-12T02:08:55.686062Z" }, "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "def squared_distance(v, w):\n", " return sum_of_squares(vector_subtract(v, w))" ] }, { "cell_type": "code", "execution_count": 27, "metadata": { "ExecuteTime": { "end_time": "2018-09-12T02:09:02.988465Z", "start_time": "2018-09-12T02:09:02.983903Z" }, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/plain": [ "2" ] }, "execution_count": 27, "metadata": {}, "output_type": "execute_result" } ], "source": [ "squared_distance(v, w)" ] }, { "cell_type": "code", "execution_count": 28, "metadata": { "ExecuteTime": { "end_time": "2018-09-12T02:09:26.432641Z", "start_time": "2018-09-12T02:09:26.429550Z" }, "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "def distance(v, w):\n", " return math.sqrt(squared_distance(v, w))\n" ] }, { "cell_type": "code", "execution_count": 29, "metadata": { "ExecuteTime": { "end_time": "2018-09-12T02:09:38.557639Z", "start_time": "2018-09-12T02:09:38.553786Z" }, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/plain": [ "1.4142135623730951" ] }, "execution_count": 29, "metadata": {}, "output_type": "execute_result" } ], "source": [ "distance(v, w)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Using lists as vectors \n", "- is great for exposition \n", "- but terrible for performance.\n", " - to use the NumPy library." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# Matrices" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "A matrix is a two-dimensional collection of numbers. \n", "- We will represent matrices as lists of lists\n", " - If A is a matrix, then A[i][j] is the element in the ith row and the jth column." ] }, { "cell_type": "code", "execution_count": 30, "metadata": { "ExecuteTime": { "end_time": "2018-09-12T02:15:43.067895Z", "start_time": "2018-09-12T02:15:43.063749Z" }, "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "A = [[1, 2, 3],\n", " [4, 5, 6]]\n", "\n", "B = [[1, 2],\n", " [3, 4],\n", " [5, 6]]" ] }, { "cell_type": "code", "execution_count": 31, "metadata": { "ExecuteTime": { "end_time": "2018-09-12T02:16:12.577964Z", "start_time": "2018-09-12T02:16:12.574091Z" }, "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "def shape(A):\n", " num_rows = len(A)\n", " num_cols = len(A[0]) if A else 0\n", " return num_rows, num_cols" ] }, { "cell_type": "code", "execution_count": 32, "metadata": { "ExecuteTime": { "end_time": "2018-09-12T02:16:20.887496Z", "start_time": "2018-09-12T02:16:20.883170Z" }, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/plain": [ "(2, 3)" ] }, "execution_count": 32, "metadata": {}, "output_type": "execute_result" } ], "source": [ "shape(A)" ] }, { "cell_type": "code", "execution_count": 34, "metadata": { "ExecuteTime": { "end_time": "2018-09-12T02:16:44.013585Z", "start_time": "2018-09-12T02:16:44.010635Z" }, "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "def get_row(A, i):\n", " return A[i]" ] }, { "cell_type": "code", "execution_count": 35, "metadata": { "ExecuteTime": { "end_time": "2018-09-12T02:16:45.185135Z", "start_time": "2018-09-12T02:16:45.180832Z" }, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/plain": [ "[4, 5, 6]" ] }, "execution_count": 35, "metadata": {}, "output_type": "execute_result" } ], "source": [ "get_row(A, 1)" ] }, { "cell_type": "code", "execution_count": 37, "metadata": { "ExecuteTime": { "end_time": "2018-09-12T02:17:11.445393Z", "start_time": "2018-09-12T02:17:11.442110Z" }, "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "def get_column(A, j):\n", " return [A_i[j] for A_i in A]" ] }, { "cell_type": "code", "execution_count": 38, "metadata": { "ExecuteTime": { "end_time": "2018-09-12T02:17:12.220804Z", "start_time": "2018-09-12T02:17:12.216292Z" }, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/plain": [ "[3, 6]" ] }, "execution_count": 38, "metadata": {}, "output_type": "execute_result" } ], "source": [ "get_column(A, 2)" ] }, { "cell_type": "code", "execution_count": 50, "metadata": { "ExecuteTime": { "end_time": "2018-09-12T02:21:41.402495Z", "start_time": "2018-09-12T02:21:41.396419Z" }, "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "def make_matrix(num_rows, num_cols, entry_fn):\n", " \"\"\"returns a num_rows x num_cols matrix\n", " whose (i,j)-th entry is entry_fn(i, j),\n", " entry_fn is a function for generating matrix elements.\"\"\"\n", " return [[entry_fn(i, j) \n", " for j in range(num_cols)]\n", " for i in range(num_rows)]\n" ] }, { "cell_type": "code", "execution_count": 71, "metadata": { "ExecuteTime": { "end_time": "2018-09-12T02:37:16.809334Z", "start_time": "2018-09-12T02:37:16.802710Z" }, "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "data": { "text/plain": [ "[[0, 1, 2, 3, 4],\n", " [1, 2, 3, 4, 5],\n", " [2, 3, 4, 5, 6],\n", " [3, 4, 5, 6, 7],\n", " [4, 5, 6, 7, 8]]" ] }, "execution_count": 71, "metadata": {}, "output_type": "execute_result" } ], "source": [ "def entry_add(i, j):\n", " \"\"\"a function for generating matrix elements. \"\"\"\n", " return i+j\n", "\n", "make_matrix(5, 5, entry_add)" ] }, { "cell_type": "code", "execution_count": 53, "metadata": { "ExecuteTime": { "end_time": "2018-09-12T02:23:07.805069Z", "start_time": "2018-09-12T02:23:07.797716Z" }, "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "data": { "text/plain": [ "[[1, 0, 0, 0, 0],\n", " [0, 1, 0, 0, 0],\n", " [0, 0, 1, 0, 0],\n", " [0, 0, 0, 1, 0],\n", " [0, 0, 0, 0, 1]]" ] }, "execution_count": 53, "metadata": {}, "output_type": "execute_result" } ], "source": [ "def is_diagonal(i, j):\n", " \"\"\"1's on the 'diagonal', \n", " 0's everywhere else\"\"\"\n", " return 1 if i == j else 0\n", "\n", "identity_matrix = make_matrix(5, 5, is_diagonal)\n", "identity_matrix" ] }, { "cell_type": "markdown", "metadata": { "ExecuteTime": { "end_time": "2018-09-12T02:25:53.668226Z", "start_time": "2018-09-12T02:25:53.663461Z" }, "slideshow": { "slide_type": "subslide" } }, "source": [ "### Matrices will be important.\n", "- using a matrix to represent a dataset\n", "- using an n × k matrix to represent a linear function that maps k-dimensional vectors to n-dimensional vectors. \n", "- using matrix to represent binary relationships. " ] }, { "cell_type": "code", "execution_count": 58, "metadata": { "ExecuteTime": { "end_time": "2018-09-12T02:28:11.642703Z", "start_time": "2018-09-12T02:28:11.636503Z" }, "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ " friendships = [(0, 1), \n", " (0, 2), \n", " (1, 2), \n", " (1, 3), \n", " (2, 3), \n", " (3, 4),\n", " (4, 5), \n", " (5, 6), \n", " (5, 7), \n", " (6, 8), \n", " (7, 8), \n", " (8, 9)]" ] }, { "cell_type": "code", "execution_count": 60, "metadata": { "ExecuteTime": { "end_time": "2018-09-12T02:29:26.728950Z", "start_time": "2018-09-12T02:29:26.716314Z" }, "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "friendships = [[0, 1, 1, 0, 0, 0, 0, 0, 0, 0], # user 0\n", " [1, 0, 1, 1, 0, 0, 0, 0, 0, 0], # user 1\n", " [1, 1, 0, 1, 0, 0, 0, 0, 0, 0], # user 2\n", " [0, 1, 1, 0, 1, 0, 0, 0, 0, 0], # user 3\n", " [0, 0, 0, 1, 0, 1, 0, 0, 0, 0], # user 4\n", " [0, 0, 0, 0, 1, 0, 1, 1, 0, 0], # user 5\n", " [0, 0, 0, 0, 0, 1, 0, 0, 1, 0], # user 6\n", " [0, 0, 0, 0, 0, 1, 0, 0, 1, 0], # user 7\n", " [0, 0, 0, 0, 0, 0, 1, 1, 0, 1], # user 8\n", " [0, 0, 0, 0, 0, 0, 0, 0, 1, 0]] # user 9" ] }, { "cell_type": "code", "execution_count": 62, "metadata": { "ExecuteTime": { "end_time": "2018-09-12T02:29:36.913500Z", "start_time": "2018-09-12T02:29:36.908769Z" }, "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 62, "metadata": {}, "output_type": "execute_result" } ], "source": [ "friendships[0][2] == 1 # True, 0 and 2 are friends " ] }, { "cell_type": "code", "execution_count": 74, "metadata": { "ExecuteTime": { "end_time": "2018-09-12T02:37:50.949363Z", "start_time": "2018-09-12T02:37:50.942135Z" }, "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "def matrix_add(A, B):\n", " if shape(A) != shape(B):\n", " raise ArithmeticError(\"cannot add matrices with different shapes\")\n", "\n", " num_rows, num_cols = shape(A)\n", " def entry_fn(i, j): return A[i][j] + B[i][j]\n", "\n", " return make_matrix(num_rows, num_cols, entry_fn)\n" ] }, { "cell_type": "code", "execution_count": 76, "metadata": { "ExecuteTime": { "end_time": "2018-09-12T02:37:56.803580Z", "start_time": "2018-09-12T02:37:56.796449Z" }, "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "data": { "text/plain": [ "[[1, 1, 2, 3, 4],\n", " [1, 3, 3, 4, 5],\n", " [2, 3, 5, 5, 6],\n", " [3, 4, 5, 7, 7],\n", " [4, 5, 6, 7, 9]]" ] }, "execution_count": 76, "metadata": {}, "output_type": "execute_result" } ], "source": [ "A = make_matrix(5, 5, is_diagonal)\n", "B = make_matrix(5, 5, entry_add)\n", "\n", "matrix_add(A, B)" ] }, { "cell_type": "code", "execution_count": 104, "metadata": { "ExecuteTime": { "end_time": "2018-09-12T03:26:10.982125Z", "start_time": "2018-09-12T03:26:10.773664Z" }, "slideshow": { "slide_type": "skip" } }, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "v = [2, 1]\n", "w = [math.sqrt(.25), math.sqrt(.75)]\n", "c = dot(v, w)\n", "vonw = scalar_multiply(c, w)\n", "o = [0,0]\n", "plt.figure(figsize=(4, 5), dpi = 100)\n", "\n", "plt.arrow(0, 0, v[0], v[1],\n", " width=0.002, head_width=.1, length_includes_head=True)\n", "plt.annotate(\"v\", v, xytext=[v[0] + 0.01, v[1]])\n", "\n", "plt.arrow(0 ,0, w[0], w[1],\n", " width=0.002, head_width=.1, length_includes_head=True)\n", "plt.annotate(\"w\", w, xytext=[w[0] - 0.1, w[1]])\n", "\n", "plt.arrow(0, 0, vonw[0], vonw[1], length_includes_head=True)\n", "plt.annotate(u\"(v•w)w\", vonw, xytext=[vonw[0] - 0.1, vonw[1] + 0.02])\n", "\n", "plt.arrow(v[0], v[1], vonw[0] - v[0], vonw[1] - v[1],\n", " linestyle='dotted', length_includes_head=True)\n", "plt.scatter(*zip(v,w,o),marker='.')\n", "plt.axis('equal')\n", "\n", "plt.show()" ] } ], "metadata": { "celltoolbar": "Slideshow", "kernelspec": { "display_name": "Python [default]", "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.5.4" }, "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": false, "sideBar": true, "skip_h1_title": false, "title_cell": "Table of Contents", "title_sidebar": "Contents", "toc_cell": false, "toc_position": {}, "toc_section_display": true, "toc_window_display": false } }, "nbformat": 4, "nbformat_minor": 2 }