Linear Algebra using numpy – Vectors

In this post we explore some common linear algebra functions and their application in pure python and numpy

Python lists are not vectors, they cannot be manipulated element-wise by default

In python we have to define our own functions for manipulating lists as vectors, and this is compared to the same operations when using numpy arrays as one-liners

In [1]:
python_list_1 = [40, 50, 60]
python_list_2 = [10, 20, 30]
python_list_3 = [35, 5, 40]

# Vector addition would result in [50, 70, 90]
# What addition between two lists returns is a concatenated list

added_list = python_list_1 + python_list_2
added_list
Out[1]:
[40, 50, 60, 10, 20, 30]

Vector Addition

In [2]:
def add_vectors(v, w):
    return [vi + wi for vi, wi in zip(v, w)]

def sum_of_all_vectors(vecs):
    return reduce(add_vectors, vecs)
In [3]:
add_vectors(python_list_1, python_list_2)
Out[3]:
[50, 70, 90]
In [4]:
sum_of_all_vectors([python_list_1, python_list_2, python_list_3])
Out[4]:
[85, 75, 130]

But, of course, in numpy, this comes for free using the + operator on our numpy arrays or using sum

In [5]:
import numpy as np
numpy_array_1 = np.array([40, 50, 60])
numpy_array_2 = np.array([10, 20, 30])
numpy_array_3 = np.array([35, 5, 40])

numpy_array_1 + numpy_array_2
Out[5]:
array([50, 70, 90])
In [6]:
sum([numpy_array_1, numpy_array_2, numpy_array_3])
Out[6]:
array([ 85,  75, 130])

Vector Subtraction

In [7]:
def subtract_vectors(v, w):
    return [vi - wi for vi, wi in zip(v, w)]
In [8]:
# [40 - 35, 50 - 5, 60 - 40]
subtract_vectors(python_list_1, python_list_3)
Out[8]:
[5, 45, 20]
In [9]:
numpy_array_1 - numpy_array_3
Out[9]:
array([ 5, 45, 20])

Scalar Multiplication

In [10]:
def scalar_multiply(c, v):
    return [c * vi for vi in v]
In [11]:
scalar_multiply(10, python_list_1)
Out[11]:
[400, 500, 600]
In [12]:
numpy_array_1 * 10
Out[12]:
array([400, 500, 600])

Vector Mean

In [13]:
def vector_mean(vecs):
    n = len(vecs)
    return scalar_multiply(1/float(n), sum_of_all_vectors(vecs))
In [14]:
vector_mean([python_list_1, python_list_2, python_list_3])
Out[14]:
[28.333333333333332, 25.0, 43.33333333333333]
In [15]:
np.mean([numpy_array_1, numpy_array_2, numpy_array_3], axis=0)
Out[15]:
array([ 28.33333333,  25.        ,  43.33333333])

Dot Product

In [16]:
def dot_product(v, w):
    """v1 * w1 + .. + vn * wn"""
    return sum(vi * wi for vi, wi in zip(v, w))
In [17]:
dot_product(python_list_1, python_list_2)
Out[17]:
3200
In [18]:
sum(numpy_array_1 * numpy_array_2)
Out[18]:
3200

Sum of Squares

In [19]:
def sum_of_squares(v):
    """ v1 * v1 + v2 * v2 ... + vn * vn"""
    # or return dot_product(v, v)
    return sum(vi ** 2 for vi in v)
In [20]:
sum_of_squares(python_list_1)
Out[20]:
7700
In [21]:
sum(numpy_array_1 ** 2)
Out[21]:
7700

Magnitude

In [22]:
import math

def magnitude(v):
    return math.sqrt(sum_of_squares(v))
In [23]:
magnitude(python_list_1)
Out[23]:
87.74964387392122
In [24]:
(sum(numpy_array_1 ** 2)) ** 0.5
Out[24]:
87.749643873921215

Distance between two vectors

In [25]:
# sqrt((v1 - w1) **2 + ... + (vn - wn) ** 2)
In [26]:
def distance(v, w):
    return magnitude(subtract_vectors(v, w))
In [27]:
distance(python_list_1, python_list_2)
Out[27]:
51.96152422706632
In [28]:
(sum((numpy_array_1 - numpy_array_2) ** 2)) ** 0.5
Out[28]:
51.96152422706632