另外有人将其改为IDL语言,http://hi.baidu.com/hilbertspace ... a738c550da4b70.html
代码如下:
实现了硬最大线性间隔分界(最简单的情况)
- ;;;;;SVM的SMO优化实现
- ;;;;借用研学论坛上luke的代码
- ;;Introduction: x: 二维样本数据.
- ;;;;;;;;;;;;;;;;n: 数据规模
- ;;;;;;;;;;;;;;;;y; 数据标志
- ;;;;;;;;;;;;;;;;w; 边界线斜率
- ;;;;;;;;;;;;;;;;b: 边界线截距
- ;;;;;;;;;;;;;;;;所以 y=wx+b 是边界线
- PRO svmlineartest
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;generate the training set;;;;;;;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- x=fltarr(2,40)
- y=intarr(40)
- x[0:1,0:19]=randomu(1.5,40)
- x[0:1,20:39]=randomu(2.5,40)+0.5
- y[0:19]=-1
- y[20:39]=1
- n=40
- plot,x[0,n/2:n-1],x[1,n/2:n-1],psym=1,xrange=[0,2],yrange=[0,2]
- oplot,x[0,0:n/2-1],x[1,0:n/2-1],psym=1,color=255
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;finished generate the training set;;;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;;;;minimise w^2, subject to: yi*(wxi+b) >= 1, then it can be converted to
- ;;;;;;sum wi*alphi=0, & , w- sum yi*alphi*xi =0 , then get
- ;;;;;;maxmize L= sum alphi-0.5* sum (yi*yj*alphi*alphj*<xi.*xj> subject to: sum yi*alphi =0, ai>=0
- ;;;;;;sumj alphi*yi*yj*xi,*xj=2
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- w=fltarr(2)
- w=svmw(x,y,n)
- END
- Function svmw,x,y,n
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;;;;;intialization;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;;;;;使用指针方便全局操作;;;;;;;;;;;;;;;;;;;;;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- alph=fltarr(n)
- C=100
- tol=0.001
- eps=1e-3
- error_cache=fltarr(n)
- alphptr=ptr_new(alph)
- b=0.0
- bptr=ptr_new(b)
- errorptr=ptr_new(error_cache)
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;;;;;Finish intialization;;;;;;;;;;;;;;;;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- numChange=0
- examineAll=1
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;;;;;以下两层循环,开始时检查所有样本,选择不符合KKT条件的两个乘子进行优化
- ;;;;;;;选择成功,返回1,否则,返回
- ;;;;;;;成功了,numChanged必然>0,从第二遍循环时,就不从整个样本中去寻找不符合KKT条件的两个乘子进行优化,
- ;;;;;;;而是从边界的乘子中去寻找,因为非边界样本需要调整的可能性更大,边界样本往往不被调整而始终停留在边界上。
- ;;;;;;;如果,没找到,再从整个样本中去找,直到整个样本中再也找不到需要改变的乘子为止,此时,算法结束。
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- while ((numChange gt 0) or examineAll) do begin
- numChanged =0
- if (examineAll) then begin
- for i=0,n-1 do begin
- numChanged+=examineExample(i,x,y,alphptr,n,bptr,errorptr)
- endfor
- endif
- if (examineAll eq 1) then examineAll=0 else if (numChanged eq 0) then examineAll=1
- endwhile
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;;计算w,b并画出图;;;;;;;;;;;;;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- w=fltarr(2)
- w[0]= total((*alphptr)*x[0,*]*y)
- w[1]= total((*alphptr)*x[1,*]*y)
- b=-(max(w[0]*x[0,0:n/2-1]+w[1]*x[1,0:n/2-1])+min(w[0]*x[0,n/2:n-1]+w[1]*x[1,n/2:n-1]))/2
- print,w
- print,b
- x1new=findgen(100)*0.01*2
- ynew=-(w[0]*x1new+b)/w[1]
- oplot, x1new,ynew
- End
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;;;;;;;;takestep用于优化两个乘子,成功,返回1,否则,返回0;;;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- Function takestep,i1,i2,x,y,alphptr,n,bptr,errorptr
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;;;;;;;;取出乘子和x,y,定义C值;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- alph=*alphptr
- b=*bptr
- C=100
- tol=0.001
- eps=1e-3
- error_cache=*errorptr
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;;;;;;;;完成取出乘子和x,y;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- if (i1 eq i2) then return, 0
- alph1 = alph[i1]
- y1 = y[i1]
- alph2 = alph[i2]
- y2 = y[i2]
- s=y1*y2
- if ((alph1 gt 0) and (alph1 lt C)) then E1=error_cache[i1] else E1=learned_func(i1,x,y,alph,n)-y1;//learned_func(int)为非线性的评价函数,即输出函数
- if ((alph2 gt 0) and (alph2 lt C)) then E2=error_cache[i2] else E2=learned_func(i2,x,y,alph,n)-y2;
- if y1 ne y2 then begin
- L= 0 > (alph[i2]-alph[i1])
- H= C < (C+alph[i2]-alph[i1])
- endif
- if y1 eq y2 then begin
- L= 0 > (alph[i2]+alph[i1]-C)
- H= C < (alph[i2]+alph[i1])
- endif
- if (L eq H) then return, 0
- k11=kernel_func(i1,i1,x,y,n);//kernel_func(int,int)为核函数
- k22=kernel_func(i2,i2,x,y,n);
- k12=kernel_func(i1,i2,x,y,n)
- eta = 2*k12-k11-k22
- if (eta lt 0) then begin
- a2=alph2 - y2*(E1-E2)/eta
- if (a2 lt L) then a2=L else if (a2 gt H) then a2=H
- endif else begin
- c1=eta/2;
- c2=y2*(E2-E1)-eta*alph2;
- Lobj=c1*L*L+c2*L
- Hobj=c1*H*H+c2*H
- if (Lobj gt (Hobj+eps)) then begin
- a2=L
- endif else if (Lobj lt Hobj-eps) then begin
- a2=H
- endif else begin
- a2=alph2
- endelse
- endelse
- if (abs(a2-alph2) lt eps*(a2+alph2+eps)) then return, 0
- a1=alph1+s*(alph2-a2)
- if (a1 lt 0) then begin
- a2+=s*a1
- a1=0
- endif else if (a1 gt C) then begin
- t=a1-C
- a2+=s*t
- a1=C
- endif
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;;;;;;;;;;更新阈值b;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- if (a1 gt 0) and (a1 lt C) then begin
- bnew=b+E1+y1*(a1-alph1)*k11+y2*(a2-alph2)*k12;
- endif else if (a2 gt 0) and (a2 lt C) then begin
- bnew=b+E2+y1*(a1-alph1)*k12+y2*(a2-alph2)*k22
- endif else begin
- b1=b+E1+y1*(a1-alph1)*k11+y2*(a2-alph2)*k12
- b2=b+E2+y1*(a1-alph1)*k12+y2*(a2-alph2)*k22
- bnew=(b1+b2)/2
- endelse
- delta_b=bnew-b
- b=bnew
- *bptr=b
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;;;;;;;;;;完成更新阈值b;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;Update weight vector to reflect change in a1&a2,if linear SVM;;;;;;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;;;;;;;;;;更新error cache;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- t1=y1*(a1-alph1);
- t2=y2*(a2-alph2);
- for i=0,n-1 do begin
- if (0 lt alph[i] and alph[i] lt C) then begin
- error_cache[i]+=t1*kernel_func(i1,i,x,y,n)+t2*(kernel_func(i2,i,x,y,n))-delta_b;
- error_cache[i1]=0.0;
- error_cache[i2]=0.0;
- endif
- endfor
- *errorptr=error_cache
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;;;;;;;;;;完成更新error cache;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;;;;;;;;;;更新lagrange乘子;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- alph[i1]=a1;Store a1 in the alpha array
- alph[i2]=a2;Store a2 in the alpha array
- *alphptr=alph
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;;;;;;;;;;完成更新lagrange乘子;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- return, 1
- End
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;;;;;;;examineExample程序;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;;;;;;;假定第一个乘子ai(位置为i1),examineExample(i1)首先检查;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;;;;;;;如果它超出tolerance而违背KKT条件,那么它就成为第一个乘子;;;;;;;;;;;;;;;;;;;;;;;
- ;;;;;;;;;然后,寻找第二个乘子(位置为i2),通过调用takeStep(i1,i2)来优化这两个乘子;;;;;;;;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- Function examineExample,i1,x,y,alphptr,n,bptr,errorptr
- alph=(*alphptr)
- tol=0.001
- C=100
- eps=1e-3
- error_cache=*errorptr
- y1=y[i1]
- alph1=alph[i1]
- if ((alph1 gt 0) and (alph1 lt C)) then E1=error_cache[i1] else E1=learned_func(i1,x,y,alph,n)-y1;//learned_func为计算输出函数
- r1=y1*E1
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;;;;;;;;;;;;;;;违反KKT条件的判断;;;;;;;;;;;;;;;;;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- if (((r1 lt -tol) and (alph1 lt C)) or (( r1 gt tol) and (alph1 gt 0))) then begin
- ;if(size(where (alph ne 0)) gt 1 ) then begin
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;;;;;;;;;;;;;;;;;;;;;使用三种方法选择第二个乘子;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;;;;;;;;1:在non-bound乘子中寻找maximum fabs(E1-E2)的样本;;;;;;;;;;;;;;
- ;;;;;;;;;;2:如果上面没取得进展,那么从随机位置查找non-boundary 样本;;;;;;
- ;;;;;;;;;;3:如果上面也失败,则从随机位置查找整个样本,改为bound样本;;;;;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- if (examineFirstChoice(i1,E1,x,y,alphptr,n,bptr,errorptr)) then return, 1
- if (examineNonBound(i1,x,y,alphptr,n,bptr,errorptr)) then return, 1
- if (examineBound(i1,x,y,alphptr,n,bptr,errorptr)) then return, 1
- endif
- ;endif
- return, 0
- End
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;;;;1:在non-bound乘子中寻找maximum fabs(E1-E2)的样本;;;;;;;;;;;;;;;;;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- Function examineFirstChoice,i1,E1,x,y,alphptr,n,bptr,errorptr
- C=100
- alph=(*alphptr)
- error_cache=*errorptr
- for k=0,n-1 do begin
- i2=-1
- tmax=0.0
- if(alph[k] gt 0) and (alph[k] lt C) then begin
- E2=error_cache[k];
- temp=abs(E1-E2);
- if (temp gt tmax) then begin
- tmax=temp;
- i2=k;
- endif
- endif
- endfor
- if (i2 ge 0) then begin
- if (takeStep(i1,i2,x,y,alphptr,n,bptr,errorptr)) then return, 1
- endif
- return, 0
- end
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;;;;2:如果上面没取得进展,那么从随机位置查找non-boundary 样本;;;;;;;;;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- function examineNonBound,i1,x,y,alphptr,n,bptr,errorptr
- C=100
- alph=(*alphptr)
- error_cache=*errorptr
- k0 = randomu(seed,1) mod n-1
- for k = 0, n-1 do begin
- i2 = (k + k0) mod n-1;//从随机位开始
- if (alph[i2] gt 0.0) and (alph[i2] lt C) then begin
- if (takeStep(i1, i2,x,y,alphptr,n,bptr,errorptr)) then begin
- return, 1;
- endif
- endif
- endfor
- return,0
- end
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;;;;如果上面也失败,则从随机位置查找整个样本,(改为bound样本);;;;;;;;;;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- function examineBound,i1,x,y,alphptr,n,bptr,errorptr
- C=100
- alph=(*alphptr)
- error_cache=*errorptr
- k0 = randomu(seed,1) mod (n-1);
- for k = 0, n-1 do begin
- i2 = (k + k0) mod (n-1);//从随机位开始
- if (alph[i2] eq 0.0 )or (alph[i2] eq C) then begin
- if (takeStep(i1, i2,x,y,alphptr,n,bptr,errorptr)) then return, 1
- endif
- endfor
- return,0
- end
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;;;;compute the learn function(y=wx+b) //test;;;;;;;;;;;;;;;;;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- Function learned_func ,i,x,y,alphlinshi,n
- s=fltarr(n)
- for j=0,n-1 do begin
- s[j]=alphlinshi[i]*alphlinshi[j]*y[i]*y[j]*(x[*,i] ## transpose(x[*,j]))
- endfor
- learned_func=total(s)
- return, learned_func
- End
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;;;;;;;;;;核函数kernel_func(int,int);;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- function kernel_func,i1,i2,x,y,n
- func=(x[*,i1] ## transpose(x[*,i2]))
- return,func
- ;float s=dot_product_func(i1,i2);
- ;s*=-2;
- ;s+=precomputed_self_dot_product[i1]+precomputed_self_dot_product[i2];
- ;return exp(-s/two_sigma_squared);
- end
复制代码 |