AI算法实现解析-C++实例

基于C++实现的AI

以下是基于C++实现的AI/机器学习相关示例,涵盖基础算法、计算机视觉、自然语言处理等领域,适合不同阶段的学习者参考:

基础机器学习算法

线性回归
使用梯度下降法预测连续值,核心公式:
图片[1] - AI算法实现解析-C++实例 - 宋马
损失函数:

逻辑回归
二分类问题实现,Sigmoid函数:

K-Means聚类
基于欧式距离的无监督聚类算法。

朴素贝叶斯分类器
文本分类示例,计算条件概率:

决策树ID3算法
通过信息增益选择特征分支。

基于C++实现全连接神经网络(MLP)
 

以下是基于C++实现全连接神经网络(MLP)的示例场景和代码片段,涵盖基础实现、优化技巧和实际应用案例。所有示例均遵循现代C++标准(C++17/20),并使用Eigen库进行矩阵运算加速。

基础MLP实现

#include <Eigen/Dense>
#include <vector>
#include <cmath>

// 激活函数
inline double sigmoid(double x) {
    return 1.0 / (1.0 + exp(-x));
}

// 网络结构定义
class MLP {
private:
    std::vector<Eigen::MatrixXd> weights;
    std::vector<Eigen::VectorXd> biases;
public:
    MLP(const std::vector<int>& layers) {
        for (size_t i = 1; i < layers.size(); ++i) {
            weights.emplace_back(Eigen::MatrixXd::Random(layers[i], layers[i-1]));
            biases.emplace_back(Eigen::VectorXd::Zero(layers[i]));
        }
    }
    
    Eigen::VectorXd forward(const Eigen::VectorXd& input) {
        Eigen::VectorXd output = input;
        for (size_t i = 0; i < weights.size(); ++i) {
            output = (weights[i] * output + biases[i]).unaryExpr(&sigmoid);
        }
        return output;
    }
};

反向传播实现

void MLP::backprop(const Eigen::VectorXd& input, 
                  const Eigen::VectorXd& target,
                  double learning_rate) {
    // 前向传播缓存
    std::vector<Eigen::VectorXd> activations;
    activations.push_back(input);
    
    Eigen::VectorXd output = input;
    for (const auto& w : weights) {
        output = (w * output).unaryExpr(&sigmoid);
        activations.push_back(output);
    }
    
    // 计算输出层误差
    Eigen::VectorXd error = (activations.back() - target).cwiseProduct(
        activations.back().cwiseProduct(Eigen::VectorXd::Ones(output.size()) - activations.back())
    );
    
    // 反向传播
    for (int i = weights.size() - 1; i >= 0; --i) {
        Eigen::MatrixXd delta = error * activations[i].transpose();
        weights[i] -= learning_rate * delta;
        biases[i] -= learning_rate * error;
        
        if (i > 0) {
            error = (weights[i].transpose() * error).cwiseProduct(
                activations[i].cwiseProduct(Eigen::VectorXd::Ones(activations[i].size()) - activations[i])
            );
        }
    }
}

应用场景示例

数字识别
MLP mnist_model({784, 128, 64, 10});  // MNIST输入为28x28=784
房价预测
MLP housing_model({13, 32, 16, 1});  // Boston Housing数据集

XOR问题
MLP xor_model({2, 4, 1});  // 经典非线性问题

时间序列预测
MLP lstm_alternative({10, 64, 32, 1});  // 替代LSTM的简化方案

其他应用
// 5. 手写公式识别
// 6. 股票价格预测  
// 7. 语音特征分类
// 8. 医疗诊断系统
// 9. 自动驾驶感知层
// 10. 推荐系统
// ... (其他20个场景)


性能优化技巧

批量处理
Eigen::MatrixXd batch_forward(const Eigen::MatrixXd& inputs) {
    Eigen::MatrixXd outputs = inputs;
    for (const auto& w : weights) {
        outputs = (w * outputs).colwise() + biases[&w - &weights[0]];
        outputs = outputs.unaryExpr(&sigmoid);
    }
    return outputs;
}

GPU加速(使用CUDA)
// 需配合cuBLAS或自定义kernel实现矩阵运算

完整训练流程示例

void train(MLP& model, 
          const std::vector<Eigen::VectorXd>& inputs,
          const std::vector<Eigen::VectorXd>& targets,
          int epochs) {
    for (int epoch = 0; epoch < epochs; ++epoch) {
        double total_loss = 0;
        for (size_t i = 0; i < inputs.size(); ++i) {
            model.backprop(inputs[i], targets[i], 0.01);
            total_loss += (model.forward(inputs[i]) - targets[i]).squaredNorm();
        }
        std::cout << "Epoch " << epoch << " Loss: " << total_loss << std::endl;
    }
}

卷积神经网络(CNN)

以下是一些关于卷积神经网络(CNN)的C++实现示例及其相关资源,涵盖从基础到进阶的应用场景。这些例子可以帮助理解CNN的核心概念和实际编码实现。

基础CNN实现示例

简单卷积层实现
使用C++实现基础的二维卷积操作,包含输入矩阵和卷积核的乘法与累加运算。

void conv2d(float* input, float* kernel, float* output, int in_h, int in_w, int k_h, int k_w) {
    for (int i = 0; i <= in_h - k_h; ++i) {
        for (int j = 0; j <= in_w - k_w; ++j) {
            float sum = 0.0f;
            for (int m = 0; m < k_h; ++m) {
                for (int n = 0; n < k_w; ++n) {
                    sum += input[(i + m) * in_w + (j + n)] * kernel[m * k_w + n];
                }
            }
            output[i * (in_w - k_w + 1) + j] = sum;
        }
    }
}

ReLU激活函数
实现逐元素的ReLU非线性激活函数。

void relu(float* data, int size) {
    for (int i = 0; i < size; ++i) {
        data[i] = std::max(0.0f, data[i]);
    }
}

最大池化层
对输入特征图进行下采样,提取主要特征。

void max_pooling(float* input, float* output, int in_h, int in_w, int pool_size) {
    int out_h = in_h / pool_size;
    int out_w = in_w / pool_size;
    for (int i = 0; i < out_h; ++i) {
        for (int j = 0; j < out_w; ++j) {
            float max_val = -FLT_MAX;
            for (int m = 0; m < pool_size; ++m) {
                for (int n = 0; n < pool_size; ++n) {
                    max_val = std::max(max_val, input[(i * pool_size + m) * in_w + (j * pool_size + n)]);
                }
            }
            output[i * out_w + j] = max_val;
        }
    }
}

进阶CNN库与框架示例

使用OpenCV的DNN模块
加载预训练的CNN模型(如Caffe或TensorFlow格式)进行图像分类。

#include <opencv2/dnn.hpp>
cv::dnn::Net net = cv::dnn::readNetFromCaffe("model.prototxt", "weights.caffemodel");
cv::Mat blob = cv::dnn::blobFromImage(image, 1.0, cv::Size(224, 224), cv::Scalar(104, 117, 123));
net.setInput(blob);
cv::Mat prob = net.forward();

TensorFlow C++ API
构建一个简单的CNN模型并训练MNIST数据集。

#include <tensorflow/cc/client/client_session.h>
tensorflow::Scope root = tensorflow::Scope::NewRootScope();
auto input = tensorflow::ops::Placeholder(root, tensorflow::DT_FLOAT);
auto conv = tensorflow::ops::Conv2D(root, input, kernel, {1, 1, 1, 1}, "SAME");

Armadillo线性代数库
实现卷积运算的高效矩阵乘法。

#include <armadillo>
arma::mat input = arma::randu(28, 28);
arma::mat kernel = arma::randu(3, 3);
arma::mat output = arma::conv2(input, kernel, "same");

手写数字识别(MNIST) 

C++手写数字识别(MNIST)实现步骤

数据预处理

MNIST数据集包含60,000个训练样本和10,000个测试样本,每个样本是28×28的灰度图像。需要将数据加载为C++可处理的格式,通常转换为一维数组或二维向量。

// 示例:读取MNIST二进制文件
void load_mnist_images(const std::string& path, std::vector<std::vector<float>>& images) {
    std::ifstream file(path, std::ios::binary);
    if (file.is_open()) {
        int magic_number, num_images, rows, cols;
        file.read((char*)&magic_number, sizeof(magic_number));
        file.read((char*)&num_images, sizeof(num_images));
        file.read((char*)&rows, sizeof(rows));
        file.read((char*)&cols, sizeof(cols));
        magic_number = ntohl(magic_number);
        num_images = ntohl(num_images);
        rows = ntohl(rows);
        cols = ntohl(cols);
        for (int i = 0; i < num_images; ++i) {
            std::vector<float> image(rows * cols);
            for (int j = 0; j < rows * cols; ++j) {
                unsigned char pixel;
                file.read((char*)&pixel, sizeof(pixel));
                image[j] = static_cast<float>(pixel) / 255.0f;
            }
            images.push_back(image);
        }
    }
}

模型构建

实现一个简单的全连接神经网络或卷积神经网络(CNN)。以下是一个全连接网络的示例:

class NeuralNetwork {
private:
    std::vector<std::vector<float>> weights;
    std::vector<float> biases;
    int input_size, hidden_size, output_size;

public:
    NeuralNetwork(int input, int hidden, int output) 
        : input_size(input), hidden_size(hidden), output_size(output) {
        // 初始化权重和偏置
        weights.resize(2);
        weights[0].resize(input_size * hidden_size);
        weights[1].resize(hidden_size * output_size);
        biases.resize(hidden_size + output_size);
        // 随机初始化
        std::random_device rd;
        std::mt19937 gen(rd());
        std::normal_distribution<float> dist(0.0f, 0.1f);
        for (auto& w : weights[0]) w = dist(gen);
        for (auto& w : weights[1]) w = dist(gen);
        for (auto& b : biases) b = dist(gen);
    }

    std::vector<float> forward(const std::vector<float>& input) {
        std::vector<float> hidden(hidden_size);
        for (int i = 0; i < hidden_size; ++i) {
            hidden[i] = biases[i];
            for (int j = 0; j < input_size; ++j) {
                hidden[i] += input[j] * weights[0][j * hidden_size + i];
            }
            hidden[i] = std::max(0.0f, hidden[i]); // ReLU
        }
        std::vector<float> output(output_size);
        for (int i = 0; i < output_size; ++i) {
            output[i] = biases[hidden_size + i];
            for (int j = 0; j < hidden_size; ++j) {
                output[i] += hidden[j] * weights[1][j * output_size + i];
            }
            output[i] = std::exp(output[i]); // Softmax (需归一化)
        }
        float sum = std::accumulate(output.begin(), output.end(), 0.0f);
        for (auto& val : output) val /= sum;
        return output;
    }
};

训练与评估

使用反向传播算法和随机梯度下降(SGD)训练模型:

void train(NeuralNetwork& nn, const std::vector<std::vector<float>>& images, 
           const std::vector<int>& labels, int epochs, float lr) {
    for (int epoch = 0; epoch < epochs; ++epoch) {
        float loss = 0.0f;
        for (size_t i = 0; i < images.size(); ++i) {
            auto output = nn.forward(images[i]);
            // 计算交叉熵损失
            loss += -std::log(output[labels[i]]);
            // 反向传播(简化版)
            // 此处省略具体实现
        }
        std::cout << "Epoch " << epoch << ", Loss: " << loss / images.size() << std::endl;
    }
}
示例代码库推荐

tiny-dnn:轻量级C++深度学习库,支持MNIST训练。

#include <tiny_dnn/tiny_dnn.h>
using namespace tiny_dnn;
void train_mnist() {
    network<sequential> net;
    net << fully_connected_layer(28*28, 100) << activation::relu()
        << fully_connected_layer(100, 10) << activation::softmax();
    adagrad optimizer;
    std::vector<vec_t> images;
    std::vector<label_t> labels;
    // 加载数据后训练
    net.train<mse>(optimizer, images, labels, 10, 1);
}

Armadillo + MLPACK:数值计算库结合机器学习库。

#include <mlpack/methods/ann/ffn.hpp>
using namespace mlpack::ann;
FFN<NegativeLogLikelihood, RandomInitialization> model;
model.Add<Linear>(100);
model.Add<ReLU>();
model.Add<Linear>(10);
model.Add<LogSoftMax>();
性能优化

使用多线程(OpenMP)加速矩阵运算。
启用SIMD指令(如AVX)优化计算。
利用GPU加速(如CUDA或OpenCL)。

通过以上步骤,可以构建一个基础的C++手写数字识别系统。实际应用中,建议使用成熟的深度学习框架(如TensorFlow C++ API或LibTorch)以提升开发效率。

图像风格迁移

以下是关于C++实现图像风格迁移的30个实例概述及核心方法,涵盖经典算法和现代框架的应用案例。每个例子均提供关键代码片段或技术要点,供参考实现。


基于OpenCV的简单风格迁移

使用OpenCV的滤波器和图像混合实现基础风格迁移效果:

#include <opencv2/opencv.hpp>
void styleTransfer(cv::Mat& src, cv::Mat& style, cv::Mat& dst) {
    cv::Mat src_gray, style_gray;
    cv::cvtColor(src, src_gray, cv::COLOR_BGR2GRAY);
    cv::cvtColor(style, style_gray, cv::COLOR_BGR2GRAY);
    cv::addWeighted(src, 0.7, style, 0.3, 0, dst);
}


基于神经网络的方法(C++接口)

使用LibTorch(PyTorch C++ API)实现快速风格迁移:

#include <torch/script.h>
torch::Tensor transfer(torch::Tensor input, torch::jit::script::Module& model) {
    std::vector<torch::jit::IValue> inputs = {input};
    return model.forward(inputs).toTensor();
}


OpenCV DNN模块加载预训练模型

加载TensorFlow或PyTorch导出的风格迁移模型:

cv::dnn::Net net = cv::dnn::readNetFromTensorflow("model.pb");
net.setInput(cv::dnn::blobFromImage(inputImg));
cv::Mat output = net.forward();

基于Gram矩阵的风格损失计算

实现风格特征提取的核心数学计算:

cv::Mat gramMatrix(cv::Mat features) {
    cv::Mat gram;
    cv::mulTransposed(features, gram, false);
    return gram / (features.total());
}

实时视频风格迁移

结合OpenCV视频捕获和轻量级模型:

cv::VideoCapture cap(0);
while (true) {
    cap >> frame;
    cv::Mat styled = transferFrame(frame);
    cv::imshow("Live Style Transfer", styled);
}

30个实例分类概览

类型 技术栈 典型应用场景
1-5: 传统方法 OpenCV滤波/混合 实时低功耗设备
6-15: 神经网络 LibTorch/ONNX Runtime 高质量艺术生成
16-20: 视频处理 OpenCV+DNN 实时视频滤镜
21-25: 移动端优化 ARM NEON/TFLite 手机APP集成
26-30: 三维扩展 OpenGL/Vulkan互操作 游戏/VR场景

完整项目参考

FastPhotoStyle:基于C++/CUDA的快速迁移实现
OpenCV contrib samples:dnn_style_transfer示例
TorchScript范例:PyTorch官方C++导出教程

(注:实际开发需根据具体需求选择框架,建议优先测试ONNX格式模型的跨平台部署能力)

目标检测(YOLO Tiny)

C++ YOLO Tiny 目标检测实例

YOLO Tiny 是 YOLO (You Only Look Once) 的轻量级版本,适用于资源受限设备。以下是 C++ 实现 YOLO Tiny 目标检测的 30 个实例,涵盖不同应用场景。

基础实例

加载 YOLO Tiny 模型

使用 OpenCV 的 DNN 模块加载预训练模型。

cv::dnn::Net net = cv::dnn::readNet("yolov3-tiny.weights", "yolov3-tiny.cfg");

设置计算后端

使用 CUDA 或 OpenCL 加速推理。

net.setPreferableBackend(cv::dnn::DNN_BACKEND_CUDA);
net.setPreferableTarget(cv::dnn::DNN_TARGET_CUDA);

图像预处理

将输入图像转换为 Blob 格式。

cv::Mat blob = cv::dnn::blobFromImage(image, 1/255.0, cv::Size(416, 416), cv::Scalar(0,0,0), true, false);

执行前向传播

将 Blob 输入网络并获取输出。

net.setInput(blob);
std::vector<cv::Mat> outputs;
net.forward(outputs, net.getUnconnectedOutLayersNames());

后处理输出

解析检测结果并绘制边界框。

for (auto& output : outputs) {
    float* data = (float*)output.data;
    for (int i = 0; i < output.rows; ++i) {
        cv::Mat scores = output.row(i).colRange(5, output.cols);
        cv::Point classIdPoint;
        double confidence;
        cv::minMaxLoc(scores, 0, &confidence, 0, &classIdPoint);
        if (confidence > confidenceThreshold) {
            // 绘制边界框
        }
    }
}

进阶实例

实时视频检测

从摄像头捕获视频流并实时检测。

cv::VideoCapture cap(0);
while (true) {
    cv::Mat frame;
    cap >> frame;
    // 检测逻辑
    cv::imshow("Detection", frame);
    if (cv::waitKey(1) == 27) break;
}

多线程处理

使用多线程加速视频处理。

void processFrame(cv::Mat frame) {
    // 检测逻辑
}

std::thread t(processFrame, frame.clone());
t.detach();

自定义对象检测

训练自定义数据集并加载模型。

cv::dnn::Net net = cv::dnn::readNet("custom-yolov3-tiny.weights", "custom-yolov3-tiny.cfg");

非极大值抑制 (NMS)

过滤重叠的检测框。

cv::dnn::NMSBoxes(boxes, confidences, confidenceThreshold, nmsThreshold, indices);

性能优化

调整输入尺寸以提高速度。

cv::Mat blob = cv::dnn::blobFromImage(image, 1/255.0, cv::Size(320, 320), cv::Scalar(0,0,0), true, false);

应用场景实例

人脸检测

使用 YOLO Tiny 检测人脸。

std::vector<std::string> classes = {"face"};

车辆检测

检测道路上的车辆。

std::vector<std::string> classes = {"car", "truck", "bus"};

行人检测

监控场景中的行人。

std::vector<std::string> classes = {"person"};

<

© 版权声明
THE END
如果内容对您有所帮助,就支持一下吧!
点赞0 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容