Trabajé en investigación toda mi vida, por lo que conozco el estereotipo de que los investigadores escriben código feo (por ejemplo, ver aquí , aquí o aquí ). Pero pensé: podemos arreglarlo, ¿verdad? Así que varias veces intenté diseñar buenos marcos de investigación. Intenté incorporar interfaces y crear abstracciones agradables utilizando libros y blogs de ingeniería de software que me gustaba leer.
Pero una y otra vez todos esos esfuerzos fueron en vano. La mayoría del software de investigación en el que trabajé nunca llegó a producción (aunque algunos sí). Habría sido fantástico para mi salud mental si alguien me hubiera dicho una simple verdad: morir el código de investigación es en realidad lo que se supone que debe suceder . En primer lugar, los investigadores no deberían dedicar mucho tiempo a diseñarlo.
Los ingenieros de software profesionales siempre menosprecian a los investigadores que no utilizan las mejores prácticas de software. Hay varias publicaciones que intentan elevar el nivel del código de investigación (por ejemplo, esta excelente publicación y un manual de código de investigación ). Pero esta publicación va al revés: explica cómo no exagerar con las mejores prácticas de software y, en cambio, invertir solo en exploración rápida. Está dirigido a empresas orientadas a la investigación cuyo objetivo es probar muchas ideas rápidamente.
Un proyecto de investigación exitoso en una empresa tiene dos fases: exploración y explotación. En la "exploración", desea probar tantas soluciones diversas como pueda. Durante la “explotación” hay que robustecer la mejor solución y convertirla en un producto útil.
Las prácticas óptimas de software son bastante diferentes entre los dos. Por eso las empresas suelen tener divisiones de investigación y de productos separadas. Todos los libros que normalmente lee sobre diseño de software tratan principalmente sobre la segunda fase de "explotación". En esta fase, usted está sentando las bases para un producto escalable. Aquí es donde entran todos los patrones de diseño: buenas API, registro, manejo de errores, etc.
Pero en la primera fase de "exploración" no se están construyendo cimientos que perdurarán para siempre. De hecho, si la mayoría de tus esfuerzos sobreviven, entonces (por definición) no exploraste lo suficiente.
Muchas de las prácticas descritas en esta publicación son ejemplos de lo que normalmente se convertiría en "deuda tecnológica". Es lo que se obtiene al no escribir código limpio, reutilizable y bien abstracto. ¿La deuda es siempre mala? Preferimos no obtener nunca un préstamo o una hipoteca, pero pedir dinero prestado suele ser una buena estrategia en la vida. Está bien endeudarse para actuar rápido y obtener ganancias más adelante.
Del mismo modo, al no endeudarse técnicamente, podría estar ralentizando su investigación. La buena noticia es que la mayoría de las veces no tendrás que devolverlo. Es probable que la mayor parte de su código de investigación muera de todos modos. Entonces, en promedio, no sufrirá toda la deuda tecnológica que ha contraído.
Muchas arquitecturas de software y técnicas de refactorización están orientadas específicamente a mejorar la reutilización del código. Existen desventajas genéricas en la reutilización de código. Pero en producción se ven superados por los conocidos beneficios (ver por ejemplo este típico post ). En los proyectos de investigación, la mayor parte del código está destinado a hundirse en el olvido. Esforzarse por reutilizar el código podría ralentizarlo.
Limitar la reutilización de código es el tipo de deuda técnica que se puede asumir en la investigación. Hay varios patrones de reutilización de código que quiero analizar: agregar una dependencia innecesaria, copiar y pegar código, mantener una gran cantidad de código de investigación compartido, inversiones prematuras en diseño.
Si conoce una biblioteca versionada en buen estado que le permitirá acelerar, ¡adelante! Pero antes de asumir una nueva dependencia, trate de evaluar si vale la pena. Cada uno adicional te acerca al infierno de la dependencia. Le hace invertir tiempo en aprenderlo y solucionarlo. Vea más peligros de las dependencias en esta publicación concisa .
Probablemente esté bien depender de algo si:
Pero tenga cuidado con una dependencia si:
no sabes cómo usarlo rápidamente, es muy nuevo (o muy viejo) o nadie parece saberlo; no hay documentos ni pruebas
es de tu monorepo y otros equipos lo cambian constantemente
incorpora muchas otras dependencias y herramientas; o simplemente es difícil de instalar
y finalmente, siente que usted (o algún LLM) puede escribir este código en unas pocas horas.
En lugar de una dependencia explícita, puedes seguir un bonito proverbio de Go: " un poco de copia es mejor que un poco de dependencia ", que es nuestro siguiente tema.
Algunos dicen que “ copiar y pegar debería ser ilegal ”. Pero, para mi sorpresa, me encontré argumentando a favor de ello con bastante frecuencia. Copiar y pegar podría ser la opción óptima durante la fase de exploración.
Si depende de una función muy utilizada de otra parte del código base, puede olvidarse de cambiarla fácilmente. Es probable que le rompas algo a alguien y tengas que dedicar un tiempo precioso a revisar y corregir el código. Pero si copias y pegas el código necesario en tu carpeta, eres libre de hacer lo que quieras con él. Esto es muy importante en proyectos de investigación donde la experimentación es una norma y no una excepción. Especialmente si no estás seguro de si los cambios van a ser útiles para todos.
Encuentro que las bases de código de aprendizaje profundo son las más adecuadas para copiar y pegar. Normalmente, la cantidad de código necesaria para describir un modelo y su entrenamiento no es tan grande. Pero al mismo tiempo podría tener muchos matices y ser difícil de generalizar. Los guiones de entrenamiento que se pueden compartir tienden a crecer hasta alcanzar un tamaño inmanejable: por ejemplo, Hugging Face transformers
Trainer tiene +4k líneas. Curiosamente, los transformadores optaron por copiar y pegar a nivel de modelo. Consulte su publicación con el razonamiento detrás de su política de "modelo de archivo único". Vea más recursos sobre la belleza de copiar y pegar al final.
Una alternativa a copiar y pegar es permanecer en una sucursal. Pero siento que supone demasiado esfuerzo para el trabajo en equipo. Además, encontré varias publicaciones más sobre la belleza de copiar y pegar; vea más publicaciones en la conclusión.
El mantenimiento de código compartido muy utilizado requiere mucho trabajo. Eche un vistazo al número de líneas de archivo torch.nn.Module
trazadas con respecto a la versión Pytorch
. Se puede ver que incluso los equipos de investigación más avanzados luchan por mantener la complejidad bajo control.
No subestime el tiempo y los recursos necesarios para mantener un gran código de investigación compartido. Cuanto más se utiliza una biblioteca de investigación, más complicada se vuelve. Sucede más rápido que en una biblioteca típica porque cada dirección de investigación tiene un caso de uso ligeramente diferente. Establezca reglas muy estrictas sobre lo que se puede aportar. De lo contrario, el código compartido se vuelve frágil y cubierto de una gran cantidad de opciones, optimizaciones con errores y casos extremos. Dado que la mayor parte del código de investigación desaparece, toda esta complejidad adicional nunca se volverá a utilizar. Eliminar parte de su código compartido le permitirá tener algo de tiempo para realizar una investigación real.
Es cierto que no desea preparar demasiado su código para el futuro, ni siquiera en producción. Intente implementar la solución más simple posible que cumpla con los requisitos. Pero en el código de producción siempre hay aspectos de mantenibilidad a considerar. Por ejemplo, el manejo de errores, la velocidad, el registro y la modularización es en lo que normalmente hay que pensar.
En el código de investigación, nada de eso importa. Sólo desea demostrar rápidamente que una idea es buena o mala de la manera más rápida posible y seguir adelante. Entonces, ¡la sucia simplicidad que lo logra sin ningún módulo o API está totalmente bien!
No pierda tiempo valioso en inversiones prematuras en software como:
El objetivo de un proyecto de investigación es encontrar una solución novedosa. Nadie sabe (por definición) cómo es. Es similar a un proceso de optimización en un panorama de investigación complicado con información limitada. Para encontrar un buen mínimo, es necesario probar muchos caminos, reconocer los buenos y malos caminos y no quedarse estancado en los mínimos locales. Para hacerlo todo rápido, a veces es necesario realizar inversiones en software en lugar de endeudarse en tecnología.
Hay varios caminos de investigación diferentes que desea probar. ¿Existe un diseño, una biblioteca o una optimización que reduciría el tiempo de la mayoría de los caminos? Debe tener cuidado de no diseñar demasiado nada porque no siempre conoce todas las ideas que está a punto de probar. Esto es muy personalizado para cada proyecto, pero aquí hay algunos ejemplos:
Los investigadores deberían poder iniciar nuevas ideas diversas rápidamente. Parece fácil al inicio del proyecto. Pero luego, gradualmente, se vuelve cada vez más difícil a medida que las personas se afianzan en sus caminos de investigación favoritos. Para abordar esto, los cambios culturales y organizativos son esenciales. Debería haber un proceso que detenga las investigaciones no prometedoras antes de invertir demasiado dinero y emociones en ellas. Los días de demostración periódicos y las revisiones técnicas por pares pueden servir como estrategias efectivas para este propósito. También es importante encontrar un equilibrio entre las personas que se lanzan a una nueva idea brillante y cierran adecuadamente los proyectos actuales.
Pero esta es una publicación de software, así que aquí hay algunas prácticas para facilitar la ramificación de nuevos proyectos:
El código ruidoso y con errores hace que los resultados sean tan ambiguos y poco concluyentes que todo el proyecto será una pérdida de tiempo. Si bien no debes diseñar demasiadas cosas, puedes seguir fácilmente estas simples reglas generales para evitar código desordenado:
Evite el código con efectos secundarios.
por defecto a funciones en lugar de clases; y con las clases, prefiera la encapsulación frente a la herencia
minimizar la longitud de funciones/clases/módulos; minimizar el número de declaraciones if
Conozco bien Python, pero uso técnicas simples. Resista la tentación de adentrarse en la maleza intelectual de las metaclases, los decoradores y la programación funcional.
Es complicado trabajar con un software que produce diferentes resultados durante diferentes ejecuciones. Si tomaste una decisión importante pero equivocada basándose en una semilla desafortunada, vas a perder mucho tiempo recuperándote. A continuación se ofrecen algunos consejos cuando se trata de software no determinista:
El remate proviene de esta publicación sobre el código de investigación:
“No te preocupas por [un buen diseño de software] porque el código no es el punto. El código es una herramienta que te brinda la respuesta que necesitas” .
Es extremadamente importante tener buenas bases de codificación. Pero al final del día, lo que importa es la exploración y el producto realmente útil. Si utiliza demasiado software de producción en la investigación, perderá el tiempo necesario para descubrir algo nuevo. En su lugar, encuentre lo que ralentiza su proceso de exploración. Acelere las rutas de investigación invirtiendo en ramificaciones rápidas, tiempo para obtener resultados y código limpio y silencioso.
Sería una locura argumentar completamente en contra de la reutilización de código. Sólo quiero señalar que la reutilización de código debe ser una actividad bien equilibrada. En la investigación, la proporción de código desechable es mayor que en la producción. La balanza se inclina aún más en contra de la reutilización. Aquí hay algunas publicaciones más excelentes con los inconvenientes de la reutilización de código:
Y aquí hay algunas publicaciones más que abogan por las prácticas de copypasting:
¡Gracias por leer! Siento que algunas partes son un poco controvertidas, ¡házmelo saber en los comentarios!
También aparece aquí .