[深度学习系列之一] C++ 实现神经网络

C++ 实现神经网络

介绍

深度学习和神经网络最近几年如火如荼,各种NN层出不穷, 这年头程序员要没听说过CNN, RNN, 还真不好意思跟人打招呼。各种库也非常多,什么pyTorch, mxnet, theano, tensorflow, keras,cntk,各种听过的没听过的满天飞。都快是全民AI学习机器学习的节奏了,怪不得Nvidia的股票一直在涨。

虽然用C++ 实现神经网络会比较麻烦,不过如果注意到以下下的trick, 在用C++ 实现神经网络时会舒服很多,代码也会非常简明,核心代码在百行左右也不是问题。

  1. C++ 没有内置的向量,矩阵库,可以自己先轮几个Vector, Matrix类以及各种数学运算操作,最好搞成链式操作。
  2. 不要用index form来推导和实现BP算法,个人比较喜欢matrix form, 公式会非常紧凑,实现起来也不太容易出错
  3. 顶层框架设计,比如先设计几个基类Model类,数据库类,定义几个通用的接口。实现具体的算法时,只要实现特定接口即可。

我最近实现了一把基本的神经网络,包括LR和多层NN模型, 使用C++11, Visual Studio 2017开发,源码放在了https://github.com/speedmancs/ML上。

训练程序的基本框架

在基类Model中,训练的框架逻辑在Fit方法中,主要流程就是SGD或者batch训练, 对于不同的模型,需要实现其中的ClearGradient, Eval, ComputeGradient, Update等方法
1. Eval 也就是神经网络的forward过程,前向计算得到当前的参数下的预测结果 数学上就是 计算 E=f(θ)
2. ComputeGradient 是BP 计算参数导数的过程, Eθ
3. 再得到导数之后, 再Update更新参数。 θ=θηEθ

void Model::Fit(const DataSet& trainingSet, const DataSet& validateSet)
{
    for (int i = 0; i < m_config.train_epoch; i++)
    {
        for (size_t j = 0; j < trainingSet.Size(); j++)
        {
            if (j % m_config.batchSize == 0) ClearGradient();
            size_t pred = Eval(trainingSet.GetData(j));
            ComputeGradient(trainingSet.GetData(j), trainingSet.GetTarget(j));
            if (j % m_config.batchSize == m_config.batchSize - 1 || j == trainingSet.Size() - 1) Update();
        }
    }
}

在batch模式下训练时,ComputeGradient需要把batch个样例的所有导数加起来,最后平均一下后进行update。在一个新的batch开始之前,需要调用ClearGradient对存储这些参数导数的变量清零。以logistic regression为例, 其中W,b分别是权重参数和偏置项, dW, db分别是其导数。

void LRModel::ClearGradient()
{
    db = 0;
    dW = 0;
}

void LRModel::Update()
{
    db.Div((float)m_config.batchSize);
    dW.Div((float)m_config.batchSize);
    b.Sub(m_config.learning_rate, db);
    W.Sub(m_config.learning_rate, dW);
}

Logistic Regression Model

有个上面的基本训练算法框架,实现具体的算法就很简单了,比如LR的模型是这样的, y 是OneHot的target, x是输入向量

Forward

y^=softmax(Wx+b)

Compute gradients

E
  • 28
    点赞
  • 207
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值