7 ene. 2018

Introducción al Perceptron con Python

Este artículo se basa en un artículo en inglés The Perceptron.

Un perceptron es un clasificador y uno de los más simples de la Red Neuronal Artificial. Lo que se busca es tomar las características de una red neuronal biológica, y replicarla como un algoritmo.

En la siguiente figura se muestra una red neuronal de dos entradas, cada entrada tiene su peso, luego se suman y la función de activación genera una salida.


La ecuación mátemática sería algo como:
y = FuncionActivacion(x1*w1+x2*w2)

La función de activación para una onda cuadrada es:


Donde la función de activación puede ser una onda cuadrada (hay más funciones de activación).

Acá otro perceptron con 5 señales de entrada.



A continuación se muestra el código:

#!/usr/bin/env python3

# coding: utf-8



# # Importar librerías

from pylab import rand,plot,show,norm

# # Clase Perceptron

class Perceptron:

 def __init__(self):

  """ inicialización del perceptron  """

  self.w = rand(2)*2-1 # pesos

  self.tasaAprendizaje = 0.1 



 def respuesta(self,x):

  """ saldia del perceptron """

  y = x[0]*self.w[0]+x[1]*self.w[1] # producto punto entre w y x

  if y >= 0:

   return 1

  else:

   return -1



 def actualizarPesos(self,x,iterError):

  """

  Actualizar estatus de los pesos, w en un tiempo t+1 es w(t+1)= w(t) + learningRate*(d-r)*x

  donde d es la salida deseada y r la respuesta del perceptro, iteError es la diferencia entre

  d y r (d-r).

  """

  self.w[0] += self.tasaAprendizaje*iterError*x[0]

  self.w[1] += self.tasaAprendizaje*iterError*x[1]



 def entrenamiento(self,data):

  """ 

  Entra todo el vector en los datos, cada vector en los datos debe tener 3 elementos,

  el tercer elemento (x[2]) debe ser etiquetado (salida deseada)

  """

  learned = False

  iteration = 0

  while not learned:

   globalError = 0.0

   for x in data: # por cada muestra

    r = self.respuesta(x)    

    if x[2] != r: # si tenemos un respuesta equivocada

     iterError = x[2] - r # respuesta deseada-respuesta actual

     self.actualizarPesos(x,iterError)

     globalError += abs(iterError)

   iteration += 1

   if globalError == 0.0 or iteration >= 100: # detiene por el criterio

    print ('iterations {}'.format(iteration))

    learned = True # detiene el aprendizaje

    



def datosGenerados(n):

    """

    genera un conjunto de datos, de dos dimensiones,  linealmente separados con

    n muestras. El tercer elemento de la muestra es la etiqueta.

    """

    xb = (rand(n)*2-1)/2-0.5

    yb = (rand(n)*2-1)/2+0.5

    xr = (rand(n)*2-1)/2+0.5

    yr = (rand(n)*2-1)/2-0.5

    inputs = []

    for i in range(len(xb)):

        inputs.append([xb[i],yb[i],1])

        inputs.append([xr[i],yr[i],-1])

    return inputs



trainset = datosGenerados(30) # generación de datos para entrenar

perceptron = Perceptron()   # Instancia del perceptron

perceptron.entrenamiento(trainset)  # Entrenamiento con el conjunto de datos

testset = datosGenerados(20)  # conjunto de datos para el test.



# Prueba del perceptron

for x in testset:

 r = perceptron.respuesta(x)

 if r != x[2]: # Si la respuesta no es correcta

  print ('error')

 if r == 1:

  plot(x[0],x[1],'ob')  

 else:

  plot(x[0],x[1],'or')



# Se gráfica una línea de separación, la cual es ortogonal a w.

n = norm(perceptron.w)

ww = perceptron.w/n

ww1 = [ww[1],-ww[0]]

ww2 = [-ww[1],ww[0]]

plot([ww1[0], ww2[0]],[ww1[1], ww2[1]],'--k')

show()





# ## 





Al ejecutar el script se tiene la siguiente gráfica:

Los puntos azules pertenecen a la primera clase y los rojos pertenecen a la segunda. La línea punteada es la línea de separación que el perceptrón aprendió durante el entrenamiento.

En siguientes artículos se seguirá trabajando con el perceptron pero usando librerías como scikit-learn y  tensorflow.

El script en python y el notebook de jupyter lo pueden descargar de github.

Introducción a Pandas

Pandas es una librería de python para analizar datos, permite multiples entrada de datos.

El artículo se basa en un artículo en inglés Building a neural network with python, y en un tutorial de pandas.

Para este tutorial se usará un conjunto de datos en formato csv  sobre vinos (análisis químico para saber el origen de los vinos).


A continuación de describe paso a paso la forma de manejar los datos a partir del archivo wine_data.csv.

El archivo Pandas.py y el Pandas.ipynb lo pueden descargar de github.

Se importa Pandas como pd:

>>> import pandas as pd

Se extrae los datos del archivo csv y se definen el nombres de las columnas:
>>> wine = pd.read_csv('wine_data.csv', names = ["Cultivator", "Alchol", "Malic_Acid", "Ash", "Alcalinity_of_Ash", "Magnesium", "Total_phenols", "Falvanoids", "Nonflavanoid_phenols", "Proanthocyanins", "Color_intensity", "Hue", "OD280", "Proline"])

Se muestran los primeros datos:
>>> wine.head()


Se muestra las dimensiones de la tabla:
>>> wine.shape
(178, 14)

Se tiene 178 filas y 14 columnas.

Se muestra las 2 primeras filas de la tabla:
wine.loc[[0,1]]


Se muestra las dos primeras filas y las columnas Cultivator y Alchol

>>> wine.loc[[0,1]][["Cultivator","Alchol"]]
 


Está introducción es necesaria ya que en futuros artículos se trabajará mucho con la librería pandas.

Graficar líneas de campo eléctrico con matplotlib y Python

Este artículo se basa en un artículo en inglés del blog scipython, con nombre Visualizing a vector field with matplotlib.

Matplotlib provee una función llamada streamplot, para crear flujos que puede usarse para representar vectores de campo.  El código python muestra la representación de un campo eléctrico a partir de multiples cargas. Las multiples cargas son seleccionadas como potencia de 2 (1 dipolo, 2 cuadrupolo, etc).

Se tiene una variable count la cual define la cantidad de cargas, en el primer caso vale 1 (dipolo).

A continuación el código:



#!/usr/bin/env python3

# coding: utf-8



# # Se importan los módulos necesarios para la graficación

import numpy as np

import matplotlib.pyplot as plt

from matplotlib.patches import Circle



# # Función que retorna el campo Eléctrico.

def E(q, r0, x, y):

    """Retorna el vector de campo eléctrico E=(Ex,Ey) de una carga q en r0"""

    den = np.hypot(x-r0[0], y-r0[1])**3

    return q * (x - r0[0]) / den, q * (y - r0[1]) / den



# # puntos de los ejes x e y.

nx, ny = 64, 64

x = np.linspace(-2, 2, nx)

y = np.linspace(-2, 2, ny)

X, Y = np.meshgrid(x, y)



# # Crear un multipolo con nq cargas

# count = número de q. En ese caso es 1 dipolo

count = 1

nq = 2**int(count)

charges = []

for i in range(nq):

    q = i%2 * 2 - 1

    charges.append((q, (np.cos(2*np.pi*i/nq), np.sin(2*np.pi*i/nq))))



# # Vector de campo eléctrico como componentes separados (Ex,Ey)

Ex, Ey = np.zeros((ny, nx)), np.zeros((ny, nx))

for charge in charges:

    ex, ey = E(*charge, x=X, y=Y)

    Ex += ex

    Ey += ey



fig = plt.figure()

ax = fig.add_subplot(111)





# # Dibujar las líneas de flujo con mapa de colores y estilos apropiados.

color = 2 * np.log(np.hypot(Ex, Ey))

ax.streamplot(x, y, Ex, Ey, color=color, linewidth=1, cmap=plt.cm.inferno,

              density=2, arrowstyle='->', arrowsize=1.5)





# # Agregar circulos para las cargas.

charge_colors = {True: '#aa0000', False: '#0000aa'}

for q, pos in charges:

    ax.add_artist(Circle(pos, 0.05, color=charge_colors[q>0]))





# # Graficar

ax.set_xlabel('$x$')

ax.set_ylabel('$y$')

ax.set_xlim(-2,2)

ax.set_ylim(-2,2)

ax.set_aspect('equal')

plt.show()



Al ejecutar el código se tiene la siguiente gráfica:

La siguiente gráfica es con count con valor a 4, osea 8 polos:

Y la última gráfica es con count con 10, osea 20 polos:


El código python  y el notebook de jupyter lo pueden obtener de un repositorio en github.

Gráfica de curvas en 3D con Python

El artículo de hoy se explicará como crear una gráfica 3D con Python.

Este artículo se basa en el artículo en inglés 3D Stem plot.

Para este caso se tiene dos archivos en un repositorio en github, uno python y otro un notebook de jupyter.

Se generará una variable x que define el eje del tiempo de dos gráficas (seno y coseno) para luego graficarlo en forma de gráfica 3D.

A continuación el código:


#!/usr/bin/env python3



# # Se importan las librerías necesarias



from numpy import linspace, sin, cos

from pylab import figure, show

from mpl_toolkits.mplot3d import Axes3D





# # generando algunos datos

x = linspace(-10,10,100);

y = sin(x);

z = cos(x);





# # Se crea la instancia de la figura y se asocia a la figura 3D

fig = figure()

ax = Axes3D(fig)





# # graficando los datos

for i in range(len(x)):

  ax.plot([x[i], x[i]], [y[i], y[i]], [0, z[i]], 

          '--', linewidth=2, color='b', alpha=.5)





# # graficando un circulo en el tope de cada curva

# plotting a circle on the top of each stem

ax.plot(x, y, z, 'o', markersize=8, 

        markerfacecolor='none', color='b',label='ib')

ax.set_xlabel('x')

ax.set_ylabel('y')

ax.set_zlabel('z')

show()



Al ejecutar el script se tiene la siguiente gráfica.