K-近鄰分類法及tabulate、rng、categorical、varfun、discretize函數用法介紹


原理:簡單比喻為——人以群分,物以類聚。

優點:對於類域的交叉或重疊較多的待分樣本集來說,K-NN較其他方法更合適。

缺點:計算量較大,因為會計算全體已知樣本的距離。

改進方法:

(1)解決計算量大,事先對已知樣本點進行剪輯,去除對分類作用不大的成分。

(2)盡可能將計算壓縮到接近測試樣本領域的小范圍內,避免盲目地與訓練樣本集中的每個樣本進行距離計算。

算法步驟:

(1)初始化距離為最大值,計算未知樣本和每個樣本的距離dist.

(2)得到目前k個最鄰近樣本的最大距離maxdist,若dist<maxdist,則將該訓練樣本作為K-近鄰樣本。

(3)重復上述計算距離的步驟,直到所有未知樣本與所有訓練樣本的距離計算完。

(4)統計k個最近鄰樣本中每個類別出現的次數。

(5)選擇出現頻率最大的類別作為未知樣本的類別。

實例介紹:

根據客戶的16個屬性,為一家銀行建一個分類器,判斷客戶是否願意購買理財產品:

 1 %% ———————————機器學習———————————————%%
 2 %%%%%%%%%%%%%%%%%%%%%%%1.K-近鄰分類%%%%%%%%%%%%%%%%%%%%%%%%%
 3 %16個屬性分別為:
 4 %age   job   marital  education default  balance  housing loan   contact
 5 %day  month  duration  campaign    pdays    previous    poutcome    y(是否願意)  
 6 load 'E:\數學建模\學習資料\程序_MATLAB數學建模方法與實踐_卓金武等\Cha5\Classification_method_examples\bank.mat';%載入記錄數據
 7 names = bank.Properties.VariableNames;%使用數據文件,記錄自變量和因變量的屬性名
 8 category = varfun(@iscellstr,bank,'Output','uniform'); %輸出格式為數值格式。為字符串的返回結果為1,為數字的返回結果為0
 9 for i = find(category)
10     bank.(names{i}) = categorical(bank.(names{i}));
11     %將bank中的屬性創建分類數組。bank.(names{i}) 的類別是bank.(names{i})經過分類后的唯一值且經過排序
12 end
13 catPred = category(1:end-1);
14 rng('default');%設置隨機數的生成方式,‘default’可以生成相同的隨機數
15 figure(1)
16 gscatter(bank.balance,bank.duration,bank.y,'kk','xo')
17 set(gca,'linewidth',2);
18 X = table2array(varfun(@double,bank(:,1:end-1)));%預測變量
19 Y = bank.y;
20 disp('數據中YES&No的統計結果');
21 tabulate(Y) %求重復數字的個數使用tabulate,占比率
22 Xnum = [X(:,~catPred) dummyvar(X(:,catPred))];
23 Ynum = double(Y)-1;
24 
25 %%%設置交叉驗證方式
26 cv = cvpartition(height(bank),'holdout',0.40);
27 Xtrain = X(training(cv),:);
28 Ytrain = Y(training(cv),:);
29 XtrainNum = Xnum(training(cv),:);
30 YtrainNum = Ynum(training(cv),:);
31 Xtest = X(test(cv),:);
32 Ytest = Y(test(cv),:);
33 XtestNum = Xnum(test(cv),:);
34 YtestNum = Ynum(test(cv),:);
35 disp('訓練集');
36 tabulate(Ytrain);
37 disp('測試集');
38 tabulate(Ytest);
39 
40 %%%訓練K-NN分類器
41 knn = ClassificationKNN.fit(Xtrain,Ytrain,'Distance','seuclidean','NumNeighbors',5);
42 %進行預測
43 [Y_knn,Yscore_knn] = knn.predict(Xtest);
44 Yscore_knn = Yscore_knn(:,2);
45 %計算混淆矩陣
46 disp('最近鄰方法分類結果:');
47 C_knn = confusionmat(Ytest,Y_knn)
MATLAB實現代碼

2.題中有關函數用法簡介:

【1】varfun函數:

語法:

1)B = varfun(func,A) 分別向表或時間表 A 的每個變量應用函數 func,並在表或時間表 B 中返回值。

函數 func 必須取一個輸入參數,並在每次調用時返回行數相同的數組。輸出參數中的第 i 個變量 B{:,i} 等於 func(A{:,i})。

如果 A 是時間表,而 func 跨多個行組聚合數據,則 varfun 將 A 中每個行組的第一個行時間指定為 B 中對應的行時間。要以表的形式返回 B 而不帶行時間,請將 'OutputFormat' 指定為 'table'。

2)B = varfun(func,A,Name,Value) 通過一個或多個 Name,Value 對組參數指定的其他選項,分別向表或時間表 A 的每個變量應用函數 func。

例如,您可以指定要傳遞給該函數的變量。

參數說明:

1)= varfun(func,A,Name,Value),'OutputFormat' - B 的格式:'table' (默認) | 'timetable' | 'uniform' | 'cell';若想返回數值向量而非表則可輸入B = varfun(func,A,'OutputFormat','uniform')。B = varfun(func,A,'GroupingVariables','Var1')表示將A中“Var1”變量進行分組(統計個數),會有單獨一列進行顯示,再將func函數(同一類別)計算出的值列出。

【2】categorical函數:

 函數說明:

categorical 是為一組有限的離散類別(例如 HighMedLow)賦值的數據類型。這些類別可以采用您指定的數學排序,例如 High > Med > Low,但這並非必須。分類數組可用來有效地存儲並方便地處理非數值數據,同時還為數值賦予有意義的名稱。分類數組的常見用法是用來指定構成表的各組行。

語法:

B = categorical(A)
B = categorical(A,valueset)
B = categorical(A,valueset,catnames)
B = categorical(A,___,Name,Value)
MATLAB實例(摘自math works官網):

轉換數組並按類別選擇數據

創建一個包含氣象站標簽的分類數組。將其添加到溫度讀數表中。然后使用類別按氣象站選擇溫度讀數。

首先,創建包含溫度讀數、日期和氣象站標簽的數組。

Temps = [58; 72; 56; 90; 76];
Dates = {'2017-04-17';'2017-04-18';'2017-04-30';'2017-05-01';'2017-04-27'}; Stations = {'S1';'S2';'S1';'S3';'S2'};

Stations 轉換為分類數組。

Stations = categorical(Stations)
Stations = 5x1 categorical array
     S1 
     S2 
     S1 
     S3 
     S2 

顯示類別。三個氣象站標簽為類別。

categories(Stations)
ans = 3x1 cell array
    {'S1'}
    {'S2'}
    {'S3'}

創建包含溫度、日期和氣象站標簽的表。

T = table(Temps,Dates,Stations)
T=5x3 table
    Temps       Dates        Stations
    _____    ____________    ________

    58       '2017-04-17'    S1      
    72       '2017-04-18'    S2      
    56       '2017-04-30'    S1      
    90       '2017-05-01'    S3      
    76       '2017-04-27'    S2      

顯示從氣象站 S2 獲得的讀數。您可以使用 == 運算符找出等於 S2Station 的值。然后使用邏輯索引選擇包含氣象站 S2 的數據的表行。

TF = (T.Stations == 'S2');
T(TF,:)
ans=2x3 table
    Temps       Dates        Stations
    _____    ____________    ________

    72       '2017-04-18'    S2      
    76       '2017-04-27'    S2      

【3】discretize函數(本題未用到):將數據分組到 bin 或類別中

例如:使用 discretize 函數(而不是 categorical)將 100 個隨機數划分為三個類別。

x = rand(100,1);

y = discretize(x,[0 .25 .75 1],'categorical',{'small','medium','large'});

summary(y)

運行結果是:

      small       22

     medium      46

     large       32

 

【4】rng隨機數生成設置函數:

rng(seed) 使用非負整數 seed 為隨機數生成函數提供種子,以使 rand、randi 和 randn 生成可預測的數字序列。

rng('shuffle') 根據當前時間為隨機數生成函數提供種子。這樣,rand、randi 和 randn 會在您每次調用 rng 時生成不同的數字序列。

rng(seed, generator) 和 rng('shuffle', generator) 另外指定 rand、randi 和 randn 使用的隨機數生成函數的類型。generator 輸入為以下項之一:

    'twister':Mersenne Twister

    'simdTwister':面向 SIMD 的快速 Mersenne Twister 算法

    'combRecursive':合並的多個遞歸

    'multFibonacci':乘法滯后 Fibonacci

    'v5uniform':傳統 MATLAB® 5.0 均勻生成函數

    'v5normal':傳統 MATLAB 5.0 正常生成函數

    'v4':傳統 MATLAB 4.0 生成函數

rng('default') 將 rand、randi 和 randn 使用的隨機數生成函數的設置重置為其默認值。這樣,會生成相同的隨機數,就好像您重新啟動了 MATLAB。默認設置是種子為 0 的 Mersenne Twister。

scurr = rng 返回 rand、randi 和 randn 使用的隨機數生成函數的當前設置。這些設置將在包含字段 'Type'、'Seed' 和 'State' 的結構體 scurr 中返回。

rng(s) 將 rand、randi 和 randn 使用的隨機數生成函數的設置還原回之前用 s = rng 等命令捕獲的值。

sprev = rng(...) 返回 rand、randi 和 randn 使用的隨機數生成函數的以前設置,然后更改這些設置。

【5】tabulate函數;

可以計算函數的個數以及在數組或矩陣中的占比率.

例如;

test = [1 2 3 3 3 5 4 1 2];

tabulate(test);

運行結果:

  Value    Count   Percent

      1        2     22.22%

      2        2     22.22%

      3        3     33.33%

      4        1     11.11%

      5        1     11.11%

test = [{'a'},{'aaa'},{'a'}];

tabulate(test)

運行結果:

Value    Count   Percent

      a        2     66.67%

    aaa        1     33.33%

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM