您好,欢迎访问三七文档
当前位置:首页 > 金融/证券 > 金融资料 > 分类算法Java代码分析
Weak.classifiers包中含有用于分类和数值预测的大部分算法的实现。这个包中最重要的是类是Classifier,它定义了任何用于分类或数值预测的学习方案的通用结构。Classifier含有三个方法,buildClassfier(),classifyInstance(),distributionForInstance().学习算法用Classifier的子类代表,因此,自动继承这三个方法。每种方案都会根据构建分类器以及它对实例进行分类的具体方式对这三个方法进行重新定义。首先先解释一下算法名字,很多人很奇怪为什么叫IB1,IBK,IBInstance-Based的缩写,但按JiaweiHan书上所写,KNN其实是Instance-basedlearning(也被称为Lazinglearning)中一种,他还讲解了基于案例的推理(Case-basedreasoning)。算法其实是KNN,但是作者论文的名字是Instance-basedLearningAlgorithms。我先介绍一下IB1,IB1就是只找一个邻居。我们还是先看buildClassifier。publicvoidbuildClassifier(Instancesinstances)throwsException{if(instances.classAttribute().isNumeric()){thrownewException(IB1:Classisnumeric!);}//类别属性是数值型的话,报错。if(instances.checkForStringAttributes()){thrownewUnsupportedAttributeTypeException(IB1:Cannothandlestringattributes!);}//检查其他属性,如果是字符串String类型,报错:不能处理//Throwawaytraininginstanceswithmissingclass缺失类别属性的实例扔掉m_Train=newInstances(instances,0,instances.numInstances());m_Train.deleteWithMissingClass();//Instance是一个类,Createemptyinstancewiththreeattributevaluesm_MinArray=newdouble[m_Train.numAttributes()];//定义一个数组,m_MinArray,数据类型是double型,共有m_Train.numAttributes()个数据。m_MaxArray=newdouble[m_Train.numAttributes()];for(inti=0;im_Train.numAttributes();i++){m_MinArray[i]=m_MaxArray[i]=Double.NaN;}//还没有将真正的实例的属性存放在这两个数组里Enumerationenu=m_Train.enumerateInstances();//列举出每个实例的属性值while(enu.hasMoreElements()){//以枚举的实例属性数量进行循环判断updateMinMax((Instance)enu.nextElement());//更新属性的最大最小值}}是的,KNN也有buildClassifier,听起来蛮奇怪的。第二个if,IB1不能对字符串属性进行学习,因为这种属性不好定义距离,比如a和ab是0.5还是1呢?然类别缺失的样本抛弃。m_MinArray和m_MaxArray分别保存每一个属性的最小值和最大值。最下面是对样本进行循环,找出最大值,最小值,updataMinMax代码如下:privatevoidupdateMinMax(Instanceinstance){for(intj=0;jm_Train.numAttributes();j++){//有多少个属性就循环多少次if((m_Train.attribute(j).isNumeric())&&(!instance.isMissing(j))){//这个属性的第j个值是数值型,并且,实例不缺失这个属性值if(Double.isNaN(m_MinArray[j])){m_MinArray[j]=instance.value(j);//value()是要返回实例的属性值。m_MaxArray[j]=instance.value(j);}else{if(instance.value(j)m_MinArray[j]){m_MinArray[j]=instance.value(j);//如果这个属性值小于之前定义的最小属性值,将其值赋给最小属性值。}else{if(instance.value(j)m_MaxArray[j]){m_MaxArray[j]=instance.value(j);//如果这个属性值大于之前定义的最大属性值,将其值赋给最大属性值。}}}}}}Double.isNaN(m_MinArray[j])判断是不是m_MinArray和m_MaxArray已经赋值过了,else,如果可以更新min和更新max。再看一下classifyInstance函数:publicdoubleclassifyInstance(Instanceinstance)throwsException{//对待分类实例进行分类的过程。if(m_Train.numInstances()==0){thrownewException(Notraininginstances!);//实例数量为0,报错}doubledistance,minDistance=Double.MAX_VALUE,//声明并且初始化classValue=0;//classValue():实例的类别属性Returnsaninstance'sclassvalueininternalformatupdateMinMax(instance);Enumerationenu=m_Train.enumerateInstances();//enumerateInstances():Returnsanenumeration(列举,枚举)ofalltheattributes.while(enu.hasMoreElements()){InstancetrainInstance=(Instance)enu.nextElement();if(!trainInstance.classIsMissing()){distance=distance(instance,trainInstance);//distance方法在后面有说明if(distanceminDistance){minDistance=distance;classValue=trainInstance.classValue();//classValue():Returnsaninstance'sclassvalueininternalformat,返回这个实例的类别属性}}}returnclassValue;}因为要进化归范化,所以对这个待分类的样本再次调用updateMinMax。???然后对训练样本进行循环,用distance计算与每一个训练样本和待分类样本的距离,如果比前面的距离小,则记录,最后返回与测试样本距离最小的样本的类别值。privatedoubledistance(Instancefirst,Instancesecond){doublediff,distance=0;//声明并且初始化为0for(inti=0;im_Train.numAttributes();i++){if(i==m_Train.classIndex()){//classIndex():Returnstheclassattribute'sindexcontinue;}if(m_Train.attribute(i).isNominal()){//Ifattributeisnominalif(first.isMissing(i)||second.isMissing(i)||((int)first.value(i)!=(int)second.value(i))){distance+=1;}}else{//Ifattributeisnumericif(first.isMissing(i)||second.isMissing(i)){if(first.isMissing(i)&&second.isMissing(i)){diff=1;}else{if(second.isMissing(i)){diff=norm(first.value(i),i);}else{diff=norm(second.value(i),i);}if(diff0.5){diff=1.0-diff;}}}else{diff=norm(first.value(i),i)-norm(second.value(i),i);}distance+=diff*diff;}}returndistance;}和JiaweiHan书里面说的一样,对离散属性来说,两个样本任一在对应属性上为缺失值,距离为1,不相等当然还是为1。对于连续属性,如果两个都是缺失值,距离为1,其中之一在对应属性上为缺失值,把另一个不为缺失值的属性值规范化,距离为1-diff,意思就是设到可能的最远(当然那个缺失值比m_MinArray还小,m_MaxArray还大,这就不对了)。如果两个都有值,就把距离相加,最后平方。为了完整性,将norm列出来:norm的作用:将属性值正常化privatedoublenorm(doublex,inti){if(Double.isNaN(m_MinArray[i])||Utils.eq(m_MaxArray[i],m_MinArray[i])){return0;}else{return(x-m_MinArray[i])/(m_MaxArray[i]-m_MinArray[i]);}//最终计算距离的时候要使用欧几里得距离函数。2)2()1(2)2(3)1(32)2(2)1(22)2(1)1(1a-a...........a-aa-aa-akk,k是属性的个数,属性值为)1(1a,)1(2a……..)1(ak的实例和属性值为)2(1a,)2(2a……..)2(ak的实例之间的距离就如上面公式所示。但是如果直接使用欧几里得公式,某些属性的结果可能被另外一些使用较大量度尺寸的属性完全削弱。所以通常要将所有属性值正常化,使之在0和1之间。通过计算:iiiivvvvminmaxminaivi是属性i的真实值,最大值和最小值是从训练集的所有实例中获得的。}如果你没有看上一篇IB1,请先看一下,因为重复的内容我在这里不会介绍了。直接看buildClassifier,这里只列出在IB1中也没有出现的代码:try{m_NumClasses=instances.numClasses();m_ClassType=instances.classAttribute().type();}catch(Exceptionex){thrownewError(Thisshouldneverbereached);}//Throwawayinitialinstancesuntilwithinthespecifiedwindowsizeif((m_WindowSize0)&&(instances.numInstances()m_WindowSize)){m_Train=newInstances(m_Train,m_Train.numInstances()-m_WindowSize,m_WindowSize);}//Computethenumberofattributesthatcontri
本文标题:分类算法Java代码分析
链接地址:https://www.777doc.com/doc-3297243 .html