BP神经网络及其C++实现

2023-05-16

0 前言

  神经网络在我印象中一直比较神秘,正好最近学习了神经网络,特别是对Bp神经网络有了比较深入的了解,因此,总结以下心得,希望对后来者有所帮助。 
  神经网络在机器学习中应用比较广泛,比如函数逼近,模式识别,分类,数据压缩,数据挖掘等领域。神经网络本身是一个比较庞大的概念,从网络结构类别来划分,大概有:多层前馈神经网络、径向基函数网络(RBF)、自适应谐振理论网络(ART)、自组织映射网络(SOM)、级联相关网络、Elman网络、Boltzmann机、受限Boltzmann机等等。 
 下面一张图是最近比较流行的网络结构: 
这里写图片描述
  今天我们要介绍的是Bp神经网络,准确的说是采用Bp算法进行训练的多层前馈神经网络,Bp算法应用比较广泛。

1基本概念:

1.1神经元模型

 机器学习中所谈论的神经网络源于生物上的神经网络,实际上指的是“神经网络“与”机器学习“的交叉部分,一个最简单的M-P神经元模型如下图所示:

 
 
  • 1
  • 2

这里写图片描述 
该神经元收到来自其他n个输入神经元传递过来的输入信号(加权和的形式),然后将其与神经元的阈值进行比较,通过激活函数进行处理,产生神经元的输出。

1.2 常用激活函数

激活函数的作用是对其他所有神经元传过来的所有信号加权和进行处理,产生神经元输出。

 
 
  • 1
  • 2

  下图是常用的激活函数,最简单的是:阶跃函数,它简单,最理想,但是性质最差(不连续/不光滑),因此在实际中,最常用的是Sigmoid函数。 
常用激活函数

1.3前馈神经网络

   多层前馈神经网络的准确定义:每一层神经元与下一层神经元全互连,神经元之间不存在同层连接,不存在跨层连接,如下图所示就是一个经典的前馈神经网络,

 
 
  • 1
  • 2

三层前馈神经网络深度学习模型 
(随便插一句,当神经网络中隐层数越来越多,达到8-9层时,就变成了一个深度 
学习模型,我曾在一篇论文中看到网络结构有达128层的,关于下面这块,下面还会再叙述)。

2.标准Bp算法


2.0 关于梯度

   首先我们应该清楚,一个多元函数的梯度方向是该函数值增大最陡的方向。具体化到1元函数中时,梯度方向首先是沿着曲线的切线的,然后取切线向上增长的方向为梯度方向,2元或者多元函数中,梯度向量为函数值f对每个变量的导数,该向量的方向就是梯度的方向,当然向量的大小也就是梯度的大小。
   梯度下降法(steepest descend method)用来求解表达式最大或者最小值的,属于无约束优化问题。梯度下降法的基本思想还是挺简单的,现假设我们要求函数f的最小值,首先得选取一个初始点后,然后下一个点的产生时是沿着梯度直线方向,这里是沿着梯度的反方向(因为求的是最小值,如果是求最大值的话则沿梯度的正方向即可),如下图所示: 

 
 
  • 1
  • 2
  • 3

这里写图片描述


2.1神经网络学习过程

 神经网络在外界输入样本的刺激下不断改变网络的连接权值,以使网络的输出不断地接近期望的输出,讲几个要点: 
(1)学习过程可以简述为:这里写图片描述 
(2)学习的本质: 对各连接权值以及所有功能神经元的阈值动态调整 
注:可以将权值与阈值的学习统一为权值的学习,即将阈值看成一个”哑节点“,如下图所示: 
这里写图片描述 
(3) 权值调整规则:即在学习过程中网络中各神经元的连接权变化所依据的一定的调整规则 ,(Bp 算法中权值调整采用的是梯度下降策略,下面会详细介绍) 
Bp网络的学习流程如下图所示: 
这里写图片描述 
(百度图库里搜的,能说明问题就行)


2.2权值调整策略:

  首先说明一句,神经网络学习属于监督学习的范畴。每输入一个样本,进行正向传播(输入层→隐层→输出层),得到输出结果以后,计算误差,达不到期望后,将误差进行反向传播(输出层→隐层→输入层),采用梯度下降策略对所有权值和阈值进行调整。 
误差计算 
注:上面的Ek是根据第k个样本数据算出的误差,可以看出:标准Bp算法每次迭代更新只针对单个样例。 
权值与阈值的调整公式如下: 
梯度下降法 
上述公式的详细推导过程见下图: 
这里写图片描述 
这里写图片描述


2.3 BP神经网络总结

(1)BP神经网络一般用于分类或者逼近问题。 
如果用于分类,则激活函数一般选用Sigmoid函数或者硬极限函数,如果用于函数逼近,则输出层节点用线性函数。 
(2) BP神经网络在训练数据时可以采用增量学习或者批量学习。 
—增量学习要求输入模式要有足够的随机性,对输入模式的噪声比较敏感,即对于剧烈变化的输入模式,训练效果比较差,适合在线处理。 
—批量学习不存在输入模式次序问题,稳定性好,但是只适合离线处理。 
(3)如何确定隐层数以及每个隐含层节点个数 
Pre隐含层节点个数不确定,那么应该设置为多少才合适呢(隐含层节点个数的多少对神经网络的性能是有影响的)? 
有一个经验公式可以确定隐含层节点数目:这里写图片描述 ,(其中h:隐含层节点数目,m:为输入层节点数目,n:为输出层节点数目,a:为之间的调节常数)。


2.4 标准BP神经网络的缺陷

(1)容易形成局部极小值而得不到全局最优值。 
(采用梯度下降法),如果仅有一个局部极小值=>全局最小,多个局部极小=>不一定全局最小。这就要求对初始权值和阀值有要求,要使得初始权值和阀值随机性足够好,可以多次随机来实现。 
(2)训练次数多使得学习效率低,收敛速度慢。 
每次更新只针对单个样本;不同样例出现”抵消“现象。 
(3)过拟合问题 
通过不断训练,训练误差达到很低,但测试误差可能会上升(泛化性能差)。 
解决策略: 
1,”早停”: 
即将样本划分成训练集和验证集,训练集用来算梯度,更新权值和阈值,验证集用来估计误差,当训练集误差降低而验证集误差升高时就停止训练,返回具有最小验证集误差的权值和阈值。 
2,”正则化方法“:正则化,即在误差目标中增加一个用于描述网络复杂程度的部分,其中参数λ常用交叉验证来确定。


2.5 BP算法的改进

(1)累积BP算法 
目的:为了减小整个训练集的全局误差,而不针对某一特定样本 
这里写图片描述 (更新策略做相应调整)

(2)利用动量法改进BP算法 
(标准Bp学习过程易震荡,收敛速度慢) 
增加动量项,引入动量项是为了加速算法收敛,即如下公式: 
这里写图片描述 
α为动量系数,通常0<α<0.9。

(3)自适应调节学习率η 
调整的基本指导思想是:在学习收敛的情况下,增大η,以缩短学习时间;当η偏大致使不能收敛(即发生震荡)时,要及时减小η,直到收敛为止。


3 工程搭建与C++实现

 实验平台:vs2013 
项目包含文件: 
工程 
项目流程如下图所示: 
这里写图片描述

(1)Bp.h

#ifndef _BP_H_  
#define _BP_H_  

#include <vector>  

//参数设置
#define LAYER    3        //三层神经网络  
#define NUM      10       //每层的最多节点数  

#define A        30.0  
#define B        10.0     //A和B是S型函数的参数  
#define ITERS    1000     //最大训练次数  
#define ETA_W    0.0035   //权值调整率  
#define ETA_B    0.001    //阀值调整率  
#define ERROR    0.002    //单个样本允许的误差  
#define ACCU     0.005    //每次迭代允许的误差  

//类型
#define Type double  
#define Vector std::vector  

struct Data
{
    Vector<Type> x;       //输入属性
    Vector<Type> y;       //输出属性
};

class BP{

public:

    void GetData(const Vector<Data>);
    void Train();
    Vector<Type> ForeCast(const Vector<Type>);
    void ForCastFromFile(BP * &);
    void ReadFile(const char * InutFileName,int m, int n);

    void ReadTestFile(const char * InputFileName, int m, int n);
    void WriteToFile(const char * OutPutFileName);

private:

    void InitNetWork();         //初始化网络  
    void GetNums();             //获取输入、输出和隐含层节点数  
    void ForwardTransfer();     //正向传播子过程  
    void ReverseTransfer(int);  //逆向传播子过程  
    void CalcDelta(int);        //计算w和b的调整量  
    void UpdateNetWork();       //更新权值和阀值  
    Type GetError(int);         //计算单个样本的误差  
    Type GetAccu();             //计算所有样本的精度  
    Type Sigmoid(const Type);   //计算Sigmoid的值  
    void split(char *buffer, Vector<Type> &vec);

private:
    int in_num;                 //输入层节点数  
    int ou_num;                 //输出层节点数  
    int hd_num;                 //隐含层节点数  

    Vector<Data> data;            //样本数据
    Vector<Vector<Type>> testdata;//测试数据
    Vector<Vector<Type>> result;  //测试结果
    int        rowLen;            //样本数量
    int        restrowLen;        //测试样本数量

    Type w[LAYER][NUM][NUM];    //BP网络的权值  
    Type b[LAYER][NUM];         //BP网络节点的阀值  

    Type x[LAYER][NUM];         //每个神经元的值经S型函数转化后的输出值,输入层就为原值  
    Type d[LAYER][NUM];         //记录delta学习规则中delta的值,使用delta规则来调整联接权重 Wij(t+1)=Wij(t)+α(Yj-Aj(t))Oi(t)
};

#endif  //_BP_H_  

 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73

(2)Bp.cpp

#include <string.h>  
#include <stdio.h>  
#include <math.h>  
#include <assert.h>  
#include <cstdlib>
#include <fstream>
#include <iostream>
using namespace std;

#include "Bp.h"  

//获取训练所有样本数据  
void BP::GetData(const Vector<Data> _data)
{
    data = _data;
}

void BP::split(char *buffer, Vector<Type> &vec)
{
    char *p = strtok(buffer, " ,");      //\t
    while (p != NULL)
    {
        vec.push_back(atof(p));
        p = strtok(NULL, " \n");
    }
}


void BP::ReadFile(const char * InutFileName, int m ,int n)
{
    FILE *pFile;
    //Test
    //pFile = fopen("D:\\testSet.txt", "r");

    pFile = fopen(InutFileName, "r");

    if (!pFile)
    {
        printf("open file %s failed...\n", InutFileName);
        exit(0);
    }

    //init dataSet  
    char *buffer = new char[100];
    Vector<Type> temp;

    while (fgets(buffer, 100, pFile))
    {
        Data t;
        temp.clear();
        split(buffer, temp);
        //data[x].push_back(temp);

        for (int i = 0; i < temp.size(); i++)
        {
            if (i < m)
                t.x.push_back(temp[i]);
            else
                t.y.push_back(temp[i]);
        }
        data.push_back(t);
    }
    //init rowLen   
    rowLen = data.size();
}

void BP::ReadTestFile(const char * InputFileName, int m, int n)
{
    FILE *pFile;

    pFile = fopen(InputFileName, "r");
    if (!pFile)
    {
        printf("open file %s failed...\n", InputFileName);
        exit(0);
    }

    //init dataSet  
    char *buffer = new char[100];
    Vector<Type> temp;

    while (fgets(buffer, 100, pFile))
    {
        Vector<Type> t;
        temp.clear();
        split(buffer, temp);
        for (int i = 0; i < temp.size(); i++)
        {
            t.push_back(temp[i]);
        }
        testdata.push_back(t);
    }

    restrowLen = testdata.size();
}

void BP::WriteToFile(const char * OutPutFileName)
{
    ofstream fout;
    fout.open(OutPutFileName);
    if (!fout)
    {
        cout << "file result.txt  open failed" << endl;
        exit(0);
    }

    Vector<Vector<Type>> ::iterator it = testdata.begin();
    Vector<Vector<Type>>::iterator itx = result.begin();
    while (it != testdata.end())  
    {    
        Vector<Type> ::iterator itt = (*it).begin();
        Vector<Type> ::iterator ittx = (*itx).begin();
        while (itt != (*it).end())
        {
             fout << (*itt) << ",";
             itt++;
        }
        fout << "\t";
        while (ittx != (*itx).end())
        {
            fout << (*ittx) << ",";
            ittx++;
        }
        it++;
        itx++;
        fout << "\n";
    }
}

//开始进行训练  
void BP::Train()
{
    printf("Begin to train BP NetWork!\n");
    GetNums();
    InitNetWork();
    int num = data.size();

    for (int iter = 0; iter <= ITERS; iter++)
    {
        for (int cnt = 0; cnt < num; cnt++)
        {
            //第一层输入节点赋值  
            for (int i = 0; i < in_num; i++)
                x[0][i] = data.at(cnt).x[i];

            while (1)
            {
                ForwardTransfer();
                if (GetError(cnt) < ERROR)    //如果误差比较小,则针对单个样本跳出循环  
                    break;
                ReverseTransfer(cnt);
            }
        }
        printf("This is the %d th trainning NetWork !\n", iter);

        Type accu = GetAccu();               //每一轮学习的均方误差E
        printf("All Samples Accuracy is %lf\n", accu);
        if (accu < ACCU) break;
    }
    printf("The BP NetWork train End!\n");
}

//根据训练好的网络来预测输出值  
Vector<Type> BP::ForeCast(const Vector<Type> data)
{
    int n = data.size();
    assert(n == in_num);
    for (int i = 0; i < in_num; i++)
        x[0][i] = data[i];

    ForwardTransfer();
    Vector<Type> v;
    for (int i = 0; i < ou_num; i++)
        v.push_back(x[2][i]);
    return v;
}

void  BP::ForCastFromFile(BP * &pBp)
{   

    Vector<Vector<Type>> ::iterator it = testdata.begin();
    Vector<Type> ou;
    while (it != testdata.end())
    {
        ou = pBp->ForeCast(*it);
        result.push_back(ou);

        it++;
    }

}

//获取网络节点数  
void BP::GetNums()
{
    in_num = data[0].x.size();                         //获取输入层节点数  
    ou_num = data[0].y.size();                         //获取输出层节点数  
    hd_num = (int)sqrt((in_num + ou_num) * 1.0) + 5;   //获取隐含层节点数    
    if (hd_num > NUM) hd_num = NUM;                     //隐含层数目不能超过最大设置  
}

//初始化网络  
void BP::InitNetWork()
{
    memset(w, 0, sizeof(w));      //初始化权值和阀值为0,也可以初始化随机值  
    memset(b, 0, sizeof(b));
}

//工作信号正向传递子过程  
void BP::ForwardTransfer()
{
    //计算隐含层各个节点的输出值  
    for (int j = 0; j < hd_num; j++)
    {
        Type t = 0;
        for (int i = 0; i < in_num; i++)
            t += w[1][i][j] * x[0][i];
        t += b[1][j];
        x[1][j] = Sigmoid(t);
    }

    //计算输出层各节点的输出值  
    for (int j = 0; j < ou_num; j++)
    {
        Type t = 0;
        for (int i = 0; i < hd_num; i++)
            t += w[2][i][j] * x[1][i];
        t += b[2][j];
        x[2][j] = Sigmoid(t);
    }
}

//计算单个样本的误差  
Type BP::GetError(int cnt)
{
    Type ans = 0;
    for (int i = 0; i < ou_num; i++)
        ans += 0.5 * (x[2][i] - data.at(cnt).y[i]) * (x[2][i] - data.at(cnt).y[i]);
    return ans;
}

//误差信号反向传递子过程  
void BP::ReverseTransfer(int cnt)
{
    CalcDelta(cnt);
    UpdateNetWork();
}

//计算所有样本的精度  
Type BP::GetAccu()
{
    Type ans = 0;
    int num = data.size();
    for (int i = 0; i < num; i++)
    {
        int m = data.at(i).x.size();
        for (int j = 0; j < m; j++)
            x[0][j] = data.at(i).x[j];
        ForwardTransfer();
        int n = data.at(i).y.size(); //样本输出的维度
        for (int j = 0; j < n; j++)
            ans += 0.5 * (x[2][j] - data.at(i).y[j]) * (x[2][j] - data.at(i).y[j]);//对第i个样本算均方误差
    }
    return ans / num;
}

//计算调整量  
void BP::CalcDelta(int cnt)
{
    //计算输出层的delta值  
    for (int i = 0; i < ou_num; i++)
        d[2][i] = (x[2][i] - data.at(cnt).y[i]) * x[2][i] * (A - x[2][i]) / (A * B);
    //计算隐含层的delta值  
    for (int i = 0; i < hd_num; i++)
    {
        Type t = 0;
        for (int j = 0; j < ou_num; j++)
            t += w[2][i][j] * d[2][j];
        d[1][i] = t * x[1][i] * (A - x[1][i]) / (A * B);
    }
}

//根据计算出的调整量对BP网络进行调整  
void BP::UpdateNetWork()
{
    //隐含层和输出层之间权值和阀值调整  
    for (int i = 0; i < hd_num; i++)
    {
        for (int j = 0; j < ou_num; j++)
            w[2][i][j] -= ETA_W * d[2][j] * x[1][i];
    }
    for (int i = 0; i < ou_num; i++)
        b[2][i] -= ETA_B * d[2][i];

    //输入层和隐含层之间权值和阀值调整  
    for (int i = 0; i < in_num; i++)
    {
        for (int j = 0; j < hd_num; j++)
            w[1][i][j] -= ETA_W * d[1][j] * x[0][i];
    }
    for (int i = 0; i < hd_num; i++)
        b[1][i] -= ETA_B * d[1][i];
}

//计算Sigmoid函数的值  
Type BP::Sigmoid(const Type x)
{
    return A / (1 + exp(-x / B));
}

 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
  • 251
  • 252
  • 253
  • 254
  • 255
  • 256
  • 257
  • 258
  • 259
  • 260
  • 261
  • 262
  • 263
  • 264
  • 265
  • 266
  • 267
  • 268
  • 269
  • 270
  • 271
  • 272
  • 273
  • 274
  • 275
  • 276
  • 277
  • 278
  • 279
  • 280
  • 281
  • 282
  • 283
  • 284
  • 285
  • 286
  • 287
  • 288
  • 289
  • 290
  • 291
  • 292
  • 293
  • 294
  • 295
  • 296
  • 297
  • 298
  • 299
  • 300
  • 301
  • 302
  • 303
  • 304
  • 305
  • 306
  • 307
  • 308
  • 309
  • 310

(3)Test.cpp

#include <iostream>  
#include <string.h>  
#include <stdio.h>  
using namespace std;

#include "Bp.h"  

int main()
{
    unsigned int Id, Od;    //样本数据的输入维数/输出维数
    int select = 0;
    BP *bp = new BP();
    const char * inputDataName = "exercisedata.txt";//训练数据文件名称
    const char * testDataName = "testdata.txt";   //测试数据文件名称
    const char * outputDataName = "result.txt";     //输出文件名称

    printf("please input sample input dimension and output dimension:\n");
    scanf("%d%d", &Id, &Od);
    bp->ReadFile(inputDataName,Id,Od);

    //exercise
    bp->Train();
    //Test
    printf("\n******************************************************\n");
    printf("*1.使用测试文件中国的数据测试 2.从控制台输入数据测试  \n");
    printf("******************************************************\n");
    scanf("%d", &select);
    switch (select)
    {
    case 1:
        bp->ReadTestFile(testDataName,Id,Od);
        bp->ForCastFromFile(bp);
        bp->WriteToFile(outputDataName);
        printf("the result have been save in the file :result.txt.\n");
        break;
    case 2:
        printf("\n\nplease input the Test Data(3 dimension ):\n");
        while (1)
        {
            Vector<Type> in;
            for (int i = 0; i < Id; i++)
            {
                Type v;
                scanf_s("%lf", &v);
                in.push_back(v);
            }
            Vector<Type> ou;
            ou = bp->ForeCast(in);
            printf("%lf\n", ou[0]);
        }
        break;
    default:
        printf("Input error!");
        exit(0);
    }

    return 0;
}


本文转自:http://blog.csdn.net/QKK612501/article/details/52893803,转载仅用于学习。



本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

BP神经网络及其C++实现 的相关文章

  • Keychron K3 Pro

    Keychron K3 Pro Keychron K3 Pro A31 连接蓝牙2 更改键盘背光模式和快速关闭开启键盘背光3 调整键盘背光亮度4 调整背光速度5 查看电池电量 Keychron K3 Pro A3 1 连接蓝牙 长按fn 4
  • miner14 export

    lotus chain export span class token operator span recent span class token operator span stateroots span class token oper
  • iTerm2 恢复窗口

    退出应用程序时关闭窗口
  • Homebrew 安装

    Homebrew Homebrew 安装添加 Homebrew 到 PATH在当前终端设置环境变量 运行参考 Homebrew 安装 span class token operator span bin span class token o
  • sed 使用#作为分隔符

    sed 将 bin sh替换为bash需要使用 进行转义 以匹配 字符使用 作为分隔符 将 bin sh替换为bash 需要使用 进行转义 以匹配 字符 sed 39 s span class token operator span spa
  • 华为 USG6625E 防火墙

    服务列表 需要设置目标端口
  • baseDeltaSeconds PROPAGATION_DELAY_SECS 设置传播延迟时间

    设置lotus传播延迟 默认区块传播延迟10秒设置环境变量参考 xff1a 默认区块传播延迟10秒 span class token string 34 baseDeltaSeconds 34 span span class token p
  • Ubuntu 18.04禁止内核更新

    apt span class token operator span mark showhold linux span class token operator span headers span class token operator
  • AMD64的4个架构级别 v1 v2 v3 v4

    查看cpu支持指令 lscpu span class token operator span grep Flags 例如 GOAMD64 61 v3 使用 AVX2 查看cpu是否支持指令 lscpu span class token op
  • Ubuntu 18.04 安装 ffmpeg

    Ubuntu 18 04 安装 ffmpeg wget http span class token punctuation span span class token operator span span class token opera
  • 图形界面无法启动的解决办法

    错误提示信息 xff1a log file 34 var log xorg 0 log 34 Using config file 34 etc X11 Xorg conf 34 gt error bad lenght in compatma
  • SUSE Linux Ubuntu 下安装mysql遇到的问题一。

    用的是阿里云的新服务器 xff0c 用的是Ubuntu不是Contos的在安装mysql的时候遇到了一些问题 在此记录一下 1 创建目录用来下载安装包 命令 xff1a mkdir usr local software 文件目录根据没有固定
  • 是时候拥抱ViewBinding了~

    是时候拥抱ViewBinding了 xff01 xff01 一 前言二 初识ViewBinding三 拥抱ViewBinding3 1 环境要求3 2 开启ViewBinding功能3 3 Activity中ViewBinding的使用3
  • linux下以rpm包安装mysql

    目录 下载 上传解压 安装 编辑my cnf配置文件 启动数据库 修改初始密码 授权远程登录 常见问题 下载 访问以下地址下载对应操作系统下所需的版本 https downloads mysql com archives community
  • sizeof用法详解

    一 sizeof是什么 sizeof是C语言的一种单目操作符 xff0c 如C语言的其他操作符 43 43 等 它并不是函数 sizeof操作符以字节形式给出了其操作数的存储大小 操作数可以是一个表达式或括在括号内的类型名 操作数的存储大小
  • 【ftp2ftp】文件以字节流的形式冲FTP1传输到FTP2,中间出现文件传输失败的问题(只传输了一半,文件损坏)

    文件传输问题 需求实现逻辑问题代码简述正确的代码代码合集 需求 代码直接实现两个ftp之间的文件相互传输 实现逻辑 ftp1的file转变成inputStream inputStream转变为字符集byte 字符集写入ftp2的output
  • 【Java】反编译Mac版Charles,修改一些功能

    目录 反编译jar使用javassist修改目标class替换CharlesContext class 参考 最近学习HTTP代理相关资料时 xff0c 偶然间发现Mac上的charles是用java实现的 xff0c 且很好破解 xff0
  • 为什么说TCP是面向流的协议?而UDP是面向数据报的协议?

    问题 经常能听人说 xff1a TCP是面向流的协议 xff0c 而UDP是面向数据报的协议 从字面理解上来说 xff0c 似懂非懂 每次都不是能彻底明白什么是流 xff0c 什么是数据报 xff1f 在大家眼里 xff0c 网络报文都是I
  • 【面试题】N级台阶(比如100级),每次可走1步或者2步,求总共有多少种走法?

    走台阶算法 xff08 本质上是斐波那契数列 xff09 在面试中常会遇到 xff0c 描述就如题目那样 xff1a 总共100级台阶 xff08 任意级都行 xff09 xff0c 小明每次可选择走1步 2步或者3步 xff0c 问走完这
  • Java访问权限修饰符的区别

    Java有四种访问权限 xff0c 其中三种有访问权限修饰符 xff0c 分别为private xff0c public和protected xff0c 还有一种不带任何修饰符 xff1a private Java语言中对访问权限限制的最窄

随机推荐

  • “二分查找”算法的时间复杂度

    算法的时间复杂度无非就是for while等包含起来的基本运算单元的循环次数 1 二分查找 二分查找 xff08 binary search xff09 xff0c 也称作折半查找 xff08 half interval search xf
  • ORA-12547与在 root 下执行 Oracle 程序时找不到 libclntsh.so.11.1解决方案

    在 root 下执行 Oracle 程序时找不到 libclntsh so 11 1时 如图所示libclntsh so 11 1 61 gt not found 解决方法 xff1a locate libclntsh so 11 1 找到
  • 【D3.js】力导向布局 + 圆形图片展示的人物关系

    前言 使用d3的力学图 xff08 力导向图 xff09 与生活中常见的人物关系图结合 xff0c 已经有了很好的例子 xff1a D3 js 进阶系列 2 0 力学图 43 人物关系图 xff0c 博主实现了下面这种样式 xff0c 已经
  • 【Android】adb 查看所有程序包名

    adb shell pm span class hljs keyword list span packages 列出所有的包名 adb shell pm list packages span class hljs label package
  • 【算法】大数乘法问题及其高效算法

    题目 编写两个任意位数的大数相乘的程序 xff0c 给出计算结果 比如 xff1a 题目描述 xff1a 输出两个不超过100位的大整数的乘积 输入 xff1a 输入两个大整数 xff0c 如1234567 和 123 输出 xff1a 输
  • 【算法】如何判断链表有环

    如何判断单链表是否存在环 有一个单向链表 xff0c 链表当中有可能出现 环 xff0c 就像题图这样 如何用程序判断出这个链表是有环链表 xff1f 不允许修改链表结构 时间复杂度O n xff0c 空间复杂度O 1 方法一 穷举遍历 方
  • 【Android】移动端接入Cronet实践

    移动端接入Cronet实践 QUIC协议获取Chromium源码编译CronetAndroid iOS buildsDesktop builds targets the current OS Running the ninja files生
  • Linux系统下安装Java环境

    目录 测试环境 下载JDK 终端模拟软件 安装前准备 tar包的安装方法 tar包的卸载 rpm包的安装方法 rpm包的卸载 测试环境 LInux系统版本 xff1a CentOS 7 64位 终端模拟软件 xff1a Xshell 6 J
  • 【Hexo】Hexo个人博客绑定域名

    Hexo个人博客绑定域名 当我们在用hexo搭建了个人博客之后 xff0c 用username github io访问难免有些奇怪 xff0c 下面就花3分钟时间对如何绑定个人域名进行描述 我这边是在阿里云买的一个域名 xff0c ycbl
  • 生产者消费者的代码实现

    当消费者获得的数据为大写字母时 xff0c 则把大写字母转换成小写字母 xff0c 并显示 xff1b 当消费者获得的数据为小写字母时 xff0c 则把小写字母转换成大写字母 xff0c 并显示 xff1b 当消费者获得的数据为字符0 1
  • 基于RobHess的SIFT图像拼接知识点随笔

    1 SIFT算法具有尺度不变性在于构建的高斯尺度空间 xff1b 2 SIFT算法具有旋转不变性在于特征方向向量 xff1b 3 K d数以图像特征点的128维特征描述子均值为依据进行划分 构建 xff1b 4 特征点匹配是一个图像的所有特
  • 最小二乘法及OpenCv函数

    1 最小二乘法 我们以最简单的一元线性模型来解释最小二乘法 什么是一元线性模型呢 xff1f 监督学习中 xff0c 如果预测的变量是离散的 xff0c 我们称其为分类 xff08 如决策树 xff0c 支持向量机等 xff09 xff0c
  • Linux服务器网络不通情况分析以及常见检查方法

    在实际运维过程中 xff0c 经常会遇到网路不通的问题 xff0c 一般此类网络不通的问题都是业务端到端的排查 本文从后端linux服务器端自查是否服务器问题 通过多年的运维经验总结 xff0c 服务器端问题导致网络不通 xff0c 大致分
  • RANSAC算法实现去除误匹配并计算拼接矩阵-随笔

    1 RANSAC算法实现去除误匹配并计算拼接矩阵流程 1 从样本集中随机抽选一个RANSAC样本 xff0c 即4个匹配点对 xff08 至少4个匹配点对 xff0c 才能计算出3 3变换矩阵 xff09 xff1b 2 计算当错误概率为0
  • linux c++ 服务器端开发面试必看书籍

    由于很多朋友希望加入到Linux c 43 43 服务器端开发的队伍中 xff0c 本人就结合自己的面试经历并整理了自己阅读的相关书籍 xff0c 同大家分享 xff0c 一起进步 人个认为以下是进入这个方向的必看书籍 xff0c 各系列难
  • C++进阶—>const、define和enum的区别和用途

    1 区别 这三种都可以定义常量 define是宏定义 xff0c 编译器不对其进行错误检查 xff0c 在预编译阶段处理 xff0c 没有作用域限制属于全局常量 xff0c 在程序中编译器会对定义的常量名以数值进行替换 xff0c 且每次替
  • MFC中基于OpenCV实现Picture Control控件成像方法

    MFC中基于OpenCV实现Picture Control控件成像方法有两种 xff0c 一种是OpenCV2 2以前版本的绘制 xff0c 另外一种是OpenCV2 2以后版本的绘制 xff08 1 xff09 在OpenCV2 2之前的
  • MFC中CFileDialog及SHBrowseForFolder

    MFC中实现通过按钮来选择文件路径或文件夹路径 xff1b xff08 1 xff09 CFileDialog类能够选择文件 xff0c 并获取其路径 xff08 当然也可以通过获取文件路径再去除文件名而获得其所在文件夹路径 xff0c 前
  • C++进阶—>带你理解多字节编码与Unicode码

    本篇文章将讲解C 43 43 开发中容易混淆的另一个概念 多字节字符集与Unicode字符集 多字节字符与宽字节字符 char与wchar t 我们知道C 43 43 基本数据类型中表示字符的有两种 xff1a char wchar t c
  • BP神经网络及其C++实现

    0 前言 神经网络在我印象中一直比较神秘 xff0c 正好最近学习了神经网络 xff0c 特别是对Bp神经网络有了比较深入的了解 xff0c 因此 xff0c 总结以下心得 xff0c 希望对后来者有所帮助 神经网络在机器学习中应用比较广泛