PHP实现感知器

什么是感知器

https://en.wikipedia.org/wiki/Perceptron
https://baike.baidu.com/item/感知器/16525448

基础公式

  1. 模型函数: $y = \sum\limits_{i=1}^mw_{i}x_{i} + b$ (w:权重; x:输入; b:偏置值)

  2. 训练规则: $\begin{cases}\ w_{i} = w_{i} + \eta(t-y)x_{i} \\\ b = b + \eta(t-y)\end{cases}$ ($\eta$:学习率; $t$:训练样本希望输出; $y$:感知器实际输出)

实现代码

  1. 感知器类

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    class Perceptron
    {
    /**
    * @var callable 激活函数
    */
    private static $activator = null;

    /**
    * @var double 偏置量
    */
    private static $bias = 0.0;

    /**
    * @var array 权重向量
    */
    private static $weights = [];

    /**
    * 构造函数
    * @param int $featureNums 感知器输入参数个数
    * @param callable 激活函数(double->double)
    */
    public function __construct($featureNums, $activator)
    {
    self::$activator = $activator;
    self::$bias = 0.0;
    self::$weights = array_fill(0, $featureNums, 0.0);
    }

    /**
    * 使用感知器预测结果
    * @param array 输入向量
    */
    public function predict($inputVector)
    {
    $activator = self::$activator;
    $sum = 0.0;
    foreach ($inputVector as $k => $v) {
    $sum += $v * self::$weights[$k];
    }
    $sum += self::$bias;
    return $activator($sum);
    }

    /**
    * 训练感知器
    * @param array 输入向量
    * @param array 输入向量对应的标签
    * @param int 迭代次数
    * @param float 学习率
    */
    public function train($inputVectors, $labels, $iterationNum, $learnRate)
    {
    for ($i = 0; $i < $iterationNum; $i++) {
    foreach ($inputVectors as $k => $vector) {
    $output = $this->predict($vector);
    $delta = $labels[$k] - $output;
    foreach ($vector as $p => $item) {
    self::$weights[$p] += $learnRate * $delta * $item;
    }
    self::$bias += $learnRate * $delta;
    }
    }
    }
    }
  2. 使用感知器类训练and操作

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    $activator = function($x) {
    return $x > 0 ? 1 : 0;
    }; // 定义激活函数
    $perceptron = new Perceptron(2, $activator); // and操作只有两个特征值
    $dataset = [[0, 0], [0, 1], [1, 0], [1, 1]]; // 训练集
    $labels = [0, 0, 0, 1]; // 训练集对应的labels
    $iterationNum = 10; // 迭代次数
    $learnRate = 0.011; // 学习率
    $perceptron->train($dataset, $labels, $iterationNum, $learnRate); // 用样本训练模型
    var_dump($perceptron->predict([0, 0])); // 使用训练好的样本预测数据