Para complementar Dikran Marsupial's respuesta, lo siguiente es una articulación de un proceso que utilizo personalmente. Esto es desde la perspectiva de la codificación de algoritmos de aprendizaje automático para la investigación, más que desde una perspectiva de ingeniería de software a nivel de producción.
Principalmente, a menudo he encontrado útil ver el proceso de codificación de un algoritmo de aprendizaje automático desde cero como la instanciación de una idea matemática:
Etapa matemática, pre-algorítmica.
Normalmente, en el aprendizaje automático se utiliza algún tipo de principio matemático o formal para guiar el desarrollo del algoritmo. Puede ser estadístico, por ejemplo, la estimación de máxima probabilidad, y lo más probable es que implique cierto grado de optimización. Por lo general, tendrá que hacer una buena cantidad de trabajo de derivación matemática, hasta que tenga lo que necesita.
Personalmente, he comprobado que se necesita tanto una sólida comprensión de los principios matemáticos que operan aquí, como seguridad absoluta en la corrección de las propias derivaciones. Cualquier confusión o incertidumbre en esta fase se agravará durante la aplicación, cuando uno tiene que preocuparse además de la depuración. Antes de pasar a la siguiente fase, suelo utilizar un paquete de cálculo simbólico o un sistema de álgebra computacional, como Mathematica para comprobar todas mis derivaciones, porque incluso un solo error en esta etapa puede llevar a la situación extremadamente indeseable de tener que buscar errores de derivación y/o depuración.
Algorítmica.
Una vez que he comprobado que mis derivaciones matemáticas son herméticas, sin errores, y que estoy en un nivel en el que puedo especificar y esbozar mi algoritmo en papel, procedo a redactar el pseudocódigo formal. Al igual que el cartel anterior, me parece que obligarse a escribirlo con algorithm2e
en LaTeX ayuda en el sentido de que te compromete de una manera que no lo hace el trabajar únicamente con lápiz y papel.
Durante esta fase de redacción del pseudocódigo, empiezo a pensar en cuestiones más relacionadas con la implementación, como adaptar mis derivaciones para que sean lo más vectorizadas posible, es decir, utilizar el menor número de bucles posible, o hacer uso de las técnicas de álgebra lineal en la medida de lo posible. Sin embargo, la preocupación por la implementación se limita a cumplir los consejos básicos y los principios estándar del diseño de algoritmos, pero no a optimizar el código.
La puesta en práctica.
Implementa el pseudocódigo en el código. Cuanto más claro sea tu pseudocódigo y más consistente sea tu notación, más fácil será esto. Algo que probablemente recogerás por ti mismo es que vale mucho la pena, como ha dicho el cartel anterior, asegurarse de que estás escribiendo código modular . Divida la escritura del código en pequeños trozos, que podrá probar individualmente.
En la mayoría de los casos, casi siempre habrá comprobaciones de cordura muy básicas que puedes hacer. Por ejemplo, si su código utiliza gradientes, puede utilizar la diferenciación finita para evaluar si se ha calculado correctamente. Si está implementando un algoritmo EM, su log-verosimilitud aumentará monotónicamente, por lo que cualquier disminución es probablemente un error de codificación, siempre que sus derivaciones sean correctas.
Optimización.
No quiero decir mucho sobre esto, excepto que puede volverse profundo muy rápidamente. En esta fase, se cronometra el código, o se utiliza toda una serie de trucos de álgebra lineal numérica, cálculo de matrices y optimización convexa para exprimir el mayor número posible de mejoras de rendimiento.
Con respecto al uso de herramientas para depurar, no sé mucho sobre las herramientas de depuración en R ya que es algo con lo que recién me estoy familiarizando. Sin embargo, parece que el depurador de RStudio es similar al de pdb
en Python.
En el caso de Python, el PyCharm El IDE es un ejemplo en el que he descubierto que las herramientas pueden mejorar enormemente el proceso de depuración. Usted puede caminar a través de cada línea de su código mientras se ejecuta, y paso a paso, paso a cabo, hacer evaluaciones de lado a lado, así como realizar un seguimiento de todos los estados de las variables a la vez. Personalmente, encuentro que los medios visuales para acceder a todos los estados de las variables a la vez son muy superiores a hacer consultas manuales en la línea de comandos utilizando pdb
. Aunque me gustaría haberlo sabido antes, insisto en que esto es sólo para consideración, y no tengo ninguna afiliación con JetBrains.
Algunas cosas finales. Como la mayoría de las cosas en la vida, se mejora con la práctica. Hay muchos documentos acompañados de código en paperswithcode.com y también hay un Reto de reproducibilidad del papel ML también.
Por último, si alguna vez te das cuenta de que la depuración está empezando a machacarte un poco el alma, he descubierto que ayuda pensar en los días en que la gente solía usar tarjetas perforadas para implementar algoritmos...