- 关于算法的引入:插件式架构设计,可移植性强,利于算法的升级。
【插件式开发相关资料】https://www.cnblogs.com/lenic/p/4129096.html
- 以BP算法为例:
1、首先定义一个接口规范
/// <summary>
/// //插件的统一入口
/// </summary>
public interface IPluginPerfrom
{
/// <summary>
/// 统一算法插件入口
/// </summary>
/// <param name="argsOutNumber">输出参数的个数</param>
/// <param name="argsOut">输出参数</param>
/// <param name="argsIn">输入参数</param>
/// <returns></returns>
string ExcuteAlgorithmPlug(int argsOutNumber, ref string[,] argsOut, string[,] argsIn, string DBConnectionString = null);
}
2、BP算法实现接口
// AForge Framework
// Approximation using Mutli-Layer Neural Network
//
// Copyright ?Andrew Kirillov, 2006
// andrew.kirillov@gmail.com
//
using System;
using System.Drawing;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Windows.Forms;
using AForge;
using AForge.Neuro;
using AForge.Neuro.Learning;
using AForge.Controls;
using IPlugin;
using Newtonsoft.Json;
using System.Linq;
using System.Text;
namespace BP
{
/// <summary>
/// Summary description for Form1.
/// </summary>
public class BP : IPluginPerfrom
{
//Chart chart = new Chart();
//实现统一接口
public string ExcuteAlgorithmPlug(int argsOutNumber, ref string[,] argsOut, string[,] argsIn, string DBConnectionString = null)
{
List<ResPreTemp> resLists = new List<ResPreTemp>();
string dataStr = argsIn[0, 0]; //Json格式的数据
List<dht11> dht11Lists = dataStr.ToList<dht11>();
double[,] arr = new double[dht11Lists.Count+1, 2];
for (int i = 0; i <dht11Lists.Count; i++)
{
TimeSpan t3 = dht11Lists[i].create_time - dht11Lists[0].create_time; // double getMillisecond = t3.TotalMilliseconds; 将这个天数转换成毫秒, 返回值是double类型的
double dobleTime = t3.TotalSeconds;
arr[i, 0] = dobleTime;
arr[i, 1] = dht11Lists[i].temperature;
}
int outPutLength = 0;
double[,] res = null;
try
{
res = SearchSolution(arr);
ResPreTemp resTemp = new ResPreTemp(dht11Lists[0].create_time, res[0, 1]);
resLists.Add(resTemp);
for (int i = 0; i <dht11Lists.Count; i++)
{
DateTime dataTimeX = dht11Lists[i].create_time.AddSeconds(res[i+1,0]);
ResPreTemp resTemp1 = new ResPreTemp(dataTimeX, res[i + 1, 1]);
resLists.Add(resTemp1);
}
}
catch (Exception e)
{
throw e;
}
return Json.ToJson(resLists);
}
//返回的结果类
public class ResPreTemp
{
public DateTime create_time;
public double temperature;
public ResPreTemp(DateTime create_time, double temperature)
{
this.create_time = create_time;
this.temperature = temperature;
}
}
//private double learningRate = Convert.ToDouble( Config.learningRate);
//private double momentum = Convert.ToDouble(Config.momentum);
//private double sigmoidAlphaValue = Convert.ToDouble(Config.sigmoidAlphaValue);
//private int neuronsInFirstLayer = Convert.ToInt32(Config.neuronsInFirstLayer);
//private int iterations = 1000;
private double learningRate =0.1;
private double momentum = 0.0;
private double sigmoidAlphaValue =2.0;
private int neuronsInFirstLayer = 20;
private int iterations = 1000;
//private Thread workerThread = null;
private bool needToStop = false;
#region
/// <summary>
/// 开始预测
/// </summary>
/// <param name="learningRateRow">学习速率</param>
/// <param name="momentumRow"></param>
/// <param name="alphaRaw">alpha值</param>
/// <param name="neuronsRow">神经元的个数</param>
/// <param name="iterationsRow">迭代次数</param>
/// <returns></returns>
private void startApproximation(string learningRateRow, string momentumRow, string alphaRaw, string neuronsRow, string iterationsRow)
{
// get learning rate
#region 神经网络参数
try
{
learningRate = Math.Max(0.00001, Math.Min(1, double.Parse(learningRateRow)));
}
catch
{
learningRate = 0.1;
}
// get momentum
try
{
momentum = Math.Max(0, Math.Min(0.5, double.Parse(momentumRow)));
}
catch
{
momentum = 0;
}
// get sigmoid's alpha value
try
{
sigmoidAlphaValue = Math.Max(0.001, Math.Min(50, double.Parse(alphaRaw)));
}
catch
{
sigmoidAlphaValue = 2;
}
// get neurons count in first layer
try
{
neuronsInFirstLayer = Math.Max(5, Math.Min(50, int.Parse(neuronsRow)));
}
catch
{
neuronsInFirstLayer = 20;
}
// iterations
try
{
iterations = Math.Max(0, int.Parse(iterationsRow));
}
catch
{
iterations = 1000;
}
#endregion
needToStop = false;
//double[,] solution = SearchSolution();
// return data;
}
#endregion
public double[,] SearchSolution(double[,] data)
{
// number of learning samples
int samples = data.GetLength(0);
// data transformation factor
double maxX = Caculate.getMax(data,0);
double minX = Caculate.getMin(data, 0);
double LengthX = maxX - minX;
double maxY = Caculate.getMax(data, 1);
double minY = Caculate.getMin(data, 1);
double LengthY = maxY - minY;
double yFactor = 1.7 / LengthY; //ymax-ymin
double yMin = minY;
double xFactor = 2.0 / LengthX;
double xMin = minX;
// prepare learning data
double[][] input = new double[samples][];
double[][] output = new double[samples][];
for (int i = 0; i < samples; i++)
{
input[i] = new double[1];
output[i] = new double[1];
// set input
input[i][0] = (data[i, 0] - xMin) * xFactor - 1.0;
// set output
output[i][0] = (data[i, 1] - yMin) * yFactor - 0.85;
}
// create multi-layer neural network
ActivationNetwork network = new ActivationNetwork(
new BipolarSigmoidFunction(sigmoidAlphaValue),
1, neuronsInFirstLayer, 1);
// create teacher
BackPropagationLearning teacher = new BackPropagationLearning(network);
// set learning rate and momentum
teacher.LearningRate = learningRate;
teacher.Momentum = momentum;
// iterations
int iteration = 1;
// solution array
double[,] solution = new double[data.GetLength(0)+1, 2];
double[] networkInput = new double[1];
// calculate X values to be used with solution function
for (int j = 0; j < data.GetLength(0) + 1; j++)
{
solution[j, 0] = minX + (double)j * LengthY / data.GetLength(0) + 1;
}
// loop
while (!needToStop)
{
// run epoch of learning procedure:学习过程的运行过程
double error = teacher.RunEpoch(input, output) / samples;
// calculate solution:预测
for (int j = 0; j < data.GetLength(0) + 1; j++)
{
networkInput[0] = (solution[j, 0] - xMin) * xFactor - 1.0;
solution[j, 1] = (network.Compute(networkInput)[0] + 0.85) / yFactor + yMin;
}
// calculate error
double learningError = 0.0;
for (int j = 0, k = data.GetLength(0); j < k; j++)
{
networkInput[0] = input[j][0];
learningError += Math.Abs(data[j, 1] - ((network.Compute(networkInput)[0] + 0.85) / yFactor + yMin));
}
// increase current iteration
iteration++;
// check if we need to stop
if ((iterations != 0) && (iteration > iterations))
break;
}
return solution;
}
}
}
注:以上的BP算法为BP算法的函数逼近,下一步是需要将BP的学习训练网络与预测过程分离,即实时进行学习训练,按任务的指定进行预测。
【BP通过反向传递误差来调整网络参数】
BP函数逼近算法通过最速下降法,通过反向传播不断调整网络的权值和阈值,不断地降低网络的误差,使得误差平方和最小。
BP神经网络模型包括输入层、隐含层和输出层。 输入层各神经网络负责接收来自外界的输入信息,并传递给中间层各神经元;中间层是内部信息处理层,负责信息变换,根据信息变化能力的需求。最后中间层可将信息传递到输出层。输出层输出期望值,经过一次迭代后,发现输出值与预期值的误差太大,则再次进入误差的反向传播过程。重复以上过程,调整各层的权值,知道BP网络的输出值的误差在可接受的范围内,则停止训练。网络学习过程结束。
【BP算法的具体步骤】
1、前馈计算
设置隐层的j个节点的输入和输出 I = f(Wij),O=f(Ij),其中f(Ij)为激励函数。
2、权值调整
设置误差函数Ep
调整输出层的权值
调整隐层的权值