1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 |
#include <iostream> #include <vector> #include <cmath> #include <cstdlib> #include <ctime> class NeuralNetwork { private: std::vector<std::vector<double>> weights1; // Weights between input and hidden layer std::vector<std::vector<double>> weights2; // Weights between hidden and output layer std::vector<double> hiddenLayer; // Neurons in the hidden layer std::vector<double> outputLayer; // Neurons in the output layer double learningRate; // Activation function (sigmoid) double sigmoid(double x) { return 1.0 / (1.0 + exp(-x)); } // Derivative of the sigmoid function double sigmoidDerivative(double x) { return x * (1.0 - x); } public: NeuralNetwork(int inputSize, int hiddenSize, int outputSize, double lr) : learningRate(lr) { srand(static_cast<unsigned>(time(0))); // Initialize weights with random values weights1.resize(inputSize, std::vector<double>(hiddenSize)); for (auto &row : weights1) { for (auto &weight : row) { weight = ((double)rand() / RAND_MAX); } } weights2.resize(hiddenSize, std::vector<double>(outputSize)); for (auto &row : weights2) { for (auto &weight : row) { weight = ((double)rand() / RAND_MAX); } } hiddenLayer.resize(hiddenSize); outputLayer.resize(outputSize); } // Feedforward process std::vector<double> feedForward(const std::vector<double> &input) { for (size_t i = 0; i < hiddenLayer.size(); ++i) { double sum = 0.0; for (size_t j = 0; j < input.size(); ++j) { sum += input[j] * weights1[j][i]; } hiddenLayer[i] = sigmoid(sum); } for (size_t i = 0; i < outputLayer.size(); ++i) { double sum = 0.0; for (size_t j = 0; j < hiddenLayer.size(); ++j) { sum += hiddenLayer[j] * weights2[j][i]; } outputLayer[i] = sigmoid(sum); } return outputLayer; } // Backpropagation process void backpropagate(const std::vector<double> &input, const std::vector<double> &target) { std::vector<double> outputError(outputLayer.size()); std::vector<double> hiddenError(hiddenLayer.size()); // Calculate error at output layer for (size_t i = 0; i < outputLayer.size(); ++i) { outputError[i] = (target[i] - outputLayer[i]) * sigmoidDerivative(outputLayer[i]); } // Calculate error at hidden layer for (size_t i = 0; i < hiddenLayer.size(); ++i) { double sum = 0.0; for (size_t j = 0; j < outputError.size(); ++j) { sum += outputError[j] * weights2[i][j]; } hiddenError[i] = sum * sigmoidDerivative(hiddenLayer[i]); } // Update weights between hidden and output layer for (size_t i = 0; i < hiddenLayer.size(); ++i) { for (size_t j = 0; j < outputLayer.size(); ++j) { weights2[i][j] += learningRate * outputError[j] * hiddenLayer[i]; } } // Update weights between input and hidden layer for (size_t i = 0; i < input.size(); ++i) { for (size_t j = 0; j < hiddenLayer.size(); ++j) { weights1[i][j] += learningRate * hiddenError[j] * input[i]; } } } // Train the neural network void train(const std::vector<std::vector<double>> &trainingInputs, const std::vector<std::vector<double>> &trainingOutputs, int epochs) { for (int i = 0; i < epochs; ++i) { for (size_t j = 0; j < trainingInputs.size(); ++j) { feedForward(trainingInputs[j]); backpropagate(trainingInputs[j], trainingOutputs[j]); } } } // Test the neural network void test(const std::vector<double> &input) { std::vector<double> output = feedForward(input); std::cout << "Output: "; for (const auto &o : output) { std::cout << o << " "; } std::cout << "\n"; } }; int main() { // Simple dataset for XOR problem std::vector<std::vector<double>> inputs = {{0, 0}, {0, 1}, {1, 0}, {1, 1}}; std::vector<std::vector<double>> outputs = {{0}, {1}, {1}, {0}}; NeuralNetwork nn(2, 2, 1, 0.5); // Train the network nn.train(inputs, outputs, 10000); // Test the network std::cout << "Testing the trained network on XOR problem:\n"; for (const auto &input : inputs) { std::cout << "Input: " << input[0] << " " << input[1] << " => "; nn.test(input); } return 0; } |
Explanation
- NeuralNetwork Class:
- The
NeuralNetwork
class implements a simple feedforward neural network with one hidden layer. - The class contains the following data members:
weights1
: Weights connecting the input layer to the hidden layer.weights2
: Weights connecting the hidden layer to the output layer.hiddenLayer
: The neurons in the hidden layer.outputLayer
: The neurons in the output layer.learningRate
: The learning rate used during backpropagation.
- The
- Feedforward Process:
- The
feedForward
method calculates the output of the network by passing the input through the hidden layer and then to the output layer, applying the sigmoid activation function at each step.
- The
- Backpropagation Process:
- The
backpropagate
method updates the weights in the network using the backpropagation algorithm. It calculates the error at the output layer, propagates it back to the hidden layer, and then updates the weights accordingly.
- The
- Training the Network:
- The
train
method trains the neural network using the training data. It repeatedly feeds the input through the network and updates the weights using backpropagation.
- The
- Testing the Network:
- The
test
method evaluates the network on new input data, printing the network’s output.
- The
- XOR Problem:
- The main function trains the network on the XOR problem, a classic problem for neural networks. The network is then tested on the same problem to verify that it has learned the correct output.