Search code examples
pythonnumpyfunctional-programmingmapreduce

Python: write outer product using map and reduce


Suppose I have a matrix

import numpy as np
from functools import reduce
np.random.seed(123)
X = np.random.normal(size=(5, 2))

and I want to compute X^t X without using numpy functions and using map, reduce and lambda functions. Since we can write X^t X as a sum of outer products, my goal would be:

def outer_product(x):
    """Computes outer product of a vector with itself"""
    pass

map(outer_product, X)

However I can't seem to find an efficient way of writing all of these with map reduce.

My Attempt

def outer(x):
    xxx = np.repeat(x, len(x))
    yyy = np.array(list(x) * len(x))
    return np.reshape(list(map(lambda x, y: x*y, xxx, yyy)), (len(x), len(x)))

so that

outer(X[0, ])

And then I've written the covariance matrix as follows

def cov(X):
    return np.array(reduce(lambda x, y: x + y, list(map(outer, X)))) / np.size(X, 0)

Solution

  • To answer your question, outer product can be defined as nested map such as

    outer = lambda V: np.array(list(map(lambda x: list(map(lambda y: x*y, V)), V)))
    
    X = np.random.normal(size=(5, 2))
    >>> outer(X[1])
    array([[ 0.08007683, -0.42624902], [-0.42624902,  2.26892377]])
    

    Actually, it is simpler to use list comprehension

    outer = lambda V: np.array([[x*x1 for a in V] for x1 in V])
    

    will give you same result. Then you can map to your matrix like

    >>> list(map(outer, X))
    [array([[ 1.17859381, -1.08274874],
           [-1.08274874,  0.99469794]]), array([[ 0.08007683, -0.42624902],
           [-0.42624902,  2.26892377]]), array([[ 0.33477825, -0.9555216 ],
           [-0.9555216 ,  2.72724264]]), array([[5.88877215, 1.04083337],
           [1.04083337, 0.18396604]]), array([[ 1.60259461, -1.0972381 ],
           [-1.0972381 ,  0.75123892]])]
    

    Your reduce part is quite nice and concise by the way. I don't think that part requires any further refactoring.