一、k-近鄰算法(k-Nearest Neighbor,KNN)
簡單地說,K-近鄰算法采用測量不同特征值之間的距離方法進行分類。
-
- 優點:精度高(計算距離)、對異常值不敏感(單純根據距離進行分類,會忽略特殊情況)、無數據輸入假定(不會對數據預先進行判定)。
- 缺點:時間復雜度高、空間復雜度高。
- 適用數據范圍:數值型和標稱型。
工作原理:
-
- 存在一個樣本數據集合,也稱作訓練樣本集,並且樣本集中每個數據都存在標簽,即我們知道樣本集中每一數據 與所屬分類的對應關系
- 輸人沒有標簽的新數據后,將新數據的每個特征與樣本集中數據對應的 特征進行比較,然后算法提取樣本集中特征最相似數據(最近鄰近)的分類標簽。
- 一般來說,我們 只選擇樣本數據集中前K個最相似的數據,這就是K-近鄰算法中K的出處,通常K是不大於20的整數。
- 最后 ,選擇K個最相似數據中出現次數最多的分類,作為新數據的分類。
原理圖例:
鄰近算法計算過程:
二、KNN實例(電影分類)
需求:使用K-近鄰算法分類愛情片和動作片。有人曾經統計過很多電影的打斗鏡頭和接吻鏡頭,下圖顯示了6部電影的打斗和接吻次數。假如有一部未看過的電影,如何確定它是愛情片還是動作片呢?我們可以使用K-近鄰算法來解決這個問題。
實驗包數據下載:提取碼
第一步:實驗數據導入:
以下實驗基於jupyter編輯器做開發!
import pandas as pd import numpy as np # 導入數據 data = pd.read_excel('./my_films.xlsx') data
數據展示圖例:
第二步:樣本數據的提取與結果分類
#樣本數據的提取 feature = data[['Action lens','Love lens']] target = data['target'] # 導入KNN類 from sklearn.neighbors import KNeighborsClassifier # 實例化算法模型,設置k值為3 # k值的設置有特定算法,這里我們的k值的預估的值 knn = KNeighborsClassifier(n_neighbors=3) # 模型訓練 knn.fit(feature,target) # KNN電影結果預估 傳入參數:打斗次數(Action lens=19),接吻次數(Love lens=18) knn.predict([[19,18]]) #結果>>>array(['Action'], dtype=object) #一種簡單的方法k值預測評分,預測k越趨近於1的值,則當前k值最適合當前模型 knn.score(feature,target) # 結果>>>0.9166666666666666
三、KNN實例(預測年收入是否大於50K美元)
- 需求:讀取adult.txt文件,最后一列是年收入,並使用KNN算法訓練模型,然后使用模型預測一個人的年收入是否大於50
- 實驗數據分析:
- 特征數據:較大機率會影響收入的參數值選取(獲取年齡、教育程度、職位、每周工作時間作為機器學習數據)
- 目標數據:獲取薪水作為對應結果
- 樣本數據的特征數據必須為可以計算int/float數據類型,如果不是則需要把數據轉換成int/float數據類型
實驗包數據下載:提取碼
第一步:實驗數據導入:
# 讀取數據 df = pd.read_csv('./data/adults.txt') df.head(3)
顯示前3條數據圖例:
第二步:樣本數據的獲取
#樣本數據的提取 feature = df[['age','education_num','occupation','hours_per_week']] target = df['salary'] # 查看數據前3行 feature.head(3)
樣本數據圖例展示:
第三步:這里獲取到的我們需要的樣本數據,但是特征數據要用於模型訓練,則需要轉換成能計算的數值型數據
注意:str類型的數據轉換成數值(int/float)類型后,注意轉換后的數值要與其他參於模型訓練的數據數值權重比基本相同,否則實驗結果不准確
# 數據轉換,將String類型數據(occupation)轉換為int # 數據去重 s = feature["occupation"].unique() # 創建一個空字典 dic = {} j = 0 for i in s: dic[i] = j j += 1 # 替換occupation這一列為數值類型,map映射 # 注意:str類型的數據轉換成數值(int/float)類型后,注意轉換后的數值與其他參於模型訓練的數據數值權重比基本相同 feature['occupation'] = feature['occupation'].map(dic) feature.head(3)
數據轉換的的特征數據展示:
第四步:數據拆分,拆分數據為兩部分(訓練數據與測試數據)
訓練數據(特征數據[自變量]&目標數據[因變量]):用於機器模型訓練
測試數據(特征數據[自變量]&目標數據[因變量]): 預測值與真實值對比,或者用於k值計算
# 樣本數據的拆分 樣本共計32560條 # 設置32500條數據為訓練數據 x_train = feature[:32500] y_train = target[:32500] # 設置最后60數據為測試數據 x_test = feature[32500:] y_test = target[32500:] # KNN模型訓練 knn = KNeighborsClassifier(n_neighbors=50) knn.fit(x_train,y_train) # 預測k值 knn.score(x_test,y_test) # k值結果>>>0.7868852459016393
第五步:預測數據與真實數據實驗對比
# 使用測試數據進行測試 print('真實的分類結果:',np.array(y_test)) print('模型的分類結果:',np.array(knn.predict(x_test))) # 結果>>> 真實的分類結果: ['<=50K' '<=50K' '<=50K' '<=50K' '>50K' '<=50K' '>50K' '<=50K' '<=50K' '<=50K' '>50K' '<=50K' '<=50K' '>50K' '<=50K' '<=50K' '<=50K' '<=50K' '>50K' '>50K' '<=50K' '<=50K' '<=50K' '<=50K' '<=50K' '<=50K' '<=50K' '<=50K' '<=50K' '<=50K' '>50K' '<=50K' '>50K' '>50K' '<=50K' '<=50K' '>50K' '<=50K' '>50K' '>50K' '<=50K' '<=50K' '<=50K' '<=50K' '<=50K' '>50K' '<=50K' '<=50K' '<=50K' '<=50K' '<=50K' '<=50K' '<=50K' '<=50K' '>50K' '<=50K' '<=50K' '>50K' '<=50K' '<=50K' '>50K'] 模型的分類結果: ['<=50K' '<=50K' '>50K' '<=50K' '>50K' '<=50K' '<=50K' '<=50K' '<=50K' '<=50K' '<=50K' '<=50K' '<=50K' '<=50K' '<=50K' '<=50K' '<=50K' '<=50K' '<=50K' '<=50K' '<=50K' '<=50K' '<=50K' '<=50K' '<=50K' '<=50K' '<=50K' '<=50K' '<=50K' '<=50K' '<=50K' '<=50K' '>50K' '>50K' '<=50K' '<=50K' '>50K' '<=50K' '>50K' '<=50K' '<=50K' '<=50K' '<=50K' '>50K' '<=50K' '<=50K' '<=50K' '<=50K' '>50K' '<=50K' '<=50K' '<=50K' '<=50K' '<=50K' '>50K' '<=50K' '<=50K' '<=50K' '<=50K' '<=50K' '<=50K']
第六步:加入測試數據,預測年收入大於50k美金結果(分類)
# 數據結果分類 age,education_num,occupation,hours_per_week knn.predict([[50,12,4,50]]) #結果>>> array(['>50K'], dtype=object)