例程:class_overlap_svm.hdev
說明:這個例程展示了如何用一個支持向量機來給一幅二維的圖像進行分類。使用二維數據的原因是因為它可以很容易地聯想成為區域和圖像。本例程中使用了三個互相重疊的類(由二維平面三個不同顏色的像素點集組成)。三類不同顏色的像素點作為樣本,將那些樣本代入支持向量機進行訓練。選取像素在二維平面的坐標作為特征向量,使支持向量機對這個二維特征區域進行分類。在結果中我們可以看到,支持向量機會將特性區域(也就是整個二維平面)中每一個的像素點分割為這三個類中的一類。因此,即使遠離受訓練的樣本區域的像素點也將其歸類到三個類別之一。
在本例程中最主要的就是展示不同的誤差容忍參數Nu對分類的影響。參數Nu的可以理解成支持向量機對樣本分類過程中存在重疊的部分分類時的判定錯誤樣本的容忍比率。在分類時,樣本質量並不一定理想,部分樣本可能落入了本該屬於其他類型的特征空間內,如圖1中重疊部分的樣本。針對這部分重疊區域,是無法對其進行很好的分類的,部分樣本最終會作為錯誤的樣本點被划分到其它區域中,如下圖中三張分類效果圖,無論分類好壞,重疊區域的部分樣本都可能落入其它類型的空間。其中參數Nu就是對錯誤樣本所占比例的容忍的上限,Nu取值太小或者太大對最終分類的效果都會造成影響,Nu的取值需要大於錯誤樣本所占的比例。
下圖1中展示了三個不同類型的訓練樣本點集在二維的特征空間的分布狀況,從圖中可以看到在圖像中心位置部分,三類樣本有重疊,Nu取值的關鍵就在於對這部分樣本的處理。
圖1.紅、綠、藍三個訓練樣本集
下面三張圖展示了Nu取值0.01、0.18和0.25時的效果圖。在訓練過程中,三個樣本集訓練的參數都是相同的,因此區別就在於樣本集的參數設置。圖2中Nu選擇太小,導致完全錯誤分類;圖3中Nu值偏小,導致二維特征空間划分時少量的錯誤樣本干擾了整個空間的分類;圖4中參數選擇剛剛好,二維特征空間分類效果也很完美。
在這里,很多人會問,如果誤差容忍選取一個較小值,為何最終分類結果中特征空間划分效果反而差,樣本落入其它空間的比例更多。這里僅說明一下我的個人理解,如有錯誤,希望大神指正:
從Halcon的代碼中我們可以看到,支持向量機學習有兩個過程——構造和訓練。在構造過程中,Nu值作為對樣本的優化負責選取三類樣本中相對獨立的成分,部分有爭議的樣本將根據參數Nu在此過程中被排除在外,不作為后面訓練時的樣本。因此,在參加訓練之前,Nu作為對樣本的優化參數,起到分離錯誤樣本的作用。當然,如果Nu取值太大,也許在這個篩選過程中,提取到的樣本並不能夠有效表示該類樣本空間,那么最終在分類時也會造成錯誤。
而在訓練過程中,支持向量機將根據訓練參數求最優平面划分特征空間。如果訓練樣本理想,那么求得的最優平面就能很好划分,如圖4所示;而如果訓練樣本本身存在很大爭議,那么在訓練過程中,算法無法很簡單地求得一個最優解,那么只能將原本低維的樣本點映射到高維進行分類,如果本身樣本存在很大問題,那么即使最終求得的解還是無法正確划分特征空間。如圖1,由於本身樣本的問題,導致求得的最終解在實際識別效果中表現糟糕。
圖2.Nu參數取值0.01時的分類效果
圖3.Nu參數取值0.18時的分類效果
圖4.Nu參數取值0.25時的分類效果
*下面部分為對Hdevelop環境的設置,這里不着重介紹 dev_close_window() dev_open_window(0,0,600,600,’black’,WindowHandle) dev_set_part(0,0,199,199) get_system(‘operating_sysytem’,OS) if(OS{0:2} = ‘Win’) set_font(WindowHandle,’-Courier New-18-*-*-*-*-1-’) //設置輸出文本的字體 else set_font(WindowHandle,’-adobe-courier-bold-r-normal—25-*-*-*-*-*-*-*’) endif dev_updata_pc(‘off’) dev_updata_window(‘off’) dev_updata_var(‘off’) *以下代碼用於構造三個樣本集:構造三個樣本區域;構造白噪聲圖像;分割白噪聲圖像;分別與樣本區域進行與運算得到樣本集 gen_ellipse(RegionClass1,60,60,rad(-45),60,40) gen_ellipse(RegionClass2,70,70,130,rad(-145),70,30) gen_ellipse(RegionClass3,140,100,rad(100),55,40) //產生一個橢圓。 //參數說明:產生的橢圓(RegionClassx) //橢圓中心坐標(140,100) //橢圓長軸的方向(rad(100)) //橢圓的長軸(55) //橢圓的短軸(40) gen_image_const(Image,’byte’,200,200) //一幅固定大小固定灰度的圖像 //參數說明:生成的圖片(Image) //圖片格式(’byte’) //圖片大小(200,200) add_noise_white(Image,ImageNoise1,60) add_noise_white(Image,ImageNoise2,60) add_noise_white(Image,ImageNoise3,60) //加入白噪聲,幅度為60 threshold(ImageNoise1,RegionNoise1,40,255) threshold(ImageNoise2,RegionNoise2,40,255) threshold(ImageNoise3,RegionNoise3,40,255) //利用全局閾值分割圖像 intersection(RegionClass1,RegionNoise1,SampleClass1) intersection(RegionClass1,RegionNoise2,SampleClass2) intersection(RegionClass1,RegionNoise3,SampleClass3)//計算兩個區域的交叉(區域的與運算) //參數說明:兩個區域(RegionClassx,RegionNoisex) //交叉的區域(SampleClassx) *用三種顏色顯示三個不同類型的樣本集 dev_clear_window() dev_set_color(‘red’) dev_display(SampleClass1) dev_set_color(‘green’) dev_display(SampleClass2) dev_set_color(‘blue’) dev_display(SampleClass3) dev_set_color(‘white’) set_tposition(WindowHandle,5,5) //設置文本的光標位置 write_string(WindowHandle,’Training samples of the 3 classes ’)//在屏幕的已設定的光標位置輸出字符串 stop()
classify_2d_feature_space(SampleClass1,SampleClass2,SampleClass3,RegionClass1,RegionClass2,RegionClass3,WindowHandle,’rbf’,0.05,0.01)//利用支持向量機進行分類,這是一個外部過程,具體不進行詳細介紹 set_tposition(WindowHandle,188,5) //光標位置(188,5) write_string(WindowHandle,’Nu = 0.01 : Wrong classification’) stop()
classify_2d_feature_space(SampleClass1,SampleClass2,SampleClass3,RegionClass1,RegionClass2,RegionClass3,WindowHandle,’rbf’,0.05,0.18)//同樣是利用SVM進行分類,只是Nu參數改為0.18 set_tposition(WindowHandle,188,5) write_string(WindowHandle,’Nu = 0.18 : Overfitting’) stop()
classify_2d_feature_space(SampleClass1,SampleClass2,SampleClass3,RegionClass1,RegionClass2,RegionClass3,WindowHandle,’rbf’,0.05,0.25)//同樣是利用SVM進行分類,只是Nu參數改為0.25 set_tposition(WindowHandle,188,5) write_string(WindowHandle,’Nu = 0.25 : ’Good generalization’)