# Perceptron

## Perceptron

![perceptron.jpg](https://cdn.hashnode.com/res/hashnode/image/upload/v1664743210219/1HZyqi8db.jpg align="left")

***Perceptron***, the foundation algorithm for deep learning, came up by  Frank Rosenblatt in 1957. Perceptrons receive multiple signals and output one signal, the signal is only two values, which are  0 or 1. Perceptron has weight, the signal is important relation to the dependence of weight.

<center><img src="https://latex.codecogs.com/svg.image?y&space;=&space;\left\{\begin{matrix}0\;&space;\:&space;(b&space;&plus;&space;w_{1}x_{2}&plus;&space;w_{2}x_{2}\leq&space;0)&space;\\1\;&space;\:&space;(b&space;&plus;&space;w_{1}x_{2}&plus;&space;w_{2}x_{2}&space;>&space;0)&space;\end{matrix}\right." title="https://latex.codecogs.com/svg.image?y = \left\{\begin{matrix}0\; \: (b + w_{1}x_{2}+ w_{2}x_{2}\leq 0) \\1\; \: (b + w_{1}x_{2}+ w_{2}x_{2} > 0) \end{matrix}\right." /></center>

In the example above, ***w_1*** and ***w_2*** are called **weight**, and ***b*** is called **bias**. By manipulating the weight and bias, people can control output. 

## Simple Example of Perceptron
### 1. AND Gate

***AND gate *** only outputs 1 when both inputs are 1.
<table>
<tr><th>x_1 (input 1)</th><th>x_1 (input 2)</th><th>y (output)</th></tr>
<tr><td>0</td><td>0</td><td>0</td></tr>
<tr><td>1</td><td>0</td><td>0</td></tr>
<tr><td>0</td><td>1</td><td>0</td></tr>
<tr><td>1</td><td>1</td><td>1</td></tr>
</table>


```python
def AND(x1, x2):
  x = np.array([x1, x2])
  w = np.array([0.5, 0.5])
  b = -0.7 # b is bias
  return 0 if np.sum(w*x) + b <= 0 else 1

print(AND(1, 1)) # 1
print(AND(1, 0)) # 0
print(AND(0, 1)) # 0
print(AND(0, 0)) # 0
```

 ### 2. OR Gate
***OR gate *** outputs 1 when either input or both outputs are 1.
<table>
<tr><th>x_1 (input 1)</th><th>x_1 (input 2)</th><th>y (output)</th></tr>
<tr><td>0</td><td>0</td><td>0</td></tr>
<tr><td>1</td><td>0</td><td>1</td></tr>
<tr><td>0</td><td>1</td><td>1</td></tr>
<tr><td>1</td><td>1</td><td>1</td></tr>
</table>

```python
def OR(x1, x2):
  x = np.array([x1, x2])
  w = np.array([0.5, 0.5])
  b = -0.2
  return 0 if np.sum(w*x) + b <= 0 else 1

print(OR(1, 1)) # 1
print(OR(1, 0)) # 1
print(OR(0, 1)) # 1
print(OR(0, 0)) # 0

```

### 3. NAND Gate
***NAND gate*** does not output 1 when both of the inputs are 1. 

<table>
<tr><th>x_1 (input 1)</th><th>x_1 (input 2)</th><th>y (output)</th></tr>
<tr><td>0</td><td>0</td><td>1</td></tr>
<tr><td>1</td><td>0</td><td>1</td></tr>
<tr><td>0</td><td>1</td><td>1</td></tr>
<tr><td>1</td><td>1</td><td>0</td></tr>
</table>

```python
def NAND(x1, x2):
  x = np.array([x1, x2])
  w = np.array([-0.5, -0.5])
  b = 0.7
  return 0 if np.sum(w*x) + b <= 0 else 1

print(NAND(1, 1)) # 0
print(NAND(1, 0)) # 1
print(NAND(0, 1)) # 1
print(NAND(0, 0)) # 1
```

### 4. XOR gate

***XOR gate*** outputs 1 only when either input is 1. Unlike AND, OR, and NAND gates, the XOR gate is not linear. Thus, it is impossible to code the XOR gate only using NumPy matrix. By using NAND, AND, and OR gates, the XOR gate can be implemented. Also, using multiple perceptrons to create the other perceptron is called ***multi-layered perceptron***.

<table>
<tr><th>x_1 (input 1)</th><th>x_1 (input 2)</th><th>y (output)</th></tr>
<tr><td>0</td><td>0</td><td>0</td></tr>
<tr><td>1</td><td>0</td><td>1</td></tr>
<tr><td>0</td><td>1</td><td>1</td></tr>
<tr><td>1</td><td>1</td><td>0</td></tr>
</table>


```python
def XOR(x1, x2):
  s1 = NAND(x1, x2)
  s2 = OR(x1, x2)
  return AND(s1, s2)

print(XOR(1, 1)) # 0
print(XOR(1, 0)) # 1
print(XOR(0, 1)) # 1
print(XOR(0, 0)) # 0
```
