编译和测试使用FANN库构建简单神经网络

⌚Time: 2026-01-15 16:33:00

👨‍💻Author: Jack Ge

简介

FANN(Fast Artificial Neural Network Library)是一个用 C/C++ 编写的开源人工神经网络库,专注于提供高性能、轻量级的神经网络实现。它支持多层前馈神经网络(MLP),并提供快速训练算法,包括标准反向传播、快速反向传播和批量训练方法。

FANN 提供简单易用的 API,可以快速创建、训练和保存神经网络模型。用户可以灵活设置网络层数、每层神经元数量、激活函数类型(Sigmoid、Tanh、线性等),以及训练参数(学习率、误差阈值等),非常适合中小型机器学习任务和快速原型开发。

FANN 支持多种数据输入输出格式,网络模型可序列化保存或加载,从而便于在不同平台或项目中复用。它也提供多语言绑定,包括 C++、Python、Java 等,方便与其他系统集成。

由于其 轻量、高效、跨平台 的特点,FANN 广泛应用于分类、回归、控制系统和预测任务中,尤其适合对资源要求不高但需要快速部署的嵌入式和桌面应用场景。

编译安装

FANN的github地址:https://github.com/libfann/fann

直接下载源码解压,需要使用cmake编译源码成库。我使用的是windows10系统,cmake3.8.0,mingw5.4

打开cmake,定位到FANN源码目录,填写输出目录。点击configure,选择自己编译系统需要的makefile类型,点finish。

configure完成之后出现红色条目,一般就不用改了

再点击1次configure,变成普通颜色之后,点击generate产生makefile文件

到输出目录,已经产生了工程文件或者makefile,使用自己的编译系统进行编译,我用的mingw。因为看到cmake配置的安装文件夹是系统程序目录,所以需要使用管理员身份运行cmd,输入下面命令开始编译

mingw32-make

编译完成后直接安装

mingw32-make install

之后就会发现安装目录出现了FANN库文件夹,目录结构:

├─bin
├─include
│  ├─gmock
│  │  └─internal
│  │      └─custom
│  └─gtest
│      └─internal
│          └─custom
└─lib
    ├─cmake
    │  ├─fann
    │  └─GTest
    └─pkgconfig

其中bin目录里面是FANN的动态链接库,需要加入系统环境变量PATH里面,确保运行时找到需要的动态库文件。include和lib是编译程序需要的头文件和库文件目录

这个库文件夹可以直接copy到需要的路径,之后使用。

测试

这是chatgpt5给的测试程序:当然,我可以给你一个使用 FANN(Fast Artificial Neural Network Library)的完整示例,演示如何训练一个简单的神经网络。

#include <stdio.h>
#include "fann.h"

int main()
{
    // 1. 创建神经网络
    const unsigned int num_input = 2;
    const unsigned int num_hidden = 3;
    const unsigned int num_output = 1;

    struct fann *ann = fann_create_standard(3, num_input, num_hidden, num_output);

    // 2. 设置激活函数
    fann_set_activation_function_hidden(ann, FANN_SIGMOID_SYMMETRIC);
    fann_set_activation_function_output(ann, FANN_SIGMOID_SYMMETRIC);

    // 3. 创建训练数据
    fann_type input[4][2] = {
        {0, 0},
        {0, 1},
        {1, 0},
        {1, 1}
    };
    fann_type output[4][1] = {
        {0},
        {1},
        {1},
        {0}
    };

    struct fann_train_data *train_data = fann_create_train(4, num_input, num_output);
    for (int i = 0; i < 4; i++) {
        for (int j = 0; j < num_input; j++){
            train_data->input[i][j] = input[i][j];
        }
        for (int j = 0; j < num_output; j++){
            train_data->output[i][j] = output[i][j];
        }
    }

    // 4. 训练网络
    fann_train_on_data(ann, train_data, 1000, 100, 0.001);

    // 5. 测试网络
    printf("XOR Neural Network Results:\n");
    for (int i = 0; i < 4; i++) {
        fann_type *calc_out = fann_run(ann, input[i]);
        printf("Input: %g, %g -> Predicted: %g, Actual: %g\n", input[i][0], input[i][1], calc_out[0], output[i][0]);
    }

    // 6. 清理
    fann_destroy_train(train_data);
    fann_destroy(ann);

    return 0;
}

编译链接,运行

g++ main.cpp -ID:\BuildTools\FANN\include -LD:\BuildTools\FANN\lib -lfann
./a.exe

这个神经网络学会了简单的XOR逻辑,结果:

Max epochs     1000. Desired error: 0.0010000000.
Epochs            1. Current error: 0.1205339134. Bit fail 2.
Epochs           93. Current error: 0.0009803015. Bit fail 0.
XOR Neural Network Results:
Input: 0, 0 -> Predicted: 0.0139892, Actual: 0
Input: 0, 1 -> Predicted: 0.913798, Actual: 1
Input: 1, 0 -> Predicted: 0.917462, Actual: 1
Input: 1, 1 -> Predicted: 0.0148878, Actual: 0

chatgpt5给的一个拟合2x^2-6函数的神经网络

#include <fann.h>
#include <iostream>
#include <vector>

int main() {
    const unsigned int num_data = 11;
    std::vector<float> x_vals, y_vals;

    // 准备数据并归一化
    for (int i = -5; i <= 5; ++i) {
        x_vals.push_back(i / 5.0f);
        y_vals.push_back((2*i*i - 6) / 44.0f * 2 - 1);
    }

    // 创建网络
    struct fann *ann = fann_create_standard(3, 1, 10, 1);
    fann_set_activation_function_hidden(ann, FANN_SIGMOID_SYMMETRIC);
    fann_set_activation_function_output(ann, FANN_LINEAR);
    fann_set_training_algorithm(ann, FANN_TRAIN_RPROP);
    fann_set_train_stop_function(ann, FANN_STOPFUNC_MSE);

    // 内存训练数据
    struct fann_train_data *train_data = fann_create_train(num_data, 1, 1);
    for (unsigned int i = 0; i < num_data; ++i) {
        train_data->input[i][0] = x_vals[i];
        train_data->output[i][0] = y_vals[i];
    }

    // 手动训练循环,自己打印
    const unsigned int max_epochs = 5000;
    const unsigned int print_every = 100;
    const float desired_error = 0.0001f;

    for (unsigned int epoch = 1; epoch <= max_epochs; ++epoch) {
        fann_train_epoch(ann, train_data); // 每轮训练一次

        if (epoch % print_every == 0) {
            float mse = fann_get_MSE(ann);
            std::cout << "Epoch " << epoch 
                      << ", MSE = " << mse << std::endl;
            if (mse < desired_error) break; // 达到目标误差就停止
        }
    }

    // 测试
    std::cout << "Testing:\n";
    for (int i = -5; i <= 5; ++i) {
        float x = i / 5.0f;
        float* y_pred = fann_run(ann, &x);
        float y_out = ((y_pred[0] + 1)/2)*44; // 反归一化
        std::cout << "x=" << i << " pred=" << y_out << " real=" << (2*i*i-6) << "\n";
    }

    fann_destroy_train(train_data);
    fann_destroy(ann);
}

输出

Epoch 100, MSE = 0.00245492
Epoch 200, MSE = 0.000612225
Epoch 300, MSE = 0.000457924
Epoch 400, MSE = 0.000353085
Epoch 500, MSE = 0.000268855
Epoch 600, MSE = 0.0002015
Epoch 700, MSE = 0.000143414
Epoch 800, MSE = 8.59194e-005
Testing:
x=-5 pred=43.8645 real=44
x=-4 pred=26.2812 real=26
x=-3 pred=11.7201 real=12
x=-2 pred=2.10291 real=2
x=-1 pred=-4.00705 real=-4
x=0 pred=-6.00509 real=-6
x=1 pred=-3.85829 real=-4
x=2 pred=1.79174 real=2
x=3 pred=11.8935 real=12
x=4 pred=26.3925 real=26
x=5 pred=43.798 real=44