Tinn核心算法解析:前向传播与反向传播实现

【免费下载链接】tinn A tiny neural network library 【免费下载链接】tinn 项目地址: https://gitcode.com/gh_mirrors/ti/tinn

Tinn是一个轻量级神经网络库,专为理解神经网络基础原理而设计。本文将深入解析Tinn库中前向传播与反向传播的核心实现,帮助初学者掌握神经网络的基本工作机制。

神经网络基础架构

Tinn采用简洁的三层架构设计:输入层、单隐藏层和输出层。这种结构在Tinn.h中通过Tinn结构体定义:

typedef struct {
    float* w;        // 所有权重
    float* x;        // 隐藏层到输出层权重
    float* b;        // 偏置值
    float* h;        // 隐藏层神经元
    float* o;        // 输出层神经元
    int nb;          // 偏置数量(固定为2)
    int nw;          // 权重数量
    int nips;        // 输入神经元数量
    int nhid;        // 隐藏层神经元数量
    int nops;        // 输出神经元数量
} Tinn;

通过xtbuild函数可以创建神经网络实例,需要指定输入层大小(nips)、隐藏层大小(nhid)和输出层大小(nops)。

前向传播:信息的前向流动

前向传播是神经网络进行预测的核心过程,在Tinn中由fprop函数实现。该过程分为两个关键步骤:

隐藏层计算

首先计算隐藏层神经元的值:

for(int i = 0; i < t.nhid; i++) {
    float sum = 0.0f;
    for(int j = 0; j < t.nips; j++)
        sum += in[j] * t.w[i * t.nips + j];
    t.h[i] = act(sum + t.b[0]);
}

这段代码计算每个隐藏层神经元的加权和,然后通过激活函数act处理。Tinn使用Sigmoid作为激活函数:1.0f / (1.0f + expf(-a))[Tinn.c#L32]。

输出层计算

隐藏层计算完成后,继续计算输出层:

for(int i = 0; i < t.nops; i++) {
    float sum = 0.0f;
    for(int j = 0; j < t.nhid; j++)
        sum += t.h[j] * t.x[i * t.nhid + j];
    t.o[i] = act(sum + t.b[1]);
}

输出层的计算方式与隐藏层类似,使用隐藏层的输出作为输入,最终得到网络的预测结果。

预测功能通过xtpredict函数对外提供,该函数调用fprop完成前向传播并返回输出层结果。

反向传播:误差的反向传播与参数更新

反向传播是神经网络学习的核心,Tinn中由bprop函数实现。该过程通过计算预测误差,并将误差从输出层反向传播到输入层,从而更新网络参数。

输出层权重更新

首先计算输出层的误差项并更新权重:

for(int j = 0; j < t.nops; j++) {
    const float a = pderr(t.o[j], tg[j]);  // 误差函数偏导数
    const float b = pdact(t.o[j]);        // 激活函数偏导数
    sum += a * b * t.x[j * t.nhid + i];
    // 更新隐藏层到输出层权重
    t.x[j * t.nhid + i] -= rate * a * b * t.h[i];
}

其中,pderr计算预测值与目标值的误差偏导数(a - b)[Tinn.c#L17],pdact计算Sigmoid函数的导数a * (1.0f - a)[Tinn.c#L38]。

输入层权重更新

基于隐藏层的误差项,更新输入层到隐藏层的权重:

for(int j = 0; j < t.nips; j++)
    t.w[i * t.nips + j] -= rate * sum * pdact(t.h[i]) * in[j];

训练过程通过xttrain函数实现,该函数先调用fprop进行前向传播,再调用bprop进行反向传播,最后返回总误差。

完整训练流程

Tinn的训练流程在test.c中得到了完整展示,典型的使用步骤包括:

  1. 创建神经网络:xtbuild(nips, nhid, nops)
  2. 循环训练:
    for(int i = 0; i < iterations; i++) {
        shuffle(data);  // 打乱数据
        float error = 0.0f;
        for(int j = 0; j < data.rows; j++) {
            error += xttrain(tinn, in, tg, rate);  // 训练样本
        }
        rate *= anneal;  // 学习率衰减
    }
    
  3. 保存/加载模型:xtsave(tinn, "saved.tinn")xtload("saved.tinn")
  4. 预测:xtpredict(loaded, in)

实践应用与优化建议

Tinn虽然简单,但已经能够完成基本的分类任务。在test.c中,它实现了对手写数字的识别,通过调整以下超参数可以优化性能:

  • 隐藏层神经元数量(nhid):测试中使用28个神经元
  • 学习率(rate):初始值设为1.0,采用退火方式衰减
  • 迭代次数(iterations):测试中使用128次迭代

初学者可以通过修改这些参数,观察对模型性能的影响,深入理解神经网络的工作原理。

总结

Tinn通过简洁的代码实现了神经网络的核心算法,包括前向传播和反向传播。通过学习Tinn的源码,特别是Tinn.c中的fprop和bprop函数,初学者可以直观理解神经网络的工作机制。Tinn证明了即使是只有几百行代码的小型库,也能有效展示神经网络的基本原理,是学习深度学习基础的理想选择。

【免费下载链接】tinn A tiny neural network library 【免费下载链接】tinn 项目地址: https://gitcode.com/gh_mirrors/ti/tinn

Logo

脑启社区是一个专注类脑智能领域的开发者社区。欢迎加入社区,共建类脑智能生态。社区为开发者提供了丰富的开源类脑工具软件、类脑算法模型及数据集、类脑知识库、类脑技术培训课程以及类脑应用案例等资源。

更多推荐