Curso
Ciência de dados é um campo interdisciplinar que usa matemática e estatística avançada para fazer previsões. Todos os algoritmos de ciência de dados usam conceitos matemáticos direta ou indiretamente. Ter uma base sólida em matemática ajuda você a criar soluções inovadoras em ciência de dados, como um sistema de recomendação. Se você manda bem em matemática, sua transição para a área fica muito mais tranquila. Como cientista de dados, você vai aplicar os conceitos fundamentais da matemática para resolver problemas.
Além de matemática, você também precisa de conhecimento de domínio, habilidades de programação, visão de negócios, capacidade analítica e uma postura curiosa. Não dá para fugir da matemática se você quer ser cientista de dados. É preciso incorporar e aprender por conta própria os fundamentos de matemática e estatística para seguir nessa carreira.
Escalar e vetor
- Escalares: Um escalar é um número único que interage com vetores no espaço por meio da multiplicação escalar.
- Vetores: Um vetor V é um conjunto ordenado de elementos. Vetor é um arranjo de números que pode ser uma linha ou uma coluna. Vetores podem ser somados entre si e multiplicados por um número real, conhecido como escalar.

# Import numpy module
import numpy as np
# creating a vector
v = np.array([1, 2, 3, 4, 5])
print(v)
[1 2 3 4 5]
# Vector Operations
# Import numpy module
import numpy as np
# Create two vector
a = np.array([1, 2, 3, 4, 5])
b = np.array([1, 2, 3, 4, 5])
# adding two vectors
add = a + b
print("Addition:",add)
# Vector Subtraction
sub = a - b
print("Subtraction:",sub)
# Vector Multiplication
mul = a * b
print("Multiplication:",mul)
# Vector Division
div = a / b
print("division",div)
Addition: [ 2 4 6 8 10]
Subtraction: [0 0 0 0 0]
Multiplication: [ 1 4 9 16 25]
division [1. 1. 1. 1. 1.]
Matriz e tensor
- Matrizes: Uma matriz é um arranjo N-D de números que representa transformações. Você pode pensar em uma matriz como uma transformação do tipo "escalar", "rotacionar", "cisalhar" e "espelhar". Ela leva pontos no espaço a outros pontos no espaço.
# Import numpy module
import numpy as np
# create 2*2 matrix
a1=np.array([[1, 2], [3, 4]])
a2=np.array([[1, 2], [3, 4]])
# Dot Product
dot_product = np.dot(a1,a2)
print("Dot Product: \n",dot_product)
# Cross Product
cross_product = np.cross(a1,a2)
print("Cross Product: \n", cross_product)
Dot Product:
[[ 7 10]
[15 22]]
Cross Product:
[0 0]
O produto escalar de dois vetores representa a projeção de um vetor sobre o outro, e o produto vetorial permite identificar o plano no qual ambos os vetores podem estar.
- Tensor: Às vezes, você vai precisar de um arranjo com mais de duas dimensões e dimensões diferentes em cada eixo, organizado em uma grade chamada tensor. A dimensão do tensor é conhecida como sua ordem (rank). Escalares e vetores também são tipos de tensores. Tensores de ordem zero são escalares, e de primeira ordem são vetores.

Determinante
Determinante é um valor escalar que representa o fator de uma matriz pelo qual comprimento (em 1 dimensão), área (2 dimensões) e volume (3 dimensões) são escalados. Se o determinante é 2, o volume (em 3D) dobra; se é 1, o volume não muda. Se o determinante é 0, a matriz não tem inversa, porque zero vezes qualquer coisa é zero.

Propriedades:
-
O determinante do produto de matrizes é o produto dos determinantes: det (M1M2)=det (M1) det (M2).
-
O determinante de uma matriz é igual ao produto de seus autovalores.
-
Se você multiplica uma matriz por uma constante, o determinante muda por det(cM)=c^N det (M). N é a dimensão da matriz.
Se sua matriz representa um brinquedo elástico, o determinante mostra o quanto você esticou esse brinquedo.
# Import numpy module
import numpy as np
# Create 2*2 matrix
arr=np.array([[1,2],[3,4]])
# Compute Determinant of a matrix
arr_det=np.linalg.det(arr)
# Print the Computed Determinant
print("Determinant:",arr_det)
Determinant: -2.0000000000000004
Autovalores e autovetores
Um autovetor de uma matriz quadrada A é um vetor não nulo tal que a multiplicação por A altera apenas a sua escala.

O autovetor também é conhecido como vetor característico. É um vetor não nulo que só muda por um fator escalar quando uma transformação linear é aplicada a ele.
Autovetores são eixos de rotação da transformação linear. Esses eixos têm direção fixa, e o autovalor é o fator pelo qual a matriz é ampliada ou reduzida. Autovalores também são chamados de valores ou raízes características. Em outras palavras, você pode dizer que autovetores definem as direções que limitam o comportamento da transformação linear e os autovalores indicam o fator de distorção.
O determinante informa a área (ou volume) dos formatos que são escalados na transformação linear. Por isso o produto dos autovalores é igual ao determinante.
# Import numpy module
import numpy as np
# Create 2*2 matrix
arr=np.array([[1,2],[3,4]])
# Find eigenvalues and eigenvectors
eigenvalues, eigenvectors = np.linalg.eig(arr)
# print the eigenvalues and eigenvectors
print("Eigen Values: \n",eigenvalues)
print("Eigen Vectors:\n", eigenvectors)
Eigen Values:
[-0.37228132 5.37228132]
Eigen Vectors:
[[-0.82456484 -0.41597356]
[ 0.56576746 -0.90937671]]
Função NORM
Às vezes, você quer medir o tamanho de um vetor. A função norma (norm) ajuda a medir esse tamanho. Ela atribui um comprimento estritamente positivo a um vetor em um espaço vetorial, exceto para o vetor zero. Inclui a norma L^p. Mapeia vetores para valores não negativos. Para vetores e matrizes, é equivalente à distância euclidiana. É igual ao maior valor singular.

# import numpy module
import numpy as np
# Create 3*3 Matrix
a = np.array([[1,2,3],[4,5,6],[7,8,9]])
# Compute norm
a_norm = np.linalg.norm(a)
# print the norm of function
print(a_norm)
16.881943016134134
Fatoração de matrizes
Fatoração de matrizes, também chamada de decomposição de matrizes, é usada para dividir uma matriz em partes constituintes. É análoga à fatoração de números, como fatorar 10 em 2 x 5. É muito utilizada para resolver sistemas lineares.
Algumas técnicas de fatoração de matrizes:
- Decomposição LU para matrizes quadradas, decompõe a matriz nos componentes L e U.
- Decomposição QR para matrizes m x n (não limitada a matrizes quadradas), decompõe a matriz nos componentes Q e R. Diferente da LU, não se restringe a matrizes quadradas.
- Decomposição de Cholesky usada para resolver mínimos quadrados na regressão linear, além de simulação e métodos de otimização.
- Decomposição em valores singulares (SVD) explicada na próxima seção.
Decomposição em valores singulares
Na seção anterior, vimos a eigendecomposição de uma matriz em autovetores e autovalores. A decomposição em valores singulares (SVD) é um tipo de fatoração que decompõe em vetores singulares e valores singulares. Tem várias aplicações úteis em processamento de sinais, psicologia, sociologia, clima, ciências atmosféricas, estatística e astronomia.

- M é uma matriz m×m
- U é uma matriz singular esquerda m×n
- Σ é uma matriz diagonal n×n com números reais não negativos.
- V é uma matriz singular direita m×n
- V* é uma matriz n×m, a transposta de V.
# Import numpy module
import numpy as np
# Create 3*3 matrix
a = np.array([[1, 3, 4], [5, 6, 9], [1, 2, 3], [7, 6, 8]])
# Decomposition of matrix using SVD
U, s, Vh = np.linalg.svd(a, full_matrices=False)
U,s,Vh
(array([[-0.27067357, -0.61678044, 0.69789573],
[-0.65939972, -0.2937857 , -0.62152182],
[-0.20244298, -0.3480035 , -0.06765408],
[-0.67152413, 0.64200111, 0.34939247]]),
array([18.0376394 , 2.34360292, 0.38870323]),
array([[-0.46961711, -0.51018039, -0.72053851],
[ 0.87911451, -0.19502274, -0.43488368],
[-0.08134773, 0.83766467, -0.54009299]]))
# Generate the initial matrix
new_a = np.dot(U, np.dot(np.diag(s), Vh))
# Print original matrix
print(new_a)
[[1. 3. 4.]
[5. 6. 9.]
[1. 2. 3.]
[7. 6. 8.]]
Pseudoinversa de Moore-Penrose
A pseudoinversa de uma matriz é uma generalização da matriz inversa. Ela é usada para calcular soluções de mínimos quadrados. A inversa de Moore-Penrose é a forma mais popular de pseudoinversa de matrizes.

# Import numpy module
import numpy as np
# Create 3*3 matrix
a = np.array([[1, 3, 4], [5, 6, 9], [1, 2, 3], [7, 6, 8]])
# Compute the (Moore-Penrose) pseudo-inverse of a matrix.
inv=np.linalg.pinv(a)
# Print pseudo-inverse of a matrix.
print(inv)
[[-0.37037037 0.03703704 -0.11111111 0.18518519]
[ 1.56296296 -1.2962963 -0.11111111 0.71851852]
[-0.84444444 0.94444444 0.16666667 -0.57777778]]
Produto de Hadamard
O produto de Hadamard, ou produto de Schur, é o produto elemento a elemento de duas matrizes originais com as mesmas dimensões. Também é conhecido como multiplicação ponto a ponto (element-wise). É mais simples do que o produto matricial. O produto de Hadamard é utilizado em algoritmos de compressão com perdas JPEG. Ele é comutativo, associativo e distributivo. Facilita obter a inversa em alguns casos e simplifica o cálculo de potências de matrizes.

O produto de Hadamard é usado em várias áreas, como correção de códigos em transmissões via satélite, teoria da informação, criptografia, reconhecimento de padrões, redes neurais, estimação por máxima verossimilhança, compressão JPEG com perdas, análise estatística multivariada e modelagem linear.
# Import numpy module
import numpy as np
# Create 2*2 matrix a1 and a2
a1=np.array([[1, 2], [3, 4]])
a2=np.array([[1, 2], [3, 4]])
# Element wise multiplication
hadamard_product = np.multiply(a1,a2)
# Print hadamard distance
print("Hadamard Product: \n", hadamard_product)
Hadamard Product:
[[ 1 4]
[ 9 16]]
Entropia
"A entropia de uma variável aleatória é uma função que busca caracterizar a imprevisibilidade dessa variável." (Entropy and Mutual Information) Ela é usada na construção automática de árvores de decisão: a cada passo de construção da árvore, a seleção de atributos pode usar critérios baseados em entropia. A seleção de modelos pode seguir o princípio da máxima entropia, que afirma que, entre modelos conflitantes, o de maior entropia é o preferido.
"Se uma variável aleatória X assume valores em um conjunto χ={x1, x2,..., xn}, e é definida por uma distribuição de probabilidade P(X), então escrevemos a entropia da variável aleatória como:" (Entropy and Mutual Information)

"Se o log na equação acima for na base 2, a entropia é expressa em bits. Se for o log natural, a entropia é expressa em nats. Mais comumente, a entropia é expressa em bits." (Entropy and Mutual Information)
# Import scipy and numpy module
import scipy.stats
import numpy as np
# Create an array
a=np.array([1,1,2,3,1,3,4,2,5,6,3,2,4,3])
# Compute probability distribution
a_pdf=scipy.stats.norm.pdf(a)
# Calculate the entropy of a distribution for given probability values.
entropy = scipy.stats.entropy(a_pdf) # get entropy from probability values
print("Entropy: ",entropy)
Entropy: 1.6688066853941022
Divergência de Kullback-Leibler
A divergência de Kullback–Leibler é a entropia relativa entre duas distribuições de probabilidade. Ela mede a distância (semelhança ou dissimilaridade) de uma distribuição em relação a outra distribuição de referência. Valor 0 indica que ambas as distribuições são idênticas. Pode ser expressa como:

Parece uma medida de distância, mas não é. Isso porque é assimétrica por natureza, ou seja, a métrica não é comutativa. Em geral, D(p, q) ≠ D(q, p). A divergência KL é muito usada na técnica de aprendizado não supervisionado "Variational Autoencoders".
# Import scipy.stats and numpy module
import scipy.stats
import numpy as np
# Create numpy arrays
a=np.array([1,1,2,3,1,3,4,2,5,6,3,2,4,3])
b=np.array([1,1,3,4,2,4,5,2,5,6,3,2,4,3])
# Compute probability distribution
a_pdf=scipy.stats.norm.pdf(a)
b_pdf=scipy.stats.norm.pdf(b)
# compute relative entropy or KL Divergence
kl_div=scipy.stats.entropy(a_pdf,b_pdf)
print("KL Divergence: ",kl_div)
KL Divergence: 0.26732496641464365
Gradiente descendente
Gradiente descendente é um dos algoritmos mais conhecidos para otimizar coeficientes e viés em regressão linear, regressão logística e redes neurais. É um processo iterativo que encontra o mínimo de uma função qualquer.


Existem três tipos de gradiente descendente: batch completo, estocástico e mini-batch. O batch completo usa o conjunto de dados inteiro para calcular o gradiente, enquanto o estocástico usa uma amostra do conjunto para o cálculo. O mini-batch combina os dois: o conjunto de treino é dividido em pequenos grupos chamados batches. Esses pequenos batches calculam a perda um a um e a média resulta na perda final.
Conclusão
Parabéns, você chegou ao final deste tutorial!
Você aprendeu conceitos matemáticos básicos para deep learning, como escalar, vetor, matriz, tensor, determinante, autovalores, autovetores, função NORM, decomposição em valores singulares (SVD), pseudoinversa de Moore-Penrose, produto de Hadamard, entropia, divergência de Kullback-Leibler e gradiente descendente.
No caminho, você também praticou esses conceitos em Python usando NumPy e SciPy.
Se quiser aprender mais sobre Python, faça estes cursos da DataCamp:
