Curso
La ciencia de datos es un campo interdisciplinar que utiliza matemáticas y estadística avanzada para hacer predicciones. Todos los algoritmos de ciencia de datos usan conceptos matemáticos de forma directa o indirecta. Tener una base sólida en matemáticas te ayudará a diseñar soluciones innovadoras de ciencia de datos, como un sistema de recomendación. Si se te dan bien las matemáticas, tu transición a la ciencia de datos será mucho más fluida. Como científico de datos, tendrás que aplicar los conceptos fundamentales de las matemáticas para resolver problemas.
Además de matemáticas, también necesitas conocimiento del dominio, habilidades de programación, competencias de negocio, capacidad analítica y una mentalidad curiosa. En ciencia de datos no hay escapatoria a las matemáticas: tendrás que adquirir y afianzar por tu cuenta las bases de matemáticas y estadística para convertirte en científico de datos.
Escalar y vector
- Escalares: Un escalar es un único número que interactúa con un vector en el espacio mediante la multiplicación escalar.
- Vectores: Un vector V es un conjunto ordenado de elementos. Un vector es un array de números que puede disponerse en fila o en columna. Los vectores se pueden sumar entre sí y multiplicar por un número real, conocido 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 y tensor
- Matrices: Una matriz es un array N-D de números que representa transformaciones. Puedes pensar en una matriz como una transformación del tipo "escalar", "rotar", "cizallar" o "voltear". Convierte puntos en el espacio en otros puntos del espacio.
# 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]
El producto punto de dos vectores representa la proyección de un vector sobre otro, y el producto cruz de dos vectores permite identificar el plano en el que pueden yacer ambos vectores.
- Tensor: A veces necesitarás un array con más de dos dimensiones y con distinta dimensión en cada eje, dispuesto en una rejilla conocida como tensor. A la dimensión del tensor se la denomina rango. Los escalares y los vectores también son tipos de tensor: los tensores de orden cero son escalares y los de primer orden son vectores.

Determinante
El determinante es un valor escalar que indica el factor por el que una matriz escala la longitud (en 1 dimensión), el área (2 dimensiones) o el volumen (3 dimensiones). Si el determinante es 2, duplica el volumen (en 3D); si es 1, no lo modifica. Si el determinante es 0, no existe inversa, porque cero multiplicado por cualquier cosa da cero.

Propiedades:
-
El determinante del producto de matrices es el producto de sus determinantes: det(M1M2)=det(M1)·det(M2).
-
El determinante de una matriz equivale al producto de sus autovalores.
-
Si multiplicas una matriz por una constante, el determinante cambia según det(cM)=c^N·det(M), donde N es la dimensión de la matriz.
Si tu matriz representa un juguete elástico, el determinante te dice cuánto lo has estirado.
# 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 y autovectores
Un autovector de una matriz cuadrada A es un vector no nulo tal que al multiplicarlo por A solo cambia su escala.

El autovector, también llamado vector característico, es un vector no nulo que solo se ve afectado por un factor escalar cuando se le aplica una transformación lineal.
Los autovectores son los ejes de rotación de la transformación lineal. Estos ejes tienen dirección fija, y el autovalor es el factor por el que la matriz escala en esa dirección. Los autovalores también se conocen como valores o raíces características. En otras palabras, los autovectores definen líneas o planos fijos que acotan el comportamiento de la transformación lineal, y los autovalores son el factor de distorsión.
El determinante te indica el área o volumen que se escala en una transformación lineal. Por eso el producto de los autovalores es igual al 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]]
Función NORM
A veces quieres medir el tamaño de un vector. La función norma te ayuda a medirlo: asigna una longitud estrictamente positiva a un vector en un espacio vectorial, excepto al vector cero. Incluye la norma L^p. Mapea vectores a valores no negativos. Para un vector (y también para matrices) es equivalente a la distancia euclidiana. Es igual al mayor 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
Factorización de matrices
La factorización de matrices, también conocida como descomposición de matrices, consiste en dividir una matriz en sus partes constituyentes. Es análoga a factorizar números, como descomponer 10 en 2 × 5. Se usa para resolver sistemas de ecuaciones lineales.
Entre las técnicas de factorización más habituales están:
- Descomposición LU, para matrices cuadradas, que descompone una matriz en los componentes L y U.
- Descomposición QR, para matrices m × n (no se limita a matrices cuadradas), que descompone una matriz en los componentes Q y R. A diferencia de LU, no está restringida a matrices cuadradas.
- Descomposición de Cholesky, utilizada para resolver mínimos cuadrados en regresión lineal, así como en métodos de simulación y optimización.
- Descomposición en valores singulares, explicada en la siguiente sección.
Descomposición en valores singulares
En la sección anterior vimos la eigen-descomposición de una matriz en autovectores y autovalores. La descomposición en valores singulares (SVD) es un tipo de factorización que descompone una matriz en vectores singulares y valores singulares. Tiene múltiples aplicaciones en procesamiento de señal, psicología, sociología, clima y ciencias atmosféricas, estadística y astronomía.

- M es una matriz m×m
- U es una matriz singular izquierda m×n
- Σ es una matriz diagonal n×n con números reales no negativos.
- V es una matriz singular derecha m×n
- V* es una matriz n×m, la traspuesta 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.]]
Seudoinversa de Moore-Penrose
La seudoinversa de una matriz es una generalización de la inversa. Se utiliza para calcular soluciones de mínimos cuadrados. La inversa de Moore-Penrose es la forma de seudoinversa de matrices más extendida.

# 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]]
Producto de Hadamard
El producto de Hadamard, o producto de Schur, es el producto elemento a elemento de dos matrices originales de la misma dimensión. También se conoce como producto punto a punto. Es más simple que el producto matricial. El producto de Hadamard se utiliza en algoritmos de compresión con pérdida JPEG. Es conmutativo, asociativo y distributivo. Facilita obtener la inversa y simplifica el cálculo de potencias de matrices.

El producto de Hadamard se emplea en campos como la corrección de código en transmisiones por satélite, teoría de la información, criptografía, reconocimiento de patrones, redes neuronales, estimación de máxima verosimilitud, compresión JPEG con pérdida, análisis estadístico multivariante y modelización lineal.
# 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]]
Entropía
"La entropía de una variable aleatoria es una función que intenta caracterizar su imprevisibilidad." (Entropy and Mutual Information). Se utiliza para construir árboles de decisión automáticos: en cada paso de construcción del árbol, la selección de características se hace con criterios de entropía. La selección de modelos se basa en el principio de máxima entropía, que afirma que, entre modelos en conflicto, el mejor es el que tiene mayor entropía.
"Si una variable aleatoria X toma valores en un conjunto χ={x1, x2,..., xn}, y está definida por una distribución de probabilidad P(X), entonces escribimos la entropía de la variable aleatoria como" (Entropy and Mutual Information)

"Si el logaritmo de la ecuación anterior es en base 2, la entropía se expresa en bits. Si se usa el logaritmo natural, la entropía se expresa en nats. Lo más habitual es expresarla en 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
Divergencia de Kullback–Leibler
La divergencia de Kullback–Leibler es la entropía relativa entre dos distribuciones de probabilidad. Mide la distancia (similitud o disimilitud) de una distribución respecto a otra de referencia. Un valor 0 de la divergencia de Kullback–Leibler indica que ambas distribuciones son idénticas. Se puede expresar como:

Suena a medida de distancia, pero no lo es. Es asimétrica por naturaleza, lo que significa que la métrica no es conmutativa. En general, D(p, q) ≠ D(q, p). La KL divergence se utiliza con frecuencia en la técnica de aprendizaje no supervisado llamada "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
Descenso de gradiente
El descenso de gradiente es uno de los algoritmos más conocidos para optimizar coeficientes y sesgo en regresión lineal, regresión logística y redes neuronales. Es un proceso iterativo que encuentra el mínimo de una función dada.


Existen tres variantes principales del algoritmo: batch completo, estocástico y mini-batch. El batch completo usa todo el conjunto de datos para calcular el gradiente, mientras que el descenso estocástico usa una muestra. El mini-batch combina ambos enfoques: el conjunto de entrenamiento se divide en pequeños grupos llamados batches. Estos lotes calculan la pérdida uno a uno y promedian el resultado final.
Conclusión
¡Enhorabuena, has llegado al final de este tutorial!
Has aprendido conceptos matemáticos básicos para deep learning como escalar, vector, matriz, tensor, determinante, autovalores, autovectores, función NORM, descomposición en valores singulares (SVD), seudoinversa de Moore-Penrose, producto de Hadamard, entropía, divergencia de Kullback–Leibler y descenso de gradiente.
Por el camino, también has practicado estos conceptos en Python usando NumPy y SciPy.
Si quieres aprender más sobre Python, echa un vistazo a estos cursos de DataCamp:
