<jupyter_start><jupyter_text>Primero importamos las librerías que vayamos a necesitar<jupyter_code>import matplotlib.pyplot as plt
import numpy as np
from sklearn.metrics import accuracy_score<jupyter_output><empty_output><jupyter_text>Vamos a crear una clase Perceptron, que incluirá las variables que necesitaremos para hacer funcionar nuestro perceptronFijamos el bias a 1, como es común para una neurona, y inicializamos dos variables vacias para los pesos y los errores. También definimos el ratio de entrenamiento (lr) y el número de iteraciones (epochs).***Funciones de la clase Perceptron:*****__linear:** función encargada de realizar el cálculo y=w_0+w_1+⋯+w_n La función np.dot multiplica dos vectores elemento a elemento, que es lo que necesitamos.**__activation_step:** función de activación. np.where nos devolverá el valor 1 cuando la entrada sea >0 y y el valor 0 en el resto de los casos**fit:** Para cada una de las entradas, calculamos y_hat, que será la label estimada pos la red, y la comparamos con y_target (las labels del dataset de entrenamiento).**predict:** función de predicción, que nos valdrá para hacer inferencia con nuevos datos una vez calculados los pesos<jupyter_code>class Perceptron(object):
    def __init__(self, lr=0.01, epochs=2000):
        self.lr = lr
        self.bias = 1
        self.epochs = epochs
        self.weights = None
        self.errors_ = []
    
    def __linear(self, X):
        return np.dot(X, self.weights[1:]) + self.weights[0]
    
    def __activation_step(self, Y):
        return np.where(Y>=0, 1, 0)

    def fit(self, X, y):
        
        assert len(X) == len(y), "X e Y deben tener la misma longitud"
        
        # Inicializa los pesos a 0, menos el peso del bias 
        # que se inicializa a 1 (self.bias)
        weights = np.zeros(X.shape[1])
        self.weights = np.insert(weights, 0, self.bias, axis=0)

        for _ in range(self.epochs):
            errors = 0
            for xi, y_target in zip(X, y):
                z = self.__linear(xi)  # Suma ponderada
                y_hat = self.__activation_step(z)  # Función de activación
                # Calculamos la diferencia entre entrada y salida, 
                # y aplicamos el learning rate
                delta = self.lr * (y_target - y_hat)  
        
                # Utilizmaos el parámetro delta calculado 
                # para actualizar los pesos
                self.weights[1:] += delta * xi
                self.weights[0] += delta
                
                errors += int(delta != 0.0)

            self.errors_.append(errors)
            #Interrumpimos el entrenamiento si el error es 0          
            if not errors:
                break

    def predict(self, X):
        assert type(self.weights) != 'NoneType', "Entrena el modelo primero."
        y_hat = np.zeros(X.shape[0],)
        for i, xi in enumerate(X):
            y_hat[i] = self.__activation_step(self.__linear(xi))
        return y_hat

    def score(sef, predictions, labels):
        return accuracy_score(labels, predictions)

    def plot(self, predictions, labels):
        assert type(self.weights) != 'NoneType',  "Entrena el modelo primero."
        plt.figure(figsize=(10,8))
        plt.grid(True)

        for input, target in zip(predictions, labels):
            plt.plot(input[0],input[1],'ro' if (target == 1.0) else 'go')

        for i in np.linspace(np.amin(predictions[:,:1]),np.amax(predictions[:,:1])):
            slope = -(self.weights[0]/self.weights[2])/(self.weights[0]/self.weights[1])  
            intercept = -self.weights[0]/self.weights[2]

            # y = mx+b, equation of a line. mx = slope, n = intercept
            y = (slope*i) + intercept
            plt.plot(i, y, color='black', marker='x', linestyle='dashed')<jupyter_output><empty_output><jupyter_text>Ahora que tenemos todo lo necesario para nuestro perceptron, vamos a veri si efectivamente podemos hacer que funcione. Para ello utilizamos la librería make_blobs de sklearn que nos permite generar nubes de puntos para utilizarlas como ejemplos de entrenamiento<jupyter_code>from sklearn.model_selection import train_test_split
from sklearn.datasets import make_blobs

# Generamos 2 clusters de puntos, con 2 features cada 1
X, y = make_blobs(n_samples=1000, n_features=2, centers=2, cluster_std=1.05, random_state=3)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.20, stratify=y)

# Inicializamos nuestro perceptron
p = Perceptron()

# Ajustamos ahora nuestro perceptron con los datos generados por make_blobs
p.fit(X_train,y_train)
p.plot((X_test), y_test)
p.score(p.predict(X_test), y_test)<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.09631365864052845, 'fraction_numerical': 0.013211165565736203, 'mean_word_length': 2.898671096345515, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 15, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '3', 'dir': 'jupyter-structured-clean-dedup', 'id': '131223', 'license': 'MIT', 'n_tokens_mistral': 1561, 'n_tokens_neox': 1497, 'n_words': 464, 'path': 'Perceptron.ipynb', 'repo_name': 'jpabloglez/Master_IA_Sanidad', 'size': '4693'}