【GitHub开源】BP神经网络分类C++实现

发布时间:2023-08-13 15:00

笔者第一篇博客,在此分享下最近编写的BP神经网络分类算法,代码已全部开源(GitHub下载地址),运行环境Ubuntu,结合OpenGL实现了训练过程的可视化

目录

  • 前言
  • 一、BP神经网络是什么?
  • 二、代码算法
    • 1.正向计算
    • 2.梯度下降反向传播算法
  • 三、运行效果
  • 四、总结


前言

接触BP神经网络已有四年,最初觉得神经网络是个很神秘的东西,后面跟着资料推导并用代码实现,玩出很多新花样,在此分享第一个应用:分类

一、BP神经网络是什么?

BP(back propagation)神经网络是1986年由Rumelhart和McClelland为首的科学家提出的概念,是一种按照误差逆向传播算法训练的多层前馈神经网络,是应用最广泛的神经网络模型之一(来自百度百科),其网络形式如下图,由输入层、隐藏层和输出层组成,复杂的有多个隐藏层,在此只讨论只有一个隐藏层的神经网络。
【GitHub开源】BP神经网络分类C++实现_第1张图片
上图中p1到pn为输入向量,a1到am为输出,可以实现n维到m维的映射。当对二维数据进行分类且只有两类数据时,输入向量可以时x、y两个维度,输出只需一个维度即可(将输出看作二进制,两个类别用一个神经元,四个类别用两个神经元,以此类推…)

二、代码算法

1.正向计算

	正向计算很简单,通过循环将输入向量按权重相乘累加再经过sigmoid函数到达隐层,再通过相同步骤到达输出层,注意输入和目标集合先进行归一化处理。
	for (int j = 0; j < m_bp_num_.HideNum; j++)
	{
		for (int i = 0; i < m_bp_num_.InNum; i++)
		{
			tmp_hide[j] += m_weight0_[i][j] * m_input_[i];
		}
		m_hideOut_[j] = BP_Sigmoid(tmp_hide[j] + m_b_[0]);
		tmp_hide[j] = 0;
	}

	for (int j = 0; j < m_bp_num_.OutNum; j++)
	{
		for (int i = 0; i < m_bp_num_.HideNum; i++)
		{
			tmp_out[j] += m_weight1_[i][j] * m_hideOut_[i];
		}
		m_outOut_[j] = BP_Sigmoid(tmp_out[j] + m_b_[1]);
		tmp_out[j] = 0; 
	}

2.梯度下降反向传播算法

反向传播推导还是有点复杂,需要一定的数学基础,具体推导过程可以百度,代码实现如下
	for (int i = 0; i < m_bp_num_.OutNum; i++)
	{
		error += (m_goal_[i] - m_outOut_[i]) * (m_goal_[i] - m_outOut_[i]) / 2.0;
		tmp_t[i] = (m_goal_[i] - m_outOut_[i]) * m_outOut_[i] * (1.0 - m_outOut_[i]);
		for (int j = 0; j < m_bp_num_.HideNum; j++)
		{
			m_weight1_[j][i] = m_weight1_[j][i] + m_rate_.RateW1 * tmp_t[i] * m_hideOut_[j];	
		}
	}
	for (int j = 0; j < m_bp_num_.HideNum; j++)
	{
		tmp_p[j] = 0.0;    
		for (int i = 0; i < m_bp_num_.OutNum; i++)
		{
			tmp_p[j] += tmp_t[i] * m_weight1_[j][i];
		}
		tmp_p[j] = tmp_p[j] * m_hideOut_[j] * (1.0 - m_hideOut_[j]);
		for (int k = 0; k < m_bp_num_.InNum; k++)
		{
			m_weight0_[k][j] = m_weight0_[k][j] + m_rate_.RateW0 * tmp_p[j] * m_input_[k];
		}
	}
	for (int i = 0; i < m_bp_num_.OutNum; i++)    
	{
		m_b_[1] += m_rate_.RateB1 * tmp_t[i];
	}
	for (int j = 0; j < m_bp_num_.HideNum; j++)
	{
		m_b_[0] += m_rate_.RateB0 * tmp_p[j];
	}

此处只贴出了BP神经网络部分的核心代码,需要完整的代码请到我的GitHub地址下载。


三、运行效果

对简单的二维数据进行分类,训练速度还是很快的,下面是运行效果(为了展示训练过程效果,将学习率调低了),图中的白点和黑点代表两种类别,通过神经网络分别将其映射为0和1,实现分类,通过OpenGL将其可视化后,训练结果非常直观。程序初始化时,我对权重初始化为随机数,多次运行有不同结果,可能会陷入局部最小点,导致图像来回抖动不收敛,调整学习率也可得到不同效果。

四、总结

除了在上位机上进行训练,我还尝试在stm23上跑了BP神经网络训练代码,训练效果bilibili视频地址
在单片机上跑反向传播训练算法还是太为难它了,不过先在上位机训练好,将权重拷出在放到单片机跑正向算法,计算速度还是很可观的,比如做颜色识别,如果使用ov7725这种低端摄像头,使用HSV等方式效果较差,我前些年做魔方机器人的时候,就尝试了多种颜色识别算法,效果都不太理想,后面使用神经网络,结果屡试不爽,魔方机器人效果展示bilibili视频地址,后面再更新用神经网络做颜色识别。
BP神经网络除了做分类,也可以做拟合,尤其在多维函数的拟合上,比如机械臂逆运动学较为复杂,可以通过正向计算得到离散点,再用神经网络拟合(此方法大多时候可能是多此一举,对于复杂结构应该是捷径)
以上就是本篇博客的全部内容了,喜欢的同学可以关注

ItVuer - 免责声明 - 关于我们 - 联系我们

本网站信息来源于互联网,如有侵权请联系:561261067@qq.com

桂ICP备16001015号