.. _sec_linear-algebra: Álgebra Linear ============== Agora que você pode armazenar e manipular dados, vamos revisar brevemente o subconjunto da álgebra linear básica que você precisa para entender e implementar a maioria dos modelos cobertos neste livro. Abaixo, apresentamos os objetos matemáticos básicos, aritméticos, e operações em álgebra linear, expressar cada um deles por meio de notação matemática e a implementação correspondente em código. Escalares --------- Se você nunca estudou álgebra linear ou aprendizado de máquina, então sua experiência anterior com matemática provavelmente consistia de pensar em um número de cada vez. E, se você já equilibrou um talão de cheques ou até mesmo pagou por um jantar em um restaurante então você já sabe como fazer coisas básicas como adicionar e multiplicar pares de números. Por exemplo, a temperatura em Palo Alto é de :math:`52` graus Fahrenheit. Formalmente, chamamos de valores que consistem de apenas uma quantidade numérica *escalar*. Se você quiser converter este valor para Celsius (escala de temperatura mais sensível do sistema métrico), você avaliaria a expressão :math:`c = \frac{5}{9}(f - 32)`, definindo :math:`f` para :math:`52`. Nesta equação, cada um dos termos—\ :math:`5`, :math:`9`, e :math:`32`—são valores escalares. Os marcadores :math:`c` e :math:`f` são chamados de *variáveis* e eles representam valores escalares desconhecidos. Neste livro, adotamos a notação matemática onde as variáveis escalares são denotadas por letras minúsculas comuns (por exemplo, :math:`x`, :math:`y`, and :math:`z`). Denotamos o espaço de todos os escalares (contínuos) *com valor real* por :math:`\mathbb{R}`. Por conveniência, vamos lançar mão de definições rigorosas do que exatamente é *espaço*, mas lembre-se por enquanto que a expressão :math:`x \in \mathbb{R}` é uma maneira formal de dizer que :math:`x` é um escalar com valor real. O símbolo :math:`\in` pode ser pronunciado “em” e simplesmente denota associação em um conjunto. Analogamente, poderíamos escrever :math:`x, y \in \{0, 1\}` para afirmar que :math:`x` e :math:`y` são números cujo valor só pode ser :math:`0` ou :math:`1`. Um escalar é representado por um tensor com apenas um elemento. No próximo trecho de código, instanciamos dois escalares e realizar algumas operações aritméticas familiares com eles, a saber, adição, multiplicação, divisão e exponenciação. .. raw:: html
mxnetpytorchtensorflow
.. raw:: html
.. code:: python from mxnet import np, npx npx.set_np() x = np.array(3.0) y = np.array(2.0) x + y, x * y, x / y, x ** y .. parsed-literal:: :class: output (array(5.), array(6.), array(1.5), array(9.)) .. raw:: html
.. raw:: html
.. code:: python import torch x = torch.tensor([3.0]) y = torch.tensor([2.0]) x + y, x * y, x / y, x**y .. parsed-literal:: :class: output (tensor([5.]), tensor([6.]), tensor([1.5000]), tensor([9.])) .. raw:: html
.. raw:: html
.. code:: python import tensorflow as tf x = tf.constant([3.0]) y = tf.constant([2.0]) x + y, x * y, x / y, x**y .. parsed-literal:: :class: output (, , , ) .. raw:: html
.. raw:: html
Vetores ------- Você pode pensar em um vetor simplesmente como uma lista de valores escalares. Chamamos esses valores de *elementos* (*entradas* ou *componentes*) do vetor. Quando nossos vetores representam exemplos de nosso conjunto de dados, seus valores têm algum significado no mundo real. Por exemplo, se estivéssemos treinando um modelo para prever o risco de inadimplência de um empréstimo, podemos associar cada candidato a um vetor cujos componentes correspondem à sua receita, tempo de emprego, número de inadimplências anteriores e outros fatores. Se estivéssemos estudando o risco de ataques cardíacos que os pacientes de hospitais potencialmente enfrentam, podemos representar cada paciente por um vetor cujos componentes capturam seus sinais vitais mais recentes, níveis de colesterol, minutos de exercício por dia, etc. Em notação matemática, geralmente denotamos os vetores em negrito, letras minúsculas (por exemplo,, :math:`\mathbf{x}`, :math:`\mathbf{y}`, and :math:`\mathbf{z})`. Trabalhamos com vetores via tensores unidimensionais. Em geral, os tensores podem ter comprimentos arbitrários, sujeito aos limites de memória de sua máquina. .. raw:: html
mxnetpytorchtensorflow
.. raw:: html
.. code:: python x = np.arange(4) x .. parsed-literal:: :class: output array([0., 1., 2., 3.]) .. raw:: html
.. raw:: html
.. code:: python x = torch.arange(4) x .. parsed-literal:: :class: output tensor([0, 1, 2, 3]) .. raw:: html
.. raw:: html
.. code:: python x = tf.range(4) x .. parsed-literal:: :class: output .. raw:: html
.. raw:: html
Podemos nos referir a qualquer elemento de um vetor usando um subscrito. Por exemplo, podemos nos referir ao elemento :math:`i^\mathrm{th}` element of :math:`\mathbf{x}` por :math:`x_i`. Observe que o elemento :math:`x_i` é um escalar, portanto, não colocamos a fonte em negrito quando nos referimos a ela. A literatura extensa considera os vetores de coluna como o padrão orientação de vetores, este livro também. Em matemática, um vetor :math:`\mathbf{x}` pode ser escrito como .. math:: \mathbf{x} =\begin{bmatrix}x_{1} \\x_{2} \\ \vdots \\x_{n}\end{bmatrix}, :label: eq_vec_def onde :math:`x_1, \ldots, x_n` são elementos do vetor. No código acessamos qualquer elemento indexando no tensor .. raw:: html
mxnetpytorchtensorflow
.. raw:: html
.. code:: python x[3] .. parsed-literal:: :class: output array(3.) .. raw:: html
.. raw:: html
.. code:: python x[3] .. parsed-literal:: :class: output tensor(3) .. raw:: html
.. raw:: html
.. code:: python x[3] .. parsed-literal:: :class: output .. raw:: html
.. raw:: html
Comprimento, Dimensionalidade e Forma ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Vamos revisitar alguns conceitos de: numref: ``sec_ndarray``. Um vetor é apenas uma matriz de números. E assim como todo array tem um comprimento, todo vetor também. Em notação matemática, se quisermos dizer que um vetor :math:`\mathbf{x}` consiste em :math:`n` escalares com valor real, podemos expressar isso como :math:`\mathbf{x} \in \mathbb{R}^n`. O comprimento de um vetor é comumente chamado de *dimensão* do vetor. Tal como acontece com uma matriz Python comum, nós podemos acessar o comprimento de um tensor chamando a função ``len ()`` embutida do Python. .. raw:: html
mxnetpytorchtensorflow
.. raw:: html
.. code:: python len(x) .. parsed-literal:: :class: output 4 .. raw:: html
.. raw:: html
.. code:: python len(x) .. parsed-literal:: :class: output 4 .. raw:: html
.. raw:: html
.. code:: python len(x) .. parsed-literal:: :class: output 4 .. raw:: html
.. raw:: html
Quando um tensor representa um vetor (com precisamente um eixo), também podemos acessar seu comprimento por meio do atributo ``.shape``. A forma é uma tupla que lista o comprimento (dimensionalidade) ao longo de cada eixo do tensor. Para tensores com apenas um eixo, a forma tem apenas um elemento. .. raw:: html
mxnetpytorchtensorflow
.. raw:: html
.. code:: python x.shape .. parsed-literal:: :class: output (4,) .. raw:: html
.. raw:: html
.. code:: python x.shape .. parsed-literal:: :class: output torch.Size([4]) .. raw:: html
.. raw:: html
.. code:: python x.shape .. parsed-literal:: :class: output TensorShape([4]) .. raw:: html
.. raw:: html
Observe que a palavra “dimensão” tende a ficar sobrecarregada nesses contextos e isso tende a confundir as pessoas. Para esclarecer, usamos a dimensionalidade de um *vetor* ou um *eixo* para se referir ao seu comprimento, ou seja, o número de elementos de um vetor ou eixo. No entanto, usamos a dimensionalidade de um tensor para se referir ao número de eixos que um tensor possui. Nesse sentido, a dimensionalidade de algum eixo de um tensor será o comprimento desse eixo. Matrizes -------- Assim como os vetores generalizam escalares de ordem zero para ordem um, matrizes generalizam vetores de ordem um para ordem dois. Matrizes, que normalmente denotamos com letras maiúsculas em negrito (por exemplo, :math:`\mathbf{X}`, :math:`\mathbf{Y}`, and :math:`\mathbf{Z}`), são representados no código como tensores com dois eixos. Em notação matemática, usamos :math:`\mathbf{A} \in \mathbb{R}^{m \times n}` para expressar que a matriz :math:`\mathbf {A}` consiste em :math:`m` linhas e :math:`n` colunas de escalares com valor real. Visualmente, podemos ilustrar qualquer matriz :math:`\mathbf{A} \in \mathbb{R}^{m \times n}` como uma tabela, onde cada elemento :math:`a_{ij}` pertence à linha :math:`i^{\mathrm{th}}` e coluna :math:`j^{\mathrm{th}}`: .. math:: \mathbf{A}=\begin{bmatrix} a_{11} & a_{12} & \cdots & a_{1n} \\ a_{21} & a_{22} & \cdots & a_{2n} \\ \vdots & \vdots & \ddots & \vdots \\ a_{m1} & a_{m2} & \cdots & a_{mn} \\ \end{bmatrix}. :label: eq_matrix_def Para qualquer :math:`\mathbf{A} \in \mathbb{R}^{m \times n}`, a forma de :math:`\mathbf{A}` é (:math:`m`, :math:`n`) ou :math:`m \times n`. Especificamente, quando uma matriz tem o mesmo número de linhas e colunas, sua forma se torna um quadrado; portanto, é chamada de *matriz quadrada*. Podemos criar uma matriz :math:`m \times n` especificando uma forma com dois componentes :math:`m` e :math:`n` ao chamar qualquer uma de nossas funções favoritas para instanciar um tensor. .. raw:: html
mxnetpytorchtensorflow
.. raw:: html
.. code:: python A = np.arange(20).reshape(5, 4) A .. parsed-literal:: :class: output array([[ 0., 1., 2., 3.], [ 4., 5., 6., 7.], [ 8., 9., 10., 11.], [12., 13., 14., 15.], [16., 17., 18., 19.]]) .. raw:: html
.. raw:: html
.. code:: python A = torch.arange(20).reshape(5, 4) A .. parsed-literal:: :class: output tensor([[ 0, 1, 2, 3], [ 4, 5, 6, 7], [ 8, 9, 10, 11], [12, 13, 14, 15], [16, 17, 18, 19]]) .. raw:: html
.. raw:: html
.. code:: python A = tf.reshape(tf.range(20), (5, 4)) A .. parsed-literal:: :class: output .. raw:: html
.. raw:: html
Podemos acessar o elemento escalar :math:`a_{ij}` de uma matriz :math:`\mathbf{A}` em: eqref: ``eq_matrix_def`` especificando os índices para a linha (:math:`i`) e coluna (:math:`j`), como :math:`[\mathbf {A}] _ {ij}`. Quando os elementos escalares de uma matriz :math:`\mathbf{A}`, como em: eqref: ``eq_matrix_def``, não são fornecidos, podemos simplesmente usar a letra minúscula da matriz :math:`\mathbf{A}` com o subscrito do índice, :math:`a_{ij}`, para se referir a :math:`[\mathbf {A}] _ {ij}`. Para manter a notação simples, as vírgulas são inseridas para separar os índices apenas quando necessário, como :math:`a_ {2, 3j}` e :math:`[\mathbf {A}] _ {2i-1, 3}`. Às vezes, queremos inverter os eixos. Quando trocamos as linhas e colunas de uma matriz, o resultado é chamado de *transposição* da matriz. Formalmente, significamos uma matriz :math:`\mathbf {A}` transposta por :math:`\mathbf {A} ^ \top` e se :math:`\mathbf {B} = \mathbf {A} ^ \top`, então :math:`b_ {ij} = a_ {ji}` para qualquer :math:`i` e :math:`j`. Assim, a transposição de :math:`\mathbf {A}` em: eqref: ``eq_matrix_def`` é uma matriz :math:`n \times m`: .. math:: \mathbf{A}^\top = \begin{bmatrix} a_{11} & a_{21} & \dots & a_{m1} \\ a_{12} & a_{22} & \dots & a_{m2} \\ \vdots & \vdots & \ddots & \vdots \\ a_{1n} & a_{2n} & \dots & a_{mn} \end{bmatrix}. Agora acessamoas a matriz transposta via código. .. raw:: html
mxnetpytorchtensorflow
.. raw:: html
.. code:: python A.T .. parsed-literal:: :class: output array([[ 0., 4., 8., 12., 16.], [ 1., 5., 9., 13., 17.], [ 2., 6., 10., 14., 18.], [ 3., 7., 11., 15., 19.]]) .. raw:: html
.. raw:: html
.. code:: python A.T .. parsed-literal:: :class: output tensor([[ 0, 4, 8, 12, 16], [ 1, 5, 9, 13, 17], [ 2, 6, 10, 14, 18], [ 3, 7, 11, 15, 19]]) .. raw:: html
.. raw:: html
.. code:: python tf.transpose(A) .. parsed-literal:: :class: output .. raw:: html
.. raw:: html
Como um tipo especial de matriz quadrada, a *matriz simétrica* :math:`\mathbf {A}` é igual à sua transposta: :math:`\mathbf{A} = \mathbf{A}^\top`. Aqui definimos uma matriz simétrica ``B``. .. raw:: html
mxnetpytorchtensorflow
.. raw:: html
.. code:: python B = np.array([[1, 2, 3], [2, 0, 4], [3, 4, 5]]) B .. parsed-literal:: :class: output array([[1., 2., 3.], [2., 0., 4.], [3., 4., 5.]]) .. raw:: html
.. raw:: html
.. code:: python B = torch.tensor([[1, 2, 3], [2, 0, 4], [3, 4, 5]]) B .. parsed-literal:: :class: output tensor([[1, 2, 3], [2, 0, 4], [3, 4, 5]]) .. raw:: html
.. raw:: html
.. code:: python B = tf.constant([[1, 2, 3], [2, 0, 4], [3, 4, 5]]) B .. parsed-literal:: :class: output .. raw:: html
.. raw:: html
Agora comparamos ``B`` com sua transposta. .. raw:: html
mxnetpytorchtensorflow
.. raw:: html
.. code:: python B == B.T .. parsed-literal:: :class: output array([[ True, True, True], [ True, True, True], [ True, True, True]]) .. raw:: html
.. raw:: html
.. code:: python B == B.T .. parsed-literal:: :class: output tensor([[True, True, True], [True, True, True], [True, True, True]]) .. raw:: html
.. raw:: html
.. code:: python B == tf.transpose(B) .. parsed-literal:: :class: output .. raw:: html
.. raw:: html
Matrizes são estruturas de dados úteis: eles nos permitem organizar dados que têm diferentes modalidades de variação. Por exemplo, as linhas em nossa matriz podem corresponder a diferentes casas (exemplos de dados), enquanto as colunas podem corresponder a diferentes atributos. Isso deve soar familiar se você já usou um software de planilha ou leu: numref: ``sec_pandas``. Assim, embora a orientação padrão de um único vetor seja um vetor coluna, em uma matriz que representa um conjunto de dados tabular, é mais convencional tratar cada exemplo de dados como um vetor linha na matriz. E, como veremos em capítulos posteriores, esta convenção permitirá práticas comuns de aprendizado profundo. Por exemplo, ao longo do eixo mais externo de um tensor, podemos acessar ou enumerar *minibatches* de exemplos de dados, ou apenas exemplos de dados se não houver *minibatch*. Tensores -------- Assim como vetores generalizam escalares e matrizes generalizam vetores, podemos construir estruturas de dados com ainda mais eixos. Tensores (“tensores” nesta subseção referem-se a objetos algébricos) nos dê uma maneira genérica de descrever matrizes :math:`n` -dimensionais com um número arbitrário de eixos. Vetores, por exemplo, são tensores de primeira ordem e matrizes são tensores de segunda ordem. Tensores são indicados com letras maiúsculas de uma fonte especial (por exemplo, :math:`\mathsf{X}`, :math:`\mathsf{Y}`, e :math:`\mathsf{Z}`) e seu mecanismo de indexação (por exemplo, :math:`x_{ijk}` e :math:`[\mathsf{X}]_{1, 2i-1, 3}`) é semelhante ao de matrizes. Os tensores se tornarão mais importantes quando começarmos a trabalhar com imagens, que chegam como matrizes :math:`n` -dimensionais com 3 eixos correspondentes à altura, largura e um eixo de *canal* para empilhar os canais de cores (vermelho, verde e azul). Por enquanto, vamos pular tensores de ordem superior e nos concentrar no básico. .. raw:: html
mxnetpytorchtensorflow
.. raw:: html
.. code:: python X = np.arange(24).reshape(2, 3, 4) X .. parsed-literal:: :class: output array([[[ 0., 1., 2., 3.], [ 4., 5., 6., 7.], [ 8., 9., 10., 11.]], [[12., 13., 14., 15.], [16., 17., 18., 19.], [20., 21., 22., 23.]]]) .. raw:: html
.. raw:: html
.. code:: python X = torch.arange(24).reshape(2, 3, 4) X .. parsed-literal:: :class: output tensor([[[ 0, 1, 2, 3], [ 4, 5, 6, 7], [ 8, 9, 10, 11]], [[12, 13, 14, 15], [16, 17, 18, 19], [20, 21, 22, 23]]]) .. raw:: html
.. raw:: html
.. code:: python X = tf.reshape(tf.range(24), (2, 3, 4)) X .. parsed-literal:: :class: output .. raw:: html
.. raw:: html
Propriedades Básicas de Aritmética de Tensores ---------------------------------------------- Escalares, vetores, matrizes e tensores (“tensores” nesta subseção referem-se a objetos algébricos) de um número arbitrário de eixos têm algumas propriedades interessantes que muitas vezes são úteis. Por exemplo, você deve ter notado da definição de uma operação elemento a elemento que qualquer operação unária elementar não altera a forma de seu operando. Similarmente, dados quaisquer dois tensores com a mesma forma, o resultado de qualquer operação binária elementar será um tensor da mesma forma. Por exemplo, adicionar duas matrizes da mesma forma realiza a adição elemento a elemento sobre essas duas matrizes. .. raw:: html
mxnetpytorchtensorflow
.. raw:: html
.. code:: python A = np.arange(20).reshape(5, 4) B = A.copy() # Cria uma cópia de `A` em `B` alocando nova memória A, A + B .. parsed-literal:: :class: output (array([[ 0., 1., 2., 3.], [ 4., 5., 6., 7.], [ 8., 9., 10., 11.], [12., 13., 14., 15.], [16., 17., 18., 19.]]), array([[ 0., 2., 4., 6.], [ 8., 10., 12., 14.], [16., 18., 20., 22.], [24., 26., 28., 30.], [32., 34., 36., 38.]])) .. raw:: html
.. raw:: html
.. code:: python A = torch.arange(20, dtype=torch.float32).reshape(5, 4) B = A.clone() # Cria uma cópia de `A` em `B` alocando nova memória A, A + B .. parsed-literal:: :class: output (tensor([[ 0., 1., 2., 3.], [ 4., 5., 6., 7.], [ 8., 9., 10., 11.], [12., 13., 14., 15.], [16., 17., 18., 19.]]), tensor([[ 0., 2., 4., 6.], [ 8., 10., 12., 14.], [16., 18., 20., 22.], [24., 26., 28., 30.], [32., 34., 36., 38.]])) .. raw:: html
.. raw:: html
.. code:: python A = tf.reshape(tf.range(20, dtype=tf.float32), (5, 4)) B = A # Não está clonando `A` para `B` para alocar nova memória A, A + B .. parsed-literal:: :class: output (, ) .. raw:: html
.. raw:: html
Especificamente, a multiplicação elemento a elemento de duas matrizes é chamada de *produto Hadamard* (notação matemática :math:`\odot`). Considere a matriz :math:`\mathbf{B} \in \mathbb{R}^{m \times n}` cujo elemento da linha :math:`i` e coluna :math:`j` é :math:`b_ {ij}`. O produto Hadamard das matrizes :math:`\mathbf {A}` (definido em :eq:`eq_matrix_def`) e :math:`\mathbf {B}` .. math:: \mathbf{A} \odot \mathbf{B} = \begin{bmatrix} a_{11} b_{11} & a_{12} b_{12} & \dots & a_{1n} b_{1n} \\ a_{21} b_{21} & a_{22} b_{22} & \dots & a_{2n} b_{2n} \\ \vdots & \vdots & \ddots & \vdots \\ a_{m1} b_{m1} & a_{m2} b_{m2} & \dots & a_{mn} b_{mn} \end{bmatrix}. .. raw:: html
mxnetpytorchtensorflow
.. raw:: html
.. code:: python A * B .. parsed-literal:: :class: output array([[ 0., 1., 4., 9.], [ 16., 25., 36., 49.], [ 64., 81., 100., 121.], [144., 169., 196., 225.], [256., 289., 324., 361.]]) .. raw:: html
.. raw:: html
.. code:: python A * B .. parsed-literal:: :class: output tensor([[ 0., 1., 4., 9.], [ 16., 25., 36., 49.], [ 64., 81., 100., 121.], [144., 169., 196., 225.], [256., 289., 324., 361.]]) .. raw:: html
.. raw:: html
.. code:: python A * B .. parsed-literal:: :class: output .. raw:: html
.. raw:: html
Multiplicar ou adicionar um tensor por um escalar também não muda a forma do tensor, onde cada elemento do tensor operando será adicionado ou multiplicado pelo escalar. .. raw:: html
mxnetpytorchtensorflow
.. raw:: html
.. code:: python a = 2 X = np.arange(24).reshape(2, 3, 4) a + X, (a * X).shape .. parsed-literal:: :class: output (array([[[ 2., 3., 4., 5.], [ 6., 7., 8., 9.], [10., 11., 12., 13.]], [[14., 15., 16., 17.], [18., 19., 20., 21.], [22., 23., 24., 25.]]]), (2, 3, 4)) .. raw:: html
.. raw:: html
.. code:: python a = 2 X = torch.arange(24).reshape(2, 3, 4) a + X, (a * X).shape .. parsed-literal:: :class: output (tensor([[[ 2, 3, 4, 5], [ 6, 7, 8, 9], [10, 11, 12, 13]], [[14, 15, 16, 17], [18, 19, 20, 21], [22, 23, 24, 25]]]), torch.Size([2, 3, 4])) .. raw:: html
.. raw:: html
.. code:: python a = 2 X = tf.reshape(tf.range(24), (2, 3, 4)) a + X, (a * X).shape .. parsed-literal:: :class: output (, TensorShape([2, 3, 4])) .. raw:: html
.. raw:: html
.. _subseq_lin-alg-reduction: Redução ------- Uma operação útil que podemos realizar com tensores arbitrários é para calcule a soma de seus elementos. Em notação matemática, expressamos somas usando o símbolo :math:`\sum`. Para expressar a soma dos elementos em um vetor :math:`\mathbf {x}` de comprimento :math:`d`, escrevemos :math:`\sum_ {i = 1} ^ d x_i`. No código, podemos apenas chamar a função para calcular a soma. .. raw:: html
mxnetpytorchtensorflow
.. raw:: html
.. code:: python x = np.arange(4) x, x.sum() .. parsed-literal:: :class: output (array([0., 1., 2., 3.]), array(6.)) .. raw:: html
.. raw:: html
.. code:: python x = torch.arange(4, dtype=torch.float32) x, x.sum() .. parsed-literal:: :class: output (tensor([0., 1., 2., 3.]), tensor(6.)) .. raw:: html
.. raw:: html
.. code:: python x = tf.range(4, dtype=tf.float32) x, tf.reduce_sum(x) .. parsed-literal:: :class: output (, ) .. raw:: html
.. raw:: html
Podemos expressar somas sobre os elementos de tensores de forma arbitrária. Por exemplo, a soma dos elementos de uma matriz :math:`m \times n` :math:`\mathbf{A}` poderia ser escrita como :math:`\sum_{i=1}^{m} \sum_{j=1}^{n} a_{ij}`. .. raw:: html
mxnetpytorchtensorflow
.. raw:: html
.. code:: python A.shape, A.sum() .. parsed-literal:: :class: output ((5, 4), array(190.)) .. raw:: html
.. raw:: html
.. code:: python A.shape, A.sum() .. parsed-literal:: :class: output (torch.Size([5, 4]), tensor(190.)) .. raw:: html
.. raw:: html
.. code:: python A.shape, tf.reduce_sum(A) .. parsed-literal:: :class: output (TensorShape([5, 4]), ) .. raw:: html
.. raw:: html
Por padrão, invocar a função para calcular a soma *reduz* um tensor ao longo de todos os seus eixos a um escalar. Também podemos especificar os eixos ao longo dos quais o tensor é reduzido por meio da soma Pegue as matrizes como exemplo. Para reduzir a dimensão da linha (eixo 0) somando os elementos de todas as linhas, especificamos ``axis = 0`` ao invocar a função. Uma vez que a matriz de entrada reduz ao longo do eixo 0 para gerar o vetor de saída, a dimensão do eixo 0 da entrada é perdida na forma de saída. .. raw:: html
mxnetpytorchtensorflow
.. raw:: html
.. code:: python A_sum_axis0 = A.sum(axis=0) A_sum_axis0, A_sum_axis0.shape .. parsed-literal:: :class: output (array([40., 45., 50., 55.]), (4,)) .. raw:: html
.. raw:: html
.. code:: python A_sum_axis0 = A.sum(axis=0) A_sum_axis0, A_sum_axis0.shape .. parsed-literal:: :class: output (tensor([40., 45., 50., 55.]), torch.Size([4])) .. raw:: html
.. raw:: html
.. code:: python A_sum_axis0 = tf.reduce_sum(A, axis=0) A_sum_axis0, A_sum_axis0.shape .. parsed-literal:: :class: output (, TensorShape([4])) .. raw:: html
.. raw:: html
Especificando ``eixo = 1`` irá reduzir a dimensão da coluna (eixo 1) ao somar os elementos de todas as colunas. Assim, a dimensão do eixo 1 da entrada é perdida na forma da saída. .. raw:: html
mxnetpytorchtensorflow
.. raw:: html
.. code:: python A_sum_axis1 = A.sum(axis=1) A_sum_axis1, A_sum_axis1.shape .. parsed-literal:: :class: output (array([ 6., 22., 38., 54., 70.]), (5,)) .. raw:: html
.. raw:: html
.. code:: python A_sum_axis1 = A.sum(axis=1) A_sum_axis1, A_sum_axis1.shape .. parsed-literal:: :class: output (tensor([ 6., 22., 38., 54., 70.]), torch.Size([5])) .. raw:: html
.. raw:: html
.. code:: python A_sum_axis1 = tf.reduce_sum(A, axis=1) A_sum_axis1, A_sum_axis1.shape .. parsed-literal:: :class: output (, TensorShape([5])) .. raw:: html
.. raw:: html
Reduzindo uma matriz ao longo de ambas as linhas e colunas por meio da soma é equivalente a somar todos os elementos da matriz. .. raw:: html
mxnetpytorchtensorflow
.. raw:: html
.. code:: python A.sum(axis=[0, 1]) # O mesmo que `A.sum()` .. parsed-literal:: :class: output array(190.) .. raw:: html
.. raw:: html
.. code:: python A.sum(axis=[0, 1]) # O mesmo que `A.sum()` .. parsed-literal:: :class: output tensor(190.) .. raw:: html
.. raw:: html
.. code:: python tf.reduce_sum(A, axis=[0, 1]) # O mesmo que `tf.reduce_sum(A)` .. parsed-literal:: :class: output .. raw:: html
.. raw:: html
Uma quantidade relacionada é a *média*, que também é chamada de *média*. Calculamos a média dividindo a soma pelo número total de elementos. No código, poderíamos apenas chamar a função para calcular a média em tensores de forma arbitrária. .. raw:: html
mxnetpytorchtensorflow
.. raw:: html
.. code:: python A.mean(), A.sum() / A.size .. parsed-literal:: :class: output (array(9.5), array(9.5)) .. raw:: html
.. raw:: html
.. code:: python A.mean(), A.sum() / A.numel() .. parsed-literal:: :class: output (tensor(9.5000), tensor(9.5000)) .. raw:: html
.. raw:: html
.. code:: python tf.reduce_mean(A), tf.reduce_sum(A) / tf.size(A).numpy() .. parsed-literal:: :class: output (, ) .. raw:: html
.. raw:: html
Da mesma forma, a função de cálculo da média também pode reduzir um tensor ao longo dos eixos especificados. .. raw:: html
mxnetpytorchtensorflow
.. raw:: html
.. code:: python A.mean(axis=0), A.sum(axis=0) / A.shape[0] .. parsed-literal:: :class: output (array([ 8., 9., 10., 11.]), array([ 8., 9., 10., 11.])) .. raw:: html
.. raw:: html
.. code:: python A.mean(axis=0), A.sum(axis=0) / A.shape[0] .. parsed-literal:: :class: output (tensor([ 8., 9., 10., 11.]), tensor([ 8., 9., 10., 11.])) .. raw:: html
.. raw:: html
.. code:: python tf.reduce_mean(A, axis=0), tf.reduce_sum(A, axis=0) / A.shape[0] .. parsed-literal:: :class: output (, ) .. raw:: html
.. raw:: html
.. _subseq_lin-alg-non-reduction: Soma não reducional ~~~~~~~~~~~~~~~~~~~ Contudo, às vezes pode ser útil manter o número de eixos inalterado ao invocar a função para calcular a soma ou média. .. raw:: html
mxnetpytorchtensorflow
.. raw:: html
.. code:: python sum_A = A.sum(axis=1, keepdims=True) sum_A .. parsed-literal:: :class: output array([[ 6.], [22.], [38.], [54.], [70.]]) .. raw:: html
.. raw:: html
.. code:: python sum_A = A.sum(axis=1, keepdims=True) sum_A .. parsed-literal:: :class: output tensor([[ 6.], [22.], [38.], [54.], [70.]]) .. raw:: html
.. raw:: html
.. code:: python sum_A = tf.reduce_sum(A, axis=1, keepdims=True) sum_A .. parsed-literal:: :class: output .. raw:: html
.. raw:: html
Por exemplo, uma vez que ``sum_A`` ainda mantém seus dois eixos após somar cada linha, podemos dividir\ ``A`` por ``sum_A`` com *broadcasting*. .. raw:: html
mxnetpytorchtensorflow
.. raw:: html
.. code:: python A / sum_A .. parsed-literal:: :class: output array([[0. , 0.16666667, 0.33333334, 0.5 ], [0.18181819, 0.22727273, 0.27272728, 0.3181818 ], [0.21052632, 0.23684211, 0.2631579 , 0.28947368], [0.22222222, 0.24074075, 0.25925925, 0.2777778 ], [0.22857143, 0.24285714, 0.25714287, 0.27142859]]) .. raw:: html
.. raw:: html
.. code:: python A / sum_A .. parsed-literal:: :class: output tensor([[0.0000, 0.1667, 0.3333, 0.5000], [0.1818, 0.2273, 0.2727, 0.3182], [0.2105, 0.2368, 0.2632, 0.2895], [0.2222, 0.2407, 0.2593, 0.2778], [0.2286, 0.2429, 0.2571, 0.2714]]) .. raw:: html
.. raw:: html
.. code:: python A / sum_A .. parsed-literal:: :class: output .. raw:: html
.. raw:: html
Se quisermos calcular a soma cumulativa dos elementos de ``A`` ao longo de algum eixo, diga\ ``eixo = 0`` (linha por linha), podemos chamar a função ``cumsum``. Esta função não reduzirá o tensor de entrada ao longo de nenhum eixo. .. raw:: html
mxnetpytorchtensorflow
.. raw:: html
.. code:: python A.cumsum(axis=0) .. parsed-literal:: :class: output array([[ 0., 1., 2., 3.], [ 4., 6., 8., 10.], [12., 15., 18., 21.], [24., 28., 32., 36.], [40., 45., 50., 55.]]) .. raw:: html
.. raw:: html
.. code:: python A.cumsum(axis=0) .. parsed-literal:: :class: output tensor([[ 0., 1., 2., 3.], [ 4., 6., 8., 10.], [12., 15., 18., 21.], [24., 28., 32., 36.], [40., 45., 50., 55.]]) .. raw:: html
.. raw:: html
.. code:: python tf.cumsum(A, axis=0) .. parsed-literal:: :class: output .. raw:: html
.. raw:: html
Produto Escalar --------------- Até agora, realizamos apenas operações elementares, somas e médias. E se isso fosse tudo que pudéssemos fazer, a álgebra linear provavelmente não mereceria sua própria seção. No entanto, uma das operações mais fundamentais é o produto escalar. Dados dois vetores :math:`\mathbf{x}, \mathbf{y} \in \mathbb{R}^d`, seu *produto escalar* :math:`\mathbf{x}^\top \mathbf{y}` (ou :math:`\langle \mathbf{x}, \mathbf{y} \rangle`) é uma soma sobre os produtos dos elementos na mesma posição: :math:`\mathbf{x}^\top \mathbf{y} = \sum_{i=1}^{d} x_i y_i`. .. raw:: html
mxnetpytorchtensorflow
.. raw:: html
.. code:: python y = np.ones(4) x, y, np.dot(x, y) .. parsed-literal:: :class: output (array([0., 1., 2., 3.]), array([1., 1., 1., 1.]), array(6.)) .. raw:: html
.. raw:: html
.. code:: python y = torch.ones(4, dtype = torch.float32) x, y, torch.dot(x, y) .. parsed-literal:: :class: output (tensor([0., 1., 2., 3.]), tensor([1., 1., 1., 1.]), tensor(6.)) .. raw:: html
.. raw:: html
.. code:: python y = tf.ones(4, dtype=tf.float32) x, y, tf.tensordot(x, y, axes=1) .. parsed-literal:: :class: output (, , ) .. raw:: html
.. raw:: html
Observe que podemos expressar o produto escalar de dois vetores de forma equivalente, realizando uma multiplicação elemento a elemento e, em seguida, uma soma: .. raw:: html
mxnetpytorchtensorflow
.. raw:: html
.. code:: python np.sum(x * y) .. parsed-literal:: :class: output array(6.) .. raw:: html
.. raw:: html
.. code:: python torch.sum(x * y) .. parsed-literal:: :class: output tensor(6.) .. raw:: html
.. raw:: html
.. code:: python tf.reduce_sum(x * y) .. parsed-literal:: :class: output .. raw:: html
.. raw:: html
Os produtos escalares são úteis em uma ampla variedade de contextos. Por exemplo, dado algum conjunto de valores, denotado por um vetor :math:`\mathbf{x} \in \mathbb{R}^d` e um conjunto de pesos denotado por :math:`\mathbf{w} \in \mathbb{R}^d`,, a soma ponderada dos valores em :math:`\mathbf{x}` de acordo com os pesos :math:`\mathbf{w}` pode ser expresso como o produto escalar :math:`\mathbf{x}^\top \mathbf{w}`. Quando os pesos não são negativos e soma a um (ou seja, :math:`\left(\sum_{i=1}^{d} {w_i} = 1\right)`), o produto escalar expressa uma *média ponderada*. Depois de normalizar dois vetores para ter o comprimento unitário, os produtos escalares expressam o cosseno do ângulo entre eles. Apresentaremos formalmente essa noção de *comprimento* posteriormente nesta seção. Produtos Matriz-Vetor --------------------- Agora que sabemos como calcular produtos escalares, podemos começar a entender *produtos vetoriais de matriz*. Lembre-se da matriz :math:`\mathbf{A} \in \mathbb{R}^{m \times n}` e o vetor :math:`\mathbf{x} \in \mathbb{R}^n` definido e visualizado em :eq:`eq_matrix_def` e :eq:`eq_vec_def` respectivamente. Vamos começar visualizando a matriz :math:`\mathbf{A}` em termos de seus vetores linha .. math:: \mathbf{A}= \begin{bmatrix} \mathbf{a}^\top_{1} \\ \mathbf{a}^\top_{2} \\ \vdots \\ \mathbf{a}^\top_m \\ \end{bmatrix}, onde cada :math:`\mathbf{a}^\top_{i} \in \mathbb{R}^n` é uma linha vetor representando a :math:`i^\mathrm{th}` linha da matriz :math:`\mathbf{A}`. O produto vetor-matriz :math:`\mathbf{A}\mathbf{x}` é simplesmente um vetor coluna de comprimento :math:`m`, cujo elemento :math:`i^\mathrm{th}` é o produto escalar :math:`\mathbf{a}^\top_i \mathbf{x}`: .. math:: \mathbf{A}\mathbf{x} = \begin{bmatrix} \mathbf{a}^\top_{1} \\ \mathbf{a}^\top_{2} \\ \vdots \\ \mathbf{a}^\top_m \\ \end{bmatrix}\mathbf{x} = \begin{bmatrix} \mathbf{a}^\top_{1} \mathbf{x} \\ \mathbf{a}^\top_{2} \mathbf{x} \\ \vdots\\ \mathbf{a}^\top_{m} \mathbf{x}\\ \end{bmatrix}. Podemos pensar na multiplicação por uma matriz :math:`\mathbf{A}\in \mathbb{R}^{m \times n}` como uma transformação que projeta vetores de :math:`\mathbb{R}^{n}` a :math:`\mathbb{R}^{m}`. Essas transformações revelaram-se extremamente úteis. Por exemplo, podemos representar rotações como multiplicações por uma matriz quadrada. Como veremos nos capítulos subsequentes, também podemos usar produtos vetoriais de matriz para descrever os cálculos mais intensivos necessário ao calcular cada camada em uma rede neural dados os valores da camada anterior. Expressando produtos de vetor-matriz em código com tensores, usamos a mesma função ``dot`` que para produtos de ponto. Quando chamamos ``np.dot (A, x)`` com uma matriz ``A`` e um vetor\ ``x``, o produto matriz-vetor é realizado. Observe que a dimensão da coluna de ``A`` (seu comprimento ao longo do eixo 1) deve ser igual à dimensão de ``x`` (seu comprimento). .. raw:: html
mxnetpytorchtensorflow
.. raw:: html
.. code:: python A.shape, x.shape, np.dot(A, x) .. parsed-literal:: :class: output ((5, 4), (4,), array([ 14., 38., 62., 86., 110.])) .. raw:: html
.. raw:: html
.. code:: python A.shape, x.shape, torch.mv(A, x) .. parsed-literal:: :class: output (torch.Size([5, 4]), torch.Size([4]), tensor([ 14., 38., 62., 86., 110.])) .. raw:: html
.. raw:: html
.. code:: python A.shape, x.shape, tf.linalg.matvec(A, x) .. parsed-literal:: :class: output (TensorShape([5, 4]), TensorShape([4]), ) .. raw:: html
.. raw:: html
Multiplicação Matriz Matriz --------------------------- Se você já pegou o jeito dos produtos escalares e produtos matriciais, então a *multiplicação matriz-matriz* deve ser direta. Digamos que temos duas matrizes :math:`\mathbf{A} \in \mathbb{R}^{n \times k}` e :math:`\mathbf{B} \in \mathbb{R}^{k \times m}`: .. math:: \mathbf{A}=\begin{bmatrix} a_{11} & a_{12} & \cdots & a_{1k} \\ a_{21} & a_{22} & \cdots & a_{2k} \\ \vdots & \vdots & \ddots & \vdots \\ a_{n1} & a_{n2} & \cdots & a_{nk} \\ \end{bmatrix},\quad \mathbf{B}=\begin{bmatrix} b_{11} & b_{12} & \cdots & b_{1m} \\ b_{21} & b_{22} & \cdots & b_{2m} \\ \vdots & \vdots & \ddots & \vdots \\ b_{k1} & b_{k2} & \cdots & b_{km} \\ \end{bmatrix}. Denotada por :math:`\mathbf{a}^\top_{i} \in \mathbb{R}^k` o vetor linha representando a :math:`i^\mathrm{th}` linha da matriz :math:`\mathbf{A}`, e :math:`\mathbf{b}_{j} \in \mathbb{R}^k` seja o vetor coluna da :math:`j^\mathrm{th}` coluna matriz :math:`\mathbf{B}`. Para produzir o produto de matrizes :math:`\mathbf{C} = \mathbf{A}\mathbf{B}`, é mais facil pensar :math:`\mathbf{A}` em termos de seus vetores linha :math:`\mathbf{B}` em termos de seus vetores coluna: .. math:: \mathbf{A}= \begin{bmatrix} \mathbf{a}^\top_{1} \\ \mathbf{a}^\top_{2} \\ \vdots \\ \mathbf{a}^\top_n \\ \end{bmatrix}, \quad \mathbf{B}=\begin{bmatrix} \mathbf{b}_{1} & \mathbf{b}_{2} & \cdots & \mathbf{b}_{m} \\ \end{bmatrix}. Então, o produto da matriz :math:`\mathbf{C} \in \mathbb{R}^{n \times m}` é produzido, pois simplesmente calculamos cada elemento :math:`c_ {ij}` como o produto escalar :math:`\mathbf{a}^\top_i \mathbf{b}_j`: .. math:: \mathbf{C} = \mathbf{AB} = \begin{bmatrix} \mathbf{a}^\top_{1} \\ \mathbf{a}^\top_{2} \\ \vdots \\ \mathbf{a}^\top_n \\ \end{bmatrix} \begin{bmatrix} \mathbf{b}_{1} & \mathbf{b}_{2} & \cdots & \mathbf{b}_{m} \\ \end{bmatrix} = \begin{bmatrix} \mathbf{a}^\top_{1} \mathbf{b}_1 & \mathbf{a}^\top_{1}\mathbf{b}_2& \cdots & \mathbf{a}^\top_{1} \mathbf{b}_m \\ \mathbf{a}^\top_{2}\mathbf{b}_1 & \mathbf{a}^\top_{2} \mathbf{b}_2 & \cdots & \mathbf{a}^\top_{2} \mathbf{b}_m \\ \vdots & \vdots & \ddots &\vdots\\ \mathbf{a}^\top_{n} \mathbf{b}_1 & \mathbf{a}^\top_{n}\mathbf{b}_2& \cdots& \mathbf{a}^\top_{n} \mathbf{b}_m \end{bmatrix}. Podemos pensar na multiplicação matriz-matriz :math:`\mathbf {AB}` simplesmente realizando :math:`m` produtos vetoriais de matriz e juntando os resultados para formar uma matriz :math:`n \times m`. No trecho a seguir, realizamos a multiplicação da matriz em ``A`` e\ ``B``. Aqui, ``A`` é uma matriz com 5 linhas e 4 colunas, e ``B`` é uma matriz com 4 linhas e 3 colunas. Após a multiplicação, obtemos uma matriz com 5 linhas e 3 colunas. .. raw:: html
mxnetpytorchtensorflow
.. raw:: html
.. code:: python B = np.ones(shape=(4, 3)) np.dot(A, B) .. parsed-literal:: :class: output array([[ 6., 6., 6.], [22., 22., 22.], [38., 38., 38.], [54., 54., 54.], [70., 70., 70.]]) .. raw:: html
.. raw:: html
.. code:: python B = torch.ones(4, 3) torch.mm(A, B) .. parsed-literal:: :class: output tensor([[ 6., 6., 6.], [22., 22., 22.], [38., 38., 38.], [54., 54., 54.], [70., 70., 70.]]) .. raw:: html
.. raw:: html
.. code:: python B = tf.ones((4, 3), tf.float32) tf.matmul(A, B) .. parsed-literal:: :class: output .. raw:: html
.. raw:: html
A multiplicação de matriz-matriz pode ser simplesmente chamada de *multiplicação de matrizes* e não deve ser confundida com o produto Hadamard. .. _subsec_lin-algebra-norms: Normas ------ Alguns dos operadores mais úteis em álgebra linear são *normas*. Informalmente, a norma de um vetor nos diz o quão *grande* é um vetor. A noção de *tamanho* em consideração aqui preocupa-se não em dimensionalidade ,mas sim a magnitude dos componentes. Na álgebra linear, uma norma vetorial é uma função :math:`f` que mapeia um vetor para um escalar, satisfazendo um punhado de propriedades. Dado qualquer vetor :math:`\mathbf{x}`, a primeira propriedade diz que se escalarmos todos os elementos de um vetor por um fator constante :math:`\alpha`, sua norma também escala pelo *valor absoluto* do mesmo fator constante: .. math:: f(\alpha \mathbf{x}) = |\alpha| f(\mathbf{x}). A segunda propriedade é a familiar desigualdade do triângulo: .. math:: f(\mathbf{x} + \mathbf{y}) \leq f(\mathbf{x}) + f(\mathbf{y}). A terceira propriedade simplesmente diz que a norma deve ser não negativa: .. math:: f(\mathbf{x}) \geq 0. Isso faz sentido, pois na maioria dos contextos, o menor *tamanho* para qualquer coisa é 0. A propriedade final requer que a menor norma seja alcançada e somente alcançada por um vetor que consiste em todos os zeros. .. math:: \forall i, [\mathbf{x}]_i = 0 \Leftrightarrow f(\mathbf{x})=0. Você pode notar que as normas se parecem muito com medidas de distância. E se você se lembra das distâncias euclidianas (pense no teorema de Pitágoras) da escola primária, então, os conceitos de não negatividade e a desigualdade do triângulo podem ser familiares. Na verdade, a distância euclidiana é uma norma: especificamente, é a norma :math:`L_2`. Suponha que os elementos no vetor :math:`n` -dimensional :math:`\mathbf{x}` são :math:`x_1, \ldots, x_n`. A :math:`L_2` *norma* de :math:`\mathbf {x}` é a raiz quadrada da soma dos quadrados dos elementos do vetor: .. math:: \|\mathbf{x}\|_2 = \sqrt{\sum_{i=1}^n x_i^2}, onde o subscrito :math:`2` é frequentemente omitido nas normas :math:`L_2`, ou seja, :math:`\|\mathbf{x}\|` é equivalente a :math:`\|\mathbf{x}\|_2`. Em código, podemos calcular a norma :math:`L_2` de um vetor da seguinte maneira. .. raw:: html
mxnetpytorchtensorflow
.. raw:: html
.. code:: python u = np.array([3, -4]) np.linalg.norm(u) .. parsed-literal:: :class: output array(5.) .. raw:: html
.. raw:: html
.. code:: python u = torch.tensor([3.0, -4.0]) torch.norm(u) .. parsed-literal:: :class: output tensor(5.) .. raw:: html
.. raw:: html
.. code:: python u = tf.constant([3.0, -4.0]) tf.norm(u) .. parsed-literal:: :class: output .. raw:: html
.. raw:: html
Em *Deep Learning*, trabalhamos com mais frequência com a norma :math:`L_2` ao quadrado. Você também encontrará frequentemente a norma :math:`L_1`, que é expresso como a soma dos valores absolutos dos elementos do vetor: .. math:: \|\mathbf{x}\|_1 = \sum_{i=1}^n \left|x_i \right|. Em comparação com a norma :math:`L_2`, é menos influenciado por outliers. Para calcular a norma :math:`L_1`, nós compomos a função de valor absoluto com uma soma sobre os elementos. .. raw:: html
mxnetpytorchtensorflow
.. raw:: html
.. code:: python np.abs(u).sum() .. parsed-literal:: :class: output array(7.) .. raw:: html
.. raw:: html
.. code:: python torch.abs(u).sum() .. parsed-literal:: :class: output tensor(7.) .. raw:: html
.. raw:: html
.. code:: python tf.reduce_sum(tf.abs(u)) .. parsed-literal:: :class: output .. raw:: html
.. raw:: html
Tanto a norma :math:`L_2` quanto a norma :math:`L_1` são casos especiais da norma mais geral :math:`L_p`: .. math:: \|\mathbf{x}\|_p = \left(\sum_{i=1}^n \left|x_i \right|^p \right)^{1/p}. Análogo a :math:`L_2` normas de vetores, a *norma de Frobenius* de uma matriz :math:`\mathbf{X} \in \mathbb{R}^{m \times n}` é a raiz quadrada da soma dos quadrados dos elementos da matriz: .. math:: \|\mathbf{X}\|_F = \sqrt{\sum_{i=1}^m \sum_{j=1}^n x_{ij}^2}. A norma Frobenius satisfaz todas as propriedades das normas vetoriais. Ele se comporta como se fosse uma norma :math:`L_2` de um vetor em forma de matriz. Invocar a função a seguir calculará a norma de Frobenius de uma matriz. .. raw:: html
mxnetpytorchtensorflow
.. raw:: html
.. code:: python np.linalg.norm(np.ones((4, 9))) .. parsed-literal:: :class: output array(6.) .. raw:: html
.. raw:: html
.. code:: python torch.norm(torch.ones((4, 9))) .. parsed-literal:: :class: output tensor(6.) .. raw:: html
.. raw:: html
.. code:: python tf.norm(tf.ones((4, 9))) .. parsed-literal:: :class: output .. raw:: html
.. raw:: html
.. _subsec_norms_and_objectives: Normas e Objetivos ~~~~~~~~~~~~~~~~~~ Embora não queiramos nos adiantar muito, já podemos ter uma intuição sobre por que esses conceitos são úteis. No *Deep Learning*, muitas vezes tentamos resolver problemas de otimização: *maximizar* a probabilidade atribuída aos dados observados; *minimizar* a distância entre as previsões e as observações de verdade. Atribuir representações vetoriais a itens (como palavras, produtos ou artigos de notícias) de modo que a distância entre itens semelhantes seja minimizada, e a distância entre itens diferentes é maximizada. Muitas vezes, os objetivos, talvez os componentes mais importantes de algoritmos de *Deep Learning* (além dos dados), são expressos como normas. Mais sobre Algebra Linear ------------------------- Apenas nesta seção, nós ensinamos a vocês toda a álgebra linear que você precisa entender um pedaço notável do aprendizado profundo moderno. Há muito mais coisas na álgebra linear e muito dessa matemática é útil para o *Deep Learning*. Por exemplo, as matrizes podem ser decompostas em fatores, e essas decomposições podem revelar estrutura de baixa dimensão em conjuntos de dados do mundo real. Existem subcampos inteiros de *Deep Learning* que se concentram no uso de decomposições de matriz e suas generalizações para tensores de alta ordem para descobrir a estrutura em conjuntos de dados e resolver problemas de previsão. Mas este livro se concentra no *Deep Learning*. E acreditamos que você estará muito mais inclinado a aprender mais matemática depois de sujar as mãos implantar modelos úteis de aprendizado de máquina em conjuntos de dados reais. Portanto, embora nos reservemos o direito de introduzir mais matemática muito mais tarde, vamos encerrar esta seção aqui. Se voce gostaria de aprender mais sobre Algebra Linear, pode procurar em `apêndice online sobre operações de algebra linear `__ ou outra excelente fonte :cite:`Strang.1993,Kolter.2008,Petersen.Pedersen.ea.2008`. Sumário ------- - Escalares, vetores, matrizes e tensores são objetos matemáticos básicos em álgebra linear. - Vetores generalizam escalares e matrizes generalizam vetores. - Escalares, vetores, matrizes e tensores têm zero, um, dois e um número arbitrário de eixos, respectivamente. - Um tensor pode ser reduzido ao longo dos eixos especificados por ``soma`` e ``média``. - A multiplicação elementar de duas matrizes é chamada de produto Hadamard. É diferente da multiplicação de matrizes. - No aprendizado profundo, geralmente trabalhamos com normas como a norma :math:`L_1`, a norma :math:`L_2` e a norma Frobenius. - Podemos realizar uma variedade de operações sobre escalares, vetores, matrizes e tensores. Exercícios ---------- 1. Prove que a transposta de uma matriz :math:`\mathbf {A}` transposta é :math:`\mathbf {A}`: :math:`(\mathbf {A} ^ \top) ^ \top = \mathbf {A}`. 2. Dadas duas matrizes :math:`\mathbf {A}` e :math:`\mathbf {B}`, mostre que a soma das transpostas é igual à transposta de uma soma: :math:`\mathbf {A} ^ \top + \mathbf {B} ^ \top = (\mathbf {A} + \mathbf {B}) ^ \top`. 3. Dada qualquer matriz quadrada :math:`\mathbf {A}`, :math:`\mathbf {A} + \mathbf {A} ^ \top` é sempre simétrica? Porque? 4. Definimos o tensor ``X`` de forma (2, 3, 4) nesta seção. Qual é a saída de ``len (X)``? 5. Para um tensor ``X`` de forma arbitrária, ``len (X)``\ sempre corresponde ao comprimento de um certo eixo de ``X``? Qual é esse eixo? 6. Execute ``A / A.sum (eixo = 1)`` e veja o que acontece. Você pode analisar o motivo? 7. Ao viajar entre dois pontos em Manhattan, qual é a distância que você precisa percorrer em termos de coordenadas, ou seja, em termos de avenidas e ruas? Você pode viajar na diagonal? 8. Considere um tensor com forma (2, 3, 4). Quais são as formas das saídas de soma ao longo dos eixos 0, 1 e 2? 9. Alimente um tensor com 3 ou mais eixos para a função ``linalg.norm`` e observe sua saída. O que essa função calcula para tensores de forma arbitrária? .. raw:: html
.. raw:: html
`Discussions `__ .. raw:: html
.. raw:: html
`Discussions `__ .. raw:: html
.. raw:: html
`Discussions `__ .. raw:: html
.. raw:: html
.. raw:: html