python實現(xiàn)KNN近鄰算法
示例:《電影類型分類》
獲取數(shù)據(jù)來源
電影名稱 | 打斗次數(shù) | 接吻次數(shù) | 電影類型 |
---|---|---|---|
California Man | 3 | 104 | Romance |
He's Not Really into Dudes | 8 | 95 | Romance |
Beautiful Woman | 1 | 81 | Romance |
Kevin Longblade | 111 | 15 | Action |
Roob Slayer 3000 | 99 | 2 | Action |
Amped II | 88 | 10 | Action |
Unknown | 18 | 90 | unknown |
數(shù)據(jù)顯示:肉眼判斷電影類型unknown是什么
from matplotlib import pyplot as plt # 用來正常顯示中文標(biāo)簽 plt.rcParams["font.sans-serif"] = ["SimHei"] # 電影名稱 names = ["California Man", "He's Not Really into Dudes", "Beautiful Woman", "Kevin Longblade", "Robo Slayer 3000", "Amped II", "Unknown"] # 類型標(biāo)簽 labels = ["Romance", "Romance", "Romance", "Action", "Action", "Action", "Unknown"] colors = ["darkblue", "red", "green"] colorDict = {label: color for (label, color) in zip(set(labels), colors)} print(colorDict) # 打斗次數(shù),接吻次數(shù) X = [3, 8, 1, 111, 99, 88, 18] Y = [104, 95, 81, 15, 2, 10, 88] plt.title("通過打斗次數(shù)和接吻次數(shù)判斷電影類型", fontsize=18) plt.xlabel("電影中打斗鏡頭出現(xiàn)的次數(shù)", fontsize=16) plt.ylabel("電影中接吻鏡頭出現(xiàn)的次數(shù)", fontsize=16) # 繪制數(shù)據(jù) for i in range(len(X)): # 散點圖繪制 plt.scatter(X[i], Y[i], color=colorDict[labels[i]]) # 每個點增加描述信息 for i in range(0, 7): plt.text(X[i]+2, Y[i]-1, names[i], fontsize=14) plt.show()
問題分析:根據(jù)已知信息分析電影類型unknown是什么
核心思想:
未標(biāo)記樣本的類別由距離其最近的K個鄰居的類別決定
距離度量:
一般距離計算使用歐式距離(用勾股定理計算距離),也可以采用曼哈頓距離(水平上和垂直上的距離之和)、余弦值和相似度(這是距離的另一種表達(dá)方式)。相比于上述距離,馬氏距離更為精確,因為它能考慮很多因素,比如單位,由于在求協(xié)方差矩陣逆矩陣的過程中,可能不存在,而且若碰見3維及3維以上,求解過程中極其復(fù)雜,故可不使用馬氏距離
知識擴展
- 馬氏距離概念:表示數(shù)據(jù)的協(xié)方差距離
- 方差:數(shù)據(jù)集中各個點到均值點的距離的平方的平均值
- 標(biāo)準(zhǔn)差:方差的開方
- 協(xié)方差cov(x, y):E表示均值,D表示方差,x,y表示不同的數(shù)據(jù)集,xy表示數(shù)據(jù)集元素對應(yīng)乘積組成數(shù)據(jù)集
cov(x, y) = E(xy) - E(x)*E(y)
cov(x, x) = D(x)
cov(x1+x2, y) = cov(x1, y) + cov(x2, y)
cov(ax, by) = abcov(x, y)
- 協(xié)方差矩陣:根據(jù)維度組成的矩陣,假設(shè)有三個維度,a,b,c
∑ij = [cov(a, a) cov(a, b) cov(a, c) cov(b, a) cov(b,b) cov(b, c) cov(c, a) cov(c, b) cov(c, c)]
算法實現(xiàn):歐氏距離
編碼實現(xiàn)
# 自定義實現(xiàn) mytest1.py import numpy as np # 創(chuàng)建數(shù)據(jù)集 def createDataSet(): features = np.array([[3, 104], [8, 95], [1, 81], [111, 15], [99, 2], [88, 10]]) labels = ["Romance", "Romance", "Romance", "Action", "Action", "Action"] return features, labels def knnClassify(testFeature, trainingSet, labels, k): """ KNN算法實現(xiàn),采用歐式距離 :param testFeature: 測試數(shù)據(jù)集,ndarray類型,一維數(shù)組 :param trainingSet: 訓(xùn)練數(shù)據(jù)集,ndarray類型,二維數(shù)組 :param labels: 訓(xùn)練集對應(yīng)標(biāo)簽,ndarray類型,一維數(shù)組 :param k: k值,int類型 :return: 預(yù)測結(jié)果,類型與標(biāo)簽中元素一致 """ dataSetsize = trainingSet.shape[0] """ 構(gòu)建一個由dataSet[i] - testFeature的新的數(shù)據(jù)集diffMat diffMat中的每個元素都是dataSet中每個特征與testFeature的差值(歐式距離中差) """ testFeatureArray = np.tile(testFeature, (dataSetsize, 1)) diffMat = testFeatureArray - trainingSet # 對每個差值求平方 sqDiffMat = diffMat ** 2 # 計算dataSet中每個屬性與testFeature的差的平方的和 sqDistances = sqDiffMat.sum(axis=1) # 計算每個feature與testFeature之間的歐式距離 distances = sqDistances ** 0.5 """ 排序,按照從小到大的順序記錄distances中各個數(shù)據(jù)的位置 如distance = [5, 9, 0, 2] 則sortedStance = [2, 3, 0, 1] """ sortedDistances = distances.argsort() # 選擇距離最小的k個點 classCount = {} for i in range(k): voteiLabel = labels[list(sortedDistances).index(i)] classCount[voteiLabel] = classCount.get(voteiLabel, 0) + 1 # 對k個結(jié)果進(jìn)行統(tǒng)計、排序,選取最終結(jié)果,將字典按照value值從大到小排序 sortedclassCount = sorted(classCount.items(), key=lambda x: x[1], reverse=True) return sortedclassCount[0][0] testFeature = np.array([100, 200]) features, labels = createDataSet() res = knnClassify(testFeature, features, labels, 3) print(res) # 使用python包實現(xiàn) mytest2.py from sklearn.neighbors import KNeighborsClassifier from .mytest1 import createDataSet features, labels = createDataSet() k = 5 clf = KNeighborsClassifier(k_neighbors=k) clf.fit(features, labels) # 樣本值 my_sample = [[18, 90]] res = clf.predict(my_sample) print(res)
示例:《交友網(wǎng)站匹配效果預(yù)測》
數(shù)據(jù)來源:略
數(shù)據(jù)顯示
import pandas as pd import numpy as np from matplotlib import pyplot as plt from mpl_toolkits.mplot3d import Axes3D # 數(shù)據(jù)加載 def loadDatingData(file): datingData = pd.read_table(file, header=None) datingData.columns = ["FlightDistance", "PlaytimePreweek", "IcecreamCostPreweek", "label"] datingTrainData = np.array(datingData[["FlightDistance", "PlaytimePreweek", "IcecreamCostPreweek"]]) datingTrainLabel = np.array(datingData["label"]) return datingData, datingTrainData, datingTrainLabel # 3D圖顯示數(shù)據(jù) def dataView3D(datingTrainData, datingTrainLabel): plt.figure(1, figsize=(8, 3)) plt.subplot(111, projection="3d") plt.scatter(np.array([datingTrainData[x][0] for x in range(len(datingTrainLabel)) if datingTrainLabel[x] == "smallDoses"]), np.array([datingTrainData[x][1] for x in range(len(datingTrainLabel)) if datingTrainLabel[x] == "smallDoses"]), np.array([datingTrainData[x][2] for x in range(len(datingTrainLabel)) if datingTrainLabel[x] == "smallDoses"]), c="red") plt.scatter(np.array([datingTrainData[x][0] for x in range(len(datingTrainLabel)) if datingTrainLabel[x] == "didntLike"]), np.array([datingTrainData[x][1] for x in range(len(datingTrainLabel)) if datingTrainLabel[x] == "didntLike"]), np.array([datingTrainData[x][2] for x in range(len(datingTrainLabel)) if datingTrainLabel[x] == "didntLike"]), c="green") plt.scatter(np.array([datingTrainData[x][0] for x in range(len(datingTrainLabel)) if datingTrainLabel[x] == "largeDoses"]), np.array([datingTrainData[x][1] for x in range(len(datingTrainLabel)) if datingTrainLabel[x] == "largeDoses"]), np.array([datingTrainData[x][2] for x in range(len(datingTrainLabel)) if datingTrainLabel[x] == "largeDoses"]), c="blue") plt.xlabel("飛行里程數(shù)", fontsize=16) plt.ylabel("視頻游戲耗時百分比", fontsize=16) plt.clabel("冰淇凌消耗", fontsize=16) plt.show() datingData, datingTrainData, datingTrainLabel = loadDatingData(FILEPATH1) datingView3D(datingTrainData, datingTrainLabel)
問題分析:抽取數(shù)據(jù)集的前10%在數(shù)據(jù)集的后90%進(jìn)行測試
編碼實現(xiàn)
# 自定義方法實現(xiàn) import pandas as pd import numpy as np # 數(shù)據(jù)加載 def loadDatingData(file): datingData = pd.read_table(file, header=None) datingData.columns = ["FlightDistance", "PlaytimePreweek", "IcecreamCostPreweek", "label"] datingTrainData = np.array(datingData[["FlightDistance", "PlaytimePreweek", "IcecreamCostPreweek"]]) datingTrainLabel = np.array(datingData["label"]) return datingData, datingTrainData, datingTrainLabel # 數(shù)據(jù)歸一化 def autoNorm(datingTrainData): # 獲取數(shù)據(jù)集每一列的最值 minValues, maxValues = datingTrainData.min(0), datingTrainData.max(0) diffValues = maxValues - minValues # 定義形狀和datingTrainData相似的最小值矩陣和差值矩陣 m = datingTrainData.shape(0) minValuesData = np.tile(minValues, (m, 1)) diffValuesData = np.tile(diffValues, (m, 1)) normValuesData = (datingTrainData-minValuesData)/diffValuesData return normValuesData # 核心算法實現(xiàn) def KNNClassifier(testData, trainData, trainLabel, k): m = trainData.shape(0) testDataArray = np.tile(testData, (m, 1)) diffDataArray = (testDataArray - trainData) ** 2 sumDataArray = diffDataArray.sum(axis=1) ** 0.5 # 對結(jié)果進(jìn)行排序 sumDataSortedArray = sumDataArray.argsort() classCount = {} for i in range(k): labelName = trainLabel[list(sumDataSortedArray).index(i)] classCount[labelName] = classCount.get(labelName, 0)+1 classCount = sorted(classCount.items(), key=lambda x: x[1], reversed=True) return classCount[0][0] # 數(shù)據(jù)測試 def datingTest(file): datingData, datingTrainData, datingTrainLabel = loadDatingData(file) normValuesData = autoNorm(datingTrainData) errorCount = 0 ratio = 0.10 total = datingTrainData.shape(0) numberTest = int(total * ratio) for i in range(numberTest): res = KNNClassifier(normValuesData[i], normValuesData[numberTest:m], datingTrainLabel, 5) if res != datingTrainLabel[i]: errorCount += 1 print("The total error rate is : {}\n".format(error/float(numberTest))) if __name__ == "__main__": FILEPATH = "./datingTestSet1.txt" datingTest(FILEPATH) # python 第三方包實現(xiàn) import pandas as pd import numpy as np from sklearn.neighbors import KNeighborsClassifier if __name__ == "__main__": FILEPATH = "./datingTestSet1.txt" datingData, datingTrainData, datingTrainLabel = loadDatingData(FILEPATH) normValuesData = autoNorm(datingTrainData) errorCount = 0 ratio = 0.10 total = normValuesData.shape[0] numberTest = int(total * ratio) k = 5 clf = KNeighborsClassifier(n_neighbors=k) clf.fit(normValuesData[numberTest:total], datingTrainLabel[numberTest:total]) for i in range(numberTest): res = clf.predict(normValuesData[i].reshape(1, -1)) if res != datingTrainLabel[i]: errorCount += 1 print("The total error rate is : {}\n".format(errorCount/float(numberTest)))
以上就是python實現(xiàn)KNN近鄰算法的詳細(xì)內(nèi)容,更多關(guān)于python實現(xiàn)KNN近鄰算法的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Python?中的?Counter?模塊及使用詳解(搞定重復(fù)計數(shù))
Counter 是一個簡單的計數(shù)器,用于統(tǒng)計某些可哈希對象的數(shù)量。它以字典的形式存儲元素和它們的計數(shù),這篇文章主要介紹了Python?中的?Counter?模塊及使用詳解(搞定重復(fù)計數(shù)),需要的朋友可以參考下2023-04-04Python selenium的安裝和下載谷歌瀏覽器鏡像驅(qū)動
Selenium是一個用于web自動化測試的框架,在使用Ajax請求數(shù)據(jù)的頁面中,會出現(xiàn) sign ,token等密鑰,借助使用Selenium框架來實現(xiàn)數(shù)據(jù)爬取很不錯,本文給大家介紹Python selenium的安裝和下載谷歌瀏覽器鏡像驅(qū)動,需要的朋友可以參考下2022-11-11詳解Python中類方法@classmethod的應(yīng)用技巧
在Python中,類方法(class method)是一種特殊的方法,可以在不創(chuàng)建類的實例的情況下調(diào)用,本文將詳細(xì)介紹類方法的概念、用法以及在實際開發(fā)中的應(yīng)用場景,希望對大家有所幫助2024-03-03Python深度學(xué)習(xí)之實現(xiàn)卷積神經(jīng)網(wǎng)絡(luò)
今天帶大家學(xué)習(xí)如何使用Python實現(xiàn)卷積神經(jīng)網(wǎng)絡(luò),這是個很難的知識點,文中有非常詳細(xì)的介紹,對小伙伴們很有幫助,需要的朋友可以參考下2021-06-06python安裝CLIP包出現(xiàn)錯誤:安裝.git報錯問題及解決
這篇文章主要介紹了python安裝CLIP包出現(xiàn)錯誤:安裝.git報錯問題及解決,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-06-06在Pandas中導(dǎo)入CSV數(shù)據(jù)時去除默認(rèn)索引的方法匯總
在Pandas中讀取CSV數(shù)據(jù)時,會默認(rèn)將第一列設(shè)為索引列index,但有時候我們并不需要索引,或者希望指定自己的索引列,本文將介紹幾種在Pandas中導(dǎo)入CSV數(shù)據(jù)時去除默認(rèn)索引的方法,需要的朋友可以參考下2023-05-05基于Python socket的端口掃描程序?qū)嵗a
這篇文章主要介紹了基于Python socket的端口掃描程序?qū)嵗a,分享了相關(guān)代碼示例,小編覺得還是挺不錯的,具有一定借鑒價值,需要的朋友可以參考下2018-02-02