前言
径向基函数神经网络是一种前馈式神经网络,包含输入层、隐含层和输出层,其多输入单输出网络结构如图2所示。根据径向基函数中心确定的方法不同,径向基神经网络有不同的学习策略。我们采用最常见的随机选取固定中心的方法。径向基函数记为:
一些神经网络的简介可以看这篇所有神经网络的特点及优缺点分析总结文章
一、RBF神经网络
RBF神经网络在电网故障中的应用,RBF神经网络改善了BP神经网络的各层之间权值和阈值的复杂运算,解决了BP神经网络的反复迭代,而且在训练过程中不收敛不稳定的现象。但同时,RBF本身的学习率等参数也影响了自身的准确性,而且计算机对伪逆的运算占用大量内存,对故障判断的实时性也有影响。
我采用的是python编译器是pycharm虚拟环境是anaconda搭建的python3.7.x环境。详细的环境配置在利用anaconda给pycharm配置python3.7版本的tensorflow虚拟环境的配置这篇文章中讲述
原理介绍我直接从我的论文里复制出来懒得整理了
在随机选取固定中心在RBF网络中,需要训练的参数是:1隐含层中基函数的中心;2隐含层中基函数的标准差;3隐含层与输出层间的权值。在随机选取固定中心的方法中,基函数的中心和标准差都是固定的,唯一需要训练的参数是隐含层与输出层之间的权值。这是一种最简单的学习策略。隐含层基函数的中心随机地从输入的样本数据中选取,且固定不变。确定中心基函数标准差按照下式选取
1.代码
代码如下(示例):
import numpy as np
from scipy.linalg import norm, pinv
import xlrd
import matplotlib.pyplot as plt
import time
import csv
start1 = time.perf_counter()
np.random.seed(50)
class RBF:
"""
RBF神经网络类
"""
def __init__(self, input_dim, num_centers, out_dim): # 输入变量数 中间层个数 输出变量数目
self.input_dim = input_dim
self.num_center = num_centers
self.out_dim = out_dim
self.beta = 0.1 # 标准差初始化定义
self.centers = [np.random.uniform(-1, 1, input_dim) for i in range(num_centers)] # 中心点初始赋值
"""
中心点个数和number_centers个数相同,坐标数量和input_dim对应
"""
self.W = np.random.random((self.num_center, self.out_dim)) # num_centers*out_dim矩阵形式
def _basisfunc(self, c, d): # 基函数计算
return np.exp(-(self.num_center * (norm(c - d) ** 2)) / self.beta**2)
def _calcAct(self, x):
G = np.zeros((x.shape[0], self.num_center), dtype=np.float) # 定义一个激活矩阵 样本数*中间层数
for ci, c in enumerate(self.centers):
for x1, xx in enumerate(x):
G[x1, ci] = self._basisfunc(c, xx)
return G
def _calcbeat(self): # 找到选取中心点最大值——及求解σ的值
bate_temp = np.zeros((self.num_center, self.num_center)) # 定义一个矩阵 隐藏层中心值确定的
for iindex, ivalue in enumerate(self.centers):
for jindex, jvalue in enumerate(self.centers):
bate_temp[iindex, jindex] = norm(ivalue - jvalue) # 依次求解各中心层的值
return np.argmax(bate_temp) # 返回最大值
def train(self, x, y):
"""
:param x: 样本数*输入变量数
:param y: 样本数*输出变量数
:return:无
"""
rnd_idx = np.random.permutation(x.shape[0])[:self.num_center] # 随机我们的输入样本
self.centers = [x[i, :] for i in rnd_idx] # 根据随机值找打对应样本中心
self.beta =3400#4410 # #self._calcbeat() # 根据样本中心计算σ值
print(self.beta)
G = self._calcAct(x) # 返回G值
self.W = np.dot(pinv(G), y) # 求解W值
#print(self.W)
pass
def predict(self, x):
G = self._calcAct(x)
y = np.dot(G, self.W)
return y
"""
获取数据(excle有其他的值所以部分行列加减没有逻辑)
%原始数据格式如下表所示(测试输出集合一样)
% | QF1(变量1)|QF2(变量2)|QF3(变量2)|err(输出结果)|
% 样本1 | 1 | 0 | 0 | 1 |
% 样本2 | 0 | 1 | 0 | 2 |
"""
data = xlrd.open_workbook('E:\\电网故障数据1.xlsx') # 获取数据
table = data.sheet_by_name('Sheet1')
rownum = table.nrows
colnum = table.ncols-1
x = np.zeros((rownum, colnum))
for i in range(rownum):
for j in range(colnum):
x[i, j] = table.cell(i, j).value
y = np.zeros(rownum)
for i in range(rownum):
y[i] = table.cell(i, colnum).value
table1 = data.sheet_by_name('Sheet2')
rownum1 = table1.nrows
colnum1 = table1.ncols-1
x1 = np.zeros((rownum1, colnum1))
for i in range(rownum1):
for j in range(colnum1):
x1[i, j] = table1.cell(i, j).value
y1 = np.zeros(rownum1)
for i in range(rownum1):
y1[i] = table1.cell(i, colnum1).value
"""
根据我们类自己定义rbf函数,从前往后分别是 变量数,隐含层数(中心点数) 输出结果数
"""
ceshi_flag=0 # 测试标志位1是测试训练数据,0是正常数据
rbf = RBF(60,1610, 1)#1610 88%
rbf.train(x, y)
end1 = time.perf_counter()
print("final is in : %s Seconds " % (end1-start1))
if ceshi_flag==1:
z = rbf.predict(x)
z1 = z
else:
z = rbf.predict(x1)
z1 = z
def Round_f(num): # 是一个取整函数
if num <= 0:
return 0
if num >= 64:
return 64
num1 = int(num)
num2 = num * 10
num3 = int(num2)
if num2<=105:
if num3 <15:
return 1
else:
if (num3 - num1 * 10) < 5:
return num1
else:
return num1+1
else:
if (num3 - num1 * 10) < 5:
return num1
else :
return num1+1
pass
for i in range(np.size(z, 0)):
z1[i] = Round_f(z[i])
f = open('RBFdata.csv','w',encoding='utf-8', newline="")
# 2. 基于文件对象构建 csv写入对象
csv_writer = csv.writer(f)
# 3. 构建列表头
#csv_writer.writerow(["姓名","年龄","性别"])
# 4. 写入csv文件内容
for i in range(np.size(z, 0)):
csv_writer.writerow([z1[i]])
# 5. 关闭文件
f.close()
rightnum = 0
if ceshi_flag==1:
for i in range(np.size(z, 0)):
if z1[i] == y[i]:
rightnum = rightnum + 1
else:
for i in range(np.size(z, 0)):
if z1[i] == y1[i]:
rightnum = rightnum + 1
print(z)
print('正确率 %0.2f' % (rightnum / (np.size(z, 0)) * 100), "%", end='')
xrow = [i for i in range(1, np.size(z, 0) + 1)]
if ceshi_flag==1:
plt.plot(xrow, y, 'k*', label=u'shiji')
plt.plot(xrow, z1, 'k-', label=u'yuce')
plt.show()
else:
xrow1 = [i for i in range(1, 49)]
xrow2 = [i for i in range(49, 97)]
xrow3 = [i for i in range(97, 145)]
xrow4 = [i for i in range(145, 193)]
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
plt.figure(1)
ax1 = plt.subplot(2, 2, 1)
ax2 = plt.subplot(2, 2, 2)
ax3 = plt.subplot(2, 2, 3)
ax4 = plt.subplot(2, 2, 4)
plt.sca(ax1)
plt.title('测试数据对照数据曲线')
plt.plot(xrow1, y1[0:48], 'b*', label=u'实际值')
plt.plot(xrow1, z1[0:48], 'k-', label=u'预测值')
plt.legend()
plt.sca(ax2)
plt.title('测试数据对照数据曲线')
plt.plot(xrow2, y1[48:96], 'b*', label=u'shiji')
plt.plot(xrow2, z1[48:96], 'k-', label=u'yuce')
plt.sca(ax3)
plt.title('测试数据对照数据曲线')
plt.plot(xrow3, y1[96:144], 'b*', label=u'shiji')
plt.plot(xrow3, z1[96:144], 'k-', label=u'yuce')
plt.sca(ax4)
plt.title('测试数据对照数据曲线')
plt.plot(xrow4, y1[144:192], 'b*', label=u'shiji')
plt.plot(xrow4, z1[144:192], 'k-', label=u'yuce')
plt.show()
简单解释一下我的代码,我首先建立了一个RBF的类函数,之后随机选取了RBF的计算中心,分别计算输入值和RBF中心的距离,训练之后的D数组用之后的学习数据再次带入测试计算准确度,并画图。
注意:
针对你的学习数据,你的中心层的个数和self.beta值是需要自己调节的,这个过程很难寻找,目前大都在做针对粒子群PSO对RBF的优化,我以后估计也会做这个函数。也会分享上来。
这是我的训练数据,正确率94%左右,还算过得去。
总结
RBF网络和BP网络一样能以任意精度逼近任何非线性函数。但由于它们使用的激励函数不同,其逼近性能也不相同。但是BP网络隐层节点数目的确定依赖于经验和试凑,很难得到最优网络。采用局部激励函数的RBF网络在很大程度上克服了上述缺点,RBF不仅有良好的泛化能力,而且对于每个输入值,只有很少几个节点具有非零激励值,因此只需很少部分节点及权值改变。学习速度可以比通常的BP算法提高上千倍,容易适应新数据,其隐层节点的数目也在训练过程中确定,并且其收敛性也较BP网络易于保证,因此可以更加容易得到最优解。