����λ�ã���ҳ > �����̳� > �̳� > ����ѧϰ�������繹�����£�

����ѧϰ�������繹�����£�

��Դ������������|��ʱ�䣺2024-12-04 10:06:51 |���Ķ���166��|�� ��ǩ�� ���� ���� �� |����������

����һƪ���¡�����ѧϰ�������繹�����ϣ��������������Բ㡢������Լ���ʧ������Ĺ�����ʽ�������н���һ���������繹����ʽ���������Ĵһ���򵥵ķ��������硣

���

����һƪ���¡� ����ѧϰ�������繹�����ϣ� �������������Բ㡢������Լ���ʧ������Ĺ�����ʽ�������н���һ���������繹����ʽ���������Ĵһ���򵥵ķ��������硣

Ŀ¼

  1. ����Network
  2. ���ݼ������� DatasetManager
  3. ���� Optimizer
  4. �������

����Network

���綨��


�����������ʱ��������ṹ����һ������Ԫ��ɵģ���Щ�����������㡢���ز������㡣Ϊ��ʵ����һ�ṹ��ͨ����ʹ��������vector���������洢��Щ�㣬��Ϊ��������ǿɱ�ģ����ܸ��ݾ��������������仯��

��ʹ�������Ѿ�������Ԥѵ��������һ���IJ���������£������ض�������ͨ��������Ҫ����ģ��΢����������Ϊ��ͬ����������в�ͬ�����ݷֲ���Ҫ�����ѵ���ǹ���������������ģ�͵���Ҫ���衣

��ѵ�������У��������ؼ������

  1. ��ʧ���� ���������ѧϰĿ�꣬ͨ����С����ʧ�������Ż�ģ�Ͳ�����ѡ����ʵ���ʧ��������ȷ��ģ���ܹ�ѧϰ����Ч��������ʾ������Ҫ��

  2. �Ż��� ���Ż����������ģ�͵IJ�������С����ʧ���������˻����IJ������¹����⣬�Ż����������ṩ���߼��Ĺ��ܣ���ѧϰ�ʵ����Ͳ������ᣬ��Щ�������������ѵ��Ч�ʺ�ģ�����ܡ�

  3. ���ݼ������� ��������ѵ����������Ч�ع������ṩ���ݣ��������ݵļ��ء�Ԥ����������������ȷ�����ݱ�������á�

����������ⲿ�ӿڣ����з���������Ҫ�����¼��ࣺ

  1. �������� ����������㡢������ʧ�������Ż��������ݼ��Ȳ�����������������Ľṹ��ѵ��������
  2. �������� ��ǰ�򴫲��ͷ��򴫲�������������ѵ���Ͳ��Թ����н���Ԥ��Ͳ������¡�
  3. ����ѵ�� ��ʹ�����úõ����ݼ���ѵ��������ִ��ָ��������ѵ�����������Ż����������

�����Ǵ���ʾ����

class Network {
private:
    vector> layers;

    shared_ptr lossFunction;
    shared_ptr optimizer;
    shared_ptr datasetManager;

public:
    void addLayer(shared_ptr layer);

    void setLossFunction(shared_ptr lossFunc);
    void setOptimizer(shared_ptr opt);
    void setDatasetManager(shared_ptr manager);

    MatrixXd forward(const MatrixXd& input);
    void backward(const MatrixXd& outputGrad);

    double train(size_t epochs, size_t batchSize);
};

ʹ��shared_ptr�ĺô���
�洢��ʽvector >��vector ��ȣ����ֱ�Ӵ洢 Layer ������Ҫ�ֶ������ڴ棬����������ͷ��ڴ棬�ⲻ�����׳����������ܵ����ڴ�й©������ָ������⡣��ʹ�� std::shared_ptr ���Դ����ڴ��������ߴ���Ľ�׳�ԺͿ�ά���ԡ�

����ѵ��


�����ѵ������ͨ�������������������ѵ���ļ��������ߴ磺

  • ���� epochs ��ָѵ�����������ĵ����Ĵ�������ÿһ��epoch�У������ʹ��ѵ�����е������������в������¡�

  • ���ߴ� batchSize ��ָ��һ�ε��������ڸ���ģ�Ͳ�����������������ÿ�ε����У�ģ�ͻ������Щ���������ݶȣ����ݴ˵���ģ�͵IJ�����

��ˣ������ѵ������������ѭ���ṹ��ɣ����ѭ���ṹ��ʾ���������Ĵ�����ֱ��������е���ʱֹͣ���ڲ�ѭ����ʾѵ�����������������ȡ�Ľ��ȣ�ֱ��ѵ�����е��������ݱ�����ʱֹͣ��

�����ѵ���������ɶ�εIJ������������£���ɵġ��������ĵĵ�����������Batch��Ϊ��λ�ġ�������˵��һ�ε����������²��裺

  1. ��ȡ���� �������ݼ��������л�ȡһ�������ݣ���������������
  2. ǰ�򴫲� ��������������ݽ����������õ�Ԥ����������Ԥ����������ʧ��
  3. ���򴫲� ��������ʧ�������ڸ���������ݶȡ�
  4. �������� ��������ʧ���ݶȵ���Ϣ�����¸����ݶȡ�
  5. ��־���� �����㲢���ÿ��epoch���ۻ���

����������£�

double Network::train(size_t epochs, size_t batchSize) {
    double totalLoss = 0.0;
    size_t sampleCount = datasetManager->getTrainSampleCount();

    for (size_t epoch = 0; epoch < epochs; ++epoch) {
        datasetManager->shuffleTrainSet();
        totalLoss = 0.0;
        for (size_t i = 0; i < sampleCount; i += batchSize) {
            // ��ȡһ��С��������
            auto batch = datasetManager->getTrainBatch(batchSize, i / batchSize);
            MatrixXd batchInput = batch.first;
            MatrixXd batchLabel = batch.second;

            // ǰ�򴫲�
            MatrixXd predicted = forward(batchInput);
            double loss = lossFunction->computeLoss(predicted, batchLabel);

            // ���򴫲�
            MatrixXd outputGrad = lossFunction->computeGradient(predicted, batchLabel);
            backward(outputGrad);

            // ��������
            optimizer->update(layers);

            // �ۼ���ʧ
            totalLoss += loss;
        }
        totalLoss /= datasetManager->getTrainSampleCount();
        // ���ÿ��epoch����ʧ����Ϣ
        std::cout << "Epoch " << epoch << ", totalLoss = " << totalLoss << "\n";
    }
    return totalLoss / (epochs * (sampleCount / batchSize)); // ����ƽ����ʧ����ʾ����
}

��������������


����Ĵ��������������������з����Ĵ���ʵ�֣�

void Network::addLayer(std::shared_ptr layer) {
    layers.push_back(layer);
}

void Network::setLossFunction(std::shared_ptr lossFunc) {
    lossFunction = lossFunc;
}

void Network::setOptimizer(std::shared_ptr opt) {
    optimizer = opt;
}

void Network::setDatasetManager(std::shared_ptr manager) {
    datasetManager = manager;
}

MatrixXd Network::forward(const MatrixXd& input) {
    MatrixXd currentInput = input;
    for (const auto& layer : layers) {
        currentInput = layer->forward(currentInput);
    }
    return currentInput;
}

void Network::backward(const MatrixXd& outputGrad) {
    MatrixXd currentGrad = outputGrad;
    for (auto it = layers.rbegin(); it != layers.rend(); ++it) {
        currentGrad = (*it)->backward(currentGrad);
    }
}

forward ����������Ϊѵ��ʱ�IJ���֮һ����������������������Ԥ�⣩���������Ϊ���з���

backward ����ֻ��ѵ��ʱʹ�ã���������ʹ����;�У����ᱻ�ⲿ���ã���ˣ����������Ϊ˽�з�����

���ݼ������� DatasetManager


���ݼ�����������Ŀ���������������ݵ������ʣ�����Ҫְ���У�

  1. �������ݣ��ṩ��Ϊ��ȫ�ɿ������ݹ�����
  2. ���ݴ��ң��Ա���˳��ƫ�ͬʱ����ģ�͵ķ���������
  3. ���ݼ����֣������ݻ���Ϊѵ��������֤���Ͳ��Լ���
  4. ���ݽӿڣ�ʹ���ⲿ�������ɵĻ�ȡ�������ݡ�
    class DatasetManager {
    private:
        MatrixXd input;
        MatrixXd label;
        std::vector trainIndices;
        std::vector valIndices;
        std::vector testIndices;

    public:
        // �������ݼ��ķ���
        void setDataset(const MatrixXd& inputData, const MatrixXd& labelData);

        // �������ݼ�Ϊѵ��������֤���Ͳ��Լ�
        void splitDataset(double trainRatio = 0.8, double valRatio = 0.1, double testRatio = 0.1);

        // ��ȡѵ��������֤���Ͳ��Լ���С��������
        std::pair getBatch(std::vector& indices, size_t batchSize, size_t offset = 0);

        // �������ѵ����
        void shuffleTrainSet();

        // ��ȡ��������
        std::pair getTrainBatch(size_t batchSize, size_t offset = 0);
        std::pair getValidationBatch(size_t batchSize, size_t offset = 0);
        std::pair getTestBatch(size_t batchSize, size_t offset = 0);

        // ��ȡ���������ķ���
        size_t getSampleCount() const;
        size_t getTrainSampleCount() const;
        size_t getValidationSampleCount() const;
        size_t getTestSampleCount() const;
    };

���ݼ���ʼ��


���ݼ���ʼ����Ϊ���������ݼ����á����ݼ����֡����ݼ����ҡ�

// �������ݼ�
void  ML::DatasetManager::setDataset(const MatrixXd& inputData, const MatrixXd& labelData) {
    input = inputData;
    label = labelData;

    trainIndices.resize(input.rows());
    std::iota(trainIndices.begin(), trainIndices.end(), 0);
    valIndices.clear();
    testIndices.clear();
}

// ����ѵ����
void ML::DatasetManager::shuffleTrainSet() {
    std::shuffle(trainIndices.begin(), trainIndices.end(), std::mt19937{ std::random_device{}() });
}

// �������ݼ�Ϊѵ��������֤���Ͳ��Լ�
void ML::DatasetManager::splitDataset(double trainRatio, double valRatio, double testRatio) {
    size_t totalSamples = input.rows();
    size_t trainSize = static_cast(totalSamples * trainRatio);
    size_t valSize = static_cast(totalSamples * valRatio);
    size_t testSize = totalSamples - trainSize - valSize;

    shuffleTrainSet();

    valIndices.assign(trainIndices.begin() + trainSize, trainIndices.begin() + trainSize + valSize);
    testIndices.assign(trainIndices.begin() + trainSize + valSize, trainIndices.end());
    trainIndices.resize(trainSize);
}

���ڴ��Ҳ�����Ƶ���ij��������������Ǹ�Ϊ��Ч�IJ����������ڲ��������ҵij�����ֱ�������ݼ��ϴ��Ҹ�Ϊ��Ч�������н��������������Ĵ���ʾ����

���ݻ�ȡ


�ڻ�ȡ����ʱ��������ȷ�������ݼ������ͣ�ѵ��������֤������Ȼ�󣬸���Ԥ������δ�С��Batchsize�����������б�����ȡ��Ӧ������������������Щ������Ӧ�����ݴ洢����ʱ�����С���󣬵������ݣ���ɶ�ȡ������

// ��ȡѵ��������֤���Ͳ��Լ���С��������
std::pair ML::DatasetManager::getBatch(std::vector& indices, size_t batchSize, size_t offset) {
    size_t start = offset * batchSize;
    size_t end = std::min(start + batchSize, indices.size());
    MatrixXd batchInput = MatrixXd::Zero(end - start, input.cols());
    MatrixXd batchLabel = MatrixXd::Zero(end - start, label.cols());

    for (size_t i = start; i < end; ++i) {
        batchInput.row(i - start) = input.row(indices[i]);
        batchLabel.row(i - start) = label.row(indices[i]);
    }

    return std::make_pair(batchInput, batchLabel);
}

// ��ȡѵ��������������
std::pair ML::DatasetManager::getTrainBatch(size_t batchSize, size_t offset) {
    return getBatch(trainIndices, batchSize, offset);
}

// ��ȡ��֤������������
std::pair ML::DatasetManager::getValidationBatch(size_t batchSize, size_t offset) {
    return getBatch(valIndices, batchSize, offset);
}

// ��ȡ���Լ�����������
std::pair ML::DatasetManager::getTestBatch(size_t batchSize, size_t offset) {
    return getBatch(testIndices, batchSize, offset);
}

���ݼ��ߴ���ⲿ�ӿ�


Ϊ���ڴ��뿪������ҪΪ���ݼ�����������ⲿ�ӿڣ��Ա����ⲿ���Ի�ȡ�������ݼ��ijߴ硣

size_t ML::DatasetManager::getSampleCount() const {
    return input.rows();
}

size_t ML::DatasetManager::getTrainSampleCount() const {
    return trainIndices.size();
}

size_t ML::DatasetManager::getValidationSampleCount() const {
    return valIndices.size();
}

size_t ML::DatasetManager::getTestSampleCount() const {
    return testIndices.size();
}

���� Optimizer


����ݶ��½���һ���Ż��㷨��������С����ʧ������ѵ��ģ�Ͳ������������ݶ��½���Batch Gradient Descent����ͬ��SGD��ÿ�θ��²���ʱֻʹ��һ����������һ��С������������������������ѵ��������ʹ��SGD�ڼ����ϸ���Ч�����ܹ�������������������ڴ������ģ����ʱ������Ϊ����ݶ��½��Ĵ���ʾ����

class Optimizer {
public:
    virtual void update(std::vector>& layers) = 0;
    virtual ~Optimizer() {}
};

class SGDOptimizer : public Optimizer {
private:
    double learningRate;
public:
    SGDOptimizer(double learningRate) : learningRate(learningRate) {}
    void update(std::vector>& layers) override;
};

void SGDOptimizer::update(std::vector>& layers) {
    for (auto& layer : layers) {
        layer->update(learningRate);
    }
}

�������


�����ϣ��������Щ���룬���ȿ��Դӱ�ƪ���£��Լ� ��һƪ���� �и��ƴ��룬���ο�����ͼƬ������Ľ��������
»úÆ÷ѧϰ£ºÉñ¾­ÍøÂç¹¹½¨£¨Ï£©
��������������⣬��ӭ��ϵ���ߣ�

ʾ��1�����Իع�


��������Ϊ���Իع�IJ���������

namespace LNR{
    // linear_regression
    void gen(MatrixXd& X, MatrixXd& y);
    void test();
}

void LNR::gen(MatrixXd& X, MatrixXd& y) {
    MatrixXd w(X.cols(), 1);

    X.setRandom();
    w.setRandom();

    X.rowwise() -= X.colwise().mean();
    X.array().rowwise() /= X.array().colwise().norm();

    y = X * w;
}

void LNR::test() {
    std::cout << std::fixed << std::setprecision(2);

    size_t input_dim = 10;
    size_t sample_num = 2000;

    MatrixXd X(sample_num, input_dim);
    MatrixXd y(sample_num, 1);

    gen(X, y);

    ML::DatasetManager dataset;
    dataset.setDataset(X, y);

    ML::Network net;

    net.addLayer(std::make_shared(input_dim, 1));

    net.setLossFunction(std::make_shared());
    net.setOptimizer(std::make_shared(0.25));
    net.setDatasetManager(std::make_shared(dataset));

    size_t epochs = 600;
    size_t batch_size = 50;
    net.train(epochs, batch_size);

    MatrixXd error(sample_num, 1);

    error = net.forward(X) - y;

    std::cout << "error=\n" << error << "\n";
}

��ϸ����

  1. gen �������������ɲ������ݡ�
  2. ����ṹ������������ṹ��ֻ����һ�����Բ㣬��������ߴ�Ϊ����ά�ȣ�����ߴ�Ϊ1��
  3. ��ʧ����������MSE�����������Ϊ��ʧ������

���չʾ

���ѵ��������Ԥ��ֵ����ʵֵ���������ͼ�����׷��֣�������нϺõ�Ԥ�⾫�ȡ�

»úÆ÷ѧϰ£ºÉñ¾­ÍøÂç¹¹½¨£¨Ï£©

ʾ��2���߼��ع�


��������Ϊ�߼��ع�IJ���������

namespace LC {
    // Linear classification
    void gen(MatrixXd& X, MatrixXd& y);
    void test();
}

void LC::gen(MatrixXd& X, MatrixXd& y) {
    MatrixXd w(X.cols(), 1);

    X.setRandom();
    w.setRandom();

    X.rowwise() -= X.colwise().mean();
    X.array().rowwise() /= X.array().colwise().norm();

    y = X * w;

    y = y.unaryExpr([](double x) { return x > 0.0 ? 1.0 : 0.0; });
}

void LC::test() {
    std::cout << std::fixed << std::setprecision(3);

    size_t input_dim = 10;
    size_t sample_num = 2000;

    MatrixXd X(sample_num, input_dim);
    MatrixXd y(sample_num, 1);

    gen(X, y);

    ML::DatasetManager dataset;
    dataset.setDataset(X, y);

    ML::Network net;

    net.addLayer(std::make_shared(input_dim, 1));
    net.addLayer(std::make_shared());

    net.setLossFunction(std::make_shared());
    net.setOptimizer(std::make_shared(0.05));
    net.setDatasetManager(std::make_shared(dataset));

    size_t epochs = 200;
    size_t batch_size = 25;
    net.train(epochs, batch_size);

    MatrixXd predict(sample_num, 1);

    predict = net.forward(X);

    predict = predict.unaryExpr([](double x) { return x > 0.5 ? 1.0 : 0.0; });

    MatrixXd error(sample_num, 1);

    error = y - predict;

    error = error.unaryExpr([](double x) {return (x < 0.01 && x>-0.01) ? 1.0 : 0.0; });

    std::cout << "��ȷ��=\n" << error.sum() / sample_num << "\n";
}

��ϸ����

  1. gen �������������ɲ������ݡ�
  2. ����ṹ������������ṹ�а���һ�����Բ㼰һ��������㣬���У����Բ�����ߴ�Ϊ����ά�ȣ�����ߴ�Ϊ1��
  3. ��ʧ���������ö��������Ϊ��ʧ������

���չʾ
��ͼ��ӳ������Ԥ������е���ʧ�仯�����Կ�����ʧ���½������ơ�
»úÆ÷ѧϰ£ºÉñ¾­ÍøÂç¹¹½¨£¨Ï£©

���ѵ������������Ԥ��������ȷ�ʡ����Է��֣�������нϺõ�Ԥ�⾫�ȡ�
»úÆ÷ѧϰ£ºÉñ¾­ÍøÂç¹¹½¨£¨Ï£©

С���Ƽ��Ķ�

�������������Ľ�Ϊ������Ϣ����������������ͬ���޹۵��֤ʵ��������

�����Ƶ����

����

ͬ������

����

ɨ��ά�����������ֻ��汾��

ɨ��ά����������΢�Ź��ںţ�

��վ�������������������ϴ��������ַ���İ�Ȩ���뷢�ʼ�[email protected]

��ICP��2022002427��-10 �湫��������43070202000427��© 2013~2025 haote.com ������