用现代C++构建前反向传播神经网络(backpropagation Neural Network)230829a

使用现代C++构建神经网络,初始化权重矩阵weights,前向、反向传播神经网络的例子。构建一个具有任意层数和每层任意结点数的全连接神经网络(backpropagation Neural Network)。这个例子也包括了基本的梯度下降优化,要求实现异或xor的神经网络,要求输入数据有四组{1,0}、{0,1}、{1,1}、{0,0},训练目标数据target也有四个{1}、{1}、{0}、{0}……要求每次train训练前初始化权重矩阵,训练结束后将weights权重矩阵保存到文本文件,以供下次添加其它训练数据后,使用上次训练的权重矩阵接着训练!要求增加1个菜单,输入4则初始化权重矩阵;输入5则保存权重矩阵到带时间戳的文本文件名(文件名带时间戳weights_yyMMdd.txt)注意时间中月份小于10月则前加0,比如01月02月!

ChatGPT

以下是使用现代C++来构建一个前向、反向传播的全连接神经网络的示例代码。这个示例解决了异或(XOR)问题,并包括了基本的梯度下降优化。该代码还包含一个菜单,用于初始化权重矩阵和保存权重矩阵到带时间戳的文件。

注意:这里只是一个简化的例子,用于说明基本的神经网络操作和文件操作。


//使用现代C++构建的前向、反向传播神经网络的例子。构建一个具有任意层数和每层任意结点数的全连接神经网络(backpropagation Neural Network)。这个例子也包括了基本的梯度下降优化,要求实现异或xor的神经网络,要求输入数据有四组{1,0}、{0,1}、{1,1}、{0,0},训练目标数据target也有四个{1}、{1}、{0}、{0}……要求每次train训练结束以后将weights权重矩阵保存到文本文件,以供下次添加其它训练数据后,使用上次训练的权重矩阵接着训练!要求增加1个菜单,输入4则初始化权重矩阵! modern异或c++ArbitraryLayerBackpropagationNN调整权重矩阵230830a.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include <iostream>
#include <vector>
//#include <cmath>
#include <fstream>
#include <random>
#include <string> //std::to_string
#pragma warning(disable : 4996)

using namespace std;

class NeuralNetwork {
//private:
public:
    vector<vector<vector<double>>> weights;
    vector<vector<double>> layers;
    vector<vector<double>> deltas;

public:
    NeuralNetwork(vector<int> topology) {
        random_device rd;
        mt19937 gen(rd());
        normal_distribution<> d(0.0, 1.0);

        // Initialize weights
        for (int i = 1; i < topology.size(); ++i) {
            vector<vector<double>> layer_weights(topology[i], vector<double>(topology[i - 1]));
            for (auto& neuron_weights : layer_weights) {
                for (auto& weight : neuron_weights) {
                    weight = d(gen);
                }
            }
            weights.push_back(layer_weights);
        }

        // Initialize layers and deltas
        for (int neurons : topology) {
            layers.push_back(vector<double>(neurons, 0.0));
            deltas.push_back(vector<double>(neurons, 0.0));
        }
    }

    //-----------------------------------------------------------------

    // 初始化网络权重和偏置
    std::vector<std::vector<std::vector<double>>> initialize_weights(const std::vector<int>& layers) {
        std::vector<std::vector<std::vector<double>>> weights;
        std::random_device rd;
        std::mt19937 gen(rd());
        std::uniform_real_distribution<> dis(0.0, 1.0);

        for (size_t i = 1; i < layers.size(); ++i) {
            std::vector<std::vector<double>> layer_weights;

            for (int j = 0; j < layers[i]; ++j) {
                std::vector<double> neuron_weights;

                for (int k = 0; k < layers[i - 1]; ++k) {
                    neuron_weights.push_back(dis(gen));
                }

                layer_weights.push_back(neuron_weights);
            }

            weights.push_back(layer_weights);
        }

        return weights;
    }
//===========================================================



    void feedForward(vector<double> input) {
        layers[0] = input;
        for (int i = 1; i < layers.size(); ++i) {
            for (int j = 0; j < layers[i].size(); ++j) {
                layers[i][j] = 0;
                for (int k = 0; k < layers[i - 1].size(); ++k) {
                    layers[i][j] += layers[i - 1][k] * weights[i - 1][j][k];
                }
                layers[i][j] = 1 / (1 + exp(-layers[i][j]));
            }
        }
    }//void feedForward(

    void feedForwarOut(vector<double> input) {
        layers[0] = input;
        for (int i = 1; i < layers.size(); ++i) {
            for (int j = 0; j < layers[i].size(); ++j) {
                layers[i][j] = 0;
                for (int k = 0; k < layers[i - 1].size(); ++k) {
                    layers[i][j] += layers[i - 1][k] * weights[i - 1][j][k];
                }
                layers[i][j] = 1 / (1 + exp(-layers[i][j]));

                cout << layers[i][j];

                cout << "]," << endl;
            }

            cout << "}; " << endl;
            cout << endl;
        }
    }//void feedForwarOut(

    //----------------------------------------------------------------------

    void backPropagate(vector<double> target) {
        for (int i = 0; i < layers.back().size(); ++i) {
            double output = layers.back()[i];
            deltas.back()[i] = output * (1 - output) * (target[i] - output);
        }

        for (int i = layers.size() - 2; i > 0; --i) {
            for (int j = 0; j < layers[i].size(); ++j) {
                double sum = 0;
                for (int k = 0; k < layers[i + 1].size(); ++k) {
                    sum += deltas[i + 1][k] * weights[i][k][j];
                }
                deltas[i][j] = layers[i][j] * (1 - layers[i][j]) * sum;
            }
        }

        for (int i = 0; i < weights.size(); ++i) {
            for (int j = 0; j < weights[i].size(); ++j) {
                for (int k = 0; k < weights[i][j].size(); ++k) {
                    weights[i][j][k] += 0.5 * deltas[i + 1][j] * layers[i][k];
                }
            }
        }
    }

    void train(vector<vector<double>> inputs, vector<vector<double>> targets, int epochs) {
        for (int i = 0; i < epochs; ++i) {
            for (int j = 0; j < inputs.size(); ++j) {
                feedForward(inputs[j]);
                backPropagate(targets[j]);
            }
        }
    }

    void saveWeights(const string& filename) {
        ofstream file(filename);
        if (file.is_open()) {
            for (const auto& layer : weights) {
                for (const auto& neuron : layer) {
                    for (const auto& weight : neuron) {
                        file << weight << " ";
                    }
                    file << endl;
                }
            }
            file.close();
        }
    }

    void loadWeights(const string& filename) {
        ifstream file(filename);
        if (file.is_open()) {
            for (auto& layer : weights) {
                for (auto& neuron : layer) {
                    for (auto& weight : neuron) {
                        file >> weight;
                    }
                }
            }
            file.close();
        }
    }
};


std::string getCurrentTimeStamp() {
    std::time_t t = std::time(nullptr); // 获取当前时间
    std::tm tm = *std::localtime(&t);  // 将 time_t 转换为 tm 结构体

    char buffer[20];
    // 格式化时间字符串为 "yyMMddHHmmss" 格式
    std::strftime(buffer, sizeof(buffer), "%y%m%d%H%M%S", &tm);

    return std::string(buffer);
}

int main() {
    vector<vector<double>> inputs = { {1, 1}, {0, 0}, {1, 0}, {0, 1} };
    vector<vector<double>> targets = { {0}, {0}, {1}, {1} };

    NeuralNetwork nn({ 2, 3, 1 });
    string weightFile = "\/weights220101.txt";

    int choice;

    for (int ii = 0; true; ++ii) {//for110ii
        cout << "Menu: \n";
        cout << "1: (调用上次weights)并继续训练,并保存weights!Load and continue training, then save weights\n";
        cout << "2:(调用上次weights)继续训练,且不保存weights!\n";
        cout << "3:不训练,只保存weights!\n";
        cout << "4: 初始化weights矩阵!Initialize new weights and train, then save weights\n";
        cout << "5:保存weights到 特定文件(带时间戳的)!\n";
        cout << "Enter your choice: ";
        cin >> choice;

        if (choice == 1) {
            nn.loadWeights(weightFile);
        }

        cout << "Training..." << endl;
        nn.train(inputs, targets, 500000);// 10000);

        if (choice == 1 || choice == 4) {
            nn.saveWeights(weightFile);
            cout << "Weights saved to " << weightFile << endl;
        }

        if (4 == choice) {
            
            nn.weights = nn.initialize_weights({ 2, 3, 1 });

        }//
        //-----------------------------------------------------
//        inputs[0] = { 1,1 };
        cout << "[1,1:_ ";
        nn.feedForwarOut(inputs[0]);

//        inputs[1] = { 0,0 };
        cout << "[0,0:_ ";
        nn.feedForwarOut(inputs[1]);
//        inputs[2] = { 1,0 };
        cout << "[1,0:_ ";
        nn.feedForwarOut(inputs[2]);
//        inputs[3] = { 0,1 };
        cout << "[0,1:_ ";
        nn.feedForwarOut(inputs[3]);
        cout << endl;


        if (5 == choice) {
            time_t now = time(0);
            tm* ltm = localtime(&now);
            std::string filename02 = "\/weights_" + getCurrentTimeStamp() + std::to_string(ltm->tm_mday) + ".txt";
            nn.saveWeights( filename02);
        }//if(5==choice
        //======================================================
    }//for110i

    return 0;
}//main(

猜你喜欢

转载自blog.csdn.net/aw344/article/details/132580018