Me gustaría proponer un tipo diferente de desafío de golf para esta comunidad:
Las redes neuronales (artificiales) son modelos de aprendizaje automático muy populares que se pueden diseñar y entrenar para aproximar cualquier función (generalmente desconocida). A menudo se usan para resolver problemas muy complejos que no sabemos cómo resolver algorítmicamente, como el reconocimiento de voz, ciertos tipos de clasificaciones de imágenes, diversas tareas en sistemas de conducción autónomos, ... Para una introducción a las redes neuronales, considere esto excelente Artículo de Wikipedia .
Como este es el primero en lo que espero ser una serie de desafíos de golf de aprendizaje automático, me gustaría mantener las cosas lo más simples posible:
En el lenguaje y marco de su elección, diseñe y entrene una red neuronal que, dado calcula su producto para todos los enteros entre (e incluyendo) y .
Objetivo de rendimiento
Para calificar, su modelo no puede desviarse en más de del resultado correcto en cualquiera de esas entradas.
Reglas
Su modelo
- debe ser una red neuronal 'tradicional' (el valor de un nodo se calcula como una combinación lineal ponderada de algunos de los nodos en una capa anterior seguida de una función de activación),
- solo puede usar las siguientes funciones de activación estándar:
- ,
- ,
- ,
- ,
- ,
- ,
- ,
- ,
- debe tomar como tupel / vector / list / ... de enteros o flotantes como su única entrada,
- devuelve la respuesta como un entero, flotante (o un contenedor adecuado, por ejemplo, un vector o una lista, que contiene esta respuesta).
Su respuesta debe incluir (o vincular) todo el código necesario para verificar sus resultados, incluidos los pesos entrenados de su modelo.
Puntuación
La red neuronal con el menor número de pesos (incluidos los pesos de sesgo) gana.
¡Disfrutar!
fuente
f(x) = x
reenviar su entrada?Respuestas:
21 13 119 pesasEsto se basa en la identidad de polarización de las formas bilineales que en el caso real unidimensional se reduce a la identidad polinómica:
Entonces,
y1
solo calcula[x+y, x-y]
usando una transformación lineal, yy3
es solo el valor absoluto dey1
como un paso de preprocesamiento para el siguiente: Luego, la parte "difícil" es calcular los cuadrados que explicaré a continuación, y después de eso simplemente calcular una diferencia y escalar qué Es de nuevo una operación lineal.Para calcular los cuadrados utilizo una serie exponencial que debería ser precisa para todos los enteros dentro de alrededor de . Esta serie es de la formas {0,1,2,…,20} 0.5
donde acabo de optimizar para los pesos=(wi)i
W2
( ). Toda esta aproximación comprende nuevamente solo dos transformaciones lineales con una activación exponencial intercalada en el medio. Este enfoque da como resultado una desviación máxima de aproximadamente .0.02
Pruébalo en línea!
fuente
abs
. Pero todo está bien de todos modos.y0
necesita 4,y1
necesita 2,y3
necesita 2,y4
necesita 1,y5
necesita 1 yy6
necesita 2. ¿Eso es 12?7 pesas
Pruébalo en línea!
Utiliza la siguiente igualdad aproximada para pequeño basado en la expansión de Taylor :ϵ ex≈1+x+x22
Elegir suficientemente pequeño nos lleva dentro de los límites de error requeridos. Tenga en cuenta que y son pesos constantes en el código.ϵ
eps
c
fuente
C = -B
(1 peso) y luego tener[e_s, e_d] = conv([A,B,C], [eps, eps])
(2 pesos) para ahorrar un peso :) (Por cierto: ¡Un enfoque muy inteligente!)exp
)3331 pesosPruébalo en línea!
Esto hace una multiplicación larga en (más o menos) binario, y por lo tanto devuelve el resultado exacto. Debería ser posible aprovechar la ventana de error 0.5 para jugar golf un poco más, pero no estoy seguro de cómo.
Las capas 1 a 6 descomponen la primera entrada en 5 "bits". Por razones de golf, no utilizamos binarios reales. El "bit" más significativo tiene un peso de -15 en lugar de 16, y cuando la entrada es 0, todos los "bits" son 0.5 (que aún funciona bien, ya que conserva la identidad
inputA = -15*a15 + 8*a8 + 4*a4 + 2*a2 + 1*a1
).fuente
43 pesas
Las dos soluciones publicadas hasta ahora han sido muy inteligentes, pero es probable que sus enfoques no funcionen para tareas más tradicionales en el aprendizaje automático (como OCR). Por lo tanto, me gustaría presentar una solución 'genérica' (sin trucos ingeniosos) para esta tarea que, con suerte, inspire a otras personas a mejorarla y dejarse atrapar por el mundo del aprendizaje automático:
Mi modelo es una red neuronal muy simple con 2 capas ocultas integradas en TensorFlow 2.0 (pero cualquier otro marco también funcionaría):
Como puede ver, todas las capas son densas (lo que ciertamente no es óptimo), la función de activación es tanh (que en realidad podría estar bien para esta tarea), excepto la capa de salida que, debido a la naturaleza de esta tarea, Tiene una función de activación lineal.
Hay 43 pesos:
Los pesos se han entrenado (con un optimizador Adam) mediante un enfoque de ajuste por capas: primero se han ajustado para minimizar el error cuadrático medio no solo en la multiplicación de enteros entre y sino en las entradas en un vecindario determinado alrededor de estos valores . Esto da como resultado una convergencia mucho mejor debido a la naturaleza del descenso del gradiente. Y representó 400 épocas de entrenamiento en 57.600 muestras de entrenamiento cada una, utilizando un tamaño de lote de 32.−10 10
A continuación, los he afinado, optimizando la desviación máxima en cualquiera de las tareas de multiplicación de enteros. Desafortunadamente, mis notas no muestran mucho ajuste fino que terminé haciendo, pero fue muy menor. Cerca de 100 épocas en esas 441 muestras de entrenamiento, con un tamaño de lote de 441.
Estos son los pesos con los que terminé:
que apenas alcanzó el objetivo de rendimiento establecido. La desviación máxima terminó siendo como lo atestigua .0.44350433 9⋅10=90.443504
Mi modelo se puede encontrar aquí y también puede probarlo en línea. en un entorno de Google Colab.
fuente
2 pesas
Me inspiraron las otras respuestas para aproximar la identidad de polarización de una manera diferente. Por cada pequeño , sostiene queϵ>0
Es suficiente tomar para este desafío.ϵ=0.01
La implementación neta neta obvia de esta aproximación toma pesos en . Estos cuatro pesos se pueden reducir a tres factorizando . Como mencioné en un comentario anterior, cada red neuronal con pesos en la precisión de la máquina puede convertirse en una red neuronal (¡enorme!) Con solo dos pesos distintos. Apliqué este procedimiento para escribir el siguiente código MATLAB:{±ϵ,±(4ϵ2)−1} {±ϵ,(4ϵ3)−1} ±(4ϵ2)−1=±ϵ⋅(4ϵ3)−1
En total, esta red neuronal consta de 1.250.010 pesos, todos los cuales residen en .{±0.1}
Cómo escapar con solo 1 peso (!)
Resulta que puede simular cualquier red neuronal que tenga pesos en con una red neuronal más grande que solo tenga un peso, a saber, . De hecho, la multiplicación por se puede implementar como{±0.1} −0.1 0.1
donde es el vector de columna de entradas, todas iguales a . Para las redes neuronales en las que la mitad de los pesos son positivos, esta transformación produce una red neuronal que es veces más grande.w 10 −0.1 10.5
La obvia generalización de este procedimiento transformará cualquier red neuronal con pesos en en una red neuronal más grande con el peso simple . Combinado con el procedimiento en mi comentario anterior, por lo tanto, sostiene que cada red neuronal con pesas de precisión mecánica puede transformarse en una red neuronal de un solo peso.{±10−k} −10−k
(Quizás deberíamos modificar cómo se puntúan los pesos reutilizados en futuros desafíos de golf de redes neuronales).
fuente