Contents

Python NumPy For Your Grandma - 6.7 Challenge: Outer Product

Setup

Calculate the element-wise outer product of two matrices, A & B.

import numpy as np

A = np.arange(10*3).reshape((10,3))
print(A)
## [[ 0  1  2]
##  [ 3  4  5]
##  [ 6  7  8]
##  [ 9 10 11]
##  [12 13 14]
##  [15 16 17]
##  [18 19 20]
##  [21 22 23]
##  [24 25 26]
##  [27 28 29]]
B = np.arange(10*5).reshape((10,5))
print(B)
## [[ 0  1  2  3  4]
##  [ 5  6  7  8  9]
##  [10 11 12 13 14]
##  [15 16 17 18 19]
##  [20 21 22 23 24]
##  [25 26 27 28 29]
##  [30 31 32 33 34]
##  [35 36 37 38 39]
##  [40 41 42 43 44]
##  [45 46 47 48 49]]

Solution 1

def outer_prod_broadcasting(A, B):
    """Broadcasting trick"""
    return A[...,None]*B[:,None]
    
outer_prod_broadcasting(A, B)
## array([[[   0,    0,    0,    0,    0],
##         [   0,    1,    2,    3,    4],
##         [   0,    2,    4,    6,    8]],
## 
##        [[  15,   18,   21,   24,   27],
##         [  20,   24,   28,   32,   36],
##         [  25,   30,   35,   40,   45]],
## 
##        [[  60,   66,   72,   78,   84],
##         [  70,   77,   84,   91,   98],
##         [  80,   88,   96,  104,  112]],
## 
##        [[ 135,  144,  153,  162,  171],
##         [ 150,  160,  170,  180,  190],
##         [ 165,  176,  187,  198,  209]],
## 
##        [[ 240,  252,  264,  276,  288],
##         [ 260,  273,  286,  299,  312],
##         [ 280,  294,  308,  322,  336]],
## 
##        [[ 375,  390,  405,  420,  435],
##         [ 400,  416,  432,  448,  464],
##         [ 425,  442,  459,  476,  493]],
## 
##        [[ 540,  558,  576,  594,  612],
##         [ 570,  589,  608,  627,  646],
##         [ 600,  620,  640,  660,  680]],
## 
##        [[ 735,  756,  777,  798,  819],
##         [ 770,  792,  814,  836,  858],
##         [ 805,  828,  851,  874,  897]],
## 
##        [[ 960,  984, 1008, 1032, 1056],
##         [1000, 1025, 1050, 1075, 1100],
##         [1040, 1066, 1092, 1118, 1144]],
## 
##        [[1215, 1242, 1269, 1296, 1323],
##         [1260, 1288, 1316, 1344, 1372],
##         [1305, 1334, 1363, 1392, 1421]]])

Solution 2

def outer_prod_einsum(A, B):
    """einsum() trick"""
    return np.einsum('ij,ik->ijk',A,B)
    
outer_prod_einsum(A, B)
## array([[[   0,    0,    0,    0,    0],
##         [   0,    1,    2,    3,    4],
##         [   0,    2,    4,    6,    8]],
## 
##        [[  15,   18,   21,   24,   27],
##         [  20,   24,   28,   32,   36],
##         [  25,   30,   35,   40,   45]],
## 
##        [[  60,   66,   72,   78,   84],
##         [  70,   77,   84,   91,   98],
##         [  80,   88,   96,  104,  112]],
## 
##        [[ 135,  144,  153,  162,  171],
##         [ 150,  160,  170,  180,  190],
##         [ 165,  176,  187,  198,  209]],
## 
##        [[ 240,  252,  264,  276,  288],
##         [ 260,  273,  286,  299,  312],
##         [ 280,  294,  308,  322,  336]],
## 
##        [[ 375,  390,  405,  420,  435],
##         [ 400,  416,  432,  448,  464],
##         [ 425,  442,  459,  476,  493]],
## 
##        [[ 540,  558,  576,  594,  612],
##         [ 570,  589,  608,  627,  646],
##         [ 600,  620,  640,  660,  680]],
## 
##        [[ 735,  756,  777,  798,  819],
##         [ 770,  792,  814,  836,  858],
##         [ 805,  828,  851,  874,  897]],
## 
##        [[ 960,  984, 1008, 1032, 1056],
##         [1000, 1025, 1050, 1075, 1100],
##         [1040, 1066, 1092, 1118, 1144]],
## 
##        [[1215, 1242, 1269, 1296, 1323],
##         [1260, 1288, 1316, 1344, 1372],
##         [1305, 1334, 1363, 1392, 1421]]])

Solution 3

def outer_prod_stride(A, B):
    """stride trick"""
    a = A.shape[-1]
    b = B.shape[-1]
    d = A.strides[-1]
    new_shape = A.shape + (b,)
    As = np.lib.stride_tricks.as_strided(A, shape=new_shape, strides=(a*d, d, 0))
    Bs = np.lib.stride_tricks.as_strided(B, shape=new_shape, strides=(b*d, 0, d))
    return As * Bs
    
outer_prod_stride(A, B)
## array([[[   0,    0,    0,    0,    0],
##         [   0,    1,    2,    3,    4],
##         [   0,    2,    4,    6,    8]],
## 
##        [[  15,   18,   21,   24,   27],
##         [  20,   24,   28,   32,   36],
##         [  25,   30,   35,   40,   45]],
## 
##        [[  60,   66,   72,   78,   84],
##         [  70,   77,   84,   91,   98],
##         [  80,   88,   96,  104,  112]],
## 
##        [[ 135,  144,  153,  162,  171],
##         [ 150,  160,  170,  180,  190],
##         [ 165,  176,  187,  198,  209]],
## 
##        [[ 240,  252,  264,  276,  288],
##         [ 260,  273,  286,  299,  312],
##         [ 280,  294,  308,  322,  336]],
## 
##        [[ 375,  390,  405,  420,  435],
##         [ 400,  416,  432,  448,  464],
##         [ 425,  442,  459,  476,  493]],
## 
##        [[ 540,  558,  576,  594,  612],
##         [ 570,  589,  608,  627,  646],
##         [ 600,  620,  640,  660,  680]],
## 
##        [[ 735,  756,  777,  798,  819],
##         [ 770,  792,  814,  836,  858],
##         [ 805,  828,  851,  874,  897]],
## 
##        [[ 960,  984, 1008, 1032, 1056],
##         [1000, 1025, 1050, 1075, 1100],
##         [1040, 1066, 1092, 1118, 1144]],
## 
##        [[1215, 1242, 1269, 1296, 1323],
##         [1260, 1288, 1316, 1344, 1372],
##         [1305, 1334, 1363, 1392, 1421]]])

Credit - https://stackoverflow.com/questions/42378936/numpy-elementwise-outer-product/42378969#42378969


Course Curriculum

  1. Introduction
    1.1 Introduction
  2. Basic Array Stuff
    2.1 NumPy Array Motivation
    2.2 NumPy Array Basics
    2.3 Creating NumPy Arrays
    2.4 Indexing 1-D Arrays
    2.5 Indexing Multidimensional Arrays
    2.6 Basic Math On Arrays
    2.7 Challenge: High School Reunion
    2.8 Challenge: Gold Miner
    2.9 Challenge: Chic-fil-A
  3. Intermediate Array Stuff
    3.1 Broadcasting
    3.2 newaxis
    3.3 reshape()
    3.4 Boolean Indexing
    3.5 nan
    3.6 infinity
    3.7 random
    3.8 Challenge: Love Distance
    3.9 Challenge: Professor Prick
    3.10 Challenge: Psycho Parent
  4. Common Operations
    4.1 where()
    4.2 Math Functions
    4.3 all() and any()
    4.4 concatenate()
    4.5 Stacking
    4.6 Sorting
    4.7 unique()
    4.8 Challenge: Movie Ratings
    4.9 Challenge: Big Fish
    4.10 Challenge: Taco Truck
  5. Advanced Array Stuff
    5.1 Advanced Array Indexing
    5.2 View vs Copy
    5.3 Challenge: Population Verification
    5.4 Challenge: Prime Locations
    5.5 Challenge: The Game of Doors
    5.6 Challenge: Peanut Butter
  6. Final Boss
    6.1 as_strided()
    6.2 einsum()
    6.3 Challenge: One-Hot-Encoding
    6.4 Challenge: Cumulative Rainfall
    6.5 Challenge: Table Tennis
    6.6 Challenge: Where’s Waldo
    6.7 Challenge: Outer Product