1. 程式人生 > >KNN演算法及python實現

KNN演算法及python實現

KNN演算法原理和python實現

K最近鄰(kNN,k-NearestNeighbor)分類演算法是資料探勘分類技術中最簡單的方法之一。 原理是:如果一個樣本在特徵空間中的k個最相鄰的樣本中的大多數屬於某一個類別,則該樣本也屬於這個類別,並具有這個類別上樣本的特性。 在這裡插入圖片描述 綠色圓要被決定賦予哪個類,是紅色三角形還是藍色四方形?如果K=3,由於紅色三角形所佔比例為2/3,綠色圓將被賦予紅色三角形那個類,如果K=5,由於藍色四方形比例為3/5,因此綠色圓被賦予藍色四方形類。 在這裡插入圖片描述 具體原理如下:在實際生活中不同的商品都有著不同的維度,如圖,如果我們的樣品想要知道在某個維度,利用歐幾里得距離公式,可以獲得他對所有點的距離,然後從小到大排列,給一個權重K,k的值是幾,就取前幾,前幾中最多的屬於哪個,它就屬於哪個 程式碼實現: knn演算法需要自定義K值,需要傳入訓練資料,這個訓練資料就是讓機器學習的資料,訓練資料是把檔案讀取變成一個數組,多個檔案相互堆疊行,就變成了矩陣。我們還需要測試資料,測試資料是一個單行矩陣。用它去跟所有的訓練資料求距離。然後需要一個標籤陣列,標籤標示他是屬於哪一類. KNN演算法實現

  1. 導包
from sklearn import datasets  
#匯入內建資料集模組                      
#匯入sklearn.neighbors模組中KNN類
import numpy as np 
#匯入KNN演算法模組
from sklearn.neighbors import KNeighborsClassifier
#資料分類
from sklearn.model_selection import train_test_split
#歸一化處理
from sklearn.preprocessing import MinMaxScaler
#混淆矩陣包
from sklearn.metrics import confusion_matrix,recall_score,classification_report,accuracy_score #匯入 精度值計算包,得自己下載,在sklearn最後裡面 import pandas as pd import matplotlib.pyplot as plt import seaborn as sns
  1. 先拿鳶尾花的訓練集做一個例子
iris=datasets.load_iris()
iris_x=iris.data 
#匯入資料,資料是個矩陣
#knn演算法中x是資料,是一個二維陣列,橫著的是資料個數,列表示資料的東西
y = iris.target scaler = MinMaxScaler()#匯入歸一化庫,歸一化有兩種方法min-max標準化(Min-Max Normalization)和Z-score標準化方法 x = scaler.fit_transform(iris_x) #歸一化的作用是把結果對映到0到1之間,目的是跟標準化一樣的 train_X,test_X, train_y, test_y = train_test_split(iris_x, y, test_size=0.2) #建立訓練資料和測試資料 # KNN模型,選擇3個鄰居 model = KNeighborsClassifier(n_neighbors=3) model.fit(train_X, train_y)#建立模型 y_pred = model.predict(test_X) cnf_matrix =confusion_matrix(test_y,y_pred) #把小數位數改為2位 np.set_printoptions(precision=2) #輸出模型精度,這個可沒有邏輯迴歸的recall print(accuracy_score(test_y,y_pred)) #混淆矩陣的含義,我們有三個分類,所以值也為3*3,0行是真實值,預測成0的9個,預測成1的0個,預測成2的0個。 #原本真實值是1,第二行,預測成0的為0個,預測成1的為一個,預測成2的為0個,全部正確 #第三個就成問題了,原本是2,預測成0的0個,預測是1的1個,這個是錯的,預測成2的7個,一共30個預測成功了29個,模型評估率96.67% cnf_matrix
  1. 資料結果如下
0.966666666667
array([[ 9,  0,  0],
       [ 0, 13,  0],
       [ 0,  1,  7]], dtype=int64)

knn演算法實現手寫體識別 原理是把圖片的畫素點變成矩陣,不同顏色的值不一樣,然後訓練資料是好多個一維矩陣組成的二維矩陣,我們的資料是一個一維矩陣也可能是好多行,每一行減去所有訓練資料,然後求尤拉距離,選取最近的幾個距離是啥,就屬於這一個類 影象處理:目的是把影象轉換成0和1的矩陣檔案

from PIL import Image#pillow這個包是為了對圖片進行處理,使其變成0和1的矩陣
im = Image.open("D:/pyProject/knn/timg2.gif",mode ="r")
width = im.size[0]
height= im.size[1]
print(width)
ftwo = open("D:/pyProject/knn/timg2.txt","a")

for w in range(0,width):
for h in range(0,height):
#切記這個方法,如果是256色的圖片返回值是int,如果是rgb返回的是元祖
col = im.getpixel((w,h))

if col == 0:
ftwo.write("1")
else:
ftwo.write("0")
print("\n")
ftwo.close()
#原理是把影象中的某個畫素點的顏色計算出來,如果他是黑色就文件中寫入1,不然寫入0
import os
#讀取資料
trains =  os.listdir("D:/pyProject/knn/digits/digits/trainingDigits")
#建立y資料的列表
yTrain=[]
path="D:/pyProject/knn/digits/digits/trainingDigits"
#建立x矩陣
x_juzhen=[]
for file in trains:
    xNum=[]
    for line in open(path+"/"+file).readlines():
        for num in line:
            if num != '\n':
               xNum.append(num) 
    num = file.split("_")[0]
    yTrain.append(num)
    x_juzhen.append(xNum)
#讀取訓練資料檔案,將其轉換成矩陣
yTrain = np.array(yTrain)
x_juzhen = np.array(x_juzhen)

#先建立模型,拿訓練資料評估下模型看看
x_train,x_test,y_train,y_test = train_test_split(x_juzhen,yTrain,test_size=0.2)
model = KNeighborsClassifier(n_neighbors=5)
model.fit(x_train,y_train)#建立模型
y_pred = model.predict(x_test)

cnf_matrix =confusion_matrix(y_test,y_pred)
print(accuracy_score(y_test,y_pred))
cnf_matrix
#模型評估率為98%

結果如下:

0.984496124031
array([[40,  0,  0,  0,  0,  0,  0,  0,  0,  0],
       [ 0, 39,  0,  0,  0,  0,  0,  0,  0,  0],
       [ 0,  0, 45,  0,  0,  0,  0,  0,  0,  0],
       [ 0,  0,  0, 51,  0,  0,  0,  0,  0,  0],
       [ 0,  1,  0,  0, 38,  0,  0,  0,  0,  0],
       [ 0,  0,  0,  0,  0, 33,  0,  0,  0,  1],
       [ 0,  0,  0,  0,  0,  0, 37,  0,  0,  0],
       [ 0,  0,  0,  0,  0,  0,  0, 29,  0,  0],
       [ 0,  2,  0,  0,  0,  0,  0,  0, 29,  0],
       [ 0,  1,  0,  0,  1,  0,  0,  0,  0, 40]], dtype=int64)

然後我們隨便拿一個手寫數字去識別

cnf_matrix.sum()
387
#387個數字,只預測錯了6個,下面我們拿一個測試資料看看
path2="D:/pyProject/knn/digits/digits/trainingDigits/7_14.txt"
test5=[]
for line in open(path2).readlines():
    for num in line:
        if num != '\n':
            test5.append(num)
test5=[test5]
test5 = np.array(test5)
y_pred = model.predict(test5)
y_pred

這個檔案的內容如下:手寫的一個數字7

00000000000000011111111110000000
00000000000001111111111110000000
00000000000001111111111110000000
00000000000111111111111110000000
00000000001111111111111110000000
00000000011111111111111100000000
00000000001111000000111110000000
00000000000100000000111110000000
00000000000000000001111100000000
00000000000000000000111100000000
00000000000000000001111000000000
00000000000000000001111000000000
00000000000000000001111000000000
00000000000000000011110000000000
00000000000000000011110000000000
00000000000000000111100000000000
00000000000000001111111111000000
00000000000001111111111111100000
00000000011111111111111111000000
00000000111111111111111110000000
00000011111111111110000000000000
00000111111111111110000000000000
00000111111110011110000000000000
00000111100000111100000000000000
00000000000000111110000000000000
00000000000000111100000000000000
00000000000000111100000000000000
00000000000000111100000000000000
00000000000001111000000000000000
00000000000001111000000000000000
00000000000011110000000000000000
00000000000011110000000000000000

輸出結果:

array(['7'],
      dtype='<U1')

放進去一個7的檔案,能夠很好地識別