计算机智能第二次作业题目二:LibSVM代码注释SVM.hstructsvm_node//用来存储单一向量中的单个特征{intindex;//索引号doublevalue;//值};structsvm_problem//存储本次参加运算的所有样本(数据集),及其所属类别。{intl;//样本总数double*y;//指向样本所属类别的数组structsvm_node**x;//指向一个存储内容为指针的数组};enum{C_SVC,NU_SVC,ONE_CLASS,EPSILON_SVR,NU_SVR};//枚举svm的类型enum{LINEAR,POLY,RBF,SIGMOID};//枚举核函数的类型structsvm_parameter{intsvm_type;//SVM类型intkernel_type;//核函数类型doubledegree;//2式中的ddoublegamma;//2,3,4式中的gammadoublecoef0;//2,4式中的r/*thesearefortrainingonly*/doublecache_size;/*inMB*///制定训练所需要的内存,默认是40Mdoubleeps;/*stoppingcriteria*/doubleC;/*forC_SVC,EPSILON_SVRandNU_SVR*///惩罚因子intnr_weight;/*forC_SVC*///权重的数目,目前在实例代码中只有两个值,一个是默认0,//另外一个是svm_binary_svc_probability函数中使用数值2。int*weight_label;/*forC_SVC*///权重,元素个数由nr_weight决定double*weight;/*forC_SVC*/doublenu;/*forNU_SVC,ONE_CLASS,andNU_SVR*/doublep;/*forEPSILON_SVR*/intshrinking;/*usetheshrinkingheuristics*///指明训练过程是否使用压缩。intprobability;/*doprobabilityestimates*///新增,指明是否要做概率估计};//以下是所用到的核函数公式:structsvm_model//用于保存训练后的训练模型,当然原来的训练参数也必须保留{svm_parameterparam;//parameter//训练参数intnr_class;//numberofclasses,=2inregression/oneclasssvm//类别数intl;//total#SV//支持向量数svm_node**SV;//SVs(SV[l])//保存支持向量的指针double**sv_coef;//相当于判别函数中的alphadouble*rho;//constantsindecisionfunctions(rho[n*(n-1)/2])//相当于判别函数中的bdouble*probA;//pariwiseprobabilityinformation//新增函数double*probB;//新增函数//forclassificationonlyint*label;//labelofeachclass(label[n])//类标int*nSV;//numberofSVsforeachclass(nSV[n])//每个类中的元素数//nSV[0]+nSV[1]+...+nSV[n-1]=lintfree_sv;//1ifsvm_modeliscreatedbysvm_load_model//标记支持向量的内容是从文件中//0ifsvm_modeliscreatedbysvm_train//取得还是训练得出的};//以下为接口函数//最主要的驱动函数,训练数据structsvm_model*svm_train(conststructsvm_problem*prob,conststructsvm_parameter*param);//用SVM做交叉验证voidsvm_cross_validation(conststructsvm_problem*prob,conststructsvm_parameter*param,intnr_fold,double*target);//保存训练好的模型到文件intsvm_save_model(constchar*model_file_name,conststructsvm_model*model);//从文件中把训练好的模型读到内存中structsvm_model*svm_load_model(constchar*model_file_name);//得到数据集的类别intsvm_get_svm_type(conststructsvm_model*model);//得到数据集的类别数(必须经过训练得到模型后才可以用)intsvm_get_nr_class(conststructsvm_model*model);//得到数据集的类别标号(必须经过训练得到模型后才可以用)voidsvm_get_labels(conststructsvm_model*model,int*label);//LibSvm2.6新增函数doublesvm_get_svr_probability(conststructsvm_model*model);//用训练好的模型预报样本的值,输出结果保留到数组中。voidsvm_predict_values(conststructsvm_model*model,conststructsvm_node*x,double*dec_values);//预报某一样本的值doublesvm_predict(conststructsvm_model*model,conststructsvm_node*x);//LibSvm2.6新增函数doublesvm_predict_probability(conststructsvm_model*model,conststructsvm_node*x,double*prob_estimates);//消除训练的模型,释放资源voidsvm_destroy_model(structsvm_model*model);//LibSvm2.6新增函数voidsvm_destroy_param(structsvm_parameter*param);//检查输入的参数,保证后面的训练能正常进行。constchar*svm_check_parameter(conststructsvm_problem*prob,conststructsvm_parameter*param);//LibSvm2.6新增函数intsvm_check_probability_model(conststructsvm_model*model);SVM.cpp#includemath.h#includestdio.h#includestdlib.h#includectype.h#includefloat.h#includestring.h#includestdarg.h#includesvm.htypedeffloatQfloat;typedefsignedcharschar;//方便控制内存存储的精度//以下使用了内联函数完成比较大小,交换数据和完全复制数据的功能,提高执行速度#ifndefmintemplateclassTinlineTmin(Tx,Ty){return(xy)?x:y;}//求最小#endif#ifndefmaxtemplateclassTinlineTmax(Tx,Ty){return(xy)?x:y;}//求最大#endiftemplateclassTinlinevoidswap(T&x,T&y){Tt=x;x=y;y=t;}//交换x,y的值templateclassS,classTinlinevoidclone(T*&dst,S*src,intn){dst=newT[n];memcpy((void*)dst,(void*)src,sizeof(T)*n);//从src中拷n个单位长度的元素到dst中}#defineINFHUGE_VAL//定义下确界#defineMalloc(type,n)(type*)malloc((n)*sizeof(type))//定义n个type类型的元素//以下的函数用作调试。#if1voidinfo(char*fmt,...){va_listap;va_start(ap,fmt);vprintf(fmt,ap);va_end(ap);}voidinfo_flush(){fflush(stdout);}#elsevoidinfo(char*fmt,...){}voidinfo_flush(){}#endif类CacheclassCache//本类主要负责运算所涉及的内存的管理,包括申请、释放等{public:Cache(intl,intsize);//构造函数。该函数根据样本数L,申请L个head_t的空间~Cache();//析构函数intget_data(constintindex,Qfloat**data,intlen);//该函数保证head_t[index]中至少有len个//float的内存,并且将可以使用的内存块的指针放在data//指针中。返回值为head_t[index]原来的数据长度。voidswap_index(inti,intj);//future_option//交换head_t[i]和head_t[j]的内容private:intl;//样本总数intsize;//所指定的全部内存structhead_t{head_t*prev,*next;//acicularlist//双向链表的前后指针Qfloat*data;//记录数据intlen;//data[0,len)iscachedinthisentry//记录长度};head_t*head;//变量指针,该指针用来记录程序所申请的内存head_tlru_head;//双向链表的头voidlru_delete(head_t*h);//从双向链表中删除某个元素的链接voidlru_insert(head_t*h);//在链表后面插入一个新的链接};voidCache::swap_index(inti,intj){for(head_t*h=lru_head.next;h!=&lru_head;h=h-next){if(h-leni){if(h-lenj)swap(h-data[i],h-data[j]);else{//giveuplru_delete(h);free(h-data);size+=h-len;h-data=0;h-len=0;}}}类KernelclassKernel{public:Kernel(intl,svm_node*const*x,constsvm_parameter¶m);//构造函数。初始化类中的部//分常量、指定核函数、克隆样本数据。如果使用RBF核函数,则计算x-sqare[i].virtual~Kernel();//析构函数staticdoublek_function(constsvm_node*x,constsvm_node*y,constsvm_parameter¶m);//核函数。但只有在预报时才用到virtualQfloat*get_Q(intcolumn,intlen)const=0;//纯虚函数,将来在子类中实现virtualvoidswap_index(inti,intj)const//虚函数,x[i]和x[j]中所存储指针的内容{swap(x[i],x[j]);if(x_square)swap(x_square[i],x_s