Álgebra Linear Computacional

Operações com Matrizes

Autor

Marcelo R. P. Ferreira

1 Introdução

Como vimos, uma matriz em matemática é apenas um array bi-dimensional de números. Em R, a noção de matriz é extendida a elementos de qualquer tipo, então, dessa forma, você pode ter uma matriz de strings, por exemplo.. Podemos criar matrizes em R utilizando a função matrix:

matrix(data = NA,
       nrow = 1,
       ncol = 1,
       byrow = FALSE,
       dimnames = NULL)

onde:

  • data é um vetor de dados;
  • nrow é o número de linhas;
  • ncol é o número de colunas;
  • byrow é um argumento lógico, onde TRUE indica que a matriz deve ser preenchida por linhas, e FALSE indica que a matriz deve ser preenchida por colunas. Por padrão, a matriz é preenchida por colunas;
  • dimnames é um argumento opcional utilizado para definir os nomes da s linhas e das colunas através de uma lista.

Exemplo:

A <- matrix(c(3,-1,2,
              4,1,0,
              -2,0,3),
            nrow = 3,
            byrow = TRUE)
A
     [,1] [,2] [,3]
[1,]    3   -1    2
[2,]    4    1    0
[3,]   -2    0    3
B <- matrix(c(2,1,3,
              -1,0,5,
              3,-1,1),
            ncol = 3,
            byrow = TRUE)
B
     [,1] [,2] [,3]
[1,]    2    1    3
[2,]   -1    0    5
[3,]    3   -1    1

Para acessar o elemento \((i,j)\) de uma matrix A, faça A[i,j]. Por exemplo:

A[2,3]
[1] 0
A[2,]
[1] 4 1 0
A[,3]
[1] 2 0 3
A[2,3] <- 1
A
     [,1] [,2] [,3]
[1,]    3   -1    2
[2,]    4    1    1
[3,]   -2    0    3

1.1 Operações ponto a ponto

Os símbolos +, -, *, / e ^ representam, respectivamente, as operações de adição, subtração, multiplicação, divisão e potenciação ponto a ponto. Ou seja, as operações são aplicadas a cada elemento da matriz. Por exemplo:

A+B
     [,1] [,2] [,3]
[1,]    5    0    5
[2,]    3    1    6
[3,]    1   -1    4
A-B
     [,1] [,2] [,3]
[1,]    1   -2   -1
[2,]    5    1   -4
[3,]   -5    1    2
A*B
     [,1] [,2] [,3]
[1,]    6   -1    6
[2,]   -4    0    5
[3,]   -6    0    3
A/B
           [,1] [,2]      [,3]
[1,]  1.5000000   -1 0.6666667
[2,] -4.0000000  Inf 0.2000000
[3,] -0.6666667    0 3.0000000
A^4
     [,1] [,2] [,3]
[1,]   81    1   16
[2,]  256    1    1
[3,]   16    0   81

Em geral, funções matemáticas como log, exp, sin, cos e etc., quando aplicadas a matrizes numéricas, correspondem à aplicação dessas funções a cada elemeneto da matriz.

1.2 Obtendo outras informações de uma matriz

As funções dim, nrow e ncol retornam, respectivamente, um vetor com o número de linhas e o número de colunas de uma matriz, o número de linhas de uma matriz, e o número de colunas de uma matriz. Exemplo:

dim(A)
[1] 3 3
nrow(A)
[1] 3
ncol(A)
[1] 3

O determinante de uma matriz quadrada é calculado através da função det. Exemplo:

det(A)
[1] 27
det(B)
[1] 29

Obtemos a transposta de uma matriz através da função t. Exemplo:

t(A)
     [,1] [,2] [,3]
[1,]    3    4   -2
[2,]   -1    1    0
[3,]    2    1    3
t(B)
     [,1] [,2] [,3]
[1,]    2   -1    3
[2,]    1    0   -1
[3,]    3    5    1
t(t(A))
     [,1] [,2] [,3]
[1,]    3   -1    2
[2,]    4    1    1
[3,]   -2    0    3

A função diag pode ser usada para retornar a diagonal de uma matriz quadrada ou para criar uma matriz diagonal a partir de um vetor. Por exemplo:

diag(A)
[1] 3 1 3
x <- diag(B)
x
[1] 2 0 1
diag(x)
     [,1] [,2] [,3]
[1,]    2    0    0
[2,]    0    0    0
[3,]    0    0    1
diag(diag(A))
     [,1] [,2] [,3]
[1,]    3    0    0
[2,]    0    1    0
[3,]    0    0    3
diag(5)
     [,1] [,2] [,3] [,4] [,5]
[1,]    1    0    0    0    0
[2,]    0    1    0    0    0
[3,]    0    0    1    0    0
[4,]    0    0    0    1    0
[5,]    0    0    0    0    1

1.3 Dando nomes às linhas e colunas

As funções rownames e colnames são úteis para atribuírmos nomes ou identificadores às linhas e colunas, respectivamente, de matrizes. Exemplo:

rownames(A) <- c("Eq1","Eq2","Eq3")
colnames(A) <- c("x","y","z")
A
     x  y z
Eq1  3 -1 2
Eq2  4  1 1
Eq3 -2  0 3

1.4 Adicionando novas linhas e colunas

As funções cbind e rbind servem para concatenar novas colunas e novas linhas, respectivamente, a matrizes. Exemplo:

C <- rbind(B,c(3,1,-2))
C
     [,1] [,2] [,3]
[1,]    2    1    3
[2,]   -1    0    5
[3,]    3   -1    1
[4,]    3    1   -2
D <- cbind(c(-2,-1,5),B)
D
     [,1] [,2] [,3] [,4]
[1,]   -2    2    1    3
[2,]   -1   -1    0    5
[3,]    5    3   -1    1

2 Multiplicação de matrizes

A multiplicação de matrizes é obtida através da função %*%. Vale ressaltar que, se temos duas matrizes \(A\) e \(B\), só é possível obter \(A\times B\) se o número de colunas de \(A\) for igual ao número de linhas de \(B\). Por exemplo:

A
     x  y z
Eq1  3 -1 2
Eq2  4  1 1
Eq3 -2  0 3
B
     [,1] [,2] [,3]
[1,]    2    1    3
[2,]   -1    0    5
[3,]    3   -1    1
A%*%B
    [,1] [,2] [,3]
Eq1   13    1    6
Eq2   10    3   18
Eq3    5   -5   -3
B%*%A
       x  y  z
[1,]   4 -1 14
[2,] -13  1 13
[3,]   3 -4  8
C
     [,1] [,2] [,3]
[1,]    2    1    3
[2,]   -1    0    5
[3,]    3   -1    1
[4,]    3    1   -2
D
     [,1] [,2] [,3] [,4]
[1,]   -2    2    1    3
[2,]   -1   -1    0    5
[3,]    5    3   -1    1
C%*%D
     [,1] [,2] [,3] [,4]
[1,]   10   12   -1   14
[2,]   27   13   -6    2
[3,]    0   10    2    5
[4,]  -17   -1    5   12
D%*%C
     [,1] [,2] [,3]
[1,]    6    0   -1
[2,]   14    4  -18
[3,]    7    7   27

Observe que a operação A%*%C não é possível, visto que \(A\) é de ordem \(3\times 3\) e \(C\) é de ordem \(4\times 3\). Nesse caso, uma mensagem de erro como Error in A %*% C : non-conformable arguments será retornada.

3 Matriz inversa e solução de sistemas de equações lineares

A inversa de uma matriz quadrada pode ser calculada através da função solve. Exemplo:

solve(A)
          Eq1        Eq2        Eq3
x  0.11111111 0.11111111 -0.1111111
y -0.51851852 0.48148148  0.1851852
z  0.07407407 0.07407407  0.2592593
solve(B)
           [,1]       [,2]        [,3]
[1,] 0.17241379 -0.1379310  0.17241379
[2,] 0.55172414 -0.2413793 -0.44827586
[3,] 0.03448276  0.1724138  0.03448276
solve(A)%*%A
             x            y             z
x 1.000000e+00 1.387779e-17  0.000000e+00
y 1.110223e-16 1.000000e+00 -5.551115e-17
z 0.000000e+00 0.000000e+00  1.000000e+00

A função solve também pode ser utilizada para obter a solução de uma sistema de equações lineares \(A\mathbf{x}=\mathbf{b}\), onde \(A_{(n\times n)}\) é a matriz de coeficientes, \(\mathbf{x}_{(n\times 1)}\) é o vetor de incógnitas (variáveis desconhecidas), e \(\mathbf{b}_{(n\times 1)}\) é o vetor de termos independentes. Por exemplo, resolver o sistema a seguir: \[\begin{align*} \begin{cases} 2x + y - z = 3 \\ -x + 3y + 2z = 12 \\ 3x + 2y + 4z = 9. \end{cases} \end{align*}\]

A solução desse sistema é dada por: \[ \begin{cases} x = \displaystyle -\frac{3}{37} \approx -0{,}0811 \\ y = \displaystyle \frac{135}{37} \approx 3{,}6486 \\ z = \displaystyle \frac{18}{37} \approx 0{,}4865. \end{cases} \]

Em R, fazemos:

A <- matrix(c(2,1,-1,
              -1,3,2,
              3,2,4), nrow = 3, byrow = TRUE)
A
     [,1] [,2] [,3]
[1,]    2    1   -1
[2,]   -1    3    2
[3,]    3    2    4
b <- c(3,12,9)
b
[1]  3 12  9
solve(A,b)
[1] -0.08108108  3.64864865  0.48648649

4 Decomposições de matrizes

4.1 Decomposição em valores singulares

A decomposição em valores singulares é útil para a implementação de diversos métodos estatísticos. Por exemplo, ela é o motor por trás da análise de componentes principais, que permite representar dados em um espaço de menor dimensão, retendo a maior parte da variabilidade.

Uma matriz \(A\) de ordem \(n\times p\) pode ser escrita como \[ A=USV^\top, \] em que as matrizes \(U\) e \(V\) são ortogonais (unitárias) e \(S\) é uma matriz diagonal. Por exemplo:

A = matrix(c(2,0,
             0,-3,
             0,0), ncol=2, byrow=TRUE)
A
     [,1] [,2]
[1,]    2    0
[2,]    0   -3
[3,]    0    0
# Aplicando a decomposição:
svd.A <- svd(A)
svd.A
$d
[1] 3 2

$u
     [,1] [,2]
[1,]    0    1
[2,]    1    0
[3,]    0    0

$v
     [,1] [,2]
[1,]    0    1
[2,]   -1    0
U <- svd.A$u
V <- svd.A$v
S <- diag(svd.A$d)
U
     [,1] [,2]
[1,]    0    1
[2,]    1    0
[3,]    0    0
V
     [,1] [,2]
[1,]    0    1
[2,]   -1    0
S
     [,1] [,2]
[1,]    3    0
[2,]    0    2
# Verificando que A = USV':
U%*%S%*%t(V)
     [,1] [,2]
[1,]    2    0
[2,]    0   -3
[3,]    0    0

4.2 Decomposição Espectral (Ou decomposição em Autovalores e Autovetores)

A decomposição em autovalores e autovetores também é uma importante ferramenta matemática utilizada na implementação de vários métodos estatísticos. Em análise de componentes principais, por exemplo, os autovalores indicam a variância em cada direção (componente principal), e os autovetores, a direção dessas variâncias, enquanto que q análise fatorial utiliza autovalores e autovetores para identificar estruturas latentes nos dados.

Dada uma matriz quadrada \(A\) (ordem \(n\times n\)), um autovetor \(\mathbf{x}\) é um vetor não nulo tal que, para algum escalar \(\lambda\) (real ou complexo), temos: \[ A\mathbf{x}=\mathbf{x}\lambda. \] Em outras palavras, sendo \(Q\) a matriz dos autovetores e \(\Lambda\) a matriz diagonal dos autovalores, temos que: \[ A=Q\Lambda Q^\top. \]

Por exemplo:

A = matrix(c(1,2,2,1), nrow=2, byrow=TRUE)
A
     [,1] [,2]
[1,]    1    2
[2,]    2    1
auto.vv = eigen(A)

auto.vv$values
[1]  3 -1
auto.vv$vectors
          [,1]       [,2]
[1,] 0.7071068 -0.7071068
[2,] 0.7071068  0.7071068

Vamos verificar que \(A\mathbf{x}=\mathbf{x}\lambda\):

x = auto.vv$vectors
lambda = auto.vv$values

A%*%x[,1]
        [,1]
[1,] 2.12132
[2,] 2.12132
x[,1]*lambda[1]
[1] 2.12132 2.12132
A%*%x[,2]
           [,1]
[1,]  0.7071068
[2,] -0.7071068
x[,2]*lambda[2]
[1]  0.7071068 -0.7071068
A%*%x
        [,1]       [,2]
[1,] 2.12132  0.7071068
[2,] 2.12132 -0.7071068
x%*%diag(lambda)
        [,1]       [,2]
[1,] 2.12132  0.7071068
[2,] 2.12132 -0.7071068

Equivalentemente, vamos verificar que \(A=Q\Lambda Q^\top\):

Q = auto.vv$vectors
Lambda = diag(lambda)

A
     [,1] [,2]
[1,]    1    2
[2,]    2    1
Q%*%Lambda%*%t(Q)
     [,1] [,2]
[1,]    1    2
[2,]    2    1

4.3 Decomposição de Cholesky

Outra decomposição importante para a estatística é a decomposição de Cholesky, a qual é utilizada, por exemplo, na geração de vetores de números aleatórios a partir da distribuição normal multivariada com uma matriz de covariância dada, em inferência utilizando Monte Carlo via Cadeias de Markov (MCMC), para amostragem eficiente, e no cálculo de verossimilhanças em modelos GARCH e hierárquicos, dentre outros.

A decomposição de Cholesky procura decompor uma matriz \(A\) na forma \(A = L^\top L\) , onde \(L\) é uma matriz triangular inferior com elementos da diagonal principal estritamente positivos. Para tanto, exige-se que a matriz \(A\) seja positiva definida. Uma matriz \(A\) é dita positiva definida se \(A\) é simétrica e se \(\mathbf{x}^\top A\mathbf{x} > 0\) para todo \(\mathbf{x}\neq 0\).

Exemplo:

A = matrix(c(4,2,0,
             2,2,1,
             0,1,2), nrow = 3, byrow=TRUE)
A
     [,1] [,2] [,3]
[1,]    4    2    0
[2,]    2    2    1
[3,]    0    1    2
# Decomposição de Cholesky
L = chol(A)
L
     [,1] [,2] [,3]
[1,]    2    1    0
[2,]    0    1    1
[3,]    0    0    1

Vamos verificar que \(A=L^\top L\):

A
     [,1] [,2] [,3]
[1,]    4    2    0
[2,]    2    2    1
[3,]    0    1    2
t(L)%*%L
     [,1] [,2] [,3]
[1,]    4    2    0
[2,]    2    2    1
[3,]    0    1    2

Vamos verificar também que \(L^{-1}L=I\)

solve(L)%*%L
     [,1] [,2] [,3]
[1,]    1    0    0
[2,]    0    1    0
[3,]    0    0    1

5 Exercícios

Resolva a lista de exercícios dada utilizando a linguagem R.