c++最简单反向传播神经网络,输入层3个nodes隐藏层4个node,输出层2个node,梯度下降……
![User](https://chat.openai.com/_next/image?url=https%3A%2F%2Fs.gravatar.com%2Favatar%2F49ed426aca1dabc616018b18ea198849%3Fs%3D480%26r%3Dpg%26d%3Dhttps%253A%252F%252Fcdn.auth0.com%252Favatars%252Fho.png&w=96&q=75)
c++最简单反向传播神经网络,输入层3个nodes隐藏层4个node,输出层2个node,梯度下降……
```
// c++神经网络22两个隐藏层有反向传播梯度下降更新权重230810a18.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
#include <iostream>
#include <vector>
//#include <cmath>
#include<sstream>////std::getline std::stof()
#include<iomanip> //std::setprecision
using namespace std;
int NodesNumofInpu25t = 9;//输入层Nodes
int NodesNhidde01n = 10;//第1个隐藏层Nodes
int NodesNhidde22n = 8;// 11;
int NodesNumOutpu2t = 4;// 5;//输出层Nodes
double Lost001 = 0.0;
class NeuralNetwork {
public:
NeuralNetwork(int input_nodes, int hidden1_nodes, int hidden2_nodes, int output_nodes)
: input_nodes(input_nodes), hidden1_nodes(hidden1_nodes), hidden2_nodes(hidden2_nodes), output_nodes(output_nodes) {
srand(time(NULL));
// 初始化权重和偏置
wih1.resize(hidden1_nodes, std::vector<double>(input_nodes));
wh1h2.resize(hidden2_nodes, std::vector<double>(hidden1_nodes));
wh2o.resize(output_nodes, std::vector<double>(hidden2_nodes));
bias_h1.resize(hidden1_nodes);
bias_h2.resize(hidden2_nodes);
bias_o.resize(output_nodes);
initWeightsAndBiases();
}
// Sigmoid激活函数及其导数
double sigmoid(double x) {
return 1.0 / (1.0 + exp(-x));
}
double sigmoid_prime(double x) {
return x * (1 - x);
}
// 前向传播Forward
std::vector<double> predict(const std::vector<double>& input) {
// 输入层到第一隐藏层
hidden1 = activate(input, wih1, bias_h1);
// 第一隐藏层到第二隐藏层
hidden2 = activate(hidden1, wh1h2, bias_h2);
// 第二隐藏层到输出层
output = activate(hidden2, wh2o, bias_o);
return output;
}
// 反向传播//Backpropagation
void train(const std::vector<double>& inputs, const std::vector<double>& targets, double lr) {
std::vector<double> outputs = predict(inputs);
// 输出层误差
std::vector<double> output_errors = subtract(targets, outputs);//
Lost001 = 0.0;
for (int ii = 0; ii < NodesNumOutpu2t; ++ii) { Lost001 += fabs(output_errors[ii]); }
//=========================================================================
// 隐藏层2误差
std::vector<double> hidden2_errors = dotT(output_errors, wh2o);
// 隐藏层1误差
std::vector<double> hidden1_errors = dotT(hidden2_errors, wh1h2);
// 更新权重: 隐藏层2到输出层
updateWeights(hidden2, output_errors, outputs, wh2o, bias_o, lr);
// 更新权重: 隐藏层1到隐藏层2
updateWeights(hidden1, hidden2_errors, hidden2, wh1h2, bias_h2, lr);
// 更新权重: 输入层到隐藏层1
updateWeights(inputs, hidden1_errors, hidden1, wih1, bias_h1, lr);
}// void train(
// // 反向传播//Backpropagation
private:
int input_nodes, hidden1_nodes, hidden2_nodes, output_nodes;
std::vector<std::vector<double>> wih1, wh1h2, wh2o;
std::vector<double> bias_h1, bias_h2, bias_o;
std::vector<double> hidden1, hidden2, output;
void initWeightsAndBiases() {
initLayerWeightsAndBiases(wih1, bias_h1);
initLayerWeightsAndBiases(wh1h2, bias_h2);
initLayerWeightsAndBiases(wh2o, bias_o);
}
void initLayerWeightsAndBiases(std::vector<std::vector<double>>& weights, std::vector<double>& biases) {
for (size_t i = 0; i < weights.size(); i++) {
for (size_t j = 0; j < weights[0].size(); j++) {
weights[i][j] = ((rand() % 2000) - 1000) / 1000.0;
}
biases[i] = ((rand() % 2000) - 1000) / 1000.0;
}
}
std::vector<double> activate(const std::vector<double>& inputs, const std::vector<std::vector<double>>& weights, const std::vector<double>& biases) {
std::vector<double> layer_output(weights.size(), 0.0);
for (size_t i = 0; i < weights.size(); i++) {
for (size_t j = 0; j < inputs.size(); j++) {
layer_output[i] += inputs[j] * weights[i][j];
}
layer_output[i] += biases[i];
layer_output[i] = sigmoid(layer_output[i]);
}
return layer_output;
}
//subtract求差:两个 向量的差
std::vector<double> subtract(const std::vector<double>& a, const std::vector<double>& b) {
std::vector<double> result(a.size(), 0.0);
for (size_t i = 0; i < a.size(); i++) {
result[i] = a[i] - b[i];
}
return result;
}
//dotT点乘
std::vector<double> dotT(const std::vector<double>& a, const std::vector<std::vector<double>>& b) {
std::vector<double> result(b[0].size(), 0.0);
for (size_t i = 0; i < b[0].size(); i++) {
for (size_t j = 0; j < a.size(); j++) {
result[i] += a[j] * b[j][i];
}
}
return result;
}
void updateWeights(const std::vector<double>& inputs, const std::vector<double>& errors, const std::vector<double>& outputs,
std::vector<std::vector<double>>& weights, std::vector<double>& biases, double lr) {
for (size_t i = 0; i < weights.size(); i++) {
for (size_t j = 0; j < weights[0].size(); j++) {
weights[i][j] += lr * errors[i] * sigmoid_prime(outputs[i]) * inputs[j];
}
biases[i] += lr * errors[i] * sigmoid_prime(outputs[i]);
}
}
};
int main() {
/* NodesNumofInpu25t = 9;
int NodesNhidde01n = 10;
int NodesNhidde22n = 11;
int NodesNumOutpu2t = 5;*/
NeuralNetwork nn(NodesNumofInpu25t, 4, 3, NodesNumOutpu2t);
std::vector<double> input001 = { 0.1, 0.2, 0.3, 0.4, 0.5 };
std::vector<double> target001 = { 0.01, 0.99 };
// Example
std::vector<double> input[5];
input[0] = { 0,1,0, 0,1,0, 0,1,0 }; //1“竖线”或 “1”字{ 1.0, 0.5, 0.25, 0.125 };
input[1] = { 0,0,0, 1,1,1,0,0,0 }; //-“横线”或 “-”减号{ 1.0, 0.5, 0.25, 0.125 };
input[2] = { 0,1,0, 1,1,1, 0,1,0 }; //+“+”加号{ 1.0, 0.5, 0.25, 0.125 };
input[3] = { 0,1,0, 0,1.2, 0, 0,1, 0 }; // '1'或 '|'字型{ 1.0, 0.5, 0.25, 0.125 };
input[4] = { 1,1,0, 1,0,1.2, 1,1,1 }; //“口”字型+{ 1.0, 0.5, 0.25, 0.125 };
std::vector<double> target[5];
target[0] = { 1.0, 0,0,0 };// , 0};//1 , 0}; //0.0, 1.0, 0.5}; //{ 0.0, 1.0 };
target[1] = { 0, 1.0 ,0,0 };// , 0};//- 91.0, 0};// , 0, 0}; //
target[2] = { 0,0,1.0,0 };// , 0};//+ 1.0, 0.5};
target[3] = { 1.0 ,0,0, 0.5 };// , 0}; //1
target[4] = { 0,0,0,0 };// , 1.0}; //“口”
for (int i = 0; i < 900000; i++) {//for220i
for (int jj = 0; jj < 5 /*4*/; ++jj) {
nn.train(input[jj], target[jj],0.1);
}//for2230jj
//nn.train(input, target, 0.1);printf(".");
if (0 == i % 10000) {
std::cout << "[Lost:" << Lost001 << std::endl;
}//if2250
Lost001 = 0;
}//for220i
std::vector<double> output = nn.predict(input[0]);
std::cout << "Predicted: " << output[0] << ", " << output[1] << std::endl;
//-----------------------------------------------
cout << endl;
input[1] = { 0,1,0, 0,1.23,0, 0,1.32,0 }; //1/
//std:; vector<double>
output = nn.predict(input[1]);
for (auto& val : output)
std::cout << std::fixed << std::setprecision(9) << val << " ";
cout << endl;
//--------------------------------------
input[1] = { 0,0,0, 1,1, 0.98, 0,0,0 }; //1/
//std:; vector<double>
output = nn.predict(input[1]);
for (auto& val : output)
std::cout << std::fixed << std::setprecision(9) << val << " ";
cout << endl;
//-------------------------------------------------------------
std::string S;
// int D[9];
do {
std::cout << std::endl << "请输入一个字符串(要求字符串是包含9个由逗号分隔的数字的字符串,如 1,2,0,0,5,0,0,8,9等): "<<std::endl;
std::getline(std::cin, S);
std::stringstream ss(S);
for (int i = 0; i < 9; ++i) {
std::string temp;
std::getline(ss, temp, ',');
input[1][i] = (double)std::stof(temp); // 将字符串转化为整数
}
std::cout << "数字数组为: ";
for (int i = 0; i < 9; ++i) {
std::cout << input[1][i] << " ";
}
output = nn.predict(input[1]);
std::cout << std::endl;
for (auto& val : output)
std::cout << std::fixed << std::setprecision(9) << val << " ";
} while (true);// 1 == 1);
//====================================================
//
return 0;
}//main
```