用支持向量机进行文理科生的分类,依据的特征主要是 数学成绩与语文成绩,这两个特征都服从高斯分布
程序代码如下:
#include
#include
using namespace std;
using namespace cv;
//生成具有一个特征的指定类别的训练数据集
void GenerateTrainData_two_feature(int sample_counts,double miu1,double sigma1,double miu2,double sigma2,Mat& train_data);
//把属于两个类的训练数据集混和起来,并记录对应的类别标签
void MixTrainDataFromTwoClasses(Mat& train_data1,Mat& train_data2,Mat& total_train_data,Mat& total_train_data_response);
int main(int argc, char* argv[])
{
int features_count = 2; //每个样本包含两个特征: 数学成绩 与 语文成绩
//生成类别一的训练数据集: 若干文科生的 数学成绩 和 语文成绩,假定这两个特征都服从高斯分布
int SampleCount1 = 200; //训练数据集1 的 样本个数
Mat TrainData1(SampleCount1,features_count,CV_32FC1); //训练数据集1 的 样本特征向量
//假定文科生的数学成绩的概率密度分布参数:均值 40,和 标准差 10
double sigma11 = 10;double miu11 = 40;
//假定文科生的语文成绩的概率密度分布参数:均值 80,和 标准差 10
double sigma12 = 10;double miu12 = 80;
//调用该函数生成文科生特征训练集
GenerateTrainData_two_feature(SampleCount1,miu11,sigma11,miu12,sigma12,TrainData1);
cout<
<<"文科生的成绩分布规律"<
(i)[0] = response;
}
cout<<"数学语文联合特征分类结果:"<
<
(i*101+j,0) = i; //第一个特征是数学成绩,0到100 TestSamples.at
(i*101+j,1) = j; //第二个特征是语文成绩, 0到100 } } //调用分类器对测试样本进行分类 for(int i=0;i<101*101;i++) { Mat sample = TestSamples.rowRange(i,i+1); float response = svm.predict(sample,false); TestSamplesResult.ptr
(i)[0] = response; } //绘制分类结果 Mat result_map(101,101,CV_8UC3); for(int i=0;i<101;i++) { for(int j=0;j<101;j++) { int label = (int)TestSamplesResult.at
(i*101+j,0); Vec3b v = label==1? Vec3b(255,0,0) : Vec3b(0,0,255); //蓝色代表第1类,红色代表第二类 result_map.at
(i,j) = v; //判决面中从左往右的顺序是语文成绩依次增加,从上往下的顺序是数学成绩依次增加 } } //把训练数据点画出来 for(int t=0;t
(t,0); pt.x = TotalSamplesData.at
(t,1); int label = SamplesResponse.ptr
(t)[0]; //白色的点是第二类的训练点集合,黑色的点是第一类的训练点集合 circle(result_map,pt,1,label==1? CV_RGB(0,0,0):CV_RGB(255,255,255)); } namedWindow("分类器判决面",0); imshow("分类器判决面",result_map); cout<
<<"判决面中 蓝色代表第1类:文科生,红色代表第二类:理科生"<
(k),train_data1.ptr
(i),sz1.width*(sizeof(float))); total_train_data_response.at
(k) = 1; k++; memcpy(total_train_data.ptr
(k),train_data2.ptr
(i),sz2.width*(sizeof(float))); total_train_data_response.at
(k) = 2; k++; } //如果两类样本的数目不一样,则把多余的样本追加到末尾 if(sz1.height > sz2.height) { for(int i = sz2.height;i
(k),train_data1.ptr
(i),sz1.width*(sizeof(float))); total_train_data_response.at
(k) = 1; k++; } } if(sz2.height > sz1.height) { for(int i = sz1.height;i
(k),train_data2.ptr
(i),sz2.width*(sizeof(float))); total_train_data_response.at
(k) = 2; k++; } } } //生成具有两个特征的指定类别的训练数据集 void GenerateTrainData_two_feature(int sample_counts,double miu1,double sigma1,double miu2,double sigma2,Mat& train_data) { int64 seed =/*100*/ getTickCount();//随机数种子,每次生成不一样的随机数 RNG rng1(seed); //创建一个随机数发生器对象 RNG rng2(seed*2); //创建一个随机数发生器对象 double MinFeatureValue = 0; // 特征的最小值 double MaxFeatureValue = 100;// 特征的最大值 //训练数据集矩阵初始化,样本按行存储,每一行是一个样本的2维特征向量, train_data = Mat::zeros(sample_counts,2,CV_32FC1); //循环生成样本特征集合 for(int i=0;i
=MinFeatureValue && a<=MaxFeatureValue) { //如果返回的随机数在指定的特征范围区间内部,则把它加入样本集 train_data.at
(i,0) = a ; } else { //如果返回的随机数超出了指定的特征范围的边界,为简单起见,直接把均值加入样本集 train_data.at
(i,0) = miu1 ; } if(b>=MinFeatureValue && b<=MaxFeatureValue) { //如果返回的随机数在指定的特征范围区间内部,则把它加入样本集 train_data.at
(i,1) = b ; } else { //如果返回的随机数超出了指定的特征范围的边界,为简单起见,直接把均值加入样本集 train_data.at
(i,1) = miu2 ; } } }
分类结果: