发布时间:2023-08-13 15:00
笔者第一篇博客,在此分享下最近编写的BP神经网络分类算法,代码已全部开源(GitHub下载地址),运行环境Ubuntu,结合OpenGL实现了训练过程的可视化
接触BP神经网络已有四年,最初觉得神经网络是个很神秘的东西,后面跟着资料推导并用代码实现,玩出很多新花样,在此分享第一个应用:分类
BP(back propagation)神经网络是1986年由Rumelhart和McClelland为首的科学家提出的概念,是一种按照误差逆向传播算法训练的多层前馈神经网络,是应用最广泛的神经网络模型之一(来自百度百科),其网络形式如下图,由输入层、隐藏层和输出层组成,复杂的有多个隐藏层,在此只讨论只有一个隐藏层的神经网络。
上图中p1到pn为输入向量,a1到am为输出,可以实现n维到m维的映射。当对二维数据进行分类且只有两类数据时,输入向量可以时x、y两个维度,输出只需一个维度即可(将输出看作二进制,两个类别用一个神经元,四个类别用两个神经元,以此类推…)
正向计算很简单,通过循环将输入向量按权重相乘累加再经过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;
}
反向传播推导还是有点复杂,需要一定的数学基础,具体推导过程可以百度,代码实现如下
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神经网络除了做分类,也可以做拟合,尤其在多维函数的拟合上,比如机械臂逆运动学较为复杂,可以通过正向计算得到离散点,再用神经网络拟合(此方法大多时候可能是多此一举,对于复杂结构应该是捷径)
以上就是本篇博客的全部内容了,喜欢的同学可以关注