stringtranslate.com

Método de gradiente conjugado

Una comparación de la convergencia del descenso de gradiente con el tamaño de paso óptimo (en verde) y el vector conjugado (en rojo) para minimizar una función cuadrática asociada con un sistema lineal dado. El gradiente conjugado, suponiendo aritmética exacta, converge como máximo en n pasos, donde n es el tamaño de la matriz del sistema (aquí n  = 2).

En matemáticas , el método del gradiente conjugado es un algoritmo para la solución numérica de sistemas particulares de ecuaciones lineales , es decir aquellos cuya matriz es positiva-semidefinida . El método del gradiente conjugado a menudo se implementa como un algoritmo iterativo , aplicable a sistemas dispersos que son demasiado grandes para ser manejados mediante una implementación directa u otros métodos directos como la descomposición de Cholesky . A menudo surgen grandes sistemas dispersos al resolver numéricamente ecuaciones diferenciales parciales o problemas de optimización.

El método del gradiente conjugado también se puede utilizar para resolver problemas de optimización sin restricciones , como la minimización de energía . Se atribuye comúnmente a Magnus Hestenes y Eduard Stiefel , [1] [2] quienes lo programaron en el Z4 , [3] y lo investigaron exhaustivamente. [4] [5]

El método del gradiente biconjugado proporciona una generalización a matrices no simétricas. Varios métodos de gradiente conjugado no lineal buscan mínimos de problemas de optimización no lineal.

Descripción del problema abordado por gradientes conjugados.

Supongamos que queremos resolver el sistema de ecuaciones lineales.

para el vector , donde la matriz conocida es simétrica (es decir, A T = A ), definida positiva (es decir, x T Ax > 0 para todos los vectores distintos de cero en R n ) y real , y también se conoce. Denotamos la solución única de este sistema por .

Derivación como método directo

El método del gradiente conjugado se puede derivar desde varias perspectivas diferentes, incluida la especialización del método de dirección conjugada para la optimización y la variación de la iteración de Arnoldi / Lanczos para problemas de valores propios . A pesar de las diferencias en sus enfoques, estas derivaciones comparten un tema común: demostrar la ortogonalidad de los residuos y la conjugación de las direcciones de búsqueda. Estas dos propiedades son cruciales para desarrollar la conocida formulación sucinta del método.

Decimos que dos vectores distintos de cero u y v son conjugados (con respecto a ) si

Como es simétrico y definido positivo, el lado izquierdo define un producto interno

Dos vectores son conjugados si y sólo si son ortogonales con respecto a este producto interno. Ser conjugado es una relación simétrica: si es conjugado con , entonces es conjugado con . Suponer que

es un conjunto de vectores mutuamente conjugados con respecto a , es decir, para todos . Entonces forma una base para y podemos expresar la solución de en esta base:

Multiplicar por la izquierda el problema con el vector produce

y entonces

Esto proporciona el siguiente método [4] para resolver la ecuación Ax = b : encuentre una secuencia de direcciones conjugadas y luego calcule los coeficientes .

Como método iterativo

Si elegimos los vectores conjugados con cuidado, es posible que no los necesitemos todos para obtener una buena aproximación a la solución . Por tanto, queremos considerar el método del gradiente conjugado como un método iterativo. Esto también nos permite resolver aproximadamente sistemas donde n es tan grande que el método directo tomaría demasiado tiempo.

Denotamos la estimación inicial para x por x 0 (podemos asumir sin pérdida de generalidad que x 0 = 0 ; de lo contrario, considere el sistema Az = bAx 0 ). Comenzando con x 0 buscamos la solución y en cada iteración necesitamos una métrica que nos diga si estamos más cerca de la solución x (que no conocemos). Esta métrica proviene del hecho de que la solución x es también el único minimizador de la siguiente función cuadrática

La existencia de un minimizador único es evidente ya que su matriz de Hesse de segundas derivadas es simétrica positiva-definida.

y que el minimizador (use D f ( x )=0) resuelve el problema inicial se desprende de su primera derivada

Esto sugiere tomar el primer vector de base p 0 como el negativo del gradiente de f en x = x 0 . El gradiente de f es igual a Axb . Comenzando con una suposición inicial x 0 , esto significa que tomamos p 0 = bAx 0 . Los otros vectores en la base se conjugarán con el gradiente, de ahí el nombre método de gradiente conjugado . Tenga en cuenta que p 0 es también el residual proporcionado por este paso inicial del algoritmo.

Sea r k el residual en el k ésimo paso:

Como se observó anteriormente, es el gradiente negativo de at , por lo que el método de descenso de gradiente requeriría moverse en la dirección rk . Aquí, sin embargo, insistimos en que las direcciones deben estar conjugadas entre sí. Una forma práctica de hacer cumplir esto es exigir que la siguiente dirección de búsqueda se construya a partir del residual actual y de todas las direcciones de búsqueda anteriores. La restricción de conjugación es de tipo ortonormal y, por tanto, el algoritmo puede verse como un ejemplo de ortonormalización de Gram-Schmidt . Esto da la siguiente expresión:

(consulte la imagen en la parte superior del artículo para conocer el efecto de la restricción de conjugación en la convergencia). Siguiendo esta dirección, la siguiente ubicación óptima está dada por

con

donde la última igualdad se deriva de la definición de . La expresión para se puede derivar si se sustituye la expresión para x k +1 en f y se minimiza con respecto a

El algoritmo resultante

El algoritmo anterior ofrece la explicación más sencilla del método del gradiente conjugado. Aparentemente, el algoritmo tal como se indica requiere el almacenamiento de todas las direcciones de búsqueda anteriores y los vectores de residuos, así como muchas multiplicaciones de matriz-vector y, por lo tanto, puede ser computacionalmente costoso. Sin embargo, un análisis más detallado del algoritmo muestra que es ortogonal a , es decir , para i ≠ j. Y es ortogonal a , es decir , para . Esto se puede considerar que a medida que avanza el algoritmo, abarca el mismo subespacio de Krylov . Donde forman la base ortogonal con respecto al producto interno estándar, y forman la base ortogonal con respecto al producto interno inducido por . Por lo tanto, puede considerarse como una proyección del subespacio de Krylov.

Es decir, si el método CG comienza con , entonces [6]

0

Este es el algoritmo más utilizado. La misma fórmula para βk también se utiliza en el método de gradiente conjugado no lineal de Fletcher-Reeves .

Se reinicia

Observamos que se calcula mediante el método de descenso de gradiente aplicado a . La configuración también haría que se calcule mediante el método de descenso de gradiente desde , es decir, se puede utilizar como una implementación simple de un reinicio de las iteraciones de gradiente conjugado. [4] Los reinicios podrían ralentizar la convergencia, pero pueden mejorar la estabilidad si el método del gradiente conjugado no se comporta correctamente, por ejemplo, debido a un error de redondeo .

Cálculo residual explícito

Las fórmulas y , que son válidas en aritmética exacta, hacen que las fórmulas y sean matemáticamente equivalentes. El primero se utiliza en el algoritmo para evitar una multiplicación adicional porque el vector ya está calculado para evaluar . Este último puede ser más preciso, sustituyendo el cálculo explícito por el implícito por la recursividad sujeta a acumulación de error de redondeo , por lo que se recomienda para una evaluación ocasional. [7]

Normalmente se utiliza una norma del residual como criterio de parada. La norma del residual explícito proporciona un nivel garantizado de precisión tanto en aritmética exacta como en presencia de errores de redondeo , donde la convergencia naturalmente se estanca. Por el contrario, se sabe que el residual implícito sigue disminuyendo en amplitud muy por debajo del nivel de errores de redondeo y, por tanto, no puede utilizarse para determinar el estancamiento de la convergencia.

Cálculo de alfa y beta.

En el algoritmo, α k se elige de manera que sea ortogonal a . El denominador se simplifica de

desde . El β k se elige de manera que esté conjugado con . Inicialmente, β k es

usando

y equivalentemente

el numerador de β k se reescribe como

porque y son ortogonales por diseño. El denominador se reescribe como

usando que las direcciones de búsqueda p k están conjugadas y nuevamente que los residuos son ortogonales. Esto da el β en el algoritmo después de cancelar α k .

Código de ejemplo en Julia (lenguaje de programación)

""" gradiente_conjugado!(A, b, x)Devuelva la solución a `A * x = b` usando el método de gradiente conjugado."""función conjugate_gradient! (  A :: MatrizAbstract , b :: VectorAbstract , x :: VectorAbstract ; tol = eps ( eltipo ( b ))   ) # Inicializar vector residual residual = b - A * x       # Inicializar el vector de dirección de búsqueda dirección_búsqueda = residual   # Calcular la norma residual al cuadrado inicialnorma ( x ) = raíz cuadrada ( suma ( x .^ 2 ))   old_resid_norm = norma ( residual )   # Iterar hasta la convergencia mientras que old_resid_norm > tol    A_dirección_de_búsqueda = A * dirección_de_búsqueda     tamaño_paso = norma_resid_antigua ^ 2 / ( dirección_búsqueda ' * A_dirección_búsqueda )       # Actualizar solución @. x = x + tamaño_paso * dirección_búsqueda        # Actualizar residual @. residual = residual - tamaño_paso * Una_dirección_búsqueda        new_resid_norm = norma ( residual )    # Actualizar vector de dirección de búsqueda @. dirección_búsqueda = residual +      ( nueva_resid_norm / antigua_resid_norm ) ^ 2 * dirección_búsqueda     # Actualizar la norma residual al cuadrado para la próxima iteración norma_resid_antigua = norma_resid_nueva   fin volver x fin

Ejemplo numérico

Considere el sistema lineal Ax = b dado por

Realizaremos dos pasos del método del gradiente conjugado comenzando con la suposición inicial.

para encontrar una solución aproximada al sistema.

Solución

Como referencia, la solución exacta es

Nuestro primer paso es calcular el vector residual r 0 asociado con x 0 . Este residual se calcula a partir de la fórmula r 0 = b - Ax 0 , y en nuestro caso es igual a

Dado que esta es la primera iteración, usaremos el vector residual r 0 como nuestra dirección de búsqueda inicial p 0 ; el método de selección de p k cambiará en iteraciones posteriores.

Ahora calculamos el escalar α 0 usando la relación

Ahora podemos calcular x 1 usando la fórmula

Este resultado completa la primera iteración, siendo el resultado una solución aproximada "mejorada" del sistema, x 1 . Ahora podemos continuar y calcular el siguiente vector residual r 1 usando la fórmula

Nuestro siguiente paso en el proceso es calcular el escalar β 0 que eventualmente se usará para determinar la siguiente dirección de búsqueda p 1 .

Ahora, usando este escalar β 0 , podemos calcular la siguiente dirección de búsqueda p 1 usando la relación

Ahora calculamos el escalar α 1 usando nuestro p 1 recién adquirido usando el mismo método que el usado para α 0 .

Finalmente, encontramos x 2 usando el mismo método que se usó para encontrar x 1 .

El resultado, x 2 , es una "mejor" aproximación a la solución del sistema que x 1 y x 0 . Si en este ejemplo se utilizara aritmética exacta en lugar de precisión limitada, entonces, en teoría, la solución exacta se habría alcanzado después de n = 2 iteraciones ( siendo n el orden del sistema).

Propiedades de convergencia

En teoría, el método del gradiente conjugado puede verse como un método directo, ya que, en ausencia de error de redondeo, produce la solución exacta después de un número finito de iteraciones, que no es mayor que el tamaño de la matriz. En la práctica, nunca se obtiene la solución exacta ya que el método del gradiente conjugado es inestable con respecto incluso a perturbaciones pequeñas; por ejemplo, la mayoría de las direcciones no son en la práctica conjugadas, debido a la naturaleza degenerativa de la generación de los subespacios de Krylov.

Como método iterativo , el método del gradiente conjugado mejora monótonamente (en la norma energética) las aproximaciones a la solución exacta y puede alcanzar la tolerancia requerida después de un número relativamente pequeño (en comparación con el tamaño del problema) de iteraciones. La mejora suele ser lineal y su velocidad está determinada por el número de condición de la matriz del sistema : cuanto mayor es, más lenta es la mejora. [8]

Si es grande, el preacondicionamiento se usa comúnmente para reemplazar el sistema original por uno que sea más pequeño que , consulte a continuación.

Teorema de convergencia

Definir un subconjunto de polinomios como

donde es el conjunto de polinomios de máximo grado .

Sean las aproximaciones iterativas de la solución exacta y defina los errores como . Ahora, la tasa de convergencia se puede aproximar como [4] [9]

donde denota el espectro y denota el número de condición .

Esto muestra que las iteraciones son suficientes para reducir el error en cualquier caso .

Tenga en cuenta que el límite importante cuando tiende a

Este límite muestra una tasa de convergencia más rápida en comparación con los métodos iterativos de Jacobi o Gauss-Seidel , que escalan como .

No se supone ningún error de redondeo en el teorema de convergencia, pero el límite de convergencia es comúnmente válido en la práctica, como lo explica teóricamente [ 5] Anne Greenbaum .

Convergencia práctica

Si se inicializa aleatoriamente, la primera etapa de iteraciones suele ser la más rápida, ya que el error se elimina dentro del subespacio de Krylov que inicialmente refleja un número de condición efectivo más pequeño. La segunda etapa de convergencia suele estar bien definida por la convergencia teórica ligada a , pero puede ser superlineal, dependiendo de la distribución del espectro de la matriz y la distribución espectral del error. [5] En la última etapa, se alcanza la precisión más pequeña posible y la convergencia se detiene o el método puede incluso comenzar a divergir. En aplicaciones informáticas científicas típicas en formato de punto flotante de doble precisión para matrices de grandes tamaños, el método del gradiente conjugado utiliza un criterio de parada con una tolerancia que termina las iteraciones durante la primera o segunda etapa.

El método del gradiente conjugado precondicionado

En la mayoría de los casos, el preacondicionamiento es necesario para asegurar una rápida convergencia del método del gradiente conjugado. Si es simétrico positivo-definido y tiene un número de condición mejor que , se puede utilizar un método de gradiente conjugado precondicionado. Toma la siguiente forma: [10]

repetir
si r k +1 es suficientemente pequeño , entonces salga del final del bucle si
finalizar repetir
El resultado es x k +1

La formulación anterior equivale a aplicar el método del gradiente conjugado regular al sistema precondicionado [11]

dónde

Se debe utilizar la descomposición de Cholesky del precondicionador para mantener la simetría (y la precisión positiva) del sistema. Sin embargo, no es necesario calcular esta descomposición y basta con saberlo . Se puede demostrar que tiene el mismo espectro que .

La matriz precondicionadora M tiene que ser simétrica positiva-definida y fija, es decir, no puede cambiar de una iteración a otra. Si se viola cualquiera de estos supuestos sobre el precondicionador, el comportamiento del método del gradiente conjugado precondicionado puede volverse impredecible.

Un ejemplo de precondicionador de uso común es la factorización incompleta de Cholesky . [12]

Uso del preacondicionador en la práctica

Es importante tener en cuenta que no queremos invertir la matriz explícitamente para poder usarla en el proceso, ya que invertir tomaría más tiempo/recursos computacionales que resolver el algoritmo de gradiente conjugado en sí. Como ejemplo, digamos que estamos usando un precondicionador proveniente de una factorización de Cholesky incompleta. La matriz resultante es la matriz triangular inferior y la matriz precondicionadora es:

Entonces tenemos que resolver:

Pero:

Entonces:

Tomemos un vector intermediario :

Dado que y y conocido, y es triangular inferior, resolverlo es fácil y computacionalmente barato mediante el uso de sustitución directa . Luego, sustituimos en la ecuación original:

Dado que y son conocidos, y es triangular superior, resolverlo es fácil y computacionalmente barato mediante el uso de sustitución hacia atrás .

Con este método, no es necesario invertirlo ni hacerlo explícitamente, y aun así obtenemos .

El método del gradiente conjugado precondicionado flexible

En aplicaciones numéricamente desafiantes, se utilizan precondicionadores sofisticados, que pueden conducir a un precondicionamiento variable, que cambia entre iteraciones. Incluso si el precondicionador es simétrico positivo-definido en cada iteración, el hecho de que pueda cambiar hace que los argumentos anteriores sean inválidos y, en pruebas prácticas, conduce a una desaceleración significativa de la convergencia del algoritmo presentado anteriormente. Usando la fórmula de Polak-Ribière

en lugar de la fórmula de Fletcher-Reeves

puede mejorar dramáticamente la convergencia en este caso. [13] Esta versión del método de gradiente conjugado precondicionado puede denominarse [14] flexible, ya que permite un precondicionamiento variable. También se ha demostrado que la versión flexible [15] es robusta incluso si el preacondicionador no es simétrico positivo definido (SPD).

La implementación de la versión flexible requiere almacenar un vector adicional. Para un precondicionador SPD fijo, ambas fórmulas para βk son equivalentes en aritmética exacta, es decir, sin el error de redondeo .

La explicación matemática del mejor comportamiento de convergencia del método con la fórmula de Polak-Ribière es que el método es localmente óptimo en este caso, en particular, no converge más lento que el método de descenso más pronunciado localmente óptimo. [dieciséis]

vs. el método de descenso más empinado localmente óptimo

Tanto en el método de gradiente conjugado original como en el precondicionado , solo es necesario configurarlo para que sean localmente óptimos, utilizando los métodos de descenso más pronunciado de búsqueda de líneas . Con esta sustitución, los vectores p son siempre los mismos que los vectores z , por lo que no es necesario almacenar los vectores p . Por lo tanto, cada iteración de estos métodos de descenso más pronunciado es un poco más barata en comparación con la de los métodos de gradiente conjugado. Sin embargo, estos últimos convergen más rápido, a menos que se utilice un precondicionador (altamente) variable y/o no SPD , ver arriba.

Método de gradiente conjugado como controlador de retroalimentación óptimo para doble integrador

El método del gradiente conjugado también se puede derivar utilizando la teoría de control óptimo . [17] En este enfoque, el método del gradiente conjugado resulta ser un controlador de retroalimentación óptimo .

sistema doble integrador
[17]

gradiente conjugado en las ecuaciones normales

El método del gradiente conjugado se puede aplicar a una matriz arbitraria de n por m aplicándola a las ecuaciones normales A T A y al vector del lado derecho A T b , ya que A T A es una matriz semidefinida positiva simétrica para cualquier A . El resultado es un gradiente conjugado en las ecuaciones normales ( CGN o CGNR ).

A T Ax = A T b

Como método iterativo, no es necesario formar A T A explícitamente en la memoria, sino solo realizar las multiplicaciones matriz-vector y transponer matriz-vector. Por lo tanto, CGNR es particularmente útil cuando A es una matriz dispersa ya que estas operaciones suelen ser extremadamente eficientes. Sin embargo, la desventaja de formar ecuaciones normales es que el número de condición κ( A T A ) es igual a κ 2 ( A ), por lo que la tasa de convergencia de CGNR puede ser lenta y la calidad de la solución aproximada puede ser sensible al redondeo. errores. Encontrar un buen preacondicionador suele ser una parte importante del uso del método CGNR.

Se han propuesto varios algoritmos (por ejemplo, CGLS, LSQR). El algoritmo LSQR supuestamente tiene la mejor estabilidad numérica cuando A está mal condicionado, es decir, A tiene un número de condición grande .

Método de gradiente conjugado para matrices hermitianas complejas

El método del gradiente conjugado con una modificación trivial se puede ampliar para resolver, dada la matriz A de valores complejos y el vector b, el sistema de ecuaciones lineales para el vector x de valores complejos, donde A es hermitiano (es decir, A' = A) y positivo -matriz definida , y el símbolo 'denota la transpuesta conjugada . La modificación trivial es simplemente sustituir la transpuesta conjugada por la transpuesta real en todas partes.

Ventajas y desventajas

Las ventajas y desventajas de los métodos de gradiente conjugado se resumen en las notas de clase de Nemirovsky y BenTal. [18] : Sección 7.3 

Un ejemplo patológico

Este ejemplo es de [19] Let y define

Ver también

Referencias

  1. ^ Hestenes, Magnus R .; Stiefel, Eduard (diciembre de 1952). "Métodos de gradientes conjugados para resolver sistemas lineales" (PDF) . Revista de Investigación de la Oficina Nacional de Normas . 49 (6): 409. doi : 10.6028/jres.049.044 .
  2. ^ Straeter, TA (1971). Sobre la extensión de la clase Davidon-Broyden de rango uno, métodos de minimización cuasi-Newton a un espacio de Hilbert de dimensión infinita con aplicaciones a problemas de control óptimo (tesis doctoral). Universidad Estatal de Carolina del Norte. hdl : 2060/19710026200 – a través del servidor de informes técnicos de la NASA.
  3. ^ Speiser, Ambros (2004). "Konrad Zuse und die ERMETH: Ein weltweiter Architektur-Vergleich" [Konrad Zuse y ERMETH: una comparación mundial de arquitecturas]. En Hellige, Hans Dieter (ed.). Geschichten der Informatik. Visionen, Paradigmen, Leitmotive (en alemán). Berlín: Springer. pag. 185.ISBN 3-540-00217-0.
  4. ^ abcd Polyak, Boris (1987). Introducción a la Optimización.
  5. ^ a b C Greenbaum, Anne (1997). Métodos iterativos para resolver sistemas lineales . doi :10.1137/1.9781611970937. ISBN 978-0-89871-396-1.
  6. ^ Paqueta, Elliot; Trogdon, Thomas (marzo de 2023). "Universalidad de los algoritmos de gradiente conjugado y MINRES en matrices de covarianza de muestra". Comunicaciones sobre Matemática Pura y Aplicada . 76 (5): 1085-1136. arXiv : 2007.00640 . doi :10.1002/cpa.22081. ISSN  0010-3640.
  7. ^ Shewchuk, Jonathan R (1994). Introducción al método del gradiente conjugado sin dolor agonizante (PDF) .
  8. ^ Saad, Yousef (2003). Métodos iterativos para sistemas lineales dispersos (2ª ed.). Filadelfia, Pensilvania: Sociedad de Matemáticas Industriales y Aplicadas. págs.195. ISBN 978-0-89871-534-7.
  9. ^ Hackbusch, W. (21 de junio de 2016). Solución iterativa de grandes sistemas dispersos de ecuaciones (2ª ed.). Suiza: Springer. ISBN 978-3-319-28483-5. OCLC  952572240.
  10. ^ Barrett, Richard; Baya, Michael; Chan, Tony F.; Demmel, James; Donato, junio; Dongarra, Jack; Eijkhout, Víctor; Pozo, Roldán; Romina, Carlos; van der Vorst, Henk. Plantillas para la solución de sistemas lineales: componentes básicos de métodos iterativos (PDF) (2ª ed.). Filadelfia, PA: SIAM. pag. 13 . Consultado el 31 de marzo de 2020 .
  11. ^ Golub, gen H.; Préstamo de Van, Charles F. (2013). Cálculos matriciales (4ª ed.). Prensa de la Universidad Johns Hopkins. segundo. 11.5.2. ISBN 978-1-4214-0794-4.
  12. ^ Conco, P.; Golub, GH; Meurant, G. (1985). "Precondicionamiento de bloques para el método de gradiente conjugado". Revista SIAM de Computación Científica y Estadística . 6 (1): 220–252. doi :10.1137/0906018.
  13. ^ Golub, gen H.; Sí, Qiang (1999). "Método de gradiente conjugado precondicionado inexacto con iteración interior-exterior". Revista SIAM de Computación Científica . 21 (4): 1305. CiteSeerX 10.1.1.56.1755 . doi :10.1137/S1064827597323415. 
  14. ^ Notay, Yvan (2000). "Gradientes conjugados flexibles". Revista SIAM de Computación Científica . 22 (4): 1444-1460. CiteSeerX 10.1.1.35.7473 . doi :10.1137/S1064827599362314. 
  15. ^ Bouwmeester, Henricus; Dougherty, Andrés; Knyazev, Andrés V. (2015). "Precondicionamiento no simétrico para métodos de gradiente conjugado y descenso más pronunciado 1". Procedia Ciencias de la Computación . 51 : 276–285. arXiv : 1212.6680 . doi : 10.1016/j.procs.2015.05.241 . S2CID  51978658.
  16. ^ Knyazev, Andrés V.; Lashuk, Ilya (2008). "Métodos de gradiente conjugado y descenso más pronunciado con preacondicionamiento variable". Revista SIAM sobre Análisis y Aplicaciones de Matrices . 29 (4): 1267. arXiv : matemáticas/0605767 . doi :10.1137/060675290. S2CID  17614913.
  17. ^ ab Ross, IM , "Una teoría de control óptimo para la optimización acelerada", arXiv :1902.09004, 2019.
  18. ^ Nemirovsky y Ben-Tal (2023). "Optimización III: Optimización convexa" (PDF) .
  19. ^ Pennington, Fabián Pedregosa, Courtney Paquette, Tom Trogdon, Jeffrey. "Tutorial de teoría de matrices aleatorias y aprendizaje automático". aprendizaje-matrix-aleatorio.github.io . Consultado el 5 de diciembre de 2023 .{{cite web}}: CS1 maint: multiple names: authors list (link)

Otras lecturas

enlaces externos