OpenCV的机器学习类定义在ml.hpp文件中,基础类是CvStatModel,其他各种分类器从这里继承而来。

今天研究CvNormalBayesClassifier分类器。

1.类定义

在ml.hpp中有以下类定义:

[cpp] view plaincopyprint?
  1. class CV_EXPORTS_W CvNormalBayesClassifier : public CvStatModel
  2. {
  3. public:
  4. CV_WRAP CvNormalBayesClassifier();
  5. virtual ~CvNormalBayesClassifier();
  6. CvNormalBayesClassifier( const CvMat* trainData, const CvMat* responses,
  7. const CvMat* varIdx=0, const CvMat* sampleIdx=0 );
  8. virtual bool train( const CvMat* trainData, const CvMat* responses,
  9. const CvMat* varIdx = 0, const CvMat* sampleIdx=0, bool update=false );
  10. virtual float predict( const CvMat* samples, CV_OUT CvMat* results=0 ) const;
  11. CV_WRAP virtual void clear();
  12. CV_WRAP CvNormalBayesClassifier( const cv::Mat& trainData, const cv::Mat& responses,
  13. const cv::Mat& varIdx=cv::Mat(), const cv::Mat& sampleIdx=cv::Mat() );
  14. CV_WRAP virtual bool train( const cv::Mat& trainData, const cv::Mat& responses,
  15. const cv::Mat& varIdx = cv::Mat(), const cv::Mat& sampleIdx=cv::Mat(),
  16. bool update=false );
  17. CV_WRAP virtual float predict( const cv::Mat& samples, CV_OUT cv::Mat* results=0 ) const;
  18. virtual void write( CvFileStorage* storage, const char* name ) const;
  19. virtual void read( CvFileStorage* storage, CvFileNode* node );
  20. protected:
  21. int     var_count, var_all;
  22. CvMat*  var_idx;
  23. CvMat*  cls_labels;
  24. CvMat** count;
  25. CvMat** sum;
  26. CvMat** productsum;
  27. CvMat** avg;
  28. CvMat** inv_eigen_values;
  29. CvMat** cov_rotate_mats;
  30. CvMat*  c;
  31. };

2.示例

此类使用方法如下:(引用别人的代码,忘记出处了,非常抱歉这个。。。)

[cpp] view plaincopyprint?
  1. //openCV中贝叶斯分类器的API函数用法举例
  2. //运行环境:win7 + VS2005 + openCV2.4.5
  3. #include "global_include.h"
  4. using namespace std;
  5. using namespace cv;
  6. //10个样本特征向量维数为12的训练样本集,第一列为该样本的类别标签
  7. double inputArr[10][13] =
  8. {
  9. 1,0.708333,1,1,-0.320755,-0.105023,-1,1,-0.419847,-1,-0.225806,0,1,
  10. -1,0.583333,-1,0.333333,-0.603774,1,-1,1,0.358779,-1,-0.483871,0,-1,
  11. 1,0.166667,1,-0.333333,-0.433962,-0.383562,-1,-1,0.0687023,-1,-0.903226,-1,-1,
  12. -1,0.458333,1,1,-0.358491,-0.374429,-1,-1,-0.480916,1,-0.935484,0,-0.333333,
  13. -1,0.875,-1,-0.333333,-0.509434,-0.347032,-1,1,-0.236641,1,-0.935484,-1,-0.333333,
  14. -1,0.5,1,1,-0.509434,-0.767123,-1,-1,0.0534351,-1,-0.870968,-1,-1,
  15. 1,0.125,1,0.333333,-0.320755,-0.406393,1,1,0.0839695,1,-0.806452,0,-0.333333,
  16. 1,0.25,1,1,-0.698113,-0.484018,-1,1,0.0839695,1,-0.612903,0,-0.333333,
  17. 1,0.291667,1,1,-0.132075,-0.237443,-1,1,0.51145,-1,-0.612903,0,0.333333,
  18. 1,0.416667,-1,1,0.0566038,0.283105,-1,1,0.267176,-1,0.290323,0,1
  19. };
  20. //一个测试样本的特征向量
  21. double testArr[]=
  22. {
  23. 0.25,1,1,-0.226415,-0.506849,-1,-1,0.374046,-1,-0.83871,0,-1
  24. };
  25. int _tmain(int argc, _TCHAR* argv[])
  26. {
  27. Mat trainData(10, 12, CV_32FC1);//构建训练样本的特征向量
  28. for (int i=0; i<10; i++)
  29. {
  30. for (int j=0; j<12; j++)
  31. {
  32. trainData.at<float>(i, j) = inputArr[i][j+1];
  33. }
  34. }
  35. Mat trainResponse(10, 1, CV_32FC1);//构建训练样本的类别标签
  36. for (int i=0; i<10; i++)
  37. {
  38. trainResponse.at<float>(i, 0) = inputArr[i][0];
  39. }
  40. CvNormalBayesClassifier nbc;
  41. bool trainFlag = nbc.train(trainData, trainResponse);//进行贝叶斯分类器训练
  42. if (trainFlag)
  43. {
  44. cout<<"train over..."<<endl;
  45. nbc.save("normalBayes.txt");
  46. }
  47. else
  48. {
  49. cout<<"train error..."<<endl;
  50. system("pause");
  51. exit(-1);
  52. }
  53. CvNormalBayesClassifier testNbc;
  54. testNbc.load("normalBayes.txt");
  55. Mat testSample(1, 12, CV_32FC1);//构建测试样本
  56. for (int i=0; i<12; i++)
  57. {
  58. testSample.at<float>(0, i) = testArr[i];
  59. }
  60. float flag = testNbc.predict(testSample);//进行测试
  61. cout<<"flag = "<<flag<<endl;
  62. system("pause");
  63. return 0;
  64. }

3.步骤

两步走:

1.调用train函数训练分类器;

2.调用predict函数,判定测试样本的类别。

以上示例代码还延时了怎样使用save和load函数,使得训练好的分类器可以保存在文本中。

4.初始化

接下来,看CvNormalBayesClassifier类的无参数初始化:

[cpp] view plaincopyprint?
  1. CvNormalBayesClassifier::CvNormalBayesClassifier()
  2. {
  3. var_count = var_all = 0;
  4. var_idx = 0;
  5. cls_labels = 0;
  6. count = 0;
  7. sum = 0;
  8. productsum = 0;
  9. avg = 0;
  10. inv_eigen_values = 0;
  11. cov_rotate_mats = 0;
  12. c = 0;
  13. default_model_name = "my_nb";
  14. }

还有另一种带参数的初始化形式:

[cpp] view plaincopyprint?
  1. CvNormalBayesClassifier::CvNormalBayesClassifier(
  2. const CvMat* _train_data, const CvMat* _responses,
  3. const CvMat* _var_idx, const CvMat* _sample_idx )
  4. {
  5. var_count = var_all = 0;
  6. var_idx = 0;
  7. cls_labels = 0;
  8. count = 0;
  9. sum = 0;
  10. productsum = 0;
  11. avg = 0;
  12. inv_eigen_values = 0;
  13. cov_rotate_mats = 0;
  14. c = 0;
  15. default_model_name = "my_nb";
  16. train( _train_data, _responses, _var_idx, _sample_idx );
  17. }

可见,带参数形式糅合了类的初始化和train函数。

另外,以Mat参数形式的对应函数版本,功能是一致的,只不过为了体现2.0以后版本的C++特性罢了。如下:

[cpp] view plaincopyprint?
  1. CV_WRAP CvNormalBayesClassifier( const cv::Mat& trainData, const cv::Mat& responses,
  2. const cv::Mat& varIdx=cv::Mat(), const cv::Mat& sampleIdx=cv::Mat() );
  3. CV_WRAP virtual bool train( const cv::Mat& trainData, const cv::Mat& responses,
  4. const cv::Mat& varIdx = cv::Mat(), const cv::Mat& sampleIdx=cv::Mat(),
  5. bool update=false );
  6. CV_WRAP virtual float predict( const cv::Mat& samples, CV_OUT cv::Mat* results=0 ) const;

5.训练

下面开始分析train函数,分析CvMat格式参数的train函数,即:

[cpp] view plaincopyprint?
  1. bool train( const CvMat* trainData, const CvMat* responses,const CvMat* varIdx = 0, const CvMat* sampleIdx=0, bool update=false );

在进入该函数之前,还要先回头看看CvNormalBayesClassifier类有哪些数据成员:

[cpp] view plaincopyprint?
  1. protected:
  2. int     var_count, var_all; //每个样本的特征维数、即变量数目,或者说trainData的列数目(在varIdx=0时)
  3. CvMat*  var_idx;        //特征子集的索引,可能特征数目为100,但是只用其中一部分训练
  4. CvMat*  cls_labels;     //类别数目
  5. CvMat** count;      //count[0...(classNum-1)],每个元素是一个CvMat(rows=1,cols=var_count)指针,代表训练数据中每一类的某个特征的数目
  6. CvMat** sum;        //sum[0...(classNum-1)],每个元素是一个CvMat(rows=1,cols=var_count)指针,代表训练数据中每一类的某个特征的累加和
  7. CvMat** productsum;     //productsum[0...(classNum-1)],每个元素是一个CvMat(rows=cols=var_count)指针,存储类内特征相关矩阵
  8. CvMat** avg;        //avg[0...(classNum-1)],每个元素是一个CvMat(rows=1,cols=var_count)指针,代表训练数据中每一类的某个特征的平均值
  9. CvMat** inv_eigen_values;//inv_eigen_values[0...(classNum-1)],每个元素是一个CvMat(rows=1,cols=var_count)指针,代表训练数据中每一类的某个特征的特征值的倒数
  10. CvMat** cov_rotate_mats;    //特征变量的协方差矩阵经过SVD奇异值分解后得到的特征向量矩阵
  11. CvMat*  c;

这些数据成员,怎样使用呢?在train函数中见分晓:

[cpp] view plaincopyprint?
  1. bool CvNormalBayesClassifier::train( const CvMat* _train_data, const CvMat* _responses,
  2. const CvMat* _var_idx, const CvMat* _sample_idx, bool update )
  3. {
  4. const float min_variation = FLT_EPSILON;
  5. bool result = false;
  6. CvMat* responses   = 0;
  7. const float** train_data = 0;
  8. CvMat* __cls_labels = 0;
  9. CvMat* __var_idx = 0;
  10. CvMat* cov = 0;
  11. CV_FUNCNAME( "CvNormalBayesClassifier::train" );
  12. __BEGIN__;
  13. int cls, nsamples = 0, _var_count = 0, _var_all = 0, nclasses = 0;
  14. int s, c1, c2;
  15. const int* responses_data;
  16. //1.整理训练数据
  17. CV_CALL( cvPrepareTrainData( 0,
  18. _train_data, CV_ROW_SAMPLE, _responses, CV_VAR_CATEGORICAL,
  19. _var_idx, _sample_idx, false, &train_data,
  20. &nsamples, &_var_count, &_var_all, &responses,
  21. &__cls_labels, &__var_idx ));
  22. if( !update )   //如果是初始训练数据
  23. {
  24. const size_t mat_size = sizeof(CvMat*);
  25. size_t data_size;
  26. clear();
  27. var_idx = __var_idx;
  28. cls_labels = __cls_labels;
  29. __var_idx = __cls_labels = 0;
  30. var_count = _var_count;
  31. var_all = _var_all;
  32. nclasses = cls_labels->cols;
  33. data_size = nclasses*6*mat_size;
  34. CV_CALL( count = (CvMat**)cvAlloc( data_size ));
  35. memset( count, 0, data_size );          //count[cls]存储第cls类每个属性变量个数
  36. sum             = count      + nclasses;//sum[cls]存储第cls类每个属性取值的累加和
  37. productsum      = sum        + nclasses;//productsum[cls]存储第cls类的协方差矩阵的乘积项sum(XiXj),cov(Xi,Xj)=sum(XiXj)-sum(Xi)E(Xj)
  38. avg             = productsum + nclasses;//avg[cls]存储第cls类的每个变量均值
  39. inv_eigen_values= avg        + nclasses;//inv_eigen_values[cls]存储第cls类的协方差矩阵的特征值
  40. cov_rotate_mats = inv_eigen_values         + nclasses;//存储第cls类的矩阵的特征值对应的特征向量
  41. CV_CALL( c = cvCreateMat( 1, nclasses, CV_64FC1 ));
  42. for( cls = 0; cls < nclasses; cls++ )    //对所有类别
  43. {
  44. CV_CALL(count[cls]            = cvCreateMat( 1, var_count, CV_32SC1 ));
  45. CV_CALL(sum[cls]              = cvCreateMat( 1, var_count, CV_64FC1 ));
  46. CV_CALL(productsum[cls]       = cvCreateMat( var_count, var_count, CV_64FC1 ));
  47. CV_CALL(avg[cls]              = cvCreateMat( 1, var_count, CV_64FC1 ));
  48. CV_CALL(inv_eigen_values[cls] = cvCreateMat( 1, var_count, CV_64FC1 ));
  49. CV_CALL(cov_rotate_mats[cls]  = cvCreateMat( var_count, var_count, CV_64FC1 ));
  50. CV_CALL(cvZero( count[cls] ));
  51. CV_CALL(cvZero( sum[cls] ));
  52. CV_CALL(cvZero( productsum[cls] ));
  53. CV_CALL(cvZero( avg[cls] ));
  54. CV_CALL(cvZero( inv_eigen_values[cls] ));
  55. CV_CALL(cvZero( cov_rotate_mats[cls] ));
  56. }
  57. }
  58. else    //如果是更新训练数据
  59. {
  60. // check that the new training data has the same dimensionality etc.
  61. if( _var_count != var_count || _var_all != var_all || !((!_var_idx && !var_idx) ||
  62. (_var_idx && var_idx && cvNorm(_var_idx,var_idx,CV_C) < DBL_EPSILON)) )
  63. CV_ERROR( CV_StsBadArg,
  64. "The new training data is inconsistent with the original training data" );
  65. if( cls_labels->cols != __cls_labels->cols ||
  66. cvNorm(cls_labels, __cls_labels, CV_C) > DBL_EPSILON )
  67. CV_ERROR( CV_StsNotImplemented,
  68. "In the current implementation the new training data must have absolutely "
  69. "the same set of class labels as used in the original training data" );
  70. nclasses = cls_labels->cols;
  71. }
  72. responses_data = responses->data.i;
  73. CV_CALL( cov = cvCreateMat( _var_count, _var_count, CV_64FC1 ));
  74. //2.处理训练数据,计算每一类的
  75. // process train data (count, sum , productsum)
  76. for( s = 0; s < nsamples; s++ )
  77. {
  78. cls = responses_data[s];
  79. int* count_data = count[cls]->data.i;
  80. double* sum_data = sum[cls]->data.db;
  81. double* prod_data = productsum[cls]->data.db;
  82. const float* train_vec = train_data[s];
  83. for( c1 = 0; c1 < _var_count; c1++, prod_data += _var_count )
  84. {
  85. double val1 = train_vec[c1];
  86. sum_data[c1] += val1;
  87. count_data[c1]++;
  88. for( c2 = c1; c2 < _var_count; c2++ )
  89. prod_data[c2] += train_vec[c2]*val1;
  90. }
  91. }
  92. //计算每一类的每个属性平均值、协方差矩阵
  93. // calculate avg, covariance matrix, c
  94. for( cls = 0; cls < nclasses; cls++ )    //对每一类
  95. {
  96. double det = 1;
  97. int i, j;
  98. CvMat* w = inv_eigen_values[cls];
  99. int* count_data = count[cls]->data.i;
  100. double* avg_data = avg[cls]->data.db;
  101. double* sum1 = sum[cls]->data.db;
  102. cvCompleteSymm( productsum[cls], 0 );
  103. for( j = 0; j < _var_count; j++ )    //计算当前类别cls的每个变量属性值的平均值
  104. {
  105. int n = count_data[j];
  106. avg_data[j] = n ? sum1[j] / n : 0.;
  107. }
  108. count_data = count[cls]->data.i;
  109. avg_data = avg[cls]->data.db;
  110. sum1 = sum[cls]->data.db;
  111. for( i = 0; i < _var_count; i++ )//计算当前类别cls的变量协方差矩阵,矩阵大小为_var_count * _var_count,注意协方差矩阵对称。
  112. {
  113. double* avg2_data = avg[cls]->data.db;
  114. double* sum2 = sum[cls]->data.db;
  115. double* prod_data = productsum[cls]->data.db + i*_var_count;
  116. double* cov_data = cov->data.db + i*_var_count;
  117. double s1val = sum1[i];
  118. double avg1 = avg_data[i];
  119. int _count = count_data[i];
  120. for( j = 0; j <= i; j++ )
  121. {
  122. double avg2 = avg2_data[j];
  123. double cov_val = prod_data[j] - avg1 * sum2[j] - avg2 * s1val + avg1 * avg2 * _count;
  124. cov_val = (_count > 1) ? cov_val / (_count - 1) : cov_val;
  125. cov_data[j] = cov_val;
  126. }
  127. }
  128. CV_CALL( cvCompleteSymm( cov, 1 ));
  129. CV_CALL( cvSVD( cov, w, cov_rotate_mats[cls], 0, CV_SVD_U_T ));
  130. CV_CALL( cvMaxS( w, min_variation, w ));
  131. for( j = 0; j < _var_count; j++ )
  132. det *= w->data.db[j];
  133. CV_CALL( cvDiv( NULL, w, w ));
  134. c->data.db[cls] = det > 0 ? log(det) : -700;
  135. }
  136. result = true;
  137. __END__;
  138. if( !result || cvGetErrStatus() < 0 )
  139. clear();
  140. cvReleaseMat( &cov );
  141. cvReleaseMat( &__cls_labels );
  142. cvReleaseMat( &__var_idx );
  143. cvFree( &train_data );
  144. return result;
  145. }

训练部分就此完成。

6.预测

下面看用于预测的predict函数的实现代码:

[cpp] view plaincopyprint?
  1. float CvNormalBayesClassifier::predict( const CvMat* samples, CvMat* results ) const
  2. {
  3. float value = 0;
  4. if( !CV_IS_MAT(samples) || CV_MAT_TYPE(samples->type) != CV_32FC1 || samples->cols != var_all )
  5. CV_Error( CV_StsBadArg,
  6. "The input samples must be 32f matrix with the number of columns = var_all" );
  7. if( samples->rows > 1 && !results )
  8. CV_Error( CV_StsNullPtr,
  9. "When the number of input samples is >1, the output vector of results must be passed" );
  10. if( results )
  11. {
  12. if( !CV_IS_MAT(results) || (CV_MAT_TYPE(results->type) != CV_32FC1 &&
  13. CV_MAT_TYPE(results->type) != CV_32SC1) ||
  14. (results->cols != 1 && results->rows != 1) ||
  15. results->cols + results->rows - 1 != samples->rows )
  16. CV_Error( CV_StsBadArg, "The output array must be integer or floating-point vector "
  17. "with the number of elements = number of rows in the input matrix" );
  18. }
  19. const int* vidx = var_idx ? var_idx->data.i : 0;
  20. cv::parallel_for(cv::BlockedRange(0, samples->rows), predict_body(c, cov_rotate_mats, inv_eigen_values, avg, samples,
  21. vidx, cls_labels, results, &value, var_count
  22. ));
  23. return value;
  24. }

可以发现,预测部分核心代码是:

[cpp] view plaincopyprint?
  1. cv::parallel_for(cv::BlockedRange(0, samples->rows), predict_body(c, cov_rotate_mats, inv_eigen_values, avg, samples,
  2. vidx, cls_labels, results, &value, var_count));

parallel_for是用于并行支持的,可能会调用tbb模块。predict_body则是一个结构体,内部的()符号被重载,实现预测功能。其完整定义如下:

[cpp] view plaincopyprint?
  1. //predict函数调用predict_body结构体的()符号重载函数,实现基于贝叶斯的分类
  2. struct predict_body
  3. {
  4. predict_body(CvMat* _c, CvMat** _cov_rotate_mats, CvMat** _inv_eigen_values, CvMat** _avg,
  5. const CvMat* _samples, const int* _vidx, CvMat* _cls_labels,
  6. CvMat* _results, float* _value, int _var_count1)
  7. {
  8. c = _c;
  9. cov_rotate_mats = _cov_rotate_mats;
  10. inv_eigen_values = _inv_eigen_values;
  11. avg = _avg;
  12. samples = _samples;
  13. vidx = _vidx;
  14. cls_labels = _cls_labels;
  15. results = _results;
  16. value = _value;
  17. var_count1 = _var_count1;
  18. }
  19. CvMat* c;
  20. CvMat** cov_rotate_mats;
  21. CvMat** inv_eigen_values;
  22. CvMat** avg;
  23. const CvMat* samples;
  24. const int* vidx;
  25. CvMat* cls_labels;
  26. CvMat* results;
  27. float* value;
  28. int var_count1;
  29. void operator()( const cv::BlockedRange& range ) const
  30. {
  31. int cls = -1;
  32. int rtype = 0, rstep = 0;
  33. int nclasses = cls_labels->cols;
  34. int _var_count = avg[0]->cols;
  35. if (results)
  36. {
  37. rtype = CV_MAT_TYPE(results->type);
  38. rstep = CV_IS_MAT_CONT(results->type) ? 1 : results->step/CV_ELEM_SIZE(rtype);
  39. }
  40. // allocate memory and initializing headers for calculating
  41. cv::AutoBuffer<double> buffer(nclasses + var_count1);
  42. CvMat diff = cvMat( 1, var_count1, CV_64FC1, &buffer[0] );
  43. for(int k = range.begin(); k < range.end(); k += 1 )//对于每个输入测试样本
  44. {
  45. int ival;
  46. double opt = FLT_MAX;
  47. for(int i = 0; i < nclasses; i++ )   //对于每一类别,计算其似然概率
  48. {
  49. double cur = c->data.db[i];
  50. CvMat* u = cov_rotate_mats[i];
  51. CvMat* w = inv_eigen_values[i];
  52. const double* avg_data = avg[i]->data.db;
  53. const float* x = (const float*)(samples->data.ptr + samples->step*k);
  54. // cov = u w u'  -->  cov^(-1) = u w^(-1) u'
  55. for(int j = 0; j < _var_count; j++ ) //计算特征相对于均值的偏移
  56. diff.data.db[j] = avg_data[j] - x[vidx ? vidx[j] : j];
  57. cvGEMM( &diff, u, 1, 0, 0, &diff, CV_GEMM_B_T );
  58. for(int j = 0; j < _var_count; j++ )//计算特征的联合概率
  59. {
  60. double d = diff.data.db[j];
  61. cur += d*d*w->data.db[j];
  62. }
  63. if( cur < opt )  //找到分类概率最大的
  64. {
  65. cls = i;
  66. opt = cur;
  67. }
  68. // probability = exp( -0.5 * cur )
  69. }//for(int i = 0; i < nclasses; i++ )
  70. ival = cls_labels->data.i[cls];
  71. if( results )
  72. {
  73. if( rtype == CV_32SC1 )
  74. results->data.i[k*rstep] = ival;
  75. else
  76. results->data.fl[k*rstep] = (float)ival;
  77. }
  78. if( k == 0 )
  79. *value = (float)ival;
  80. }//for(int k = range.begin()...
  81. }//void operator()...
  82. };

Normal Bayes 分类器过程详解相关推荐

  1. SVM分类器原理详解

    SVM分类器原理详解 标签: svm文本分类java 2015-08-21 11:51 2399人阅读 评论(0) 收藏 举报  分类: 数据挖掘 文本处理(16)  机器学习 分类算法(10)  目 ...

  2. 01_什么是one-hot编码、one-hot编码过程详解、为什么需要one-hot编码?one-hot编码的优缺点、使用sklearn中的API举例

    以下资料来自:网络+最后的整合 https://www.cnblogs.com/shuaishuaidefeizhu/p/11269257.html https://www.cntofu.com/bo ...

  3. 浅谈嵌入式MCU软件开发之startup过程详解(从复位向量到main函数之前的准备工作)

    引言 一般工程师都怕研究MCU的startup过程,其原因可能有:1.觉得没有必要,startup的过程和启动代码在新建工程时,并且已经默认加入并配置好,能够保证MCU正常工作,只要关系main()函 ...

  4. zabbix 监控过程详解

    监控过程详解 1.修改密码及中文版 按如上操作即可,选择中文以后,点击下面的update即可更新成功 为了安全起见修改密码 修改完成后同样点击更新即可. 2.创建主机及主机群组 1.定义一个主机群组 ...

  5. Spring生命周期Bean初始化过程详解

    Spring生命周期Bean初始化过程详解 Spring 容器初始化 Spring Bean初始化 BeanFactory和FactoryBean 源码分析 Bean的实例化 preInstantia ...

  6. python人脸识别opencv_Python基于Opencv来快速实现人脸识别过程详解(完整版)

    前言 随着人工智能的日益火热,计算机视觉领域发展迅速,尤其在人脸识别或物体检测方向更为广泛,今天就为大家带来最基础的人脸识别基础,从一个个函数开始走进这个奥妙的世界. 首先看一下本实验需要的数据集,为 ...

  7. nagios配置过程详解

    一.nagios配置过程详解 1.nagios默认配置文件介绍  nagios安装完毕后,默认的配置文件在/usr/local/nagios/etc目录下,每个文件或目录含义如下表所示: 2.配置文件 ...

  8. 机器学习分类器评价指标详解(Precision, Recall, PR, ROC, AUC等)(一)

    为了系统性地理解机器学习模型的不同评价指标及其之间的关系,我们将从其定义出发,探究其物理含义及彼此之间的联系,并从数学上给出相应的公式推导,以方便后续用到时复习理解.由于篇幅较长,因此将其分为两篇,这 ...

  9. 图像特征提取(VGG和Resnet特征提取卷积过程详解)

    图像特征提取(VGG和Resnet算法卷积过程详解) 第一章 图像特征提取认知 1.1常见算法原理和性能 众所周知,计算机不认识图像,只认识数字.为了使计算机能够"理解"图像,从而 ...

最新文章

  1. a标签onclick事件解析
  2. 软件测试概述--基础篇
  3. iPhone 利用CG API画一个饼图(Pie chart)
  4. 深入理解this机制系列第三篇——箭头函数
  5. java paint调用,求教 如何调用这个paint
  6. Ivan and Burgers(CF-1100F)
  7. Linux Shell高级技巧(四)
  8. 大数据_Flink_数据处理_流式数据源测试---Flink工作笔记0010
  9. C#连接Oracle中文乱码问题解决方法
  10. python的property用法_Python的@property使用方法详解
  11. X79双cpu linux,Sandy Bridge-E处理器、X79芯片组详尽官方规格
  12. 自学按键精灵写脚本,非常有用的一个函数
  13. Mysql 省市县乡 地址分割
  14. 2-2-2-webpack打包
  15. 计算与推断思维 十六、比较两个样本
  16. 关于EFS加密原理及破解浅谈
  17. 题8.9:写一函数,将一个3x3的整型矩阵转置。
  18. 【全网独家,收藏吧】10年全部《信息资源管理》真题整理,第2章 信息化规划与组织
  19. JAVA的卸载与重新安装
  20. 3D成像方法 汇总(原理解析)--- 双目视觉、激光三角、结构光、ToF、光场、全息...

热门文章

  1. 服务机器人---充电桩
  2. 高通camera驱动分析
  3. 如何解决Bluetooth系统设计的棘手问题
  4. formatnumber js_javascript js format number 数字格式化
  5. JAVA-接口和抽象类的区别
  6. VS Code 1.29 发布,众多新功能有没有你想要的?
  7. 二维数组,锯齿数组和集合 C# 一维数组、二维数组(矩形数组)、交错数组(锯齿数组)的使用 C# 数组、多维数组(矩形数组)、锯齿数组(交叉数组)...
  8. PHP安装编译错误及解决办法
  9. json过滤特殊字符
  10. 企业为什么需要网络流量分析