本文重点:
- 多项式拟合
- 贪心随机训练
- 径向基函数
- 径向基函数网络模型
多项式系数
所谓多项式,其实就是由变量和常系数组成的数学表达式,其中的运算只有加法、减法、乘法和正整数的幂运算
比如
f
(
x
)
=
2
x
2
+
4
x
+
6
f(x)=2x^2+4x+6
f(x)=2x2+4x+6
接受一个值x,返回一个值y,输入、输出向量的大小均为1,式中三个系数分别为:2,4,6。其中,各系数均乘以变量x的幂项,系数2乘以x的平方,系数4乘以x,系数6则乘以x的0次幂,也就是常数1,表现出来就是一个单纯的常数项。
上述函数的3个系数可作为一个向量并表示如下:
[2,4,6]
一般情况下系数的值需要使用机器学习算法来确定。要达到这个目的,就需要用包含各种预期输出的训练集来对算法进行训练,其中,不同的预期输出对应于各种不同的输入,这样的训练数据可以经由实验收集。要将这些数据拟合为二次多项式,机器学习算法就很有用处。
通过模拟产生一些训练数据。
训练入门
在训练期间调整一个机器学习算法的长期记忆的方法有很多,接下来我们使用的是“贪心随机训练算法”
贪心随机训练算法
概括起来基本上就是为长期记忆向量随机选取一组值。算法的“贪心”之处在于它只保存到当前为止效果最好的一组长期记忆值,如果新的长期记忆值比上一组性能更优,毫无疑问算法会选择保存新的这一组值而丢弃之前的值,这一算法有时也被称作“随机漫步算法”。
"""
ltm当前的长期记忆向量
lowRange随机范围的最小值
highRange随机范围的最大值
"""
function iteration(ltm,lowRange,highRange):
oldScore = calculateScore(ltm) #评估当前状态的性能
lem = ltm.length
oldLtm = ltm.clone #保存当前的副本 以免提升失败
for i in range(0,lem):#随机设置一个状态
ltm[i]=rand(lowRange,highRange)
#评估新的随机状态
newScore = calculateScore(ltm)
#贪心判定,新的随机状态相对于上一个状态是否有性能上的提升,如果没有,则恢复上一个状态
if(newScore>oldScore):
ltm = oldLtm.clone
迭代函数把随机值赋给长期记忆向量,将随机赋值前后的评估得分进行比较,如果得分没有下降,则丢弃新的长期记忆值并恢复上一个状态的长期记忆值。算法只接受性能有所改善的结果,这正是算法被称作“贪心”的原因,却并非总是最佳策略。
贪心随机训练算法的结果一般被作为一个基准,可以将贪心随机训练算法的结果与要评估的新算法进行比较,如果新算法的表现不比贪心随机训练算法好,就说明新算法的性能堪忧。
径向基函数网络
一种可以用于回归和分类的统计模型。
径向基函数网络有一个代表“长期记忆”的向量,但不存在“短期记忆”向量,其中“长期记忆”由系数和其他参数组合而成。
径向基函数
径向基函数关于其在x轴上的中点对称,并在中点处达到最大值,这一最大值称作“峰值”,且峰值一般为1。实际上在径向基函数网络中,峰值总是1,中点则视情况而定。
径向基函数可以是多维的,但无论输入向量是多少维,输出都总是一个标量值。
有很多场景的径向基函数,比如高斯函数。
返回的则是一个标量值——这是通过计算径向基函数的输入向量和中心向量之间的距离实现的,其中“距离”记为r。当然,要使计算能够进行,输入向量和中心向量维数必须相同。只要计算出了这个r,接下来就可以计算出对应的径向基函数值了——所有的径向基函数都要用到这个计算出的“距离”r。
双重竖线的符号表示计算的是“距离”。欧氏距离是径向基函数中最常用的距离概念,但在特殊情况下,也有可能使用其他的距离概念。
高斯径向基函数:
常用的径向基函数包括:
- 多二次函数(Multiquadric);
- 逆二次函数(Inverse quadratic);
- 逆多二次函数(Inverse multiquadric);
- 多重调和样条(Polyharmonic spline);
- 薄板样条(Thin plate spline)。
径向基函数网络
径向基函数网络是一种既可以用于分类问题,也可以用于回归问题的统计模型。该网络本质上就是一至多个径向基函数的加权求和,其中每个径向基函数均接受一个带权重的输入,从而对输出进行预测。
径向基函数网络的长期记忆向量由几个不同的部分组成:
- 输入系数;
- 输出系数(求和系数);
- 径向基函数放缩范围(在各维度上范围相同);
- 径向基函数中心向量。
径向基函数网络把这所有的元素保存为一个向量,这个向量即为该径向基函数网络的“长期记忆向量”。稍后我们会使用贪心随机训练算法或爬山算法来训练网络,以使其长期记忆向量的值达到能够根据提供的特征数据正确判断鸢尾花类别的程度。
实现径向基函数网络
要创建一个径向基函数网络,需要提供下列3项信息:
- 输入通道数目;
- 径向基函数数目;
- 输出通道数目。
输入和输出的数目决定于输入和输出向量的大小,对于选定数据集,这些值也是给定的。径向基函数的数目就稍微主观一些,使用的径向基函数越多,模型得到预期结果的性能就越好,但同时也会导致模型的时间效率下降。
初始化径向基函数网络的伪代码
function initRBFNetwork(
theInputCount,//网络的输入通道数目
rbfCount,//网络中径向基函数的数目
theOutputCount//网络的输出通道数目
){
result = new RBFNetwork()
//给网络设置几个简单的参数
result.inputCount = theInputCount
result.outputCount = theOutputCount
//计算输入和输出权重的数目
//由于额外的偏置节点,因此要在输出中加1
inputWeightCount = inputCount*rbfCount
outputWeightCount = (rbfCount+1)*outputCount
rbfParams = (rbfCount+1)*outputCount
rbfParams = (inputCount+1)*rbfCount
//为长期记忆向量分配足够的空间
result.longTermMemory = alloc(inputWeightCount+outputWeightCount+rbfParams)
//设置网络的其他参数
result.indexInputWeights = 0;
result.indexOutputWeights = inputWeightCount+rbfParams;
//分配径向基函数
result.rbf = new FnRBF[rbfCount]
//设置每一个径向基函数
for i in range(0,rbfCount){
//获取当前径向基函数对应的索引
rbfIndex = inputWeightCount +((inputCount+1)*i)
}
//分配一个高斯函数,并指定输入数目和该径向基函数参数在长期记忆向量中的存储位置 高斯函数的参数是宽度和中心点位置
result.rbf[i]=new GaussianFunction(inputCount,result.longTermMemory,rbfIndex)
//返回新生成的网络
return result;
}
名为“result”的对象来保存径向基函数网络,其中保存的内容包括长期记忆向量和网络的其他基本参数。
计算径向基函数网络的输出:
function computeRBFNetwork(
input ,#输入向量
network#径向基函数网络
){
//首先计算每个径向基函数的输出值,添加一个额外的径向基函数输出值作为偏置,偏置总为1
rbfOutput = alloc(network.rbf.length+1)
//偏置值总为1
rbfOutput[rbfOutput.length-1]=1
for rbfIndex in range(0,network,rbf,length){
//输入加权
weightedIndex = allo(input.length)
for inputIndex from 0 to input.length{
memoryIndex = network.indexInputWeights+(rbfIndex*network.inputCount)+inputIndex
weightedInput[inputIndex] = input[inputIndex]*network.longTermMemory[memoryIndex]
}
//计算当前径向基函数的值
rbfOutput[rbfIndex] =network.rbf[rbfIndex].evaluate(weightedInput)
}
//计算输出值 各径向基函数输出的加权结果
result = alloc(network.outputCount)
for outputIndex from 0 to result.length{
sum = 0
for rbfIndex from 0 to rbfOutput.length{
//径向基函数个数在原来的基础上加1,作为偏置项
memoryIndex = network.indexOutputWeights+(outputIndex*(network.rbf.length+1))+rbfIndex;
sum +=rbfOutput[rbfIndex]*network.longTermMemory[memoryIndex]
}
result[outputIndex] = sum
}
//最后 返回计算结果
return result
}