Aprendizaje automático en OCaml o Haskell?
machine-learning (10)
Espero usar Haskell u OCaml en un nuevo proyecto porque R es demasiado lento. Necesito poder usar máquinas vectory de soporte, idealmente separando cada ejecución para que se ejecute en paralelo. Quiero utilizar un lenguaje funcional y tengo la sensación de que estos dos son los mejores en lo que respecta al rendimiento y la elegancia (me gusta Clojure, pero no fue tan rápido en una prueba corta). Me inclino por OCaml porque parece haber más soporte para la integración con otros idiomas, por lo que podría ser una mejor opción a largo plazo (por ejemplo, OCaml-R ).
¿Alguien sabe de un buen tutorial para este tipo de análisis, o un ejemplo de código, en Haskell u OCaml?
Aunque es correcto que el paralelismo multinúcleo en el nivel de subprocesos sea mejor soportado en Haskell, parece que se podría vivir con el paralelismo de nivel de proceso (de su frase: idealmente separando cada ejecución para ejecutar en paralelo .) Que se soporta bastante bien en OCaml . Keith señaló que Haskell tiene un sistema de tipo más poderoso, pero también se puede decir que OCaml tiene un sistema de módulos más poderoso que Haskell.
Como han señalado otros, la curva de aprendizaje de OCaml será más baja que la de Haskell; es probable que sea más productivo más rápido en OCaml. Dicho esto, aprender OCaml es un gran paso hacia el aprendizaje de Haskell porque muchos de los conceptos subyacentes son muy similares, por lo que siempre puedes migrar a Haskell más tarde y encontrar muchas cosas familiares allí. Y como ha señalado, hay un puente OCaml-R.
Como ejemplos de Haskell y Ocaml en el aprendizaje automático, consulte las páginas principales de Hal Daume y Lloyd Allison . IMO es mucho más sencillo lograr un rendimiento similar al de C ++ en Ocaml, que en Haskell. A través de, como ya se dijo, Haskell tiene una comunidad mucho más agradable (paquetes, herramientas y soporte), sintaxis y características (es decir, FFI, mónadas de probabilidad a través de clases de tipos) y soporte de programación en paralelo.
Después de haber renovado OCaml-R, tengo algunos comentarios que hacer sobre la integración de OCaml y R. Podría valer la pena utilizar OCaml para llamar al código R, funciona, pero aún no es exactamente sencillo. Entonces usarlo para pilotar R vale la pena. La integración de la funcionalidad R mucho más a fondo sigue siendo engorrosa, ya que, por ejemplo, queda mucho por hacer para exportar el sistema de tipo R y los datos a OCaml de manera transparente (tendrá trabajo que hacer). Además, la interacción de R''s GC y OCaml''s GC es un punto delicado: usted libera n valores en O (n ^ 2) tiempo, lo cual no es bueno (para resolver este punto, o necesita una R API más flexible, en la medida de lo posible tal como lo entiendo, o implementar un GC en el enlace mismo como una gran matriz R para la interacción adecuada entre los GC).
En pocas palabras, optaría por el enfoque "piloto R de OCaml".
Las contribuciones en la capa de interacción de GC y en el mapeo de tipos de datos R a OCaml son bienvenidas.
El único problema que puedo ver es que OCaml no admite el paralelismo multinúcleo, mientras que GHC tiene un excelente soporte y rendimiento. Si está buscando utilizar múltiples hilos de ejecución, en llamadas múltiples, GHC Haskell será mucho más fácil.
En segundo lugar, el Haskell FFI es más poderoso (es decir, hace más con menos código) que OCaml, y hay más bibliotecas disponibles (a través de Hackage: http://hackage.haskell.org ) así que no creo que las interfaces extranjeras ser un factor decisivo.
En lo que respecta a la integración de varios idiomas, la combinación de C y Haskell es notablemente fácil, y lo digo como alguien que (a diferencia de los dones ) no es muy experto en ninguno de los dos. Cualquier otro lenguaje que se integre bien con C no debería ser mucho más complicado; siempre puede recurrir a una capa de interfaz delgada en C si nada más. Para bien o para mal, C sigue siendo la lengua de programación, por lo que Haskell es más que aceptable para la mayoría de los casos.
...pero. Dice que está motivado por problemas de rendimiento y quiere usar "un lenguaje funcional". De esto infiero que no estás familiarizado previamente con los idiomas sobre los que preguntas. Entre las características definitorias de Haskell está que, de forma predeterminada, utiliza una evaluación no estricta y estructuras de datos inmutables, que son increíblemente útiles de muchas maneras, pero también significa que la optimización de Haskell para el rendimiento a menudo es radicalmente diferente de otros idiomas, y también Los instintos ingeniosos pueden desviarlos de maneras desconcertantes. Es posible que desee explorar temas relacionados con el rendimiento en la wiki de Haskell para tener una idea de los problemas.
Lo cual no quiere decir que no puedas hacer lo que quieras en Haskell, sin duda puedes. De hecho, tanto la pereza como la inmutabilidad pueden explotarse para obtener beneficios de rendimiento ( la tesis de Chris Okasaki ofrece algunos buenos ejemplos). Pero tenga en cuenta que habrá una pequeña curva de aprendizaje cuando se trata de lidiar con el rendimiento.
Tanto Haskell como OCaml proporcionan los preciosos beneficios de utilizar un lenguaje de familia ML, pero para la mayoría de los programadores, OCaml ofrece una curva de aprendizaje más suave y mejores resultados inmediatos.
Es difícil dar una respuesta definitiva sobre esto. Haskell tiene las ventajas que Don mencionó junto con tener un sistema de tipo más poderoso y una sintaxis más limpia. OCaml será más fácil de aprender si vienes de casi cualquier otro idioma (esto se debe a que Haskell es una función tan funcional como los lenguajes funcionales), y trabajar con estructuras de acceso aleatorio mutables puede ser un poco torpe en Haskell. También es probable que encuentre las características de rendimiento de su código OCaml más intuitivas que Haskell debido a la evaluación perezosa de Haskell.
Realmente, recomendaría que evalúes ambos si tienes tiempo. Estos son algunos recursos relevantes de Haskell:
- http://hackage.haskell.org/package/hslibsvm
- http://hackage.haskell.org/package/HSvm
- Real World Haskell : este es un gran libro de libre acceso para Haskell
- Aprende Haskell : este tutorial es simplemente divertido de leer
Ah, si miras más hacia Haskell, asegúrate de inscribirte en las listas Haskell Beginners y Haskell Cafe . La comunidad es amigable y está ansiosa por ayudar a los recién llegados (¿se muestra mi parcialidad?).
Es posible que desee echar un vistazo a esto: http://www.haskell.org/pipermail/haskell-cafe/2010-May/077243.html
La respuesta tardía, pero una biblioteca de aprendizaje automático en Haskell está disponible aquí: https://github.com/mikeizbicki/HLearn
Esta biblioteca implementa varios algoritmos ML que están diseñados para tener una validación cruzada mucho más rápida que las implementaciones habituales. Se basa en los siguientes clasificadores algebraicos en papel : un enfoque genérico para una validación cruzada rápida, capacitación en línea y capacitación paralela . Los autores reclaman una aceleración de 400x en comparación con la misma tarea en Weka.
Si la velocidad es su principal preocupación, entonces vaya por C. Haskell es bastante bueno en cuanto a rendimiento pero nunca va a obtener tan rápido como C. Hasta donde sepa, el único lenguaje funcional que ha mejorado a C en un punto de referencia es Stalin Scheme, pero eso es muy viejo y nadie sabe realmente cómo funciona.
Escribí bibliotecas de programación genética donde el rendimiento era clave y lo escribí en un estilo funcional en C. El estilo funcional me permitió paralelizarlo fácilmente usando OMP y escala linealmente hasta 8 núcleos en un solo proceso. Ciertamente no se puede hacer eso en OCaml aunque Haskell está mejorando todo el tiempo con respecto a la concurrencia y el paralelismo.
La desventaja de usar C fue que tardé meses en encontrar finalmente todos los errores y detener los volcados del núcleo, lo que fue extremadamente desafiante debido a la concurrencia. Haskell probablemente habría atrapado el 90% de esos errores en la primera compilación.
¿Así que apresúrate a cualquier precio? Mirando hacia atrás, desearía haber usado Haskell ya que podría soportarlo 2 o 3 veces más lento si hubiera ahorrado más de un mes en tiempo de desarrollo.
Hal Daume ha escrito varios algoritmos importantes de aprendizaje automático durante su Ph.D. (ahora es profesor asistente y estrella en ascenso en la comunidad de aprendizaje automático)
En su página web, hay un SVM, un árbol de decisión simple y una regresión logística, todo en OCaml. Al leer estos códigos, puede tener una idea de cómo se implementan los modelos de aprendizaje automático en OCaml.
También me gustaría mencionar F #, un nuevo lenguaje .Net similar a OCaml. Aquí hay un modelo de gráfico de factores escrito en F # que analiza los datos de juego de ajedrez. Esta investigación también tiene una publicación NIPS.
Mientras que FP es adecuado para implementar modelos de aprendizaje automático y minería de datos. Pero lo que puede obtener más aquí NO es el rendimiento. Es correcto que FP soporte la computación paralela mejor que los lenguajes imperativos, como C # o Java. ¡Pero implementar una SVM paralela, o árbol de decisiones, tiene muy poca relación con el lenguaje! Paralelo es paralelo. Las optimizaciones numéricas detrás del aprendizaje automático y la minería de datos generalmente son imperativas, escribirlas de manera puramente funcional suele ser difícil y menos eficiente. Hacer que estos sofisticados algoritmos sean paralelos es una tarea muy difícil en el nivel de algoritmo, no en el nivel de lenguaje. Si desea ejecutar 100 SVM en paralelo, FP ayuda aquí. Pero no veo la dificultad de ejecutar 100 libsvm paralelos en C ++, no tener en cuenta que el único hilo libsvm es más eficiente que un paquete svm no probado de Haskell.
Entonces, ¿qué dan los lenguajes de FP, como F #, OCaml, Haskell?
Fácil de probar tu código. Los lenguajes de FP suelen tener un intérprete de alto nivel, puede probar sus funciones sobre la marcha.
Pocos estados mutables. Esto significa que al pasar el mismo parámetro a una función, esta función siempre da el mismo resultado, por lo que la depuración es fácil en los FP.
El código es sucinto. Escriba inferencia, coincidencia de patrones, cierres, etc. Se enfoca más en la lógica del dominio y menos en la parte del lenguaje. Entonces cuando escribes el código, tu mente está pensando principalmente en la lógica de programación misma.
Escribir código en MF es divertido.