C++实现简单的二分类神经网络
#include
class Network { private: int epoches; // 训练次数 double learning_rate; // 学习率 double w1, w2, w3, w4, w5, w6; // 网络参数 double b1, b2, b3;
public: Network(int epoches, double learning_rate) // 初始化网络参数 : epoches(epoches), learning_rate(learning_rate), w1(0.2), w2(0.4), w3(0.5), w4(0.7), w5(0.3), w6(0.6), b1(0.4), b2(0.5), b3(0.3) {}
// Sigmoid激活函数
double sigmoid(double x) {
return 1 / (1 + exp(-x));
}
// Sigmoid函数的导数
double deriv_sigmoid(double x) {
return sigmoid(x) * (1 - sigmoid(x));
}
// 前向传播,计算输出值
double forward(double x, double y) {
double h1 = sigmoid(w1 * x + w2 * y + b1); // 计算隐藏层节点1的值
double h2 = sigmoid(w3 * x + w4 * y + b2); // 计算隐藏层节点2的值
double output = sigmoid(w5 * h1 + w6 * h2 + b3); // 计算输出层节点的值
return output;
}
// 训练网络
void train(vector<pair<double, double>> data) {
for (int i = 0; i < epoches; ++i) { // 循环训练epoches次
double total_loss = 0;
for (auto point : data) { // 遍历训练数据
double x = point.first;
double y = point.second;
double target = (x > 0 && y > 0) ? 0 : 1; // 根据数据点位置确定目标标签
// 前向传播
double h1 = sigmoid(w1 * x + w2 * y + b1);
double h2 = sigmoid(w3 * x + w4 * y + b2);
double output = sigmoid(w5 * h1 + w6 * h2 + b3);
// 计算损失和梯度
double loss = pow(output - target, 2); // 计算均方误差
double dloss_doutput = 2 * (output - target); // 损失函数对输出值的导数
double doutput_dw5 = h1 * deriv_sigmoid(w5 * h1 + w6 * h2 + b3); // 输出层权重w5的梯度
double doutput_dw6 = h2 * deriv_sigmoid(w5 * h1 + w6 * h2 + b3); // 输出层权重w6的梯度
double doutput_db3 = deriv_sigmoid(w5 * h1 + w6 * h2 + b3); // 输出层偏置b3的梯度
double dh1_dw1 = x * deriv_sigmoid(w1 * x + w2 * y + b1); // 隐藏层节点1权重w1的梯度
double dh1_dw2 = y * deriv_sigmoid(w1 * x + w2 * y + b1); // 隐藏层节点1权重w2的梯度
double dh2_dw3 = x * deriv_sigmoid(w3 * x + w4 * y + b2); // 隐藏层节点2权重w3的梯度
double dh2_dw4 = y * deriv_sigmoid(w3 * x + w4 * y + b2); // 隐藏层节点2权重w4的梯度
double dh1_db1 = deriv_sigmoid(w1 * x + w2 * y + b1); // 隐藏层节点1偏置b1的梯度
double dh2_db2 = deriv_sigmoid(w3 * x + w4 * y + b2); // 隐藏层节点2偏置b2的梯度
// 更新参数
w5 -= learning_rate * dloss_doutput * doutput_dw5; // 更新输出层权重w5
w6 -= learning_rate * dloss_doutput * doutput_dw6; // 更新输出层权重w6
b3 -= learning_rate * dloss_doutput * doutput_db3; // 更新输出层偏置b3
w1 -= learning_rate * dloss_doutput * doutput_dw5 * dh1_dw1; // 更新隐藏层节点1权重w1
w2 -= learning_rate * dloss_doutput * doutput_dw5 * dh1_dw2; // 更新隐藏层节点1权重w2
w3 -= learning_rate * dloss_doutput * doutput_dw6 * dh2_dw3; // 更新隐藏层节点2权重w3
w4 -= learning_rate * dloss_doutput * doutput_dw6 * dh2_dw4; // 更新隐藏层节点2权重w4
b1 -= learning_rate * dloss_doutput * doutput_dw5 * dh1_db1; // 更新隐藏层节点1偏置b1
b2 -= learning_rate * dloss_doutput * doutput_dw6 * dh2_db2; // 更新隐藏层节点2偏置b2
total_loss += loss;
}
cout << "Epoch " << i + 1 << ", Loss: " << total_loss << endl;
}
}
// 预测
int predict(double x, double y) {
double output = forward(x, y);
return (output >= 0.5) ? 1 : 0; // 根据输出值判断分类结果
}
};
int main() { vector<pair<double, double>> data = {{1, 2}, {-1, -2}, {3, 4}, {-3, -4}}; // 初始化训练数据 Network network(1000, 0.1); // 创建网络对象 network.train(data); // 训练网络 double x, y;
cout << "请输入点的坐标(x, y): ";
cin >> x >> y; // 输入待预测点的坐标
int label = network.predict(x, y); // 预测点的标签
cout << "预测标签: " << label << endl;
return 0;
}
原文地址: https://www.cveoy.top/t/topic/qzwH 著作权归作者所有。请勿转载和采集!