Haskell 'n' Cayered Ann Forward Pass -- haskell campo con reinventing-the-wheel campo con neural-network camp codereview Relacionados El problema

Haskell 'n' layered ANN forward pass


2
vote

problema

Español

Estoy tratando de escribir un simple 'n' en capas ANN en Haskell para el aprendizaje supervisado, finalmente tendrá la espalda la punta y podrás usarlo de manera paso a paso a través de una GUI que gráfica Función de error. Esto es para aprender (por lo que no estoy buscando sugerencias en las bibliotecas que ya resuelven este problema). En esta revisión, estoy buscando su opinión sobre cómo organizé mi código y si hay mejores formas de representar una red neuronal en Haskell.

El enfoque que estoy tratando de tomar es separar el paso adelante del pase hacia atrás, de modo que la capacitación pueda ser controlada por el consumidor (en lugar de tener una red que sea solo una oportunidad de IO que hace hacia adelante, y GT. ; volver recursivamente hasta el error & lt; x). La razón de esto es que luego puedo separar la representación del estado de las redes en cualquier pase dado (es decir, después de cada paso delantero, puedo simplemente rendir la pérdida actual de toda la red aplicando la función de costo a través del vector de salida). < / p>

Aquí está el código actual para un paso adelante de la red. Se necesita una lista de doble (que es el vector de entrada) y una lista de matriz de doble (donde cada elemento en la lista es una matriz de pesas que representa los pesos de cada conexión en una capa dada en la red). La función de activación luego crea un vector de salida que aplica recursivamente una función de su extensión a través de cada capa hasta que se haya evaluado la capa final 'n'.

Aquí está el código para eso:

  module Training (randomWeights, activate, cost) where    import Data.Matrix   import System.Random    activate :: [Double] -> [Matrix Double] -> Matrix Double   activate i weights = forwardPass inputs weights where     inputSize = length i     inputs = fromList 1 inputSize i     forwardPass inputs weights       | length weights == 1 = squashedOutputs       | otherwise = forwardPass (squashedOutputs) (tail weights)       where         squashedOutputs = mapPos ((row, col) a -> leakyRelu a) layerOutputs where           layerOutputs = multStd2 inputs (head weights)           leakyRelu a             | a > 0.0 = a             | otherwise = 0.01 * a    randomWeights :: (RandomGen g) => g -> Int -> Int -> Matrix Double   randomWeights generator inputSize outputSize = weights where     weights = matrix inputSize outputSize ((col, row) -> (take 10000 $ randomRs (-1.0, 1.0) generator)!!(col * row))   

La función de pesos aleatorios se consume en la función principal de mi programa y se usa para generar la lista de matriz de doble que se debe pasar al saliente (es decir, cada peso de las capas).

La función principal se ve así:

    main :: IO()   main = do     generator <- newStdGen      let expected = 0.0     let inputs = [0, 1]      let inputWeights = randomWeights generator (length inputs) 3     let hiddenWeights = randomWeights generator 3 1     let outputWeights = randomWeights generator 1 1      let outputs = activate inputs [inputWeights, hiddenWeights, outputWeights]      print inputs     print outputs   

por lo tanto, es un poco como una prueba de unidad (finalmente, envolveré el circuito de activación / retroceso en una estructura que un usuario puede controlar con un botón 'Siguiente' en una GUI, pero por ahora simplemente quiero una base sólida de adelante construir fuera.

¿Todo esto se ve como un haskell razonable, o hay algunas mejoras obvias que puedo hacer?

Original en ingles

I'm trying to write a simple 'n' layered ANN in haskell for supervised learning, it will eventually have back prop and you'll be able to use it in a step by step fashion through a GUI which will graph the error function. This is for learning (so I'm not looking for suggestions on libraries that already solve this problem). In this review I'm mainly looking for feedback on how I've arranged my code and if there are better ways to represent a neural network in Haskell.

The approach I'm trying to take is to separate the forward pass from the backward pass, so that the training can be controlled by the consumer (rather than having a network that is just a one shot IO which does forward -> back recursively until error < x). The reason for this is that I can then separate the rendering of the networks state at any given pass (i.e. after each forward pass I can easily just render the current loss of the whole network by applying the cost function across the output vector).

Here is the current code for a forward pass of the network. It takes a list of double (which is the input vector) and a list of matrix of double (where each element in the list is a weight matrix representing the weights of each connection on a given layer in the network). The activation function then creates an output vector by recursively applying a forwardPass function through each layer until the final layer 'n' has been evaluated.

Here is the code for that:

module Training (randomWeights, activate, cost) where    import Data.Matrix   import System.Random    activate :: [Double] -> [Matrix Double] -> Matrix Double   activate i weights = forwardPass inputs weights where     inputSize = length i     inputs = fromList 1 inputSize i     forwardPass inputs weights       | length weights == 1 = squashedOutputs       | otherwise = forwardPass (squashedOutputs) (tail weights)       where         squashedOutputs = mapPos (\(row, col) a -> leakyRelu a) layerOutputs where           layerOutputs = multStd2 inputs (head weights)           leakyRelu a             | a > 0.0 = a             | otherwise = 0.01 * a    randomWeights :: (RandomGen g) => g -> Int -> Int -> Matrix Double   randomWeights generator inputSize outputSize = weights where     weights = matrix inputSize outputSize (\(col, row) -> (take 10000 $ randomRs (-1.0, 1.0) generator)!!(col * row)) 

The randomWeights function is consumed in the main function of my program and is used to generate the list of matrix of double to be passed to the forwardPass (i.e. each layers weights).

The main function looks like this:

  main :: IO()   main = do     generator <- newStdGen      let expected = 0.0     let inputs = [0, 1]      let inputWeights = randomWeights generator (length inputs) 3     let hiddenWeights = randomWeights generator 3 1     let outputWeights = randomWeights generator 1 1      let outputs = activate inputs [inputWeights, hiddenWeights, outputWeights]      print inputs     print outputs 

So it a bit like a unit test (eventually I will wrap the activate/backprop loop into a structure that a user can control by a 'next' button on a GUI, but for now I simply want a solid forwardPass foundation to build off.

Does all of this look like reasonable haskell, or are there some obvious improvements I can make?

        
 
 

Lista de respuestas

1
 
vote
vote
La mejor respuesta
 

(col, row) -> (take 10000 $ randomRs (-1.0, 1.0) generator)!!(col * row)

Oh, hombre, me conseguiste ", no, no, no, no, no, no, como si no lo hubiera hecho: D. take 10000 no hace nada aquí. html, body, div, span, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, abbr, address, cite, code, del, dfn, em, img, ins, kbd, q, samp, small, strong, sub, sup, var, b, i, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td, article, aside, figure, footer, header,&nbsp;hgroup, menu, nav, section, menu, time, mark, audio, video { margin:0px; padding:0px; border:0px; outline:0px; font-size:100%; vertical-align:baseline; background:transparent; } 0 vendrá al mismo cuando cambie html, body, div, span, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, abbr, address, cite, code, del, dfn, em, img, ins, kbd, q, samp, small, strong, sub, sup, var, b, i, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td, article, aside, figure, footer, header,&nbsp;hgroup, menu, nav, section, menu, time, mark, audio, video { margin:0px; padding:0px; border:0px; outline:0px; font-size:100%; vertical-align:baseline; background:transparent; } 1 y html, body, div, span, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, abbr, address, cite, code, del, dfn, em, img, ins, kbd, q, samp, small, strong, sub, sup, var, b, i, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td, article, aside, figure, footer, header,&nbsp;hgroup, menu, nav, section, menu, time, mark, audio, video { margin:0px; padding:0px; border:0px; outline:0px; font-size:100%; vertical-align:baseline; background:transparent; } 2 , tal vez quiera html, body, div, span, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, abbr, address, cite, code, del, dfn, em, img, ins, kbd, q, samp, small, strong, sub, sup, var, b, i, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td, article, aside, figure, footer, header,&nbsp;hgroup, menu, nav, section, menu, time, mark, audio, video { margin:0px; padding:0px; border:0px; outline:0px; font-size:100%; vertical-align:baseline; background:transparent; } 3 ? html, body, div, span, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, abbr, address, cite, code, del, dfn, em, img, ins, kbd, q, samp, small, strong, sub, sup, var, b, i, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td, article, aside, figure, footer, header,&nbsp;hgroup, menu, nav, section, menu, time, mark, audio, video { margin:0px; padding:0px; border:0px; outline:0px; font-size:100%; vertical-align:baseline; background:transparent; } 4 va a ser recalculado para cada par html, body, div, span, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, abbr, address, cite, code, del, dfn, em, img, ins, kbd, q, samp, small, strong, sub, sup, var, b, i, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td, article, aside, figure, footer, header,&nbsp;hgroup, menu, nav, section, menu, time, mark, audio, video { margin:0px; padding:0px; border:0px; outline:0px; font-size:100%; vertical-align:baseline; background:transparent; } 6 Corrige eso. Llamar al resultado de la línea html, body, div, span, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, abbr, address, cite, code, del, dfn, em, img, ins, kbd, q, samp, small, strong, sub, sup, var, b, i, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td, article, aside, figure, footer, header,&nbsp;hgroup, menu, nav, section, menu, time, mark, audio, video { margin:0px; padding:0px; border:0px; outline:0px; font-size:100%; vertical-align:baseline; background:transparent; } 7 es poco más que un comentario. html, body, div, span, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, abbr, address, cite, code, del, dfn, em, img, ins, kbd, q, samp, small, strong, sub, sup, var, b, i, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td, article, aside, figure, footer, header,&nbsp;hgroup, menu, nav, section, menu, time, mark, audio, video { margin:0px; padding:0px; border:0px; outline:0px; font-size:100%; vertical-align:baseline; background:transparent; } 8 puede evitar el pase de generador, y también detenerlo generar los mismos valores aleatorios para cada llamada a pesos aleatorios.

  html, body, div, span, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, abbr, address, cite, code, del, dfn, em, img, ins, kbd, q, samp, small, strong, sub, sup, var, b, i, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td, article, aside, figure, footer, header,&nbsp;hgroup, menu, nav, section, menu, time, mark, audio, video { margin:0px; padding:0px; border:0px; outline:0px; font-size:100%; vertical-align:baseline; background:transparent; } 9  
 

\(col, row) -> (take 10000 $ randomRs (-1.0, 1.0) generator)!!(col * row)

Oh man you got me going "no no no no no no" like I long haven't :D. take 10000 does nothing here. col * row is going to come out to the same when you switch row and col, perhaps you want col + inputSize * row? randomRs is going to be recalculated for each (col,row) pair - fromList fixes that. Calling the line's result weights is little more than a comment. MonadRandom can avert the generator passery, and also stop you generating the same random values for each call to randomWeights.

activate :: [Double] -> [Matrix Double] -> Matrix Double activate i = foldl squash (fromLists [i]) where   squash inputs weights = fmap leakyRelu $ multStd2 inputs weights   leakyRelu a     | a > 0.0 = a     | otherwise = 0.01 * a  randomWeights :: Int -> Int -> IO (Matrix Double) randomWeights rows cols = fromList rows cols <$> getRandomRs (-1.0, 1.0)  main :: IO () main = do   let inputs = [0, 1]    inputWeights <- randomWeights (length inputs) 3   hiddenWeights <- randomWeights 3 1   outputWeights <- randomWeights 1 1    let outputs = activate inputs [inputWeights, hiddenWeights, outputWeights]    print inputs   print outputs 
 
 
   
   

Relacionados problema

5  Simulador de red neuronal con OpenMP  ( Neural network simulator with openmp ) 
Escribí un simple simulador de red neuronal (el tipo biofísico) desde cero, y esperaba obtener algunos comentarios sobre cómo puedo acelerar las cosas, o cual...

12  La red neuronal parece ser lenta  ( Neural network appears to be slow ) 
Tengo algo de código neuronal Julia, que espero acelerar. Posiblemente está simplemente mal diseñado, pero no estoy convencido. # This is line 1 (for the p...

4  Implementando el modelo Barabási-Albert  ( Implementing the barab%c3%a1si albert model ) 
Estoy escribiendo un código para el modelo Barabási-Albert (BA) con nodo y bordes específicos. El algoritmo es casi como [1] de la siguiente manera: 1....

4  Simulación simple de red neural en C ++ (Ronda 2)  ( Simple neural network simulation in c round 2 ) 
Intro Ayer He publicado esta pregunta . Desde entonces, he actualizado mi código para incorporar estas sugerencias . También he eliminado la dependencia d...

4  Red Neural Propagación Atrás  ( Back propagation neural network ) 
Esta es la primera vez que intenté escribir una propagación de la espalda Ann y me gustaría saber qué personas más experimentadas lo piensan. El código está d...

5  Diferentes funciones de activación de red neuronal y descenso de degradado  ( Different neural network activation functions and gradient descent ) 
He implementado un montón de funciones de activación para redes neuronales, y solo quiero tener validación de que funcionan correctamente matemáticamente. Imp...

4  Simulación simple de red neural en C ++ (Ronda 3)  ( Simple neural network simulation in c round 3 ) 
Como mencioné al final de mi Ronda 2 Respuesta , he necesitado expandir mi código en Para producir fielmente los datos necesarios para la FIGURA 1 de este p...

4  Implementación de Python del algoritmo de propagación de la espalda sin sesgo  ( Python implementation of back propagation algorithm without bias ) 
Este programa implementa el algoritmo de propagación de la red de la red neuronal con un ejemplo. ¿Podemos hacerlo más eficiente? from setuptools.namespace...

4  Clasificador de red neuronal artificial en Matlab  ( Artificial neural network classifier in matlab ) 
Estoy tratando de construir un clasificador de red neuronal. He creado una red neuronal con 1 capa oculta (25 neuronas) y 1 capa de salida (1 neurona / clasif...

8  Red neuronal de Python: número arbitrario de nodos ocultos  ( Python neural network arbitrary number of hidden nodes ) 
Estoy tratando de escribir una red neuronal que solo requiere que el usuario especifique la dimensionalidad de la red. Concretamente, el usuario podría defini...




© 2022 respuesta.top Reservados todos los derechos. Centro de preguntas y respuestas reservados todos los derechos