2023-2-14 神经网络基础

C++从零实现神经网络

在这里插入图片描述
基本要素:

  1. 神经元节点
  2. 层 layer
  3. 权值weight
  4. 偏置项 bias

计算过程:
前向传播:加权求和(线性)、激活函数(非线性)
反向传播:用BP算法更新权值

分类图:
在这里插入图片描述

net类基本组成

#ifndef NET_H
#define NET_H
#endif // NET_H
#pragma once
#include <iostream>
#include<opencv2\core\core.hpp>
#include<opencv2\highgui\highgui.hpp>
//#include<iomanip>
#include"Function.h"
namespace liu
{
    class Net
    {
    public:
        std::vector<int> layer_neuron_num;
        std::vector<cv::Mat> layer;
        std::vector<cv::Mat> weights;
        std::vector<cv::Mat> bias;
    public:
        Net() {};
        ~Net() {};
        //Initialize net:genetate weights matrices、layer matrices and bias matrices
        // bias default all zero
        void initNet(std::vector<int> layer_neuron_num_);
        //Initialise the weights matrices.
        void initWeights(int type = 0, double a = 0., double b = 0.1);
        //Initialise the bias matrices.
        void initBias(cv::Scalar& bias);
        //Forward
        void forward();
        //Forward
        void backward();
    protected:
        //initialise the weight matrix.if type =0,Gaussian.else uniform.
        void initWeight(cv::Mat &dst, int type, double a, double b);
        //Activation function
        cv::Mat activationFunction(cv::Mat &x, std::string func_type);
        //Compute delta error
        void deltaError();
        //Update weights
        void updateWeights();
    };
}

极简版神经网络

#include<bits/stdc++.h>
using namespace std;
double getMSEloss(double x1,double x2){
    return (x1 - x2)*(x1 - x2);
}
class NNetwork
{
    private:
    int epoches;
    double learning_rate;
    double w1,w2,w3,w4,w5,w6;
    double b1,b2,b3;
    public:
    NNetwork(int es,double lr);
    double sigmoid(double x);
    double deriv_sigmoid(double x);
    double forward(vector<double> data);
    void train(vector<vector<double>> data,vector<double> label);
    void predict(vector<vector<double>> test_data,vector<double> test_label);
};
NNetwork::NNetwork(int es,double lr):epoches(es),learning_rate(lr){
    // 超参数、参数初始化
    w1=w2=w3=w4=w5=w6=0;
    b1=b2=b3=0;
}
double NNetwork::sigmoid(double x){
    // 激活函数
    return 1/(1+exp(-x));
}
double NNetwork::deriv_sigmoid(double x){
    // 激活函数求导
    double y = sigmoid(x);
    return y*(1-y);
}
double NNetwork::forward(vector<double> data){
    // 前向传播
    double sum_h1 = w1 * data[0] + w2 * data[1] + b1;
    double h1 = sigmoid(sum_h1);
    double sum_h2 = w3 * data[0] + w4 * data[1] + b2;
    double h2 = sigmoid(sum_h2);
    double sum_o1 = w5 * h1 + w6 * h2 + b3;
    return sigmoid(sum_o1);
}
void NNetwork::train(vector<vector<double>> data,vector<double> label){
    for(int epoch=0;epoch<epoches;++epoch){
        int total_n = data.size();
        for(int i=0;i<total_n;++i){
            vector<double> x = data[i];
            double sum_h1 = w1 * x[0] + w2 * x[1] + b1;
            double h1 = sigmoid(sum_h1);
            double sum_h2 = w3 * x[0] + w4 * x[1] + b2;
            double h2 = sigmoid(sum_h2);
            double sum_o1 = w5 * h1 + w6 * h2 + b3;
            double o1 = sigmoid(sum_o1);
            double pred = o1;
 
            double d_loss_pred = -2 * (label[i] - pred);
 
            double d_pred_w5 = h1 * deriv_sigmoid(sum_o1);
            double d_pred_w6 = h2 * deriv_sigmoid(sum_o1);
            double d_pred_b3 = deriv_sigmoid(sum_o1);
            
            double d_pred_h1 = w5 * deriv_sigmoid(sum_o1);
            double d_pred_h2 = w6 * deriv_sigmoid(sum_o1);
 
            double d_h1_w1 = x[0] * deriv_sigmoid(sum_h1);
            double d_h1_w2 = x[1] * deriv_sigmoid(sum_h1);
            double d_h1_b1 = deriv_sigmoid(sum_h1);
 
            double d_h2_w3 = x[0] * deriv_sigmoid(sum_h2);
            double d_h2_w4 = x[1] * deriv_sigmoid(sum_h2);
            double d_h2_b2 = deriv_sigmoid(sum_h2);
 
            w1 -= learning_rate * d_loss_pred * d_pred_h1 * d_h1_w1;
            w2 -= learning_rate * d_loss_pred * d_pred_h1 * d_h1_w2;
            b1 -= learning_rate * d_loss_pred * d_pred_h1 * d_h1_b1;
            w3 -= learning_rate * d_loss_pred * d_pred_h2 * d_h2_w3;
            w4 -= learning_rate * d_loss_pred * d_pred_h2 * d_h2_w4;
            b2 -= learning_rate * d_loss_pred * d_pred_h2 * d_h2_b2;
            w5 -= learning_rate * d_loss_pred * d_pred_w5;
            w6 -= learning_rate * d_loss_pred * d_pred_w6;
            b3 -= learning_rate * d_loss_pred * d_pred_b3; 
        }
        if(epoch%10==0){
            double loss = 0;
            for(int i=0;i<total_n;++i){
                double pred = forward(data[i]);
                loss += getMSEloss(pred,label[i]);
            }
            cout<<"epoch "<<epoch<<" loss: "<<loss<<endl;
        }
    }
}
void NNetwork::predict(vector<vector<double>> test_data,vector<double> test_label){
    int n = test_data.size();
    double cnt = 0;
    for(int i=0;i<n;++i){
        double pred = forward(test_data[i]);
        pred = pred>0.5?1:0;
        cnt += (test_label[i]==pred);
    }
    cout<<"correct rate:"<<cnt/n<<endl;
}
int main(){
    vector<vector<double>> data = {{-2,-1},{25,6},{17,4},{-15,-6}};
    vector<double> label = {1,0,0,1};
    NNetwork network = NNetwork(1000,0.1);
    network.train(data,label);
    vector<vector<double>> test_data  = {{-3,-4},{-5,-4},{12,3},{-13,-4},{9,12}};
    vector<double> test_label = {1,1,0,1,0};
    network.predict(test_data,test_label);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值