Acabo de ver un curso en youtube que explica, con matemáticas sencillas, como construir un perceptrón, básicamente una red neuronal artificial que recoge datos de entrada y elabora respuestas de salida.
Creo que sólo con las matemáticas de bachillerato es entendible.
https://www.youtube.com/playlist?lis...wWiF8a_52dQ3JQ
Si miráis en su listas de reproducción, también hay vídeos divulgativos, y unos vídeos de mecánica clásica (para explicar posteriormente la mecánica cuántica) también fácilmente entendible.
PD: no sabía muy bien donde ubicar el hilo por ser tan variados los vídeos a los que me refiero....
- - - Actualizado - - -
He intentado hacer el ejercicio que propone al final en el último vídeo. Ya acabé la red, el problema me surge que no "aprende" si no que "memoriza" el resultado.
Sii queréis echar un vistazo, os paso los códigos de la red:
Neuronas por capa: 3 5 5 4
Objetivo: resolución de ecuación de segundo grado ax^+bx+c=0, 3 variables entrada a b c, 4 variables de salida, 2 por cada solución: y_1 + y_2 i, y_3 + y_4 i.
Función, que a partir de las entradas, calcula la salida:
Función de entrenamiento:
Archivos de ejemplo de pesos ("w") y soluciones ("solutions").
Me parece bastante sencillo octave, en el sentido de poder convertir varios sumatorios en multiplicaciones matriciales, para los deltas el cálculo es elemento a elemento, lo único que carece de producto tensorial que hay que hacerlo "a mano". Si cogéis los pesos, veréis que sólo están entrenados para la primera solución.. Y otro problema que debo resolver es controlar el formato, para que salgan por pantalla números decimales pero sin necesidad de verse por ejemplo números del tipo: 12.5300000..
A ver si consigo que funcione bien.
Un saludo.
Creo que sólo con las matemáticas de bachillerato es entendible.
https://www.youtube.com/playlist?lis...wWiF8a_52dQ3JQ
Si miráis en su listas de reproducción, también hay vídeos divulgativos, y unos vídeos de mecánica clásica (para explicar posteriormente la mecánica cuántica) también fácilmente entendible.
PD: no sabía muy bien donde ubicar el hilo por ser tan variados los vídeos a los que me refiero....
- - - Actualizado - - -
He intentado hacer el ejercicio que propone al final en el último vídeo. Ya acabé la red, el problema me surge que no "aprende" si no que "memoriza" el resultado.
Sii queréis echar un vistazo, os paso los códigos de la red:
Neuronas por capa: 3 5 5 4
Objetivo: resolución de ecuación de segundo grado ax^+bx+c=0, 3 variables entrada a b c, 4 variables de salida, 2 por cada solución: y_1 + y_2 i, y_3 + y_4 i.
Función, que a partir de las entradas, calcula la salida:
Código:
function RNA(x) # resolviendo la ecuación ax^+bx+c=0, introducir: x=[a b c] v_min=-10^2; # Valores maximo y minimo que puede tomar las entradas y salidas V_max=10^2; printf("%fx^2 + %fx + %f = 0 \n", x(1), x(2), x(3)); s_1=scale(x, v_min, V_max, 0, 1); # se reescalan las variables de entrada de [v_min,V_max] -> [0,1] load("w"); # se carga el archivo con los pesos y los umbrales s_2=neuron(s_1*w_1 + u_2); # se procesan las salidas de cada neurona s_3=neuron(s_2*w_2 + u_3); s_4=neuron(s_3*w_3 + u_4); y=scale(s_4, 0, 1, v_min, V_max); # se vuelven a reescalar los valores de salida de [0,1] -> [v_min,V_max] # array de 4 dimensiones, 2 posibles resultados de la ecuacion dados en forma compleja: (y1 + y2i, y3 + y4i) if((y(1)+y(2)*i)==(y(3)+y(4)*i)) #se imprime el resultado por pantalla printf("x = %f + %f i\n \n", y(1), y(2)); else printf("x_1 = %f + %f i, x_2 = %f + %f i \n \n", y(1), y(2), y(3), y(4)); endif endfunction function s=neuron(a) s=sigmoid(a); #funcionamiento de neurona endfunction function y=sigmoid(x) # función sigmoide y=1./(1+e.^(-x)); endfunction function y=scale(x, x_0, x_1, y_0, y_1) # escalado basado en función lineal y = ((y_1-y_0)/(x_1 - x_0))*(x - x_0) + y_0; endfunction
Código:
function train() v_min=-10^2; # Valores maximo y minimo que puede tomar las entradas y salidas V_max=10^2; h=0.1; # razon de aprendizaje n=500; # numero de veces de practica l=1; # identificador de la solucion load("w"); # se carga el archivo con los pesos y los umbrales load("solutions"); # se cargan las soluciones if((v(l,1)+v(l,2)*i)==(v(l,3)+v(l,4)*i)) # se imprimen las soluciones por pantalla printf("solucion: x = %f + %f i\n \n", v(l,1), v(l,2)); else printf("soluciones: x_1 = %f + %f i, x_2 = %f + %f i \n \n", v(l,1), v(l,2), v(l,3), v(l,4)); endif v(l,:)=scale(v(l,:), v_min, V_max, 0, 1); # se reescalan los resultados de [v_min,V_max] -> [0,1] for k=1:n [s_1, s_2, s_3, s_4]=RNA_ap(x(l,:)); # La red neuronal calcula los resultados y pasa las variables d_4=s_4.*(1-s_4).*(s_4-v(l,:)); # Calculamos los deltas d_3=s_3.*(1-s_3).*(w_3*d_4')'; d_2=s_2.*(1-s_2).*(w_2*d_3')'; # Calculamos las derivadas parciales del error con respecto a los pesos y umbrales for i=1:length(s_1) for j=1:length(d_2) Dw_1(i,j)=s_1(i)*d_2(j); end end for i=1:length(s_2) for j=1:length(d_3) Dw_2(i,j)=s_2(i)*d_3(j); end end for i=1:length(s_3) for j=1:length(d_4) Dw_3(i,j)=s_3(i)*d_4(j); end end Du_2=d_2; Du_3=d_3; Du_4=d_4; w_1=w_1-h*Dw_1; # aplicamos el descenso del gradiente w_2=w_2-h*Dw_2; w_3=w_3-h*Dw_3; u_2=u_2-h*Du_2; u_3=u_3-h*Du_3; u_4=u_4-h*Du_4; save("w", "w_1", "w_2", "w_3", "u_2", "u_3", "u_4"); # guardamos los w end endfunction function [s_1, s_2, s_3, s_4]=RNA_ap(x) #copia de RNA(x) solo que esta funcion envia lo que da cada salida v_min=-10^2; V_max=10^2; printf("%fx^2 + %fx + %f=0 \n", x(1), x(2), x(3)); s_1=scale(x, v_min, V_max, 0, 1); load("w"); s_2=neuron(s_1*w_1 + u_2); s_3=neuron(s_2*w_2 + u_3); s_4=neuron(s_3*w_3 + u_4); y=scale(s_4, 0, 1, v_min, V_max); if((y(1)+y(2)*i)==(y(3)+y(4)*i)) printf("x=%f+%fi\n \n", y(1), y(2)); else printf("x_1 = %f + %f i, x_2 = %f + %f i \n \n", y(1), y(2), y(3), y(4)); endif endfunction function s=neuron(a) s=sigmoid(a); #funcionamiento de neurona endfunction function y=sigmoid(x) # función sigmoide y=1./(1+e.^(-x)); endfunction function y=scale(x, x_0, x_1, y_0, y_1) # escalado basado en función lineal y = ((y_1-y_0)/(x_1 - x_0))*(x - x_0) + y_0; endfunction
Código:
# name: w_1 # type: matrix # rows: 3 # columns: 5 9.479945325724249e-12 9.479945325724249e-12 9.479945325724249e-12 9.479945325724249e-12 9.479945325724249e-12 9.085312104172701e-12 9.085312104172701e-12 9.085312104172701e-12 9.085312104172701e-12 9.085312104172701e-12 9.4799423346112e-12 9.4799423346112e-12 9.4799423346112e-12 9.4799423346112e-12 9.4799423346112e-12 # name: w_2 # type: matrix # rows: 5 # columns: 5 4.349679783926101e-06 4.349679783926101e-06 4.349679783926101e-06 4.349679783926101e-06 4.349679783926101e-06 4.349679783926101e-06 4.349679783926101e-06 4.349679783926101e-06 4.349679783926101e-06 4.349679783926101e-06 4.349679783926101e-06 4.349679783926101e-06 4.349679783926101e-06 4.349679783926101e-06 4.349679783926101e-06 4.349679783926101e-06 4.349679783926101e-06 4.349679783926101e-06 4.349679783926101e-06 4.349679783926101e-06 4.349679783926101e-06 4.349679783926101e-06 4.349679783926101e-06 4.349679783926101e-06 4.349679783926101e-06 # name: w_3 # type: matrix # rows: 5 # columns: 4 0.004444573136243404 0 0.004444573150566376 0 0.004444573136243404 0 0.004444573150566376 0 0.004444573136243404 0 0.004444573150566376 0 0.004444573136243404 0 0.004444573150566376 0 0.004444573136243404 0 0.004444573150566376 0 # name: u_2 # type: matrix # rows: 1 # columns: 5 1.877219459307957e-11 1.877219459307957e-11 1.877219459307957e-11 1.877219459307957e-11 1.877219459307957e-11 # name: u_3 # type: matrix # rows: 1 # columns: 5 8.69935956783051e-06 8.69935956783051e-06 8.69935956783051e-06 8.69935956783051e-06 8.69935956783051e-06 # name: u_4 # type: matrix # rows: 1 # columns: 4 0.008889125120897654 0 0.008889125085089874 0
Código:
# name: x # type: matrix # rows: 4 # columns: 3 1 -2 1 1 2 1 1 0 -1 1 0 -4 # name: v # type: matrix # rows: 4 # columns: 4 1 0 1 0 -1 0 -1 0 1 0 -1 0 2 0 -2 0
A ver si consigo que funcione bien.
Un saludo.
Comentario