KNN算法---Python實現

# -*- coding: UTF-8 -*-

import numpy as np
import random
import matplotlib.pyplot as plt
from matplotlib.colors import ListedColormap


""" 產生高斯隨機數據作爲樣本數據集

    Parameters
    ----------
    mean :  高斯均值
    sigma :  高斯函數方差
    count: 要產生的數據個數
    ----------
    return : 產生的數據列表
"""
def GaussNum(mean,sigma,count):
    res = [0] * count
    for i in range(count):
        res[i] = random.gauss(mean,sigma) 
    return res


""" 計算點與點之間的距離,這裏裏二維數據爲例

    Parameters
    ----------
    inX :  測試樣本,數組
    x :  x
    y: y
    ----------
    return : 測試樣本與(x,y)的距離
"""
def Distance_for_dot(inX,x,y):
    size = len(inX)
    sum = 0
    for i in range(size):
        sum += ((inX[0] - x) ** 2 + (inX[1] - y) ** 2)
    return sum ** 0.5


""" knn分類

    Parameters
    ----------
    inX :  測試樣本,數組
    x :  x
    y: y
    labels: 數據樣本標籤
    k: knn中k值,爲選取最近點的數量
    ----------
    return : inX被判定的劃分類
"""
def knn_Classify(inX,x,y,labels,k):

    # 計算樣本數據的個數
    dataSetSize = len(x)
    # 建立數組,用來存放測試數據與每個樣本數據的距離
    distances_for_eachSample = [0] * dataSetSize
    # print(type(distances_for_eachSample))
    # 數據與標籤dict,key值爲距離,value值爲該樣本數據的類別,這裏假設所有距離都不相等
    data_and_label = {}
    # 對於樣本數據集,一次求距離,並且與自己的類別合併,存入data_and_label
    for i in range(dataSetSize):
        distances_for_eachSample[i] = Distance_for_dot(inX,x[i],y[i])
        data_and_label[distances_for_eachSample[i]] = labels[i]

    # 這裏排序完成後,data_and_labels變爲list型
    # 按鍵值對(key)排序
    data_and_label = sorted(data_and_label.items(),key = lambda d:d[0])
    print(len(data_and_label))
    # print((data_and_label))
    # res 保持最近K個樣本數據,按照類別進行個數統計。key值爲類別,value值爲此類別個數統計
    res = {}
    for i in range(k):
        if (res.__contains__(data_and_label[i][1])):
            # print(data_and_label[i][1])
            res[data_and_label[i][1]] += 1
        else:
            res[data_and_label[i][1]] = 1
    # 對res 按照value值排序
    res = sorted(res.items(),key = lambda d:d[1],reverse = True)
    print(res)

    draw_point(inX,res[0][0])
    print("the result is : %s" %res[0][0])


def draw_point(inX,color):
    plt.scatter(inX[0],inX[1],c=color,marker='*',s=400,alpha=0.8)


# 產生訓練數據集,在數據集中自動分爲三類,並且畫出圖
def data_generate():
    x1 = GaussNum(15,7,200)
    y1 = GaussNum(20,7,200)

    x2 = GaussNum(30,7,200)
    y2 = GaussNum(50,8,200)

    x3 = GaussNum(5,7,200)
    y3 = GaussNum(40,7,200)

    plt.scatter(x1,y1,c='b',marker='s',s=50,alpha=0.8)
    plt.scatter(x2,y2,c='k',marker='^',s=50,alpha=0.8)
    plt.scatter(x3,y3,c='r',marker='o',s=50,alpha=0.8)
    # 這裏list可以直接用 + 合併
    x = x1 + x2 + x3
    y = y1 + y2 + y3
    labels = ["blue"]*200+["black"]*200+["red"]*200

    return x,y,labels


if __name__ == '__main__':
    x,y,labels = data_generate()
    for i in range(3):
        knn_Classify([20 - (i-1) * 10,40 - (i-1) * 10 ],x,y,labels,20)

    plt.show()

運行結果:
這裏寫圖片描述

這裏寫圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章