C++版本MLP手动实现

这是一个C++实现的多层感知机(MLP)模板类,包括初始化、训练、保存、加载权重、打印权重等功能。代码中包含了激活函数、梯度计算、权重更新等关键步骤,适用于神经网络的学习与实践。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Ann.cpp


#include <string>
#include <iostream>
#include <fstream>
#include <cmath>
#include <cstdlib>
#include <iomanip>
#include <unistd.h>
#include <stdio.h>
#include <sstream>
#include <unistd.h>
#include <pthread.h>


using std :: cout;
using std :: endl;
using std :: cin;
using std :: string;
using std :: stringstream;


//int const static LIMIT = 19;


template <typename T>
class Ann
{
public:
    Ann(int input , int argc , int * detailed , int output);
    virtual ~Ann();
    void load(string filename);
    void save();
    void print_weight();
    void train(T ** set , int number , int times , double rate , double lambda , double limit , double probality , double decay , int addition , int extract);
    bool adjust_output(double * target);
    bool adjust_hidden();
    void calculator(bool flag = false);
    int get_argc_input();
    int get_argc_output();
    void set_input(double * argc);
    bool get_result(int goal);
    void write_file(string filename);
private:
    double * input , ** level , * output , *** weight , ***best_weight, * target , * err , ** offset , ** best_offset;
    bool ** dropout;
    T ** set , ** temp;
    double rate , lambda , limit , probality , backup;
    int argc_input , argc_level , argc_output , * info;
    double ** list , ** medium , ** origin;
    double *** record;
    int point , max , temp_point;
    stringstream stream;
    void init(int input , int argc , int * detailed , int end);
    void init_level();
    double sigmod(double value);
    void free(double * array);
    void free(int argc , double ** matrix);
    void free(int argc , int * argv , double *** matrix);
    void free(int * array);
    void copy(int * info , int * detailed , int argc);
    double sum(int level , int input , int output);
    double get_random();
    void print_output();
    void print_input();
    void print_level();
    double get_err(int i);
    void pre_process(T ** set , int value);
    double offset_sum(int target);
    double get_regular();
    double softmax(T ** set , int const point , int const max , int const argc_output , int const value , bool flag = false);
    void compute_gradient(int point , int max);
    void copy_level(int i);
    void copy_input(int i);
    void copy_list(int i);
    double gaussrand();
    void test();
    bool check(T ** set  , T ** check, int train , int confirm);
    int best_train , best_confirm;
    string itos(int data);
    void deal_for_svm(T ** set , int value);
    void reset();
    void segmentation(T ** set , int * count , int value , double rate , int addition , int extract);
    void generate_svm(T ** set , string filename , int number , int size);
};


template<typename T>
void Ann<T> :: generate_svm(T ** set , string filename , int number , int size)
{
    std::ofstream out;
    out.open(filename.c_str());
    if(out.is_open())
    {
        for(int i = 0 ; i < number ; i++)
        {
            out << set[i][size] << " ";
            for(int j = 0 ; j < size ; j++)
            {
                out << j+1 << ":" << set[i][j] << " " ;
            }
            out << "\n";
        }
    }
    cout << "generate over . " << endl;
}




template <typename T>
void Ann<T> :: reset()
{
    for (int i = 0; i < argc_level; ++i)
    {
        for (int j = 0; j < info[i]; ++j)
        {
            dropout[i][j] = get_random() > probality ? true : false;
        }
    }
}


template <typename T>
string Ann<T> :: itos(int data)
{
    stream << data;
    string result = stream.str();
    stream.clear();
    stream.str("");
    return result;
}


template <typename T>
bool Ann<T> :: check(T ** set , T ** check , int train , int size)
{
    int err_train = 0 , err_confirm = 0;
    bool flag = false;
    for (int i = 0; i < train; ++i)
    {
        set_input(set[i]);
        calculator(true);
        if(!get_result(set[i][argc_input]))
        {
            err_train ++;
        }
        if(flag)
        {
            cout << "check for input : " << set[i][argc_input] << endl;
            int max = 0;
            for (int j = 1; j < argc_output; ++j)
            {
                if(output[j] > output[max]) max = j;
            }
            cout << "check for calculator : " << max << endl << endl << endl;
        }
    }


    if(flag) cout << "--------------------" << endl;
    for (int i = 0; i < size; ++i)
    {
        set_input(check[i]);
        calculator(true);
        if(!get_result(check[i][argc_input]))
        {
            err_confirm ++;
        }
        if(flag)
        {
            cout << "check for input : " << check[i][argc_input] << endl;
            int max = 0;
            for (int j = 1; j < argc_output; ++j)
            {
                if(output[j] > output[max]) max = j;
            }
            cout << "check for calculator : " << max << endl << endl << endl;
        }
    }
    cout << "Error in train for : " << err_train << endl;
    cout << "Number for : " << train << endl;
    cout << "Rate for : " << 1 - (double)err_train / train << endl;
    cout << "Error in check for : " << err_confirm << endl;
    cout << "Number for : " << size << endl;
    cout << "Rate for : " << 1 - (double)err_confirm / size << endl;
    if(err_train * 0.2 + err_confirm * 0.8  < best_train * 0.2 + best_confirm * 0.8)
    {
        best_train = err_train;
        best_confirm = err_confirm;
        save();
        return true;
    }
    return false;
}


template <typename T>
double Ann<T> :: gaussrand()
{
    {
        static double V1, V2, S;
        static int phase = 0;
        double X;
        if ( phase == 0 )
        {
            do
            {
                double U1 = (double)rand() / RAND_MAX;
                double U2 = (double)rand() / RAND_MAX;
                V1 = 2 * U1 - 1;
                V2 = 2 * U2 - 1;
                S = V1 * V1 + V2 * V2;
            }
            while(S >= 1 || S == 0);
            X = V1 * sqrt(-2 * log(S) / S);
        }
        else
        {
            X = V2 * sqrt(-2 * log(S) / S);
        }
        phase = 1 - phase;
        return X;
    }
}


template <typename T>
void Ann<T> :: test()
{
    for (int i = 0; i < point; ++i)
    {
        for (int j = 0; j < argc_input; ++j)
        {
            if(origin[i][j] != origin[i][j])
            {
                cout << "origin failed ." << endl;
                exit(1);
            }
        }
        for (int j = 0; j < argc_output; ++j)
        {
            if(list[i][j] != list[i][j])
            {
                cout << "list failed ." << endl;
                exit(1);
            }
        }
        for (int j = 0; j < argc_level; ++j)
        {
            for (int k = 0; k < info[j]; ++k)
            {
                if(record[i][j][k] != record[i][j][k])
                {
                    cout << "record failed " << endl;
                    exit(1);
                }
            }
        }
    }
}


template <typename T>
void Ann<T> :: copy_level(int position)
{
    for (int i = 0; i < argc_level; ++i)
    {
        for (int j = 0 ; j < info[i]; ++j)
        {
            record[position][i][j] = level[i][j];
        }
    }
}


template <typename T>
void Ann<T> :: copy_input(int position)
{
    for (int i = 0; i < argc_input; ++i)
    {
        origin[position][i] = input[i];
    }
}


template <typename T>
void Ann<T> :: copy_list(int position)
{
    for (int i = 0; i < argc_output; ++i)
    {
        list[position][i] = output[i];
    }
}


template <typename T>
void Ann<T> :: compute_gradient(int point , int max)
{
    double list_back[point][max];
    for (int i = argc_level - 1 ; i >= 0; --i)
    {
        if(i == argc_level - 1)
        {
            {
                int m = info[i] , n = point , p = argc_output;
                for (int j = 0; j < m; ++j)
                {
                    for (int k = 0; k < p; ++k)
                    {
                        double sum = 0;
                        for (int h = 0; h < n; ++h)
                        {
                            sum += record[h][i][j] * list[h][k];
                        }
                        medium[j][k] = sum;
                    }
                }
            }
            for (int j = 0; j < argc_output; ++j)
            {
                offset[i+1][j] += -rate * offset_sum(j);
            }
            {
                int m = point , n = argc_output , p = info[i];
                for (int j = 0; j < m; ++j)
                {
                    for (int k = 0; k < p; ++k)
                    {
                        double sum = 0;
                        for (int h = 0; h < n; ++h)
                        {
                            sum += list[j][h] * weight[i+1][k][h];
                        }
                        list_back[j][k] = record[j][i][k] <= 0 ? 0 : sum;
                    }
                }
                for (int i = 0; i < m; ++i)
                {
                    for (int j = 0; j < p; ++j)
                    {
                        list[i][j] = list_back[i][j];
                    }
                }
            }
            for (int j = 0; j < info[argc_level-1]; ++j)
            {
                if(dropout[i][j])
                {
                    for (int k = 0; k < argc_output; ++k)
                    {
                        //if(get_random() > probality)
                        {
                            weight[i+1][j][k] += -(rate * (medium[j][k] + lambda * weight[i+1][j][k]));
                 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值