This commit is contained in:
RobinB27
2026-01-13 15:29:29 +01:00
2 changed files with 9 additions and 6 deletions

Binary file not shown.

View File

@@ -59,21 +59,24 @@ Sei $A = ab^\top$. Dann gilt $y = Ax \Leftrightarrow y = a(b^\top x)$, was dasse
\inlineex Für zwei Matrizen $A, B \in \R^{n \times p}$ mit geringem Rang $p \ll n$, dann kann mithilfe eines Tricks die Rechenzeit von \verb|np.triu(A @ B.T) @ x| von $\tco{pn^2}$ auf $\tco{pn}$ reduziert werden. \inlineex Für zwei Matrizen $A, B \in \R^{n \times p}$ mit geringem Rang $p \ll n$, dann kann mithilfe eines Tricks die Rechenzeit von \verb|np.triu(A @ B.T) @ x| von $\tco{pn^2}$ auf $\tco{pn}$ reduziert werden.
Die hier beschriebene Operation berechnet $\text{Upper}(AB^\top) x$ wobei $\text{Upper}(X)$ das obere Dreieck der Matrix $X$ zurück gibt. Die hier beschriebene Operation berechnet $\text{Upper}(AB^\top) x$ wobei $\text{Upper}(X)$ das obere Dreieck der Matrix $X$ zurück gibt.
Wir nennen diese Matrix hier $R$. Wir nennen diese Matrix hier $R$.
\innumpy können wir den folgenden Ansatz verwenden, um die Laufzeit zu verringern: \innumpy können wir den folgenden Ansatz verwenden, um die Laufzeit zu verringern:
Da die Matrix $R$ eine obere Dreiecksmatrix ist, ist das Ergebnis die Teilsummen von unserem Umgekehrten Vektor $x$, also können wir mit \verb|np.cumsum(x[::-1], axis=0)[::-1]| die Kummulative Summe berechnen. Da die Matrix $R$ eine obere Dreiecksmatrix ist, ist das Ergebnis die Teilsummen von unserem Umgekehrten Vektor $x$,
Das \verb|[::-1]| dient hier lediglich dazu, den Vektor $x$ umzudrehen, sodass das richtige Resultat entsteht. also können wir mit \verb|x[::-1].cumsum(axis=0)[::-1]| die Kummulative Summe berechnen.
Das \verb|[::-1]| dient hier lediglich dazu, den Vektor $x$ umzudrehen, sodass das richtige Resultat entsteht und die \texttt{axis=0} muss nur spezifiziert werden,
falls wir nicht den Default von \texttt{None} wollen, welcher die \texttt{cumsum} auf \texttt{x.flat} ausführt.
Die vollständige Implementation sieht so aus: Die vollständige Implementation sieht so aus:
\begin{code}{python} \begin{code}{python}
def low_rank_matrix_vector_product(A: np.ndarray, B: np.ndarray, x: np.ndarray): def low_rank_matrix_vector_product(A: np.ndarray, B: np.ndarray, x: np.ndarray):
n, _ = A.shape n = A.shape[0]
y = np.zeros(n) y = np.zeros(n) # Results vector
# Compute B * x with broadcasting (x needs to be reshaped to 2D) # Compute B * x with broadcasting (x needs to be reshaped to 2D)
v = B * x[:, None] v = B * x[:, None]
# s is defined as the reverse cummulative sum of our vector # s is defined as the reverse cummulative sum of our vector
# (and we need it reversed again for the final calculation to be correct) # (and we need it reversed again for the final calculation to be correct)
s = np.cumsum(v[::-1], axis=0)[::-1] s = v[::-1].cumsum(axis=0)[::-1]
y = np.sum(A * s) y = np.sum(A * s)
\end{code} \end{code}