基于C++實現的AI
以下是基于C++實現的AI/機器學習相關示例,涵蓋基礎算法、計算機視覺、自然語言處理等領域,適合不同階段的學習者參考:
基礎機器學習算法
-
線性回歸
使用梯度下降法預測連續值,核心公式:
損失函數:
-
邏輯回歸
二分類問題實現,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個測試樣本,每個樣本是28x28的灰度圖像。需要將數據加載為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"};
-
<