Principios Basicos sobre Deep Learning
Tags: python, machinelearning, datascience, tutorial
Published: 2020-09-11 18:30:34

# Primero: neuronas artificiales
La arquitectura de las redes neuronales biológicas fueron la inspiración para descubrir como construir una maquina inteligente. Esta es la lógica detras de redes neuronales artificiales (artificial neural networks, o ANN en ingles): una RNA es un modelo de aprendizaje automático inspirado por las redes de neuronas biológicas que se encuentran en nuestro cerebro.

## Poder de computo con neuronas
El neurofisiologo Warren McCullcoh y el matemático Walter Pitts propusieron un modelo muy simple de una neurona biológica, que más tarde se comenzó a conocer como una *neurona artificial*: tiene una o más entradas binarias (0-1) y una salida binaria. La neurona artificial activa la salida cuando más de un cierto número de sus entradas esta activa.

## El Perceptron

El *perceptron* es una de las arquitecturas de RNA mas simples, inventada en 1957 por Frank Rosenblatt. Está basada en una neurona artificial levemente diferente llamada *unidad lógica de umbral* (threshold logic unit, o TLU en ingles). Las entradas y salidas son números (en lugar de valores binarios 0-1), y cada conexión de entrada esta asociada a un peso. 

> No podía escribir ecuaciones en LaTeX y por esa razón todas las ecuaciones estarán en formato Gist.

{% gist https://gist.github.com/ruizleandro/3ed0aed320aba796b1ddd412dd690603.js %}

Una sola ULU puede ser usada para una clasificación lineal binaria simple. Computa una combinación lineal de las entradas, y si el resultado excede un determinado límite, la salida es de clase positiva. De otra manera la salida es de clase negativa (al igual que una regresión logística o un clasificador SVM lineal).

Un perceptron esta compuesto basicamente por una sola capa de ULUs, con una ULU conectada a cada entrada. Cuando todas las neuronas en una capa estan conectadas a cada neurona de la capa anterior (por ejemplo, las neuronas de entrada), la capa es llamada una *capa completamente conectada*, o una *capa densa*. Ademas, una caracteristica de sesgo adicional es generalmente añadida (x_0 = 1): tipicamente es representada usando un tipo especial de neurona llamada *neurona de sesgo*, que da como resultado 1 todo el tiempo. Un perceptron con dos entradas y tres salidas puede clasificar instancias simultaneamente en tres clases binarias diferentes, lo que lo convierte en clasificador de multiples salidas.

Esta ecuación hace posible calcular de manera eficiente las salidas de una capa de neuronas artificiales para varios casos a la vez:

{% gist 
https://gist.github.com/ruizleandro/52f27046c6af3a076e40f6d5a87cc1c2.js %}

Asi que, ¿cómo se entrena a un perceptron? Cuando son entrenados toman en cuenta el error producido por la red cuando realiza una predicción; la regla de aprendizaje del perceptron informa conexiones que ayudan a reducir el error. Más especificamente, el perceptron se alimenta una instancia de entrenamiento a la vez, y para cada instancia realiza una predicción. Para cada neurona de salida que produjo una predicción erronea, refuerza los pesos de conexión de las entradas que habrían contribuido a la predicción correcta.

Ecuacion de la regla de aprendizaje de un perceptron (con pesos actualizados):

{% gist https://gist.github.com/ruizleandro/597484dfc6ee9f6f38038e3e6d1c9e7c.js %}

El limite de decisión de cada neurona de salida es lineal, por lo tanto los perceptrones son incapaces de aprender patrones complejos (como un clasificador de regresión logística). De todas maneras, si las instancias de entrenamiento son separables linealmente, Rosenblatt demostró que este algoritmo puede converger a una solución. Esto es llamado el *teorema de convergencia del perceptron*.

Scikit-Learn provee una clase `Perceptron` que implementa una red de un solo ULU:

```python
import numpy as np
from sklearn.datasets import load_iris
from sklearn.linear_model import Perceptron

iris = load_iris()
X = iris.data[:, (2, 3)]
y = (iris.target == 0).astype(np.int)

per_clf = Perceptron()
per_clf.fit(X, y)

y_pred = per_clf.predict([[2, 0.5]])
```

Quizas te hayas dado cuenta que el algoritmo de aprendizaje del perceptron se parece mucho a un descenso de gradiente estocástico (Stochastic Gradient Descent). De hecho, la clase `Perceptron` de Scikit-Learn es equivalente a usar un `SGDClassifier` con los siguientes hiperparámetros: `loss='perceptron'`, `learning_rate='constant'`, `eta=0.1` (la tasa de aprendizaje), y `penalty=None` (sin regularización).

Ten en cuenta que al contrario de los clasificadores de regresión logística, los perceptrones no dan como resultado una probabilidad de clase; en su lugar, hace predicciones basado en un limite duro. Esta es una de las razones para preferir regresión logística sobre un perceptron. 

En su monografía de 1969 *Perceptrons*, Marvin Minsky y Seymour Papert subrayaron un número de serias debilidades en los perceptrones- en particular el hecho de que son incapaces de resolver algunos problemas triviales. Esto es verdad en cualquier otro modelo de clasificación lineal (como los de regresión logística).

Resulta que algunas de las limitaciones de los perceptrones pueden ser eliminadas al apilar multiples perceptrones. La RNA resultante es llamada *Perceptron Multicapa* (MLP).

Hace unas semanas, escribi un [articulo](https://dev.to/ruizleandro/build-a-multilayer-perceptron-with-pyspark-5bkj) (en ingles) sobre como crear un Perceptron multicapa con PySpark. Les dejo el repositorio de GitHub con una introducción al aprendizaje profundo y un Jupyter notebook donde probamos el algoritmo:

![GitHub Button](https://dev-to-uploads.s3.amazonaws.com/i/mynx7l56xj1egcavypzu.png)
<figure>
  <figcaption>[Link a GitHub](https://github.com/ruizleandro/Deep-Learning-PySpark)</figcaption>
</figure>

# Conclusión

Eso es todo por el articulo de hoy, muchas gracias por llegar hasta acá.