Domanda

Sto disperatamente cercando di evitare un for Loop in Matlab, ma non riesco a capire come farlo. Ecco la situazione:

ne ho due m x n matrici A e B e due vettori v e w di lunghezza d. Voglio moltiplicare esterno A e v in modo da ottenere un m x n x d matrice dove il (i,j,k) l'ingresso è A_(i,j) * v_k, e allo stesso modo per B e w.

Successivamente, voglio aggiungere il risultato m x n x d matrici e poi prendi il mean Lungo l'ultima dimensione per recuperare un m x n matrice.

Sono abbastanza sicuro di poter gestire l'ultima parte, ma la prima parte mi ha completamente bloccato. Ho provato a usare bsxfun inutilmente. Qualcuno sa un modo efficiente per farlo? Grazie mille!

MODIFICARE: Questa revisione arriva dopo le tre grandi risposte di seguito. Gnovice ha la migliore risposta alla domanda che ho posto senza dubbio. Tuttavia, la domanda che intendevo porre implica la quadratura di ogni voce prima di prendere la media. Ho dimenticato di menzionare questa parte in origine. Dato questo fastidio, entrambe le altre risposte funzionano bene, ma il trucco intelligente di fare l'algebra prima della codifica non aiuta questa volta. Grazie per l'aiuto a tutti!

È stato utile?

Soluzione

MODIFICARE:

Anche se il problema nella domanda è stato aggiornato, un approccio algebrico può ancora essere utilizzato per semplificare le questioni. Non devi ancora preoccuparti delle matrici 3D. Il tuo risultato sarà solo questo:

output = mean(v.^2).*A.^2 + 2.*mean(v.*w).*A.*B + mean(w.^2).*B.^2;

Se le matrici e i vettori sono grandi, questa soluzione ti darà prestazioni molto migliori a causa della ridotta quantità di memoria richiesta rispetto alle soluzioni che utilizzano Bsxfun o Repmat.


Spiegazione:

Supponendo M è la matrice m-by-n-by-d che si ottiene di conseguenza prima di prendere la media lungo la terza dimensione, questo è ciò che una durata lungo la terza dimensione conterrà:

M(i,j,:) = A(i,j).*v + B(i,j).*w;

In altre parole, il vettore v ridimensionato da A(i,j) più il vettore w ridimensionato da B(i,j). E questo è ciò che ottieni quando applichi una quadratura di elementi:

M(i,j,:).^2 = (A(i,j).*v + B(i,j).*w).^2;
            = (A(i,j).*v).^2 + ...
              2.*A(i,j).*B(i,j).*v.*w + ...
              (B(i,j).*w).^2;

Ora, quando prendi la media attraverso la terza dimensione, il risultato per ogni elemento output(i,j) sarà il seguente:

output(i,j) = mean(M(i,j,:).^2);
            = mean((A(i,j).*v).^2 + ...
                   2.*A(i,j).*B(i,j).*v.*w + ...
                   (B(i,j).*w).^2);
            = sum((A(i,j).*v).^2 + ...
                  2.*A(i,j).*B(i,j).*v.*w + ...
                  (B(i,j).*w).^2)/d;
            = sum((A(i,j).*v).^2)/d + ...
              sum(2.*A(i,j).*B(i,j).*v.*w)/d + ...
              sum((B(i,j).*w).^2)/d;
            = A(i,j).^2.*mean(v.^2) + ...
              2.*A(i,j).*B(i,j).*mean(v.*w) + ...
              B(i,j).^2.*mean(w.^2);

Altri suggerimenti

Prova a rimodellare i vettori v e w essere 1 x 1 x d:

  mean (bsxfun(@times, A, reshape(v, 1, 1, [])) ...
        + bsxfun(@times, B, reshape(w, 1, 1, [])), 3)

Qui sto usando [] nell'argomento a reshape Per dirgli di riempire quella dimensione in base al prodotto di tutte le altre dimensioni e al numero totale di elementi nel vettore.

Uso repmat per piastrellare la matrice nella terza dimensione.

A =

     1     2     3
     4     5     6

>> repmat(A, [1 1  10])

ans(:,:,1) =

     1     2     3
     4     5     6


ans(:,:,2) =

     1     2     3
     4     5     6

eccetera.

Non devi ancora ricorrere a loop espliciti o ad anello indiretto usando bsxfun et al. Per i requisiti aggiornati. Puoi ottenere ciò che desideri con una semplice soluzione vettoriale come segue

output = reshape(mean((v(:)*A(:)'+w(:)*B(:)').^2),size(A));

Dal momento che OP lo dice solo v e w sono vettori di lunghezza d, la soluzione sopra dovrebbe funzionare per i vettori di riga e colonna. Se sono noti per essere vettori di colonna, v(:) può essere sostituito da v e allo stesso modo per w.


Puoi verificare se questo corrisponde La risposta di Lambdageek (modificato per quadare i termini) come segue

outputLG = mean ((bsxfun(@times, A, reshape(v, 1, 1, [])) ...
        + bsxfun(@times, B, reshape(w, 1, 1, []))).^2, 3);

isequal(output,outputLG)

ans =

     1
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top