# 簡介

Rosenblatt 於 1958 年提出第一個神經網路模型，稱為感知器，這個模型是基於 1943 年 McCulloch 與 Pitts 所提出的神經元模型，該模型的數學公式如下。

(1)
\begin{align} Y = sign \biggl[ \sum_{i=1}^n x_i w_i - \theta \biggr] \end{align}

# 感知器的訓練方式

1. 初始化

(2)
\begin{align} Y(p) = step \biggl[ \sum_{i=1}^n x_i(p) w_i(p) - \theta \biggr] \end{align}

3. 權重訓練

(3)
\begin{align} w_i(p+1) = w_i(p) + \Delta w_i(p) \end{align}
(4)
\begin{align} \Delta w_i(p) = \alpha * x_i(p) * e(p) \end{align}
(5)
$$e(p) = Y_d(p)-Y(p)$$

4. 一代一代增加 p, 重複 2-3 步驟。

# 感知器實作

using System;

class Perceptron
{
double[] x, w;
double theta = 0.5, alpha = 0.01;

public static double[,] andTable = { { 0, 0, 0 }, { 0, 1, 0 }, { 1, 0, 0 }, { 1, 1, 1 } };
public static double[,] orTable = { { 0, 0, 0 }, { 0, 1, 1 }, { 1, 0, 1 }, { 1, 1, 1 } };
public static double[,] xorTable = { { 0, 0, 0 }, { 0, 1, 1 }, { 1, 0, 1 }, { 1, 1, 0 } };

static void Main(string[] args)
{
learn("and", andTable);
learn("or",  orTable);
//        learn("xor", xorTable);
}

public Perceptron()
{
x = new double[2];
w = new double[2];
}

bool training(double[,] truthTable)
{
for (int loop=0; loop<100; loop++)
{
double eSum = 0.0;
Console.WriteLine("============== loop : {0} ================", loop);
for (int i = 0; i < truthTable.GetLength(0); i++)
{
double[] x = { truthTable[i, 0], truthTable[i, 1] };
double yd = truthTable[i, 2];
double y = step(x, w, theta);
double e = yd - y;
eSum += e;
double[] dw = new double[2];
dw[0] = alpha * x[0] * e;     w[0] += dw[0];
dw[1] = alpha * x[1] * e;     w[1] += dw[1];
Console.WriteLine("x=({0:F0},{1:F0}) w=({2:F4},{3:F4}) y={4:F4} yd={5:F0} e={6:F4}",
x[0],  x[1],      w[0],  w[1],     y,        yd,      e);
}
if (eSum == 0.0) return true;
}
return false;
}

static double step(double[] x, double[] w, double theta) {
double result = w[0] * x[0] + w[1] * x[1] - theta;
if (result >= 0)
return 1;
else
return 0;
}

public static double[] learn(string tableName, double[,] truthTable)
{
Console.WriteLine("================== 學習 {0} 函數 ====================", tableName);
Perceptron p = new Perceptron();
if (p.training(truthTable))
Console.WriteLine("學習成功 !");
else
Console.WriteLine("學習失敗 !");
return p.w;
}
}