The Khatri-Rao Product Visualized

The Khatri-Rao product takes two matrices with the same number of columns and pairs their columns up, replacing each pair by its Kronecker product. The result is a tall matrix with the same number of columns as the inputs. As a result it keeps the width fixed while the heights are multiplied.


1. Definition: the column-wise Kronecker product

Write A=[a1a2⋯aK]\textcolor{#0d9488}{A} = \begin{bmatrix} \textcolor{#0d9488}{a_1} & \textcolor{#0d9488}{a_2} & \cdots & \textcolor{#0d9488}{a_K} \end{bmatrix} and B=[b1b2⋯bK]\textcolor{#b45309}{B} = \begin{bmatrix} \textcolor{#b45309}{b_1} & \textcolor{#b45309}{b_2} & \cdots & \textcolor{#b45309}{b_K} \end{bmatrix} as lists of columns, with ak∈RI\textcolor{#0d9488}{a_k} \in \mathbb{R}^{I} and bk∈RJ\textcolor{#b45309}{b_k} \in \mathbb{R}^{J}. On a matrix, a subscript picks a column and a superscript picks a row: ak\textcolor{#0d9488}{a_k} is the kk-th column of A\textcolor{#0d9488}{A}, and ai\textcolor{#0d9488}{a^i} (section 3) is its ii-th row. The Khatri-Rao product is defined column by column:

A⊙B⏟IJ×K=[a1⊗b1⏟IJ×1a2⊗b2⋯aK⊗bK]\underbrace{\textcolor{#0d9488}{A} \odot \textcolor{#b45309}{B}}_{IJ \times K} = \begin{bmatrix} \underbrace{\textcolor{#0d9488}{a_1} \otimes \textcolor{#b45309}{b_1}}_{IJ \times 1} & \textcolor{#0d9488}{a_2} \otimes \textcolor{#b45309}{b_2} & \cdots & \textcolor{#0d9488}{a_K} \otimes \textcolor{#b45309}{b_K} \end{bmatrix}

Column kk of the output depends only on column kk of each input. Nothing mixes across columns.

The two inputs have K=2K = 2 columns each. In the figure below, matching columns share a color: the entries of AA are circles, the columns of BB are blocks.

a₁ a₂ A b₁ b₂ B
A ⊙ B

An example with 2×22 \times 2 inputs

[a11a12a21a22]⊙[b11b12b21b22]=[a1⊗b1⏟first columnsa2⊗b2⏟second columns]=[a11[b11b21]a12[b12b22]a21[b11b21]a22[b12b22]]=[a11b11a12b12a11b21a12b22a21b11a22b12a21b21a22b22]\begin{aligned} \begin{bmatrix} \textcolor{#0d9488}{a_{11}} & \textcolor{#0d9488}{a_{12}} \\ \textcolor{#0d9488}{a_{21}} & \textcolor{#0d9488}{a_{22}} \end{bmatrix} \odot \begin{bmatrix} \textcolor{#b45309}{b_{11}} & \textcolor{#b45309}{b_{12}} \\ \textcolor{#b45309}{b_{21}} & \textcolor{#b45309}{b_{22}} \end{bmatrix} &= \begin{bmatrix} \underbrace{\textcolor{#0d9488}{a_1} \otimes \textcolor{#b45309}{b_1}}_{\text{first columns}} & \underbrace{\textcolor{#0d9488}{a_2} \otimes \textcolor{#b45309}{b_2}}_{\text{second columns}} \end{bmatrix} \\ \\ &= \begin{bmatrix} \textcolor{#0d9488}{a_{11}} \textcolor{#b45309}{\begin{bmatrix} b_{11} \\ b_{21} \end{bmatrix}} & \textcolor{#0d9488}{a_{12}} \textcolor{#b45309}{\begin{bmatrix} b_{12} \\ b_{22} \end{bmatrix}} \\[6pt] \textcolor{#0d9488}{a_{21}} \textcolor{#b45309}{\begin{bmatrix} b_{11} \\ b_{21} \end{bmatrix}} & \textcolor{#0d9488}{a_{22}} \textcolor{#b45309}{\begin{bmatrix} b_{12} \\ b_{22} \end{bmatrix}} \end{bmatrix} \\ \\ &= \begin{bmatrix} \textcolor{#0d9488}{a_{11}}\textcolor{#b45309}{b_{11}} & \textcolor{#0d9488}{a_{12}}\textcolor{#b45309}{b_{12}} \\ \textcolor{#0d9488}{a_{11}}\textcolor{#b45309}{b_{21}} & \textcolor{#0d9488}{a_{12}}\textcolor{#b45309}{b_{22}} \\ \textcolor{#0d9488}{a_{21}}\textcolor{#b45309}{b_{11}} & \textcolor{#0d9488}{a_{22}}\textcolor{#b45309}{b_{12}} \\ \textcolor{#0d9488}{a_{21}}\textcolor{#b45309}{b_{21}} & \textcolor{#0d9488}{a_{22}}\textcolor{#b45309}{b_{22}} \end{bmatrix} \end{aligned}

The second step is a 2×22 \times 2 grid of blocks, not of numbers: each block is one whole column of B\textcolor{#b45309}{B}, written out as a stacked pair and scaled by a single entry of A\textcolor{#0d9488}{A}. Column 11 of the answer therefore only ever sees b1\textcolor{#b45309}{b_1}, and column 22 only ever sees b2\textcolor{#b45309}{b_2}, never the whole of B\textcolor{#b45309}{B}. That single difference is what separates ⊙\odot from ⊗\otimes.


2. One column at a time: the Kronecker product of two columns

Zoom in on a single column pair a\textcolor{#0d9488}{a}, b\textcolor{#b45309}{b}. Inside this section a subscript indexes an entry of that one column, not a column of a matrix. The Kronecker product a⊗b\textcolor{#0d9488}{a} \otimes \textcolor{#b45309}{b} stacks one scaled copy of b\textcolor{#b45309}{b} per entry of a\textcolor{#0d9488}{a}:

a⊗b=[a1a2a3]⊗b=[a1ba2ba3b]\begin{aligned} \textcolor{#0d9488}{a} \otimes \textcolor{#b45309}{b} &= \begin{bmatrix} \textcolor{#0d9488}{a_1} \\ \textcolor{#0d9488}{a_2} \\ \textcolor{#0d9488}{a_3} \end{bmatrix} \otimes \textcolor{#b45309}{b} \\ \\ &= \begin{bmatrix} \textcolor{#0d9488}{a_1} \textcolor{#b45309}{b} \\ \textcolor{#0d9488}{a_2} \textcolor{#b45309}{b} \\ \textcolor{#0d9488}{a_3} \textcolor{#b45309}{b} \end{bmatrix} \end{aligned}

Laying those same three blocks side by side instead of stacking them gives the outer product baT\textcolor{#b45309}{b}\textcolor{#0d9488}{a^T}:

baT=[b1b2][a1a2a3]=[a1b1a2b1a3b1a1b2a2b2a3b2]\begin{aligned} \textcolor{#b45309}{b}\textcolor{#0d9488}{a^T} &= \begin{bmatrix} \textcolor{#b45309}{b_1} \\ \textcolor{#b45309}{b_2} \end{bmatrix} \begin{bmatrix} \textcolor{#0d9488}{a_1} & \textcolor{#0d9488}{a_2} & \textcolor{#0d9488}{a_3} \end{bmatrix} \\ \\ &= \begin{bmatrix} \textcolor{#0d9488}{a_1}\textcolor{#b45309}{b_1} & \textcolor{#0d9488}{a_2}\textcolor{#b45309}{b_1} & \textcolor{#0d9488}{a_3}\textcolor{#b45309}{b_1} \\ \textcolor{#0d9488}{a_1}\textcolor{#b45309}{b_2} & \textcolor{#0d9488}{a_2}\textcolor{#b45309}{b_2} & \textcolor{#0d9488}{a_3}\textcolor{#b45309}{b_2} \end{bmatrix} \end{aligned}

Its columns are a1b\textcolor{#0d9488}{a_1}\textcolor{#b45309}{b}, a2b\textcolor{#0d9488}{a_2}\textcolor{#b45309}{b} and a3b\textcolor{#0d9488}{a_3}\textcolor{#b45309}{b}, the very blocks that the Kronecker product stacks.

⊗ = a b a ⊗ b

Three copies of b\textcolor{#b45309}{b}, each tinted by the entry of a\textcolor{#0d9488}{a} that scales it. The output length is the product of the two input lengths.

Both layouts hold the same numbers in the same order, because vec⁡\operatorname{vec} reads a matrix one column at a time and stacks those columns into a single long vector. That is why the Khatri-Rao product has a natural interpretation as an outer product in disguise:

a⊗b⏟blocks stacked=vec⁡(baT⏟blocks side by side)\underbrace{\textcolor{#0d9488}{a} \otimes \textcolor{#b45309}{b}}_{\text{blocks stacked}} = \operatorname{vec}\big(\underbrace{\textcolor{#b45309}{b}\textcolor{#0d9488}{a^T}}_{\text{blocks side by side}}\big)

Each column of A⊙B\textcolor{#0d9488}{A} \odot \textcolor{#b45309}{B} is a flattened outer product matrix.


3. The row-wise variant

Swapping rows for columns gives the face-splitting product. For A∈RI×J\textcolor{#0d9488}{A} \in \mathbb{R}^{I \times J} and B∈RI×K\textcolor{#b45309}{B} \in \mathbb{R}^{I \times K}, the matrix A∙B∈RI×JK\textcolor{#0d9488}{A} \bullet \textcolor{#b45309}{B} \in \mathbb{R}^{I \times JK} has rows ai⊗bi\textcolor{#0d9488}{a^i} \otimes \textcolor{#b45309}{b^i}, where ai\textcolor{#0d9488}{a^i} is the ii-th row of A\textcolor{#0d9488}{A}. The two are transposes of each other:

A∙B=(AT⊙BT)T\textcolor{#0d9488}{A} \bullet \textcolor{#b45309}{B} = (\textcolor{#0d9488}{A^T} \odot \textcolor{#b45309}{B^T})^T

Its defining property is that it turns a Kronecker product of inputs into an elementwise product of outputs:

(A∙B)(x⊗y)⏟Kronecker in=(Ax)∗(By)⏟Hadamard out(\textcolor{#0d9488}{A} \bullet \textcolor{#b45309}{B})\underbrace{(\textcolor{#0d9488}{x} \otimes \textcolor{#b45309}{y})}_{\text{Kronecker in}} = \underbrace{(\textcolor{#0d9488}{Ax}) * (\textcolor{#b45309}{By})}_{\text{Hadamard out}}

where ∗* is the elementwise (Hadamard) product.

Proof

The identity holds row by row, so watch a single row ii, with a\textcolor{#0d9488}{a} short for ai\textcolor{#0d9488}{a^i} and b\textcolor{#b45309}{b} short for bi\textcolor{#b45309}{b^i}.

Both Kronecker products are indexed by the pair (j,k)(j,k): entry (j,k)(j,k) is ajbk\textcolor{#0d9488}{a_j}\textcolor{#b45309}{b_k} on one side and xjyk\textcolor{#0d9488}{x_j}\textcolor{#b45309}{y_k} on the other:

[(A∙B)(x⊗y)]i=(a⊗b)⋅(x⊗y)=∑j,kajbkxjyk=∑j,k(ajxj)⏟depends on j(bkyk)⏟depends on k=(∑jajxj)(∑kbkyk)=(a⋅x)(b⋅y)=[(Ax)∗(By)]i\begin{aligned} \big[(\textcolor{#0d9488}{A} \bullet \textcolor{#b45309}{B})(\textcolor{#0d9488}{x} \otimes \textcolor{#b45309}{y})\big]_i &= (\textcolor{#0d9488}{a} \otimes \textcolor{#b45309}{b}) \cdot (\textcolor{#0d9488}{x} \otimes \textcolor{#b45309}{y}) \\ \\ &= \sum_{j,k} \textcolor{#0d9488}{a_j} \textcolor{#b45309}{b_k} \textcolor{#0d9488}{x_j} \textcolor{#b45309}{y_k} \\ &= \sum_{j,k} \underbrace{(\textcolor{#0d9488}{a_j x_j})}_{\textcolor{#0d9488}{\text{depends on } j}} \underbrace{(\textcolor{#b45309}{b_k y_k})}_{\textcolor{#b45309}{\text{depends on } k}} \\ \\ &= \Big(\sum_j \textcolor{#0d9488}{a_j x_j}\Big) \Big(\sum_k \textcolor{#b45309}{b_k y_k}\Big) \\ \\ &= (\textcolor{#0d9488}{a} \cdot \textcolor{#0d9488}{x})(\textcolor{#b45309}{b} \cdot \textcolor{#b45309}{y}) \\ &= \big[(\textcolor{#0d9488}{Ax}) * (\textcolor{#b45309}{By})\big]_i \end{aligned}

4. Three properties worth remembering

4.1 The Gram matrix collapses to a Hadamard product

(A⊙B)T(A⊙B)=(ATA)∗(BTB)(\textcolor{#0d9488}{A} \odot \textcolor{#b45309}{B})^T (\textcolor{#0d9488}{A} \odot \textcolor{#b45309}{B}) = (\textcolor{#0d9488}{A^TA}) * (\textcolor{#b45309}{B^TB})

Proof

Entry (k,l)(k,l) of the left side is the dot product of column kk with column ll, and the two families separate:

[(A⊙B)T(A⊙B)]kl=(ak⊗bk)T(al⊗bl)=(akTal)⏟[ATA]kl(bkTbl)⏟[BTB]kl=[(ATA)∗(BTB)]kl\begin{aligned} \big[(\textcolor{#0d9488}{A} \odot \textcolor{#b45309}{B})^T (\textcolor{#0d9488}{A} \odot \textcolor{#b45309}{B})\big]_{kl} &= (\textcolor{#0d9488}{a_k} \otimes \textcolor{#b45309}{b_k})^T (\textcolor{#0d9488}{a_l} \otimes \textcolor{#b45309}{b_l}) \\ \\ &= \underbrace{(\textcolor{#0d9488}{a_k^T a_l})}_{\textcolor{#0d9488}{[A^TA]_{kl}}} \underbrace{(\textcolor{#b45309}{b_k^T b_l})}_{\textcolor{#b45309}{[B^TB]_{kl}}} \\ \\ &= \big[(\textcolor{#0d9488}{A^TA}) * (\textcolor{#b45309}{B^TB})\big]_{kl} \end{aligned}

A K×KK \times K answer that never touches the IJ×KIJ \times K matrix A⊙B\textcolor{#0d9488}{A} \odot \textcolor{#b45309}{B}. This is the single most useful fact about ⊙\odot.


4.2 It expresses a weighted sum of outer products as a matrix-vector product

(A⊙B)x=vec⁡(Bdiag⁡(x)AT)(\textcolor{#0d9488}{A} \odot \textcolor{#b45309}{B})x = \operatorname{vec}\big(\textcolor{#b45309}{B} \operatorname{diag}(x) \textcolor{#0d9488}{A^T}\big)

Proof

Read the left side one column at a time, then replace each Kronecker column by the outer product it flattens:

(A⊙B)x=∑kxk (ak⊗bk)⏟weighted sum of the columns=∑kxkvec⁡(bkakT)=vec⁡(∑kxk bkakT)=vec⁡(Bdiag⁡(x)AT)\begin{aligned} (\textcolor{#0d9488}{A} \odot \textcolor{#b45309}{B})x &= \underbrace{\sum_k x_k \, (\textcolor{#0d9488}{a_k} \otimes \textcolor{#b45309}{b_k})}_{\text{weighted sum of the columns}} \\ \\ &= \sum_k x_k \operatorname{vec}(\textcolor{#b45309}{b_k}\textcolor{#0d9488}{a_k^T}) \\ \\ &= \operatorname{vec}\Big(\sum_k x_k \, \textcolor{#b45309}{b_k}\textcolor{#0d9488}{a_k^T}\Big) \\ \\ &= \operatorname{vec}\big(\textcolor{#b45309}{B} \operatorname{diag}(x) \textcolor{#0d9488}{A^T}\big) \end{aligned}

The last step is the outer-product reading of a matrix product: diag⁡(x)\operatorname{diag}(x) hands weight xkx_k to the kk-th pairing of a column of B\textcolor{#b45309}{B} with a row of AT\textcolor{#0d9488}{A^T}.


4.3 The mixed product rule carries over

(A⊗B)(C⊙D)=(AC)⊙(BD)(\textcolor{#0d9488}{A} \otimes \textcolor{#b45309}{B})(\textcolor{#0d9488}{C} \odot \textcolor{#b45309}{D}) = (\textcolor{#0d9488}{AC}) \odot (\textcolor{#b45309}{BD})

Proof

Column kk of C⊙D\textcolor{#0d9488}{C} \odot \textcolor{#b45309}{D} is itself a Kronecker product, so the mixed product rule for ⊗\otimes applies to it directly:

[(A⊗B)(C⊙D)]k=(A⊗B)(ck⊗dk)=Ack⊗Bdk=[(AC)⊙(BD)]k\begin{aligned} \big[(\textcolor{#0d9488}{A} \otimes \textcolor{#b45309}{B})(\textcolor{#0d9488}{C} \odot \textcolor{#b45309}{D})\big]_k &= (\textcolor{#0d9488}{A} \otimes \textcolor{#b45309}{B})(\textcolor{#0d9488}{c_k} \otimes \textcolor{#b45309}{d_k}) \\ \\ &= \textcolor{#0d9488}{Ac_k} \otimes \textcolor{#b45309}{Bd_k} \\ \\ &= \big[(\textcolor{#0d9488}{AC}) \odot (\textcolor{#b45309}{BD})\big]_k \end{aligned}

The Khatri-Rao product is also associative: (A⊙B)⊙C=A⊙(B⊙C)(A \odot B) \odot C = A \odot (B \odot C).