# PRÁCTICA 02.
# Perceptrón Simple.

### OBJETIVO:

Que el alumno implemente el perceptrón simple y lo aplique en distintos conjuntos de datos aplicando variaciones en la forma de aprendizaje del perceptrón.


```python
%matplotlib inline

import matplotlib.pyplot as plt
import matplotlib.cm as cm
from mpl_toolkits.mplot3d import Axes3D

import json, matplotlib
from IPython.core.pylabtools import figsize
figsize(11, 5)

from ipywidgets import interact, interact_manual, interactive, fixed
import ipywidgets as widgets
from IPython.display import display
import numpy as np

```


```python
class Perceptron:
    def __init__(self, num_inputs, weights = None, seed = 0):
        if weights: self.weights = np.copy(weights)
        else:
            np.random.seed(seed)
            self.weights = np.random.rand(num_inputs)
            
    def predict(self, input):
        ponderate_sum = np.dot(input, self.weights)
        result = 1.0 if ponderate_sum > 0 else 0.0
        
        return np.float64(result), ponderate_sum
    
    def train(self, input, desired_output, learning_rate):
        prediction, _ = self.predict(input)
        if prediction == desired_output: return
        
        add_or_substract = 1.0 if (prediction == 0.0 and desired_output == 1.0)  else -1.0
        self.weights = self.weights + (add_or_substract * input)
        
    def train_epoch(self, input_set, output_set, learning_rate, may_print = True):
        for index, input in enumerate(input_set):
            output = output_set[index]
            if may_print: print(f"input={input} index={index}")

            prediction, ponderate = self.predict(input)
            if may_print: print(f"prediction={prediction} real={output} ponderate={ponderate} ")

            self.train(input, output, learning_rate)

            prediction, ponderate = self.predict(input)
            if may_print: print(f"prediction={prediction} real={output} ponderate={ponderate} ")
            if may_print: print()

        
```

### PERCEPTRÓN

Un perceptrón simple es una unidad computacional con un umbral $\theta$, que al recibir $X \text{ de }n$ entradas reales $X = x_1, x_2, \cdots, x_n$ a través de sus pesos asociados $W = w_1, w_2, \cdots, w_n$, da una salida de valor 1 si la desigualdad $\sum_{i=1}^{n}w_ix_i \geq \theta$ se cumple, en otro caso la salida es 0.

La ley de aprendizaje se define como: $w_i(t+1) = w_i (t) + \alpha · d(x) · x_i$


$$
\
d(x)= 
\begin{cases}
1, & \text{si } x \in A;\\
-1, & \text{si } x \in B
\end{cases}
\
$$

y $\alpha$ la tasa de aprendizaje. Los pesos no se modifican si $x$ está bien clasificado.

1.- Implementa la clase Perceptron que contenga lo siguiente:
   * Inicialización del perceptrón dados los pesos iniciales.
   * Función **evalua_escalon** que reciba X y evalúe la salida utilizando la función escalón en el intervalo [0,1].
   * Función **entrena**, debe entrenar al perceptrón: modificación de los pesos en una iteración cada que se llame a esta función dada una tasa de aprendizaje.
   
2.- Crea un *Perceptron* de pesos iniciales aleatorios y entrénalo con el conjunto de datos datosAND con inicialización de pesos aleatorios.
    
 * Completa la función **entrenaPerceptronAND** y utiliza tu función **entrena** para que en cada paso de entrenamiento se dibuje el conjunto de datos y el plano que divide al conjunto, tal como se muestra en la figura (utiliza colores para diferenciar al conjunto de datos)
 
 
 
HINT1: Recuerda que el vector de pesos W contiene el vector normal al plano.
 
HINT2: Puedes utilizar la función scatter y plot_surface


```python
data_and = np.array([[1, 0, 0, 0],
                     [1, 0 ,0, 1],
                     [1, 0, 1, 0],
                     [1, 0, 1, 1],
                     [1, 1, 0, 0],
                     [1, 1, 0, 1],
                     [1, 1, 1, 0],
                     [1, 1, 1, 1]]).astype(np.float64)

answers_and = np.array([0,0,0,0,0, 0, 0, 1]).astype(np.float64)

num_inputs = 4
perceptron = Perceptron(num_inputs)

for i in range(6):
    perceptron.train_epoch(data_and, answers_and, 0.08)

    
x = np.linspace(-0.1, 1.1, 30)
y = np.linspace(-0.1, 1.1, 30)

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

@interact_manual()
def entrenaPerceptronAND():
    input_1 = data_and[:, 1]
    input_2 = data_and[:, 2]
    input_3 = data_and[:, 3]
    
    d = perceptron.weights[0]
    a, b, c = perceptron.weights[1:]

    x = np.linspace(-1,1,10)
    y = np.linspace(-1,1,10)

    X,Y = np.meshgrid(x,y)
    Z = (d - a*X - b*Y) / c
    
    fig = plt.figure()
    plane = fig.add_subplot(111, projection='3d')
    
    plane.set_xlabel('input_1')
    plane.set_ylabel('input_2')
    plane.set_zlabel('input_3')
    plane.plot_surface(X, Y, Z)
    plane.scatter(*data_and[:, 1:].T, c=answers_and)
    

    
    
```

    input=[1. 0. 0. 0.] index=0
    prediction=1.0 real=0.0 ponderate=0.5488135039273248 
    prediction=0.0 real=0.0 ponderate=-0.45118649607267525 
    
    input=[1. 0. 0. 1.] index=1
    prediction=1.0 real=0.0 ponderate=0.09369668692422162 
    prediction=0.0 real=0.0 ponderate=-1.9063033130757785 
    
    input=[1. 0. 1. 0.] index=2
    prediction=0.0 real=0.0 ponderate=-0.8484231200010314 
    prediction=0.0 real=0.0 ponderate=-0.8484231200010314 
    
    input=[1. 0. 1. 1.] index=3
    prediction=0.0 real=0.0 ponderate=-1.3035399370041345 
    prediction=0.0 real=0.0 ponderate=-1.3035399370041345 
    
    input=[1. 1. 0. 0.] index=4
    prediction=0.0 real=0.0 ponderate=-0.7359971297002558 
    prediction=0.0 real=0.0 ponderate=-0.7359971297002558 
    
    input=[1. 1. 0. 1.] index=5
    prediction=0.0 real=0.0 ponderate=-1.191113946703359 
    prediction=0.0 real=0.0 ponderate=-1.191113946703359 
    
    input=[1. 1. 1. 0.] index=6
    prediction=0.0 real=0.0 ponderate=-0.1332337536286119 
    prediction=0.0 real=0.0 ponderate=-0.1332337536286119 
    
    input=[1. 1. 1. 1.] index=7
    prediction=0.0 real=1.0 ponderate=-0.588350570631715 
    prediction=1.0 real=1.0 ponderate=3.411649429368285 
    
    input=[1. 0. 0. 0.] index=0
    prediction=0.0 real=0.0 ponderate=-0.45118649607267525 
    prediction=0.0 real=0.0 ponderate=-0.45118649607267525 
    
    input=[1. 0. 0. 1.] index=1
    prediction=1.0 real=0.0 ponderate=0.09369668692422162 
    prediction=0.0 real=0.0 ponderate=-1.9063033130757785 
    
    input=[1. 0. 1. 0.] index=2
    prediction=1.0 real=0.0 ponderate=0.15157687999896874 
    prediction=0.0 real=0.0 ponderate=-1.8484231200010313 
    
    input=[1. 0. 1. 1.] index=3
    prediction=0.0 real=0.0 ponderate=-2.3035399370041345 
    prediction=0.0 real=0.0 ponderate=-2.3035399370041345 
    
    input=[1. 1. 0. 0.] index=4
    prediction=0.0 real=0.0 ponderate=-0.7359971297002557 
    prediction=0.0 real=0.0 ponderate=-0.7359971297002557 
    
    input=[1. 1. 0. 1.] index=5
    prediction=0.0 real=0.0 ponderate=-1.191113946703359 
    prediction=0.0 real=0.0 ponderate=-1.191113946703359 
    
    input=[1. 1. 1. 0.] index=6
    prediction=0.0 real=0.0 ponderate=-0.13323375362861167 
    prediction=0.0 real=0.0 ponderate=-0.13323375362861167 
    
    input=[1. 1. 1. 1.] index=7
    prediction=0.0 real=1.0 ponderate=-0.5883505706317148 
    prediction=1.0 real=1.0 ponderate=3.411649429368285 
    
    input=[1. 0. 0. 0.] index=0
    prediction=0.0 real=0.0 ponderate=-1.4511864960726752 
    prediction=0.0 real=0.0 ponderate=-1.4511864960726752 
    
    input=[1. 0. 0. 1.] index=1
    prediction=0.0 real=0.0 ponderate=-0.9063033130757784 
    prediction=0.0 real=0.0 ponderate=-0.9063033130757784 
    
    input=[1. 0. 1. 0.] index=2
    prediction=1.0 real=0.0 ponderate=0.15157687999896874 
    prediction=0.0 real=0.0 ponderate=-1.8484231200010313 
    
    input=[1. 0. 1. 1.] index=3
    prediction=0.0 real=0.0 ponderate=-1.3035399370041345 
    prediction=0.0 real=0.0 ponderate=-1.3035399370041345 
    
    input=[1. 1. 0. 0.] index=4
    prediction=1.0 real=0.0 ponderate=0.26400287029974434 
    prediction=0.0 real=0.0 ponderate=-1.7359971297002557 
    
    input=[1. 1. 0. 1.] index=5
    prediction=0.0 real=0.0 ponderate=-1.191113946703359 
    prediction=0.0 real=0.0 ponderate=-1.191113946703359 
    
    input=[1. 1. 1. 0.] index=6
    prediction=0.0 real=0.0 ponderate=-1.1332337536286117 
    prediction=0.0 real=0.0 ponderate=-1.1332337536286117 
    
    input=[1. 1. 1. 1.] index=7
    prediction=0.0 real=1.0 ponderate=-0.5883505706317148 
    prediction=1.0 real=1.0 ponderate=3.411649429368285 
    
    input=[1. 0. 0. 0.] index=0
    prediction=0.0 real=0.0 ponderate=-2.4511864960726752 
    prediction=0.0 real=0.0 ponderate=-2.4511864960726752 
    
    input=[1. 0. 0. 1.] index=1
    prediction=0.0 real=0.0 ponderate=-0.9063033130757785 
    prediction=0.0 real=0.0 ponderate=-0.9063033130757785 
    
    input=[1. 0. 1. 0.] index=2
    prediction=0.0 real=0.0 ponderate=-0.8484231200010313 
    prediction=0.0 real=0.0 ponderate=-0.8484231200010313 
    
    input=[1. 0. 1. 1.] index=3
    prediction=1.0 real=0.0 ponderate=0.6964600629958655 
    prediction=0.0 real=0.0 ponderate=-2.3035399370041345 
    
    input=[1. 1. 0. 0.] index=4
    prediction=0.0 real=0.0 ponderate=-0.7359971297002557 
    prediction=0.0 real=0.0 ponderate=-0.7359971297002557 
    
    input=[1. 1. 0. 1.] index=5
    prediction=0.0 real=0.0 ponderate=-0.1911139467033589 
    prediction=0.0 real=0.0 ponderate=-0.1911139467033589 
    
    input=[1. 1. 1. 0.] index=6
    prediction=0.0 real=0.0 ponderate=-0.13323375362861167 
    prediction=0.0 real=0.0 ponderate=-0.13323375362861167 
    
    input=[1. 1. 1. 1.] index=7
    prediction=1.0 real=1.0 ponderate=0.4116494293682851 
    prediction=1.0 real=1.0 ponderate=0.4116494293682851 
    
    input=[1. 0. 0. 0.] index=0
    prediction=0.0 real=0.0 ponderate=-3.4511864960726752 
    prediction=0.0 real=0.0 ponderate=-3.4511864960726752 
    
    input=[1. 0. 0. 1.] index=1
    prediction=0.0 real=0.0 ponderate=-2.9063033130757785 
    prediction=0.0 real=0.0 ponderate=-2.9063033130757785 
    
    input=[1. 0. 1. 0.] index=2
    prediction=0.0 real=0.0 ponderate=-2.8484231200010313 
    prediction=0.0 real=0.0 ponderate=-2.8484231200010313 
    
    input=[1. 0. 1. 1.] index=3
    prediction=0.0 real=0.0 ponderate=-2.3035399370041345 
    prediction=0.0 real=0.0 ponderate=-2.3035399370041345 
    
    input=[1. 1. 0. 0.] index=4
    prediction=0.0 real=0.0 ponderate=-0.7359971297002557 
    prediction=0.0 real=0.0 ponderate=-0.7359971297002557 
    
    input=[1. 1. 0. 1.] index=5
    prediction=0.0 real=0.0 ponderate=-0.1911139467033589 
    prediction=0.0 real=0.0 ponderate=-0.1911139467033589 
    
    input=[1. 1. 1. 0.] index=6
    prediction=0.0 real=0.0 ponderate=-0.13323375362861167 
    prediction=0.0 real=0.0 ponderate=-0.13323375362861167 
    
    input=[1. 1. 1. 1.] index=7
    prediction=1.0 real=1.0 ponderate=0.4116494293682851 
    prediction=1.0 real=1.0 ponderate=0.4116494293682851 
    
    input=[1. 0. 0. 0.] index=0
    prediction=0.0 real=0.0 ponderate=-3.4511864960726752 
    prediction=0.0 real=0.0 ponderate=-3.4511864960726752 
    
    input=[1. 0. 0. 1.] index=1
    prediction=0.0 real=0.0 ponderate=-2.9063033130757785 
    prediction=0.0 real=0.0 ponderate=-2.9063033130757785 
    
    input=[1. 0. 1. 0.] index=2
    prediction=0.0 real=0.0 ponderate=-2.8484231200010313 
    prediction=0.0 real=0.0 ponderate=-2.8484231200010313 
    
    input=[1. 0. 1. 1.] index=3
    prediction=0.0 real=0.0 ponderate=-2.3035399370041345 
    prediction=0.0 real=0.0 ponderate=-2.3035399370041345 
    
    input=[1. 1. 0. 0.] index=4
    prediction=0.0 real=0.0 ponderate=-0.7359971297002557 
    prediction=0.0 real=0.0 ponderate=-0.7359971297002557 
    
    input=[1. 1. 0. 1.] index=5
    prediction=0.0 real=0.0 ponderate=-0.1911139467033589 
    prediction=0.0 real=0.0 ponderate=-0.1911139467033589 
    
    input=[1. 1. 1. 0.] index=6
    prediction=0.0 real=0.0 ponderate=-0.13323375362861167 
    prediction=0.0 real=0.0 ponderate=-0.13323375362861167 
    
    input=[1. 1. 1. 1.] index=7
    prediction=1.0 real=1.0 ponderate=0.4116494293682851 
    prediction=1.0 real=1.0 ponderate=0.4116494293682851 
    



    interactive(children=(Button(description='Run Interact', style=ButtonStyle()), Output()), _dom_classes=('widge…


### MÍNIMOS CUADRADOS

La meta es encontrar los pesos $w$ que mejor mapean los datos de entrada en los datos objetivo. Con ese fin, se plantea la ecuación de error:

\begin{equation}
    E(w) = \frac{1}{2} \| \bar{y} − \bar{t} \|^2
\end{equation}

Con $\bar{t}$ el vector de datos objetivo, $\bar{y}$ el vector de salidas asociadas $ y(x) = X^Tw $

A partir de la ecuación anterior obtenemos:

\begin{equation}
E(w) = \frac{1}{2}(\bar{y}-\bar{t})^T(\bar{y}-\bar{t})
\end{equation}

Derivando respecto a $w$

\begin{equation}
\frac{dE(w)}{dw} = \phi(\bar{y}-\bar{t})
\end{equation}

con $\phi= [x^1  \cdots x^N] \text{ y }x^i$ el i−ésimo vector de datos de entrada a la red. $N$ el número de datos/registros de entrenamiento.

De lo anterior tenemos:

\begin{equation}
w = (\phi \phi^T)^{-1}\phi \bar{t}
\end{equation}



### ENTRENAMIENTO Y PRUEBA

Hay dos fases en el modelado con redes neuronales:
* **Fase de entrenamiento:** Se utiliza un conjunto de datos o patrones de entrenamiento
para determinar los pesos que definen el modelo. Se calculan de manera iterativa con el objeto de minimizar el error cometido entre la salida obtenida por la red neuronal y la salida deseada.

* **Fase de prueba:** Se utiliza para estimar el error de generalización del modelo.



1. Dado el conjunto de datos datos.txt anexo, entrena un perceptrón con el 70% de los datos (elegidos aleatoriamente). El otro 30% será el conjunto de prueba.

2. Para el mismo conjunto de entrenamiento, calcula los pesos $w$ con el método de mínimos cuadrados.

2. Grafica y compara los resultados de $w$ obtenidos del entrenamiento del perceptrón y el de mínimos cuadrados. La salida dece ser similar a la figura siguiente:


3. Utiliza el conjunto de prueba para obtener la exactitud de los modelos.

OBS:  El archivo datos.txt contiene 3 columnas separadas por comas, las dos primeras columnas son el valor del conjunto $X = \{x_1, x_2\}$; la tercer columna son los datos objetivo $\bar{t}$


El criterio de parada tómalo como un número fijo de iteraciones o hasta que el conjunto esté  totalmente clasificado y fija la tasa de aprendizaje a una constante.



```python
# Split data
data = np.loadtxt(open("data.csv", "rb"), delimiter=",").astype(np.float64)
np.random.shuffle(data)
number_of_points = len(data)
split_index = int(0.7 * number_of_points)

training, test = data[ : split_index], data[split_index : ]

training_input, training_output = training[:, [0, 1]], training[:, 2]
test_input, test_output = test[:, [0, 1]], test[:, 2]

bias = np.ones((len(training_input), 1))
training_input = np.concatenate( (bias, training_input), axis=1)

bias = np.ones((len(test_input), 1))
test_input = np.concatenate( (bias, test_input), axis=1)

training_pure_data = training_input[:, 1:].T
test_pure_data = test_input[:, 1:].T
```


```python
num_inputs = 3
perceptron2 = Perceptron(num_inputs)

for i in range(20):
    perceptron2.train_epoch(training_input, training_output, 0.08, False)
```


```python
b, w1, w2 = perceptron2.weights
x = -b / w1
y = -b / w2

d = y
c = -y / x

line_x_coords = np.array([-1, x])
line_y_coords = c * line_x_coords + d

plt.plot(line_x_coords, line_y_coords)
plt.scatter(*test_pure_data, c=test_output)

plt.show()
```


```python
# 𝑤=(𝜙𝜙𝑇)−1𝜙𝑡¯
phi = np.matrix(test_pure_data)
t = np.matrix(test_output)
y, b = (phi * phi.T)**-1 * phi * t.T
```


```python
line_x_coords = np.array([-1, 4])
line_y_coords = y * line_x_coords + b

plt.plot(line_x_coords, line_y_coords)

plt.show()
```

06094fbd8f4ecb3232604c653c5cbbb4428420d2
ipynb
Jupyter Notebook
Basics_with_Pytorch/Perceptron/.ipynb_checkpoints/Simple Perceptron-checkpoint.ipynb
SoyOscarRH/LearningNeuralNetworks
dd5be94b38b3a0efb3428f76d3416227a92c8265
MIT
2020-01-20T19:56:35.000Z
2021-09-24T14:47:33.000Z
Basics_with_Pytorch/Perceptron/.ipynb_checkpoints/Simple Perceptron-checkpoint.ipynb
SoyOscarRH/LearningNeuralNetworks
dd5be94b38b3a0efb3428f76d3416227a92c8265
MIT
Basics_with_Pytorch/Perceptron/.ipynb_checkpoints/Simple Perceptron-checkpoint.ipynb
SoyOscarRH/LearningNeuralNetworks
dd5be94b38b3a0efb3428f76d3416227a92c8265
MIT
Qwen/Qwen-72B
1. YES
2. YES