時間:2022-09-12來源:www.farandoo.com作者:電腦系統城
k-近鄰算法(K-Nearest Neighbour algorithm),又稱 KNN 算法,是數據挖掘技術中原理最簡單的算法。
工作原理:給定一個已知標簽類別的訓練數據集,輸入沒有標簽的新數據后,在訓練數據集中找到與新數據最鄰近的 k 個實例,如果這 k 個實例的多數屬于某個類別,那么新數據就屬于這個類別。簡單理解為:由那些離 X 最近的 k 個點來投票決定 X 歸為哪一類。
(1)計算已知類別數據集中的點與當前點之間的距離;
(2)按照距離遞增次序排序;
(3)選取與當前點距離最小的 k 個點;
(4)確定前k個點所在類別的出現頻率;
(5)返回前 k 個點出現頻率最高的類別作為當前點的預測類別。
判斷一個電影是愛情片還是動作片。
電影名稱 | 搞笑鏡頭 | 擁抱鏡頭 | 打斗鏡頭 | 電影類型 | |
---|---|---|---|---|---|
0 | 功夫熊貓 | 39 | 0 | 31 | 喜劇片 |
1 | 葉問3 | 3 | 2 | 65 | 動作片 |
2 | 倫敦陷落 | 2 | 3 | 55 | 動作片 |
3 | 代理情人 | 9 | 38 | 2 | 愛情片 |
4 | 新步步驚心 | 8 | 34 | 17 | 愛情片 |
5 | 諜影重重 | 5 | 2 | 57 | 動作片 |
6 | 功夫熊貓 | 39 | 0 | 31 | 喜劇片 |
7 | 美人魚 | 21 | 17 | 5 | 喜劇片 |
8 | 寶貝當家 | 45 | 2 | 9 | 喜劇片 |
9 | 唐人街探案 | 23 | 3 | 17 | ? |
歐氏距離
構建數據集
1 2 3 4 5 6 7 |
rowdata = { "電影名稱" : [ '功夫熊貓' , '葉問3' , '倫敦陷落' , '代理情人' , '新步步驚心' , '諜影重重' , '功夫熊貓' , '美人魚' , '寶貝當家' ], "搞笑鏡頭" : [ 39 , 3 , 2 , 9 , 8 , 5 , 39 , 21 , 45 ], "擁抱鏡頭" : [ 0 , 2 , 3 , 38 , 34 , 2 , 0 , 17 , 2 ], "打斗鏡頭" : [ 31 , 65 , 55 , 2 , 17 , 57 , 31 , 5 , 9 ], "電影類型" : [ "喜劇片" , "動作片" , "動作片" , "愛情片" , "愛情片" , "動作片" , "喜劇片" , "喜劇片" , "喜劇片" ] } |
計算已知類別數據集中的點與當前點之間的距離
1 2 |
new_data = [ 24 , 67 ] dist = list ((((movie_data.iloc[: 6 , 1 : 3 ] - new_data) * * 2 ). sum ( 1 )) * * 0.5 ) |
將距離升序排列,然后選取距離最小的 k 個點「容易擬合·以后專欄再論」
1 2 3 |
k = 4 dist_l = pd.DataFrame({ 'dist' : dist, 'labels' : (movie_data.iloc[: 6 , 3 ])}) dr = dist_l.sort_values(by = 'dist' )[:k] |
確定前 k 個點的類別的出現概率
1 2 |
re = dr.loc[:, 'labels' ].value_counts() re.index[ 0 ] |
選擇頻率最高的類別作為當前點的預測類別
1 2 3 |
result = [] result.append(re.index[ 0 ]) result |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 |
# 導入數據集 datingTest = pd.read_table( 'datingTestSet.txt' ,header = None ) datingTest.head() # 分析數據 % matplotlib inline import matplotlib as mpl import matplotlib.pyplot as plt #把不同標簽用顏色區分 Colors = [] for i in range (datingTest.shape[ 0 ]): m = datingTest.iloc[i, - 1 ] # 標簽 if m = = 'didntLike' : Colors.append( 'black' ) if m = = 'smallDoses' : Colors.append( 'orange' ) if m = = 'largeDoses' : Colors.append( 'red' ) #繪制兩兩特征之間的散點圖 plt.rcParams[ 'font.sans-serif' ] = [ 'Simhei' ] #圖中字體設置為黑體 pl = plt.figure(figsize = ( 12 , 8 )) # 建立一個畫布 fig1 = pl.add_subplot( 221 ) # 建立兩行兩列畫布,放在第一個里面 plt.scatter(datingTest.iloc[:, 1 ],datingTest.iloc[:, 2 ],marker = '.' ,c = Colors) plt.xlabel( '玩游戲視頻所占時間比' ) plt.ylabel( '每周消費冰淇淋公升數' ) fig2 = pl.add_subplot( 222 ) plt.scatter(datingTest.iloc[:, 0 ],datingTest.iloc[:, 1 ],marker = '.' ,c = Colors) plt.xlabel( '每年飛行??屠锍?#39; ) plt.ylabel( '玩游戲視頻所占時間比' ) fig3 = pl.add_subplot( 223 ) plt.scatter(datingTest.iloc[:, 0 ],datingTest.iloc[:, 2 ],marker = '.' ,c = Colors) plt.xlabel( '每年飛行??屠锍?#39; ) plt.ylabel( '每周消費冰淇淋公升數' ) plt.show() # 數據歸一化 def minmax(dataSet): minDf = dataSet. min () maxDf = dataSet. max () normSet = (dataSet - minDf ) / (maxDf - minDf) return normSet datingT = pd.concat([minmax(datingTest.iloc[:, : 3 ]), datingTest.iloc[:, 3 ]], axis = 1 ) datingT.head() # 切分訓練集和測試集 def randSplit(dataSet,rate = 0.9 ): n = dataSet.shape[ 0 ] m = int (n * rate) train = dataSet.iloc[:m,:] test = dataSet.iloc[m:,:] test.index = range (test.shape[ 0 ]) return train,test train,test = randSplit(datingT) # 分類器針對約會網站的測試代碼 def datingClass(train,test,k): n = train.shape[ 1 ] - 1 # 將標簽列減掉 m = test.shape[ 0 ] # 行數 result = [] for i in range (m): dist = list ((((train.iloc[:, :n] - test.iloc[i, :n]) * * 2 ). sum ( 1 )) * * 5 ) dist_l = pd.DataFrame({ 'dist' : dist, 'labels' : (train.iloc[:, n])}) dr = dist_l.sort_values(by = 'dist' )[: k] re = dr.loc[:, 'labels' ].value_counts() result.append(re.index[ 0 ]) result = pd.Series(result) test[ 'predict' ] = result # 增加一列 acc = (test.iloc[:, - 1 ] = = test.iloc[:, - 2 ]).mean() print (f '模型預測準確率為{acc}' ) return test datingClass(train,test, 5 ) # 95% |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
import os #得到標記好的訓練集 def get_train(): path = 'digits/trainingDigits' trainingFileList = os.listdir(path) train = pd.DataFrame() img = [] # 第一列原來的圖像轉換為圖片里面0和1,一行 labels = [] # 第二列原來的標簽 for i in range ( len (trainingFileList)): filename = trainingFileList[i] txt = pd.read_csv(f 'digits/trainingDigits/{filename}' , header = None ) #32行 num = '' # 將32行轉變為1行 for i in range (txt.shape[ 0 ]): num + = txt.iloc[i,:] img.append(num[ 0 ]) filelable = filename.split( '_' )[ 0 ] labels.append(filelable) train[ 'img' ] = img train[ 'labels' ] = labels return train train = get_train() # 得到標記好的測試集 def get_test(): path = 'digits/testDigits' testFileList = os.listdir(path) test = pd.DataFrame() img = [] # 第一列原來的圖像轉換為圖片里面0和1,一行 labels = [] # 第二列原來的標簽 for i in range ( len (testFileList)): filename = testFileList[i] txt = pd.read_csv(f 'digits/testDigits/{filename}' , header = None ) #32行 num = '' # 將32行轉變為1行 for i in range (txt.shape[ 0 ]): num + = txt.iloc[i,:] img.append(num[ 0 ]) filelable = filename.split( '_' )[ 0 ] labels.append(filelable) test[ 'img' ] = img test[ 'labels' ] = labels return test test = get_test() # 分類器針對手寫數字的測試代碼 from Levenshtein import hamming def handwritingClass(train, test, k): n = train.shape[ 0 ] m = test.shape[ 0 ] result = [] for i in range (m): dist = [] for j in range (n): d = str (hamming(train.iloc[j, 0 ], test.iloc[i, 0 ])) dist.append(d) dist_l = pd.DataFrame({ 'dist' :dist, 'labels' :(train.iloc[:, 1 ])}) dr = dist_l.sort_values(by = 'dist' )[:k] re = dr.loc[:, 'labels' ].value_counts() result.append(re.index[ 0 ]) result = pd.Series(result) test[ 'predict' ] = result acc = (test.iloc[:, - 1 ] = = test.iloc[:, - 2 ]).mean() print (f '模型預測準確率為{acc}' ) return test handwritingClass(train, test, 3 ) # 97.8% |
(1)簡單好用,容易理解,精度高,理論成熟,既可以用來做分類也可以用來做回歸;
(2)可用于數值型數據和離散型數據;
(3)無數據輸入假定;
(4)適合對稀有事件進行分類。
(1)計算復雜性高;空間復雜性高;
(2)計算量大,所以一般數值很大的適合不用這個,但是單個樣本又不能太少,否則容易發生誤分;
(3)樣本不平衡問題(即有些類別的樣本數量很多,而其他樣本的數量很少);
(4)可理解性比較差,無法給出數據的內在含義
到此這篇關于Python實現K-近鄰算法的示例代碼的文章就介紹到這了
2022-09-12
Flask框架debug與配置項的開啟與設置詳解2022-06-25
python中range是什么意思 python中range()函數的用法2022-03-01
PHP如何從txt文件中讀取數據詳解Python中pycharm編輯器界面風格修改方法,本文通過圖文并茂的形式給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值...
2021-03-29