Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <cmath>
- #include <random>
- #include <iostream>
- #include <time.h>
- using namespace std;
- template<typename T>
- struct Vector {
- private:
- T* elements;
- size_t _size;
- public:
- Vector() : elements(nullptr), _size(0) {}
- Vector(const size_t size) {
- this->elements = new T[size]{ T(0) };
- this->_size = size;
- }
- Vector(const Vector<T>& other) {
- this->_size = other._size;
- this->elements = new T[_size];
- for (size_t i = 0; i < _size; ++i)
- this->elements[i] = other.elements[i];
- }
- Vector<T>& operator =(const Vector<T>& other) {
- if (this == &other)
- return *this;
- delete[] this->elements;
- this->_size = other._size;
- this->elements = new T[this->_size];
- for (size_t i = 0; i < this->_size; ++i)
- this->elements[i] = other.elements[i];
- return *this;
- }
- Vector(Vector<T>&& other) : _size(other._size), elements(other.elements) {
- other._size = 0;
- other.elements = nullptr;
- }
- Vector<T>& operator =(Vector<T>&& other) {
- if (this == &other)
- return *this;
- delete[] this->elements;
- this->_size = other._size;
- this->elements = other.elements;
- other._size = 0;
- other.elements = nullptr;
- return *this;
- }
- size_t size() const { return _size; }
- T& operator[](const size_t index) {
- if (index < _size)
- return elements[index];
- }
- ~Vector() {
- delete[] elements;
- this->_size = 0;
- }
- };
- template<typename T>
- struct Matrix {
- private:
- Vector<T>* _matrix;
- size_t _rows;
- size_t _cols;
- public:
- Matrix() : _matrix(nullptr), _rows(0), _cols(0) {}
- Matrix(const size_t rows, const size_t cols) {
- this->_matrix = new Vector<T>[rows];
- for (size_t i = 0; i < rows; ++i)
- _matrix[i] = Vector<T>(cols);
- this->_rows = rows;
- this->_cols = cols;
- }
- Matrix(const Matrix<T>& other) {
- this->_rows = other._rows;
- this->_cols = other._cols;
- this->_matrix = new Vector<T>[_rows] { _cols };
- for (size_t i = 0; i < _rows; ++i)
- for (size_t j = 0; j < _cols; ++j)
- this->_matrix[i][j] = other._matrix[i][j];
- }
- Matrix<T>& operator =(const Matrix<T>& other) {
- if (this == &other)
- return *this;
- delete[] _matrix;
- this->_rows = other._rows;
- this->_cols = other._cols;
- _matrix = new Vector<T>[this->_rows]{ this->_cols };
- for (size_t i = 0; i < this->_rows; ++i)
- for (size_t j = 0; j < this->cols; ++j)
- _matrix[i][j] = other._matrix[i][j];
- return *this;
- }
- Matrix(Matrix<T>&& other)
- : _matrix(other._matrix), _rows(other._rows), _cols(other._cols) {
- other._matrix = nullptr;
- other._rows = 0;
- other._cols = 0;
- }
- Matrix<T>& operator =(Matrix<T>&& other) {
- if (&other == this)
- return *this;
- delete[] this->_matrix;
- this->_matrix = other._matrix;
- this->_rows = other._rows;
- this->_cols = other._cols;
- other._matrix = nullptr;
- other._rows = 0;
- other._cols = 0;
- return *this;
- }
- size_t rows() const { return _rows; }
- size_t cols() const { return _cols; }
- Vector<T>& operator[] (const size_t _rows) {
- if (_rows < this->_rows)
- return _matrix[_rows];
- }
- ~Matrix() {
- delete[] _matrix;
- this->_rows = 0;
- this->_cols = 0;
- }
- };
- struct NeuralNetwork {
- private:
- struct Neuron {
- double_t value;
- double_t error;
- public:
- Neuron(double_t value = 0) : value(value), error(0) {}
- operator double_t& () { return value; }
- };
- struct Weight {
- double_t value;
- double_t delta;
- public:
- Weight(double_t value = 0) : value(value), delta(0) {}
- operator double_t& () { return value; }
- };
- size_t count_layers;
- Matrix<Weight>* weights;
- Vector<Neuron>* layers;
- double_t E;
- double_t a;
- //Функция активации
- double_t(*activationFunc)(const double_t value) = [](const double_t value) {
- return value > 0.5 ? (double_t)1 : 0;
- };
- //Производная функции активации
- double_t(*derivativeFunc)(const double_t value) = [](const double_t value) {
- return (double_t)1;
- };
- double_t getRandomWeight() { return (double_t)(rand()) / RAND_MAX - 0.5; }
- public:
- NeuralNetwork(const size_t* dimensions, const size_t size,
- const double_t E = 0.5, const double_t a = 0.5) {
- srand(time(NULL));
- this->count_layers = size;
- this->weights = new Matrix<Weight>[count_layers - 1];
- this->layers = new Vector<Neuron>[count_layers];
- this->E = E;
- this->a = a;
- //Инициализация весов и слоев
- for (size_t i = 0; i < count_layers - 2; ++i) {
- weights[i] = Matrix<Weight>(dimensions[i] + 1, dimensions[i + 1] + 1);
- layers[i] = Vector<Neuron>(dimensions[i]);
- }
- weights[size - 2] = Matrix<Weight>(dimensions[size - 2] + 1, dimensions[size - 1]);
- layers[size - 2] = Vector<Neuron>(dimensions[size - 2]);
- layers[size - 1] = Vector<Neuron>(dimensions[size - 1]);
- fillRandomWeights();
- }
- //Заполнение весов случайными значениями от [-0.5, 0.5]
- void fillRandomWeights() {
- for (size_t i = 0; i < count_layers - 1; ++i)
- for (size_t j = 0; j < layers[i].size(); ++j) {
- for (size_t k = 0; k < layers[i + 1].size(); ++k)
- weights[i][j][k] = getRandomWeight();
- }
- }
- //Прямое прохождение
- void feedForward() {
- for (size_t i = 1; i < count_layers; ++i)
- for (size_t j = 0; j < layers[i].size(); ++j) {
- double_t summ = weights[i - 1][layers[i - 1].size()][j];
- for (size_t k = 0; k < layers[i - 1].size(); ++k)
- summ += layers[i - 1][k] * weights[i - 1][k][j];
- layers[i][j] = activationFunc(summ);
- }
- }
- //Расчет ошибок у выходных нейронов
- void findOutError(double_t* ideals) {
- size_t li = count_layers - 1;
- for (size_t i = 0; i < layers[li].size(); ++i) {
- layers[li][i].error = ideals[i] - layers[li][i];/*(ideals[i] - layers[li][i]) * derivativeFunc(layers[li][i]);*/
- //cout << layers[li][i].error << endl;
- }
- }
- //Расчет ошибок у скрытых нейронов
- void findHiddenError() {
- for (size_t i = count_layers - 2; i >= 1; --i)
- for (size_t j = 0; j < layers[i].size(); ++j) {
- double_t error = 0;
- for (size_t k = 0; k < layers[i + 1].size(); ++k)
- error += layers[i + 1][k].error * weights[i][j][k];
- layers[i][j].error = derivativeFunc(layers[i][j]) * error;
- }
- }
- //Обратное прохождение
- void backWards() {
- for (size_t i = 0; i < count_layers - 1; ++i) {
- for (size_t j = 0; j < layers[i].size(); ++j) {
- for (size_t k = 0; k < layers[i + 1].size(); ++k) {
- weights[i][j][k].delta = E * layers[i][j] * layers[i + 1][k].error + a * weights[i][j][k].delta;
- weights[i][j][k] += weights[i][j][k].delta;
- }
- }
- //Корректировка весок связанные с нейронами смещения
- for (size_t k = 0; k < layers[i + 1].size(); ++k) {
- weights[i][layers[i].size()][k].delta = E * layers[i + 1][k].error + a * weights[i][layers[i].size()][k].delta;
- weights[i][layers[i].size()][k] += weights[i][layers[i].size()][k].delta;
- }
- }
- }
- //Установка входных данных
- void setInputs(double_t* inputs) {
- for (size_t i = 0; i < layers[0].size(); ++i)
- layers[0][i] = inputs[i];
- }
- //Расчет ошибки сета
- double_t getTrainError(double_t* ideals) {
- size_t li = count_layers - 1;
- double_t error = 0;
- //cout << "Выходные значения нейронной сети: [";
- for (size_t i = 0; i < layers[li].size(); ++i) {
- error += (ideals[i] - layers[li][i]) * (ideals[i] - layers[li][i]);
- //cout << i << " = " << layers[li][i] << " ";
- }
- //cout << "]" << endl;
- return error / layers[li].size();
- }
- //Функция обучения
- void study(double_t** inputs, double_t** ideals, size_t count) {
- double_t error = 0;
- size_t epoch = 0;
- do {
- error = 0;
- for (size_t stepTrain = 0; stepTrain < count; ++stepTrain) {
- /*cout << "Идеальные ответы: " << inputs[stepTrain][0] << " ";
- if (inputs[stepTrain][2] == 0) cout << "& ";
- else cout << (inputs[stepTrain][2] == 0.5 ? "| " : "^ ");
- cout << inputs[stepTrain][1] << " = [0 = " << ideals[stepTrain][0] << ", 1 = " << ideals[stepTrain][1] << "]\n";*/
- setInputs(inputs[stepTrain]);
- feedForward();
- findOutError(ideals[stepTrain]);
- findHiddenError();
- backWards();
- double_t test = getTrainError(ideals[stepTrain]);
- error += test;
- cout << "Итоговая ошибка сета: " << test << endl;
- }
- error /= count;
- ++epoch;
- cout << epoch << " " << error << endl;
- } while (error >= 0.05);
- }
- //Получить выходные значения
- Vector<double_t> getOutputs(double_t* inputs) {
- setInputs(inputs);
- feedForward();
- Vector<double_t> res(layers[count_layers - 1].size());
- for (size_t i = 0; i < res.size(); ++i)
- res[i] = layers[count_layers - 1][i];
- return res;
- }
- ~NeuralNetwork() {
- delete[] weights;
- delete[] layers;
- }
- };
- double_t normalize_data(double_t val, double_t min, double_t max) {
- return (val - min) / (max - min);
- }
- double_t denormalize_data(double_t val, double_t min, double_t max) {
- return min + val * (max - min);
- }
- int main() {
- setlocale(LC_ALL, "Russian");
- getchar();
- //Размеры слоёв
- size_t* dimensions = new size_t[3]{ 3, 2, 2 };
- //Тренировочный сет
- double_t** trainSet = new double_t * [4] {
- new double_t[3]{ 0, 0, 2 },
- new double_t[3]{ 0, 1, 2 },
- new double_t[3]{ 1, 0, 2 },
- new double_t[3]{ 1, 1, 2 }
- };
- //Нормализация данных
- for (size_t i = 0; i < 4; ++i)
- trainSet[i][2] = normalize_data(trainSet[i][2], 0, 2);
- //Идеальные значения
- double_t** ideals = new double_t * [4] {
- new double_t[2]{ 1, 0 }, new double_t[2]{ 0, 1 },
- new double_t[2]{ 0, 1 }, new double_t[2]{ 1, 0 }
- };
- size_t size_train_set = 4;
- NeuralNetwork n(dimensions, 3, 0.4, 0.4);
- n.study(trainSet, ideals, size_train_set);
- delete[] dimensions;
- for (size_t i = 0; i < size_train_set; ++i) {
- delete[] trainSet[i];
- delete[] ideals[i];
- }
- delete[] trainSet;
- delete[] ideals;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement