求无依赖第三方库的C++机器学习实现方法及简单示例
手动用C++实现机器学习:线性回归示例
核心流程拆解
不管什么机器学习模型,通用流程都逃不过这几步:
- 数据预处理:对原始数据做归一化/标准化,消除量纲影响
- 模型定义:用数学表达式描述模型(比如线性回归的
y = wx + b) - 损失函数:衡量预测值和真实值的差异
- 优化算法:通过迭代调整模型参数,最小化损失
- 训练与评估:用训练数据更新参数,用测试数据验证效果
C++完整实现代码
下面是一个预测房屋价格的简化场景(假设房屋面积x对应价格y),全程仅依赖C++标准库:
#include <iostream> #include <vector> #include <cmath> #include <algorithm> // 数据归一化:把数值缩放到[0,1]区间 void normalize(std::vector<double>& data) { double min_val = *std::min_element(data.begin(), data.end()); double max_val = *std::max_element(data.begin(), data.end()); for (auto& val : data) { val = (val - min_val) / (max_val - min_val); } } // 线性回归预测:y = w*x + b double predict(double x, double w, double b) { return w * x + b; } // 计算均方误差(MSE)损失 double calculate_loss(const std::vector<double>& x, const std::vector<double>& y, double w, double b) { double total_loss = 0.0; for (size_t i = 0; i < x.size(); ++i) { double pred = predict(x[i], w, b); total_loss += std::pow(pred - y[i], 2); } return total_loss / x.size(); } // 计算梯度:损失对w和b的偏导数 void calculate_gradient(const std::vector<double>& x, const std::vector<double>& y, double w, double b, double& dw, double& db) { dw = 0.0; db = 0.0; for (size_t i = 0; i < x.size(); ++i) { double pred = predict(x[i], w, b); dw += (pred - y[i]) * x[i]; db += (pred - y[i]); } dw /= x.size(); db /= x.size(); } // 训练模型:批量梯度下降 void train_model(const std::vector<double>& x, const std::vector<double>& y, double& w, double& b, double learning_rate, int epochs) { for (int epoch = 0; epoch < epochs; ++epoch) { double dw, db; calculate_gradient(x, y, w, b, dw, db); // 更新参数 w -= learning_rate * dw; b -= learning_rate * db; // 每100轮打印一次损失 if (epoch % 100 == 0) { double loss = calculate_loss(x, y, w, b); std::cout << "Epoch " << epoch << ", Loss: " << loss << std::endl; } } } int main() { // 模拟训练数据:房屋面积(平方米) -> 价格(万元) std::vector<double> x_train = {50, 60, 70, 80, 90, 100}; std::vector<double> y_train = {15, 18, 21, 24, 27, 30}; // 数据归一化 normalize(x_train); normalize(y_train); // 初始化模型参数:w和b初始为0 double w = 0.0; double b = 0.0; // 训练参数 double learning_rate = 0.1; int epochs = 1000; // 训练模型 train_model(x_train, y_train, w, b, learning_rate, epochs); // 测试:输入归一化后的面积(对应原始85平米) double x_test = (85 - 50) / (100 - 50); // 原始85平米归一化后的值 double y_pred = predict(x_test, w, b); // 反归一化得到真实价格 double y_pred_real = y_pred * (30 - 15) + 15; std::cout << "\n预测85平米房屋价格:" << y_pred_real << "万元" << std::endl; return 0; }
代码关键部分解释
- 数据归一化:避免不同特征的数值范围差异过大(比如面积是几十,价格是几万),导致梯度下降收敛慢。这里用最小-最大归一化,把数据缩到0-1区间。
- 模型预测:完全遵循线性回归的数学公式
y = wx + b,没有任何黑箱逻辑。 - 损失函数:用均方误差衡量预测偏差,这是回归任务最常用的损失计算方式。
- 梯度计算:手动推导损失对w和b的偏导数,这是梯度下降的核心——明确参数往哪个方向调整能减少损失。
- 训练循环:迭代更新w和b,每次用全部训练数据计算梯度(批量梯度下降),直到损失趋于稳定。
进阶建议
- 这个示例是单特征线性回归,你可以扩展到多特征(比如加入房间数、楼层等),只需要把
w改成向量,计算梯度时对应每个特征的偏导即可。 - 可以尝试实现逻辑回归(分类任务),只需要把预测函数换成
sigmoid,损失函数换成交叉熵。 - 手动实现时重点要理解每一步的数学原理,而不是照搬代码——比如为什么用MSE?梯度下降的数学推导是什么?
内容的提问来源于stack exchange,提问作者Bryan Anthony
相关产品推荐
相关产品推荐

