RBF神经网络极简介绍及其算法的R语言实现
(2013-10-29 13:06:59)分类: R |
最近deep
learning的研究和话题开始又火了起来。然而我却还停留在RBF神经网络的阶段。真是屌丝得不能再屌丝。对SVM也还是一知半解,机器学习最多也就是个入门级别,看来离成为一名数据科学家和数据工作者的道路还很远。
这一周时间在研究神经网络,当然内容是很初级的。所以这篇日志比较适合入门者。我写下它也权当是学习过程的记录。写了点R代码,也共享出来。这篇日记不涉及任何数学公式。
RBF在我看来,本质上就是非参数回归模型(参见Element of statistical learning的11章)。依据Cover的理论,它先将数据非线性映射到一个更高维度的空间中,然后再在高维空间用线性模型来做回归或者分类。从而得到一个较好的效果。
Vapnik曾经说过,一个好的理论是最为实用的。Cover的理论体现了这一点。Cover理论是说,数据在高维空间更倾向于线性可分的,或者更倾向于用线性模型来拟合。从这个理论出发,发展出来了一系列模型。都取得了不错的效果。
RBF神经网络,是首先利用RBF,即径向基函数,来首先将数据映射到一个更高的空间。关于RBF,可以参看我的读书笔记。之后的在高维空间上的线性模型,是比较容易实现的。这里就不多说了。
基于上面的描述,RBF神经网络的学习过程包含了两步,第一步要学习RBF的参数。一般来说选择Gaussian函数作为RBF,则其参数包括两个,位置参数和刻度参数,即center和width。最简单的方法是用kmeans聚类,学习出center,而用每个聚类中的方差来作为width的估计。
学习完RBF的参数之后,我们需要学习高维空间中线性模型的系数,该系数,可以使用基本的最小二乘方法,但是很可能遇见矩阵求逆很麻烦的情况。因此,往往是用递归最小二乘RLS,给出其中需要求逆的矩阵的一个递归形式,使得计算上比较方便。
关于RBF神经网络更多的内容,请参看神经网络与机器学习一书。
闲话不多说了,下面直接上代码。代码用R语言写成,其中包含3个函数,simData用来生成模拟的数据,用以RBF网络的训练和检测。Euc_dist用以计算两个向量的欧式距离。mysign则给出某个值的符号。训练RBF的算法即为上述的,最为基础和简单的Kmeans和RLS。
simData=function(radius,width,distance,sample_size)
{
aa1=runif(sample_size/2)
aa2=runif(sample_size/2)
rad=(radius-width/2)+width*aa1
theta=pi*aa2
x=rad*cos(theta)
y=rad*sin(theta)
label=1*rep(1,length(x))
x1=rad*cos(-theta)+rad
y1=rad*sin(-theta)-distance
label1=-1*rep(1,length(x1))
n_row=length(x)+length(x1)
data=matrix(rep(0,3*n_row),nrow=n_row,ncol=3)
data[,1]=c(x,x1)
data[,2]=c(y,y1)
data[,3]=c(label,label1)
data
}
dataSim=simData(radius=10,width=6,distance=-6,sample_size=3000)
plot(dataSim[,1],dataSim[,2],col=ifelse(dataSim[,3]==1,"red","green"),xlab="x",ylab="y")
Euc_dist=function(a,b)
{
sqrt(sum((a-b)^2))
}
mysign=function(d)
{
1*(d>=0)+(-1)*(d<0)
}
#############算法主体部分######################################
num_input=dim(dataSim)[2]-1
#输入训练样本为矩阵
num_hidden_node=6
#隐层结点数
num_out=1
#输出层结点数
data_train=dataSim
num_train=dim(data_train)[1]
########初始化
c_threshold=1e-3
c_delta=Inf
w=matrix(rep(0,num_hidden_node*num_out),nrow=num_hidden_node,ncol=num_out)
#权重矩阵
sig=0.01
P=matrix(rep(0,6^2),nrow=6)
#RLS算法中的R^-1
for(i in 1:6)
{P[i,i]=1*sig^(-1)}
c=simData(radius=10,width=6,distance=-6,sample_size=num_hidden_node)
#RBF中心的初值
c=c[,-3]
iter_train_min=10
#训练次数
epochs=50 #轮次
w_threshold=1e-8
mse_threshold=1e-6
w_delta=Inf
n=1
m=1
eta=1 #学习速率
err=0 #错误检测计数器
pos_vector=rep(1,num_train)
#位置向量,用以标记属于某个聚类的样本的位置
mse=vector()
ee=vector()
################Kmeans算法
while(c_delta>c_threshold
&&
n<=num_train)
{
x=data_train[n,-3]
y=data_train[n,3]
eu_dist=vector()
for(i
in 1:num_hidden_node)
{
eu_dist[i]=Euc_dist(x,c[i,])
}
eu_min_value=min(eu_dist)
eu_min_pos=order(eu_dist)[1]
c[eu_min_pos,]=c[eu_min_pos,]+eta*(x-c[eu_min_pos,])
pos_vector[n]=eu_min_pos
n=n+1
}
############计算每个聚类中的方差
tem_vec=vector()
sigma=vector()
for(i in
1:num_hidden_node)
{
tem_vec=(pos_vector==i)
dist_temp=0
for(j
in 1:num_train)
{
if(tem_vec[j]==TRUE)
dist_temp=Euc_dist(c[i,],data_train[j,-3])+dist_temp
}
sigma[i]=dist_temp/sum(tem_vec)
}
g=matrix(rep(0,num_hidden_node),nrow=num_hidden_node)
#####################训练输出层权重
for(epoch in
1:epochs)
{
random_seq=sample(seq(1:num_train),replace=FALSE)
data_randomized_tr=data_train[random_seq,]
for(m
in 1:num_train)
{
x=data_randomized_tr[m,-3]
d=data_randomized_tr[m,3]
for(i
in 1:num_hidden_node)
g[i,]=exp(-t(x-c[i,])%*%(x-c[i,])/(2*sigma[i]^2))
#########RLS算法
pai=P%*%g
kk=pai/(1+t(g)%*%pai)[1,1]
e=d-mysign(t(w)%*%g)
w_delta=t(kk*e[1,1])
ee[m]=d-mysign(t(w)%*%g)
w=w+t(w_delta)
P=P-kk%*%t(g)%*%P
}
mse[epoch]=mean(ee^2)
if(mse[epoch]
}
print(w)
print(c)
##########################RBF网络检验##############################
o=vector()
gg=matrix(rep(0,num_hidden_node),nrow=num_hidden_node)
data_test=simData(radius=10,width=6,distance=-6,sample_size=2000)
num_test=dim(data_test)[1]
for(i in 1:num_test)
{
xx=data_test[i,-3]
for(j in
1:num_hidden_node)
{gg[j,]=exp(-t(xx-c[j,])%*%(xx-c[j,])/(2*sigma[j]^2))
o[i]=t(w)%*%gg}
if(abs(mysign(o[i])-data_test[i,3])>1e-6)
err=err+1
}
err/num_test
最后得到的效果还行,3000个训练样本,2000个检测样本,最终分类错误率在8%以内。当然,由于随机数,如果你在自己机器上跑上述代码,获得的结果应该与我的不同。
以上内容是用了一周时间完成。包括读算法和编代码。有两点感受:1,R语言的神经网络包的功能还是比较弱。Matlab的神经网络工具箱,是目前我所见功能最强大的。2,R语言还是比较适合向量运算。处理起矩阵来,还是觉得有点别扭。
这一周时间在研究神经网络,当然内容是很初级的。所以这篇日志比较适合入门者。我写下它也权当是学习过程的记录。写了点R代码,也共享出来。这篇日记不涉及任何数学公式。
RBF在我看来,本质上就是非参数回归模型(参见Element of statistical learning的11章)。依据Cover的理论,它先将数据非线性映射到一个更高维度的空间中,然后再在高维空间用线性模型来做回归或者分类。从而得到一个较好的效果。
Vapnik曾经说过,一个好的理论是最为实用的。Cover的理论体现了这一点。Cover理论是说,数据在高维空间更倾向于线性可分的,或者更倾向于用线性模型来拟合。从这个理论出发,发展出来了一系列模型。都取得了不错的效果。
RBF神经网络,是首先利用RBF,即径向基函数,来首先将数据映射到一个更高的空间。关于RBF,可以参看我的读书笔记。之后的在高维空间上的线性模型,是比较容易实现的。这里就不多说了。
基于上面的描述,RBF神经网络的学习过程包含了两步,第一步要学习RBF的参数。一般来说选择Gaussian函数作为RBF,则其参数包括两个,位置参数和刻度参数,即center和width。最简单的方法是用kmeans聚类,学习出center,而用每个聚类中的方差来作为width的估计。
学习完RBF的参数之后,我们需要学习高维空间中线性模型的系数,该系数,可以使用基本的最小二乘方法,但是很可能遇见矩阵求逆很麻烦的情况。因此,往往是用递归最小二乘RLS,给出其中需要求逆的矩阵的一个递归形式,使得计算上比较方便。
关于RBF神经网络更多的内容,请参看神经网络与机器学习一书。
闲话不多说了,下面直接上代码。代码用R语言写成,其中包含3个函数,simData用来生成模拟的数据,用以RBF网络的训练和检测。Euc_dist用以计算两个向量的欧式距离。mysign则给出某个值的符号。训练RBF的算法即为上述的,最为基础和简单的Kmeans和RLS。
simData=function(radius,width,distance,sample_size)
{
}
dataSim=simData(radius=10,width=6,distance=-6,sample_size=3000)
plot(dataSim[,1],dataSim[,2],col=ifelse(dataSim[,3]==1,"red","green"),xlab="x",ylab="y")
Euc_dist=function(a,b)
{
}
mysign=function(d)
{
}
#############算法主体部分######################################
print(w)
print(c)
##########################RBF网络检验##############################
o=vector()
gg=matrix(rep(0,num_hidden_node),nrow=num_hidden_node)
data_test=simData(radius=10,width=6,distance=-6,sample_size=2000)
num_test=dim(data_test)[1]
for(i in 1:num_test)
{
}
err/num_test
以上内容是用了一周时间完成。包括读算法和编代码。有两点感受:1,R语言的神经网络包的功能还是比较弱。Matlab的神经网络工具箱,是目前我所见功能最强大的。2,R语言还是比较适合向量运算。处理起矩阵来,还是觉得有点别扭。
前一篇:中国式价值投资——摘抄
后一篇:R与灰色预测G(1,1)