<tr id="ieeco"><small id="ieeco"></small></tr>
<acronym id="ieeco"></acronym>

機器學習之KNN最鄰近分類算法

前些天發現了一個巨牛的人工智能學習網站,通俗易懂,風趣幽默,忍不住分享一下給大家。點擊跳轉到教程。

KNN算法簡介

KNN(K-Nearest Neighbor)最鄰近分類算法是數據挖掘分類(classification)技術中最簡單的算法之一,其指導思想是”近朱者赤,近墨者黑“,即由你的鄰居來推斷出你的類別。

KNN最鄰近分類算法的實現原理:為了判斷未知樣本的類別,以所有已知類別的樣本作為參照,計算未知樣本與所有已知樣本的距離,從中選取與未知樣本距離最近的K個已知樣本,根據少數服從多數的投票法則(majority-voting),將未知樣本與K個最鄰近樣本中所屬類別占比較多的歸為一類。

? ? ? ? ? 以上就是KNN算法在分類任務中的基本原理,實際上K這個字母的含義就是要選取的最鄰近樣本實例的個數,在 scikit-learn 中 KNN算法的 K 值是通過 n_neighbors 參數來調節的,默認值是 5。

? ? ? ? ? 如下圖所示,如何判斷綠色圓應該屬于哪一類,是屬于紅色三角形還是屬于藍色四方形?如果K=3,由于紅色三角形所占比例為2/3,綠色圓將被判定為屬于紅色三角形那個類,如果K=5,由于藍色四方形比例為3/5,因此綠色圓將被判定為屬于藍色四方形類。

由于KNN最鄰近分類算法在分類決策時只依據最鄰近的一個或者幾個樣本的類別來決定待分類樣本所屬的類別,而不是靠判別類域的方法來確定所屬類別的,因此對于類域的交叉或重疊較多的待分樣本集來說,KNN方法較其他方法更為適合。

? ? ? ? ? ?KNN算法的關鍵:

? ? ? ? ? ?(1) 樣本的所有特征都要做可比較的量化

? ? ? ? ? ?若是樣本特征中存在非數值的類型,必須采取手段將其量化為數值。例如樣本特征中包含顏色,可通過將顏色轉換為灰度值來實現距離計算。

? ? ? ? ? ?(2) 樣本特征要做歸一化處理

? ? ? ? ? ?樣本有多個參數,每一個參數都有自己的定義域和取值范圍,他們對距離計算的影響不一樣,如取值較大的影響力會蓋過取值較小的參數。所以樣本參數必須做一些 scale 處理,最簡單的方式就是所有特征的數值都采取歸一化處置。

? ? ? ? ? ?(3) 需要一個距離函數以計算兩個樣本之間的距離

? ? ? ? ? ?通常使用的距離函數有:歐氏距離、余弦距離、漢明距離、曼哈頓距離等,一般選歐氏距離作為距離度量,但是這是只適用于連續變量。在文本分類這種非連續變量情況下,漢明距離可以用來作為度量。通常情況下,如果運用一些特殊的算法來計算度量的話,K近鄰分類精度可顯著提高,如運用大邊緣最近鄰法或者近鄰成分分析法。

以計算二維空間中的A(x1,y1)、B(x2,y2)兩點之間的距離為例,歐氏距離和曼哈頓距離的計算方法如下圖所示:

(4) 確定K的值

? ? ? ? ? ?K值選的太大易引起欠擬合,太小容易過擬合,需交叉驗證確定K值。

KNN算法的優點:

? ? ? ? ? ?1.簡單,易于理解,易于實現,無需估計參數,無需訓練;

? ? ? ? ? ?2. 適合對稀有事件進行分類;

? ? ? ? ? ?3.特別適合于多分類問題(multi-modal,對象具有多個類別標簽), kNN比SVM的表現要好。

KNN算法的缺點:

? ? ? ? ? ?KNN算法在分類時有個主要的不足是,當樣本不平衡時,如一個類的樣本容量很大,而其他類樣本容量很小時,有可能導致當輸入一個新樣本時,該樣本的K個鄰居中大容量類的樣本占多數,如下圖所示。該算法只計算最近的鄰居樣本,某一類的樣本數量很大,那么或者這類樣本并不接近目標樣本,或者這類樣本很靠近目標樣本。無論怎樣,數量并不能影響運行結果??梢圆捎脵嘀档姆椒?和該樣本距離小的鄰居權值大)來改進。

該方法的另一個不足之處是計算量較大,因為對每一個待分類的文本都要計算它到全體已知樣本的距離,才能求得它的K個最近鄰點。

可理解性差,無法給出像決策樹那樣的規則。

KNN算法實現

要自己動手實現KNN算法其實不難,主要有以下三個步驟:

? ? ? ? ? ?算距離:給定待分類樣本,計算它與已分類樣本中的每個樣本的距離;

? ? ? ? ? ?找鄰居:圈定與待分類樣本距離最近的K個已分類樣本,作為待分類樣本的近鄰;

? ? ? ? ? ?做分類:根據這K個近鄰中的大部分樣本所屬的類別來決定待分類樣本該屬于哪個分類;

以下是使用Python實現KNN算法的簡單示例:

import math
import csv
import operator
import random
import numpy as np
from sklearn.datasets import make_blobs

#Python version 3.6.5

# 生成樣本數據集 samples(樣本數量) features(特征向量的維度) centers(類別個數)
def createDataSet(samples=100, features=2, centers=2):
    return make_blobs(n_samples=samples, n_features=features, centers=centers, cluster_std=1.0, random_state=8)

# 加載鳶尾花卉數據集 filename(數據集文件存放路徑)
def loadIrisDataset(filename):
    with open(filename, 'rt') as csvfile:
        lines = csv.reader(csvfile)
        dataset = list(lines)
        for x in range(len(dataset)):
            for y in range(4):
                dataset[x][y] = float(dataset[x][y])
        return dataset
    
# 拆分數據集 dataset(要拆分的數據集) split(訓練集所占比例) trainingSet(訓練集) testSet(測試集)
def splitDataSet(dataSet, split, trainingSet=[], testSet=[]):
    for x in range(len(dataSet)):
        if random.random() <= split:
            trainingSet.append(dataSet[x])
        else:
            testSet.append(dataSet[x])
# 計算歐氏距離 
def euclideanDistance(instance1, instance2, length):
    distance = 0
    for x in range(length):
        distance += pow((instance1[x] - instance2[x]), 2)
    return math.sqrt(distance)

# 選取距離最近的K個實例
def getNeighbors(trainingSet, testInstance, k):
    distances = []
    length = len(testInstance) - 1
    for x in range(len(trainingSet)):
        dist = euclideanDistance(testInstance, trainingSet[x], length)
        distances.append((trainingSet[x], dist))
    distances.sort(key=operator.itemgetter(1))
    
    neighbors = []
    for x in range(k):
        neighbors.append(distances[x][0])
    return neighbors

#  獲取距離最近的K個實例中占比例較大的分類
def getResponse(neighbors):
    classVotes = {}
    for x in range(len(neighbors)):
        response = neighbors[x][-1]
        if response in classVotes:
            classVotes[response] += 1
        else:
            classVotes[response] = 1
    sortedVotes = sorted(classVotes.items(), key=operator.itemgetter(1), reverse=True)
    return sortedVotes[0][0]

# 計算準確率
def getAccuracy(testSet, predictions):
    correct = 0
    for x in range(len(testSet)):
        if testSet[x][-1] == predictions[x]:
            correct += 1
    return (correct / float(len(testSet))) * 100.0


def main():
    # 使用自定義創建的數據集進行分類
    # x,y = createDataSet(features=2)
    # dataSet= np.c_[x,y]
    
    # 使用鳶尾花卉數據集進行分類
    dataSet = loadIrisDataset(r'C:\DevTolls\eclipse-pureh2b\python\DeepLearning\KNN\iris_dataset.txt')
        
    print(dataSet)
    trainingSet = []
    testSet = []
    splitDataSet(dataSet, 0.75, trainingSet, testSet)
    print('Train set:' + repr(len(trainingSet)))
    print('Test set:' + repr(len(testSet)))
    predictions = []
    k = 7
    for x in range(len(testSet)):
        neighbors = getNeighbors(trainingSet, testSet[x], k)
        result = getResponse(neighbors)
        predictions.append(result)
        print('>predicted=' + repr(result) + ',actual=' + repr(testSet[x][-1]))
    accuracy = getAccuracy(testSet, predictions)
    print('Accuracy: ' + repr(accuracy) + '%')
main()
    

尾花卉數據文件百度網盤下載鏈接:https://pan.baidu.com/s/10vI5p_QuM7esc-jkar2zdQ 密碼:4und

KNN算法應用

使用KNN算法處理簡單分類任務

在scikit-learn中,內置了若干個玩具數據集(Toy Datasets),還有一些API讓我們可以自己動手生成一些數據集。接下來我們將使用scikit-learn的make_blobs函數來生成一個樣本數量為200,分類數量為2的數據集,并使用KNN算法來對其進行分類。

# 導入畫圖工具
import matplotlib.pyplot as plt
# 導入數組工具
import numpy as np
# 導入數據集生成器
from sklearn.datasets import make_blobs
# 導入KNN 分類器
from sklearn.neighbors import KNeighborsClassifier
# 導入數據集拆分工具
from sklearn.model_selection import train_test_split

# 生成樣本數為200,分類數為2的數據集
data=make_blobs(n_samples=200, n_features=2,centers=2, cluster_std=1.0, random_state=8)
X,Y=data

# 將生成的數據集進行可視化
# plt.scatter(X[:,0], X[:,1],s=80, c=Y,  cmap=plt.cm.spring, edgecolors='k')
# plt.show()

clf = KNeighborsClassifier()
clf.fit(X,Y)

# 繪制圖形
x_min,x_max=X[:,0].min()-1,X[:,0].max()+1
y_min,y_max=X[:,1].min()-1,X[:,1].max()+1
xx,yy=np.meshgrid(np.arange(x_min,x_max,.02),np.arange(y_min,y_max,.02))
z=clf.predict(np.c_[xx.ravel(),yy.ravel()])

z=z.reshape(xx.shape)
plt.pcolormesh(xx,yy,z,cmap=plt.cm.Pastel1)
plt.scatter(X[:,0], X[:,1],s=80, c=Y,  cmap=plt.cm.spring, edgecolors='k')
plt.xlim(xx.min(),xx.max())
plt.ylim(yy.min(),yy.max())
plt.title("Classifier:KNN")

# 把待分類的數據點用五星表示出來
plt.scatter(6.75,4.82,marker='*',c='red',s=200)

# 對待分類的數據點的分類進行判斷
res = clf.predict([[6.75,4.82]])
plt.text(6.9,4.5,'Classification flag: '+str(res))

plt.show()

?程序執行后得到結果如下圖所示:

使用KNN算法處理多元分類任務

接下來,我們再使用scikit-learn的make_blobs函數來生成一個樣本數量為500,分類數量為5的數據集,并使用KNN算法來對其進行分類。

# 導入畫圖工具
import matplotlib.pyplot as plt
# 導入數組工具
import numpy as np
# 導入數據集生成器
from sklearn.datasets import make_blobs
# 導入KNN 分類器
from sklearn.neighbors import KNeighborsClassifier
# 導入數據集拆分工具
from sklearn.model_selection import train_test_split

# 生成樣本數為500,分類數為5的數據集
data=make_blobs(n_samples=500, n_features=2,centers=5, cluster_std=1.0, random_state=8)
X,Y=data

# 將生成的數據集進行可視化
# plt.scatter(X[:,0], X[:,1],s=80, c=Y,  cmap=plt.cm.spring, edgecolors='k')
# plt.show()

clf = KNeighborsClassifier()
clf.fit(X,Y)

# 繪制圖形
x_min,x_max=X[:,0].min()-1,X[:,0].max()+1
y_min,y_max=X[:,1].min()-1,X[:,1].max()+1
xx,yy=np.meshgrid(np.arange(x_min,x_max,.02),np.arange(y_min,y_max,.02))
z=clf.predict(np.c_[xx.ravel(),yy.ravel()])

z=z.reshape(xx.shape)
plt.pcolormesh(xx,yy,z,cmap=plt.cm.Pastel1)
plt.scatter(X[:,0], X[:,1],s=80, c=Y,  cmap=plt.cm.spring, edgecolors='k')
plt.xlim(xx.min(),xx.max())
plt.ylim(yy.min(),yy.max())
plt.title("Classifier:KNN")

# 把待分類的數據點用五星表示出來
plt.scatter(0,5,marker='*',c='red',s=200)

# 對待分類的數據點的分類進行判斷
res = clf.predict([[0,5]])
plt.text(0.2,4.6,'Classification flag: '+str(res))
plt.text(3.75,-13,'Model accuracy: {:.2f}'.format(clf.score(X, Y)))

plt.show()

?程序執行后得到結果如下圖所示:

使用KNN算法進行回歸分析

這里我們使用scikit-learn的make_regression生成數據集來進行實驗,演示KNN算法在回歸分析中的表現。

# 導入畫圖工具
import matplotlib.pyplot as plt
# 導入數組工具
import numpy as np

# 導入用于回歸分析的KNN模型
from sklearn.neighbors import KNeighborsRegressor
# 導入數據集拆分工具
from sklearn.model_selection import train_test_split
# 導入數據集生成器
from sklearn.datasets.samples_generator import make_regression
from docutils.utils.math.math2html import LineWriter

# 生成樣本數為200,分類數為2的數據集
X,Y=make_regression(n_samples=100,n_features=1,n_informative=1,noise=50,random_state=8)

# 將生成的數據集進行可視化
# plt.scatter(X,Y,s=80, c='orange',  cmap=plt.cm.spring, edgecolors='k')
# plt.show()
reg = KNeighborsRegressor(n_neighbors=5)

reg.fit(X,Y)

# 將預測結果用圖像進行可視化
z = np.linspace(-3,3,200).reshape(-1,1)
plt.scatter(X,Y,c='orange',edgecolor='k')
plt.plot(z,reg.predict(z),c='k',Linewidth=3)
#
plt.title("KNN Regressor")

plt.show()

??程序執行后得到結果如下圖所示:

KNN算法項目實戰----酒的分類

from sklearn.datasets.base import load_wine
from sklearn.model_selection import train_test_split
from sklearn.neighbors import KNeighborsClassifier
import numpy as np

# 從 sklearn的datasets模塊載入數據集加載酒的數據集
wineDataSet=load_wine()
print(wineDataSet)
print("紅酒數據集中的鍵:\n{}".format(wineDataSet.keys()))
print("數據概況:\n{}".format(wineDataSet['data'].shape))
print(wineDataSet['DESCR'])

# 將數據集拆分為訓練數據集和測試數據集
X_train,X_test,y_train,y_test=train_test_split(wineDataSet['data'],wineDataSet['target'],random_state=0)
print("X_train shape:{}".format(X_train.shape))
print("X_test shape:{}".format(X_test.shape))
print("y_train shape:{}".format(y_train.shape))
print("y_test shape:{}".format(y_test.shape))

knn = KNeighborsClassifier(n_neighbors=1)
knn.fit(X_train,y_train)
print(knn)

# 評估模型的準確率
print('測試數據集得分:{:.2f}'.format(knn.score(X_test,y_test)))

# 使用建好的模型對新酒進行分類預測
X_new = np.array([[13.2,2.77,2.51,18.5,96.6,1.04,2.55,0.57,1.47,6.2,1.05,3.33,820]])
prediction = knn.predict(X_new)
print("預測新酒的分類為:{}".format(wineDataSet['target_names'][prediction]))

?執行程序后打印如下結果:

X_train shape:(133, 13)
X_test shape:(45, 13)
y_train shape:(133,)
y_test shape:(45,)
KNeighborsClassifier(algorithm='auto', leaf_size=30, metric='minkowski',
           metric_params=None, n_jobs=1, n_neighbors=1, p=2,
           weights='uniform')
測試數據集得分:0.76
預測新酒的分類為:['class_2']

參考書籍:《深入淺出 Python 機器學習》 作者:段小手

已標記關鍵詞 清除標記
相關推薦
??2020 CSDN 皮膚主題: 大白 設計師:CSDN官方博客 返回首頁
彩票送彩金