【PHP FANN】听说PHP也可以处理神经网络,所以我尝试了一下
在PHP的模块中,有一个名为FANN(Fast Artificial Neural Network)的模块。在数据分析领域,首先会考虑使用R来完成,但是我尝试使用FANN进行简单的基于Web的机器学习。由于我还在边阅读文档边尝试的过程中,所以会随时更新。
FANN是什么
快速人工神经网络库(FANN)是一个由C语言编写的开源神经网络库,它不仅仅是专门为PHP设计的模块。
-
- 誤差逆伝播法(BackProp)による学習を主にサポート
-
- 動作がかなり高速
-
- 最短3ステップで簡単に機械学習(リソース作成、学習、実行)
- 英語ドキュメントは豊富である
以下有许多选项。
尽管日本语页面非常稀少,但以下页面提供的概述可供参考:FANN – 日本大学。
PHP中的FANN
有一個可以從PHP中操作上述FANN庫的選項。
雖然開頭的鏈接是官方文件,但沒有翻譯且幾乎沒有範例,而且在功能上也不一定全部可用。
幾乎沒有用日文撰寫的先例,但我認為這個很有趣。
嘗試使用PHP FANN(快速人工神經網絡)來賺錢。
安装
保持默认设置无法使用。首先需要安装FANN官方的库。
Redhat系列:$ sudo yum install fann-devel
Ubuntu系列:$ sudo apt-get install libfann-dev
Mac OS:$ brew install homebrew/science/fann
关于Windows和brew等内容省略。
接下来在PECL中安装FANN。
(这就相当于是一个封装器吗?)
$ sudo pecl安装fann
包裹细节请点击此处
PECL :: 包裹 :: fann – PHP
在使用之前,先了解人工神经网络(ANN)的基本笔记。
由于在网络上有大量关于人工神经网络(Artificial Neural Network,缩写为ANN)的知识,以下将仅提供链接和简要的笔记。
大意
ANN是一种被称为机器学习的数据分析方法,它是基于大脑神经细胞之间网络的数学模型。
参考:神经网络(NN)
简单来说,ANN是所谓的“函数”,通过将数据集输入到这个“函数”中可以得到解答。
基本的流程分为两步,即学习和执行。
“学习”是利用现有数据进行“函数的(自动)设计”,
“执行”是将实际数据输入到该函数中并得到解输出。
学习
脑细胞之间的连接方式并非一开始就被设计好了,而是随着外部环境(即输入)的不同而不断变化和优化。人工神经网络也如此,网络的设计是根据给定的输入和答案来逐渐优化构建的。
参考:有监督学习 | 东京大学全球消费智能捐赠讲座
根据答案自动调整网络的过程被称为“有监督学习”,而“误差反向传播法(反向传播法)”则是其中一种调整方法的知名方式。
大致上来说,
-
- 首先,随机创建一个网络(严格来说是随机设置图的权重)。
-
- 为实际需要进行学习的事件准备输入和输出的数据集。
-
- 将数据集的输入输入,获得一个临时的解的估计值。
- 将该解与数据集的输出(实际解)进行比较,计算误差,并调整网络使误差变小。
在阶段4中,根据离输出最近的网络连接进行反向调整,从输出向输入方向进行调整,这个过程被称为”误差反向传播”。
执行
输入实际数据并获得解答。
多维非线性函数具有对噪声具有抵抗力的特点。
问题所在
使用误差逆传播算法的人工神经网络存在问题。
局部最小值
当进行学习时,一般来说,误差会不断减少。
然而,由于误差逆传播法旨在设计误差逐渐减小的特性,在局部位置上误差可能会变得更大,从而导致进一步的学习变得不可能。
放弃对准确性的追求——再谈“软件信息处理”(3):ITpro
【Think IT】第2部分:了解神经网络的结构!(3/3)
過度學習 (guò dù
通过大量的学习,可以在已知模式的问题上以高精度求解。然而,一旦输入稍有不同,系统就会完全错位解答。这种现象被称为过度学习,而这样的系统对输入的噪音很敏感,且缺乏灵活性。年纪大的人常被认为思维固化,这与此相似。误差逆传播法的问题(原文链接:https://www.mi.t.u-tokyo.ac.jp/labshine/murakami-lab/member/senior/understanding-neural-network/back-propagation-error.html)
简单函数的用法
好了好了,终于来用PHP了。
基本上,我正在参考开头介绍的这篇文章。我感谢前人的指导。
让我们试着使用PHP FANN(快速人工神经网络)来赚钱。
创建资源
有一些函数可供选择,但是我们将以数组为例创建ANN的基本资源。
$layers = [3, 5, 1];
$ann = fann_create_standard_array(count($layers), $layers);
$layers是一个数组,其中输入层有3个节点,中间层有5个节点,输出层有1个节点,表示了一个ANN。
如果使用它作为参数来执行fann_create_standard_array函数,将返回FANN资源$ann。
在资源创建后,自动会在输入层和每个中间层中添加一个偏置神经元,因此在这个例子中,输入层将会有4个节点,中间层将会有6个节点。
资源配置
下面是设置相关信息,由于默认情况下已经设置了一些适当的值,所以即使几乎不去调整也能够使用。
fann_set_activation_function_hidden($ann, FANN_ELLIOT_SYMMETRIC);
fann_set_activation_function_output($ann, FANN_ELLIOT_SYMMETRIC);
然而,由于激活函数对学习有很大影响,所以可能需要进行调整。
这是上述指令中,通过将资源作为第一个参数,并指定类型作为第二个参数来设置的。
主要可以在第二个参数中指定以下选项:
FANN_LINEAR:表示为y=x的直线一次函数
FANN_THRESHOLD:当x大于等于0时,y=0;当x小于0时,y=1,也被称为阶跃函数
FANN_SIGMOID:输出为0到1的S型函数,经常使用
FANN_SIGMOID_SYMMETRIC:输出为-1到1的S型函数,也称为双曲正切函数
FANN_ELLIOT:输出为0到1的快速收敛的函数,比S型函数更快
FANN_ELLIOT_SYMMETRIC:将上述Elliott函数的输出调整为-1到1
FANN_SIN:输出为-1到1的常规正弦函数
FANN_SIN_SYMMETRIC:经过压缩,输出范围为0到1的正弦函数
这些激活函数的详细公式以及其他公式可以在这里找到。
这附近似乎还有很多未被触及到的地方。
数据学习
$data = array(
["input" => [101.81, 102.11], "output" => [1]],
["input" => [101.55, 101.92], "output" => [0]],
["input" => [100.98, 101.03], "output" => [1]],
...
..
);
$data = .. // 正規化処理
fann_reset_MSE($ann);
foreach($data as $learn){
fann_train($ann, $learn["input"], $learn["input"]);
}
$mse = fann_get_MSE($this->ann);
预先创建学习的数据数组。
需要注意的是数据的数值范围,基本上输入应在0~1的范围内(某些激活函数可为-1~1)。
理想情况下,教师数据(输出)应该是离散值0和1(某些函数可为-1, 0, 1)。(需要出处)
在这个例子中,我们输入了美元兑日元的数值,但是需要将1美元100日元至120日元的范围缩放为-1~1的范围,进行”正规化”。
如何在神经网络中进行数据正规化?- 科学 | 【OKWAVE】
之后,将数据反复输入到fann_train中。
在完成后,获取MSE(均方误差:二次误差)并确认学习的程度。
进行考试
$test = [100.08, 100.57];
// $test も正規化する必要がある
$result = fann_run($ann, $test);
如果您提供了与您输入的学习元素数量相同的测试数据,结果将以数组的形式返回。
由于结果也经过了规范化,因此需要将其转换回实际值(这里省略了,请见谅)。
我尝试创建了一个rapper类。
由于ANN具有状态转换,因此以过程型命令为基础的命令难以使用…
因此,我仅封装了最基本的命令,并创建了一个包含简单统计处理的类。
我还提供了示例。
GitHub | ukkz/php-fannWrapper
以下是基本的方法。
// ANN層構造指定
$layers = [5, 8, 3];
// 正規化の範囲指定
$range = array("max" => 1.0, "min" => -1.0);
// リソース作成
$ann = new fannWrapper($layers);
// データセットを用意して統計情報を得ておく
$data_raw = [ ... ];
$stats = fannWrapper::stats($data_raw);
// データの正規化
$data = fannWrapper::scaling($data_raw, $range["max"], $range["min"]);
foreach($data as ..){
// 入力と出力を適当に処理して$inputと$outputに
// 学習実行
$ann->train($input, $output);
}
// テストデータを実行し、もとのデータの範囲にスケールする
$test = [ ... ];
$result = fannWrapper::scaling($ann->run($test_n), $stats["max"], $stats["min"], $range["max"], $range["min"]);
// HTML Canvasで視覚的に表示できるようにノードの配置情報等を出力
$canvasX = 800; $canvasY = 450; $padding = 50;
$neuron_position = json_encode($ann->visualize($canvasX, $canvasY, $padding));
$neuron_connection = json_encode($ann->getConnection());
试用一下看能否经得起实际应用
我将使用实际数据来测试。
这次我大致学习了汇率变动。
数据是从这里获取的,是两年的美元对日元的日线数据,我挑选了适当的时间段来使用。
利用人工神经网络(ANN)进行汇率预测已有很多先例。
这些比如非常准确,令人惊讶。
使用计算机预测汇率变动
那么,使用PHP FANN的代码如下所示。
由于使用了自定义的封装函数,可能会稍微有些难以理解,敬请谅解。
<?php
require_once("fannWrapper.php");
// ##############################
// ### 学習範囲
// 0から790日目までで任意の範囲
$start = 250;
$stop = 350;
// ### ニューラルネットワークの層構造の指定
// 入力層は7、出力層は1
$layers = [5, 10, 3, 1];
// ### 正規化の範囲
// 活性化関数に***_SYMMETRICを指定する場合は1から-1でそれ以外は1から0
$range = array("max" => 1.0, "min" => -1.0);
// ### テスト配列
// 直近5日間のドル円レート
$test = [100.29, 101.40, 101.11, 100.97, 101.03];
// ##############################
// FANNラッパークラス
$ann = new fannWrapper($layers);
// データを読み込み
$json = file_get_contents("usdjpy.json");
$data = json_decode($json, true);
// 与えられた範囲を抜き出して数値のみの配列をつくる
$usdjpy = [];
for ($i=$start; $i < $stop; $i++) {
if (!isset($data[$i])) break;
$usdjpy[] = (float)$data[$i]["rate"];
}
// 配列の統計情報を連想配列で返す
$stats = fannWrapper::stats($usdjpy);
// 正規化
$usdjpy = fannWrapper::scaling($usdjpy, $range["max"], $range["min"]);
foreach ($usdjpy as $k => $v) {
if (!isset($usdjpy[$k+5])) break;
// 入力配列
$input = [$usdjpy[$k], $usdjpy[$k+1], $usdjpy[$k+2], $usdjpy[$k+3], $usdjpy[$k+4]];
// 出力配列
$output = [$usdjpy[$k+5]];
// 学習実行
$ann->train($input, $output);
}
// 学習結果を保存(オプション)
$ann->save("usdjpy.net");
// 予測テスト実行
// テストデータは実世界のものなので、教育したデータにあわせて正規化して入力
$test_n = [];
for ($i=0; $i < count($test); $i++) {
$test_n[$i] = fannWrapper::scaling([$test[$i]], $range["max"], $range["min"], $stats["max"], $stats["min"]);
}
$result = fannWrapper::scaling($ann->run($test_n), $stats["max"], $stats["min"], $range["max"], $range["min"]);
// 表示
echo $result[0];
?>
结果
使用学习得到的数据,我将结果通过HTML Canvas和jQuery flotr2转化成图形。
网络图
左侧的粉红色节点表示输入,右侧的红色节点表示输出。
输入了5天的数据,输出了1天的数据。
中间层是黑色节点,绿色和蓝色节点表示偏置。
黑色图形的浓度会根据连接的强度而变化。
汇率波动和平方差变化
黄绿色代表着美元兑日元汇率数据,而水色则表示平方误差的变化趋势。基本上,误差会逐渐减小,但当汇率发生大幅变动时,暂时会导致误差增大。
推定利率和統計
以下是最终的均方误差值和预测汇率的表格。
在这个例子中,预测值大约为101.93日元,但实际值为101.827日元。对于交易员来说,这是一个较大的误差,但可以用来推测汇率可能会比前一天上升。
下表是关于使用的学习数据的统计信息。
我尝试将一般的处理放入自己编写的类中,但结果比我想象的更方便。
总结
-
- PHPだけでも一応は機械学習ができる!
- ローカルでやるだけならやっぱりRとかPythonがいいかとおもいます。