Calcolo delle variabili polinomiali di contrasto


11

Per favore, mi dia un'idea di come ricodificare in modo efficiente una variabile (fattore) categoriale nell'insieme delle variabili di contrasto polinomiale ortogonale.

Per molti tipi di variabili di contrasto (ad es. Deviazione, semplice, Helmert, ecc.) Il passaggio è:

  1. Comporre la matrice dei coefficienti di contrasto corrispondente al tipo.
  2. Invertire o generalizzare-invertire per ottenere la matrice di codici.

Per esempio:

Suppose there is 3-group factor and we want to recode it into a set of deviation  contrast variables.
The last group is treated as reference. Then the contrast coefficients matrix L is

         Group1 Group2 Group3
   var1   2/3   -1/3   -1/3
   var2  -1/3    2/3   -1/3

and ginv(L) is then the sought-for coding matrix

         var1 var2
  Group1   1    0
  Group2   0    1
  Group3  -1   -1

(We might also use inv(L) instead if we add a row for constant, equal to 1/3, at the head of L.)

Esiste un modo uguale o simile per ottenere variabili di contrasto polinomiale? Se sì, quale sarebbe la matrice C e come comporla? In caso contrario, qual è ancora il modo per calcolare le variabili di contrasto polinomiale in modo efficiente (ad es. Mediante algebra di matrice).


1
Ho esaminato la tua domanda dopo aver verificato (per inciso) che i risultati qr.qy()concordano con i calcoli manuali qr.Q(qr(X))seguiti da Q%*%zsul mio post. Mi chiedo davvero se posso dire qualcosa di diverso per rispondere alla tua domanda senza duplicazioni. Non voglio davvero fare un brutto lavoro ... Ho letto abbastanza dei tuoi post per avere molto rispetto per te ... Se trovo un modo per esprimere il concetto senza codice, concettualmente attraverso l'algebra lineare, Ci tornerò. Sono felice, tuttavia, che tu abbia trovato la mia esplorazione della questione di un certo valore. I migliori auguri, Toni.
Antoni Parellada,

@Antoni, grazie. Il mio obiettivo è essere in grado di codificarlo (in SPSS, con la sua sintassi). È possibile capire come funzionano le funzioni menzionate?
ttnphns,

Risposte:


5

Come segue al mio precedente post su questo argomento, voglio condividere alcune esplorazioni provvisorie (anche se incomplete) delle funzioni dietro l'algebra lineare e le relative funzioni R. Questo dovrebbe essere un lavoro in corso.

Parte dell'opacità delle funzioni ha a che fare con la forma "compatta" della decomposizione Householder . L'idea alla base della scomposizione della Capofamiglia è quella di riflettere i vettori attraverso un iperpiano determinato da un vettore unitario come nel diagramma seguente, ma selezionando questo piano in modo mirato in modo da proiettare ogni vettore di colonna della matrice originale sul vettore unità standard . Il vettore norm-2 normalizzato può essere utilizzato per calcolare le diverse trasformazioni della famiglia .u A e 1 1 u I - 2QRuAe11uI2uuTx

inserisci qui la descrizione dell'immagine

La proiezione risultante può essere espressa come

sign(xi=x1)×x[1000]+[x1x2x3xm]

Il vettore rappresenta la differenza tra i vettori di colonna nella matrice che vogliamo scomporre e i vettori corrispondenti al riflesso attraverso il sottospazio o "specchio" determinati da .vxAyu

Il metodo usato da LAPACK libera la necessità di conservare la prima voce nei riflettori Householder trasformandoli in . Invece di normalizzare il vettore in con , è solo la voce del pugno che viene convertita in ; tuttavia, questi nuovi vettori - chiamali possono ancora essere usati come vettori direzionali.1vuu=11w

La bellezza del metodo è che dato che in una decomposizione è triangolare superiore, possiamo effettivamente sfruttare gli elementi in sotto la diagonale per riempirli con questi riflettori . Per fortuna, le voci principali in questi vettori sono tutte uguali a , evitando un problema nella diagonale "contestata" della matrice: sapendo che sono tutte non è necessario includerle e possono restituire la diagonale alle voci di .RQR0Rw11R

La matrice "QR compatto" nella funzione qr()$qrpuò essere intesa approssimativamente come l'aggiunta della matrice e della matrice triangolare "memoria" inferiore per i riflettori "modificati".R

La proiezione di Household avrà ancora la forma , ma non lavoreremo con ( ), ma piuttosto con un vettore , di cui solo la prima voce è garantita come eI2uuTxux=1w1

(1)I2uuTx=I2wwwTwx=I2wwTw2x .

Si potrebbe presumere che sarebbe giusto memorizzare questi riflettori sotto la diagonale o escludendo la prima voce di e chiamarla un giorno. Tuttavia, le cose non sono mai così facili. Invece ciò che è memorizzato al di sotto della diagonale in è una combinazione di e dei coefficienti nella trasformazione della famiglia espressa come (1), tale che, definendo come:wR1qr()$qrwtau

τ=wTw2=w2 , i riflettori possono essere espressi come . Questi vettori "riflettori" sono quelli memorizzati proprio sotto nel cosiddetto "compatto ".reflectors=w/τRQR

Ora siamo a un grado di distanza dai vettori e la prima voce non è più , quindi l'output di dovrà includere la chiave per ripristinarli poiché insistiamo sull'esclusione della prima voce dei vettori "riflettore" per si adatta a tutto . Quindi stiamo vedendo i valori nell'output? Bene, no, sarebbe prevedibile. Invece nell'output di (dove è memorizzata questa chiave) troviamo .w1qr()qr()$qrτqr()$qrauxρ=reflectors22=wTwτ2/2

Così incorniciati in rosso sotto, vediamo i "riflettori" ( ), escluso il loro primo ingresso.w/τ

inserisci qui la descrizione dell'immagine

Tutto il codice è qui , ma poiché questa risposta riguarda l'intersezione di codifica e algebra lineare, incollerò l'output per facilità:


options(scipen=999)
set.seed(13)
(X = matrix(c(rnorm(16)), nrow=4, byrow=F))
           [,1]      [,2]       [,3]       [,4]
[1,]  0.5543269 1.1425261 -0.3653828 -1.3609845
[2,] -0.2802719 0.4155261  1.1051443 -1.8560272
[3,]  1.7751634 1.2295066 -1.0935940 -0.4398554
[4,]  0.1873201 0.2366797  0.4618709 -0.1939469

Ora ho scritto la funzione House()come segue:

   House = function(A){
    Q = diag(nrow(A))
    reflectors = matrix(0,nrow=nrow(A),ncol=ncol(A))
    for(r in 1:(nrow(A) - 1)){ 
        # We will apply Householder to progressively the columns in A, decreasing 1 element at a time.
        x = A[r:nrow(A), r] 
        # We now get the vector v, starting with first entry = norm-2 of x[i] times 1
        # The sign is to avoid computational issues
        first = (sign(x[1]) * sqrt(sum(x^2))) +  x[1]
        # We get the rest of v, which is x unchanged, since e1 = [1, 0, 0, ..., 0]
        # We go the the last column / row, hence the if statement:
        v = if(length(x) > 1){c(first, x[2:length(x)])}else{v = c(first)}
        # Now we make the first entry unitary:
        w = v/first
        # Tau will be used in the Householder transform, so here it goes:
        t = as.numeric(t(w)%*%w) / 2
        # And the "reflectors" are stored as in the R qr()$qr function:
        reflectors[r: nrow(A), r] = w/t
        # The Householder tranformation is:
        I = diag(length(r:nrow(A)))
        H.transf = I - 1/t * (w %*% t(w))
        H_i  = diag(nrow(A))
        H_i[r:nrow(A),r:ncol(A)] = H.transf
        # And we apply the Householder reflection - we left multiply the entire A or Q
        A = H_i %*% A
        Q = H_i %*% Q
    }
    DECOMPOSITION = list("Q"= t(Q), "R"= round(A,7), 
            "compact Q as in qr()$qr"=  
            ((A*upper.tri(A,diag=T))+(reflectors*lower.tri(reflectors,diag=F))), 
            "reflectors" = reflectors,
            "rho"=c(apply(reflectors[,1:(ncol(reflectors)- 1)], 2, 
                function(x) sum(x^2) / 2), A[nrow(A),ncol(A)]))
    return(DECOMPOSITION)
}

Confrontiamo l'output con le funzioni integrate di R. Innanzitutto la funzione fatta in casa:

(H = House(X))
$Q
            [,1]        [,2]       [,3]       [,4]
[1,] -0.29329367 -0.73996967  0.5382474  0.2769719
[2,]  0.14829152 -0.65124800 -0.5656093 -0.4837063
[3,] -0.93923665  0.13835611 -0.1947321 -0.2465187
[4,] -0.09911084 -0.09580458 -0.5936794  0.7928072

$R
          [,1]       [,2]       [,3]      [,4]
[1,] -1.890006 -1.4517318  1.2524151 0.5562856
[2,]  0.000000 -0.9686105 -0.6449056 2.1735456
[3,]  0.000000  0.0000000 -0.8829916 0.5180361
[4,]  0.000000  0.0000000  0.0000000 0.4754876

$`compact Q as in qr()$qr`
            [,1]        [,2]       [,3]      [,4]
[1,] -1.89000649 -1.45173183  1.2524151 0.5562856
[2,] -0.14829152 -0.96861050 -0.6449056 2.1735456
[3,]  0.93923665 -0.67574886 -0.8829916 0.5180361
[4,]  0.09911084  0.03909742  0.6235799 0.4754876

$reflectors
            [,1]        [,2]      [,3] [,4]
[1,]  1.29329367  0.00000000 0.0000000    0
[2,] -0.14829152  1.73609434 0.0000000    0
[3,]  0.93923665 -0.67574886 1.7817597    0
[4,]  0.09911084  0.03909742 0.6235799    0

$rho
[1] 1.2932937 1.7360943 1.7817597 0.4754876

alle funzioni R:

qr.Q(qr(X))
            [,1]        [,2]       [,3]       [,4]
[1,] -0.29329367 -0.73996967  0.5382474  0.2769719
[2,]  0.14829152 -0.65124800 -0.5656093 -0.4837063
[3,] -0.93923665  0.13835611 -0.1947321 -0.2465187
[4,] -0.09911084 -0.09580458 -0.5936794  0.7928072

qr.R(qr(X))
          [,1]       [,2]       [,3]      [,4]
[1,] -1.890006 -1.4517318  1.2524151 0.5562856
[2,]  0.000000 -0.9686105 -0.6449056 2.1735456
[3,]  0.000000  0.0000000 -0.8829916 0.5180361
[4,]  0.000000  0.0000000  0.0000000 0.4754876

$qr
            [,1]        [,2]       [,3]      [,4]
[1,] -1.89000649 -1.45173183  1.2524151 0.5562856
[2,] -0.14829152 -0.96861050 -0.6449056 2.1735456
[3,]  0.93923665 -0.67574886 -0.8829916 0.5180361
[4,]  0.09911084  0.03909742  0.6235799 0.4754876

$qraux
[1] 1.2932937 1.7360943 1.7817597 0.4754876

+1, ma suppongo che SPSS abbia funzioni integrate per la decomposizione QR (o sbaglio?), Quindi se l'obiettivo è codificare qualcosa in SPSS che coinvolge QR, difficilmente è necessario implementare manualmente l'algoritmo QR.
ameba dice di reintegrare Monica il

@amoeba Grazie. Dato che siamo soli, lasciami confidare con te: l'autore del PO non ha bisogno di alcun aiuto da parte mia, ma ho preso il suo commento (sopra) sul funzionamento interno delle (specificamente) funzioni R che ho usato nel post di accompagnamento come una divertente sfida personale, perché mi ha fatto capire quanto poco capissi queste implementazioni della fattorizzazione QR integrate nelle funzioni R. Dal momento che è stato incredibilmente difficile per me trovare buone referenze o ottenere risposte che facessero davvero la differenza chiedendo online, sto pubblicando ciò che ho ottenuto dopo più impegno di quanto non voglia ammettere.
Antoni Parellada,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.