【機器學習】實驗三 Parzen窗 KNN
阿新 • • 發佈:2019-02-16
一、實驗內容
-
考慮上面表格中點的parzen window估計和分類器。設視窗函式為球面高斯函式:
- a) 編寫一個程式,根據Parzen視窗對任意測試點x進行分類估計。使用三維資料訓練你的分類器。設h = 1,分類樣本點為:。
- b) h = 0.1, 重複a)
-
考慮在不同維數下的k-最近鄰密度估計
-
(a)編寫一個程式,對於一維的情況,當有n個數據樣本點時,進行k-緊鄰概率密度估計。對錶格中的類別w3,中的特徵x1,用程式畫出當k = 1,3,5時的概率密度估計結果。
-
(b)編寫一個程式,對於二維的情況,當有n個數據樣本點時,進行k-緊鄰概率密度估計。對錶格中的類別w2,中的特徵,用程式畫出當k = 1,3,5時的概率密度估計結果。
-
( c )對上表中三個類別的三維資料編寫一個k-近鄰分類器。當k=1,3,5時,對下面點的概率密度進行估計。
-
-
使用的資料:
二、實驗環境
- linux系統
- g++編譯器6.3.0及以上版本
- matlab 2016a
- 可在windows下使用同樣或更高版本的g++編譯器編譯,但需要修改Makefile檔案,刪除命令rm改為del, 可執行檔案main改為main.exe
三、理論知識
-
非引數估計:不假定其分佈符合哪種分佈,而是直接用樣本和待判定向量計算其條件概率。
-
關鍵公式:, Parzen方法是固定體積求.而KNN方法是固定要包含的樣本個數,求幾何體體積。
-
估計概率密度:估計概率密度的時候,我們最終的輸出結果應該是一個概率值。
- Parzen方法:以輸入的x為中心,輸入的h為半徑(邊長),做一個球體(超幾何體),然後看這個類的樣本中有多少個樣本在這個球體內部,這個數量就是上面公式中的,將其代入公式中求出,這個值就是我們想要的值。
- KNN方法:在這個類別的樣本中找到距離x (輸入資料)最近的K (是輸入資料)個樣本,然後再在找到的這K個樣本中找到離他最遠的那個樣本,以他們之間的距離為半徑,以輸入的x為中心,做一個球體,這個球體的體積就是.將其代入上述公式,求出即可。
-
分類:
-
將上面的帶入到貝葉斯公式,最後貝葉斯公式變成了 。
-
parzen方法:是在以待判定向量x為中心以h為邊長(半徑)的超幾何體所包含的樣本中樣本的數量。是上述超幾何體所包含的全部樣本數量。由於在判定後驗概率大小的時候,對於所有類別都是相同的。所以我們在計算的時候只需要計算。。最後比較各個類別中的大小,那個大則屬於哪一類。
-
KNN方法:就是找到距離輸入向量x最近的K個向量,然後看找到的這些樣本中,哪一類的最多則判為哪一類。
-
四、實驗過程
1、parzen窗
- 由於題目中要求進行分類,所以我們沒有必要直接求出,只要求出,然後哪個大,就屬於那類。關鍵程式碼如下:
int NPE::judgePar(string vec_str_in, float h)
{
this->storage.reset();
Matrix vec1 = this->userInputProcess(vec_str_in);
float g = - FLT_MAX, temp = 0;//將g賦值為最小浮點數
int victory = -1;
for (int counter1 = 1; counter1 <= this->classSize; counter1++)
{
temp = 0;
for (int counter2 = 0; counter2 < this->sampleSize; counter2++)
{
Matrix vec2 = vec1 - this->storage.readData();
temp += exp(-(vec2.trans()*vec2).matrixToFloat()/(2*pow(h,2)));
}
if (temp > g)
{
g = temp;
victory = counter1;
}
}
return victory;
}
- 結果
2、kNN
新加函式及其正確性說明
- 這次比上次在Matrix類中增加了友元函式eDist來計算歐氏距離,下面驗證其正確性,這個函式會在C小題中用到。
- 程式碼:
就是計算[1.55,2.66]和[2,3]之間的歐式距離
cout<<eDist(npe.userInputProcess("[1.55,2.66]"), npe.userInputProcess("[2,3]"));
- 結果:
- 結果驗證:
a小題
- 找到最近的k個點然後V = 2*dis, dis是x到第k個最近點之間的歐式距離。
x取了[0,3]之間的數,每隔0.01取一個值。 - 結果:
k = 1,3,5
b小題
- 基本和a小題一樣,不同之處就在於,這裡是二維,所以V應該是面積,以x為圓心,x到離它最近的第k個點的歐式距離為半徑,求面積。畫圖時,x軸取[-3,3],每隔0.1取一個值,y軸取[-3,4],每隔0.1取一個值。
- 結果:
c小題
五、遇到的問題
1、思路和演算法都正確,結果不正確
- 在編寫parzen方法時思路就像上面說的,是正確的,結果就是不正確。所以我在思考是我的程式碼有問題,還是抄資料的時候出了錯誤。所以,就想百度一個已有的程式碼,然後用我的樣本資料去執行這個程式碼。如果結果和網上的一樣說明我的資料是沒有問題的,是程式碼實現時出錯了;反之,就是資料有問題。百度了一個已經寫好的程式碼1(python語言),看了下實現思路,和我的不一樣,是直接求概率密度,這樣就更好了,兩種方法驗證,我copy下來,使用我的資料檔案執行,發現結果正確,這就說明我的資料是沒有問題的,然後就debug。把所有變數一一輸出。。。。。。。一大堆操作。最後發現,原來是判決第一個向量後讀取檔案指標到了檔案末尾,然後沒有把他移到開頭,就開始判斷下一個向量了,導致出錯。
- matlab不常用三維畫圖不會,弄了好久好不容易弄出上面的圖,雖然很醜。。。。