一、原理
什麼是K近鄰?就是KNN,當N=1的時候就是最近鄰了。
k近鄰算法簡單、直觀:給定一個訓練數據集,對新的輸入實例,在訓練數據集中找到與該實例最鄰近的k個實例,這k個實例多數屬於某個類,就把該輸入實例分爲這個類。
上面這個公式,就是找出投票最多的那一類!!!
二、幾大要點:
1、k近鄰法沒有顯式的學習過程。
2、個基本要素:
距離度量:
k值的選擇:
選擇較小的k值,就相當於用較小的鄰域中的訓練實例進行預測,“學習”的近似誤差(approximation error)會減小,只有與輸入實例較近的(相似的)訓練實例纔會對預測結果起作用。但缺點是“學習”的估計誤差(estimation error)會增大,預測結果會對近鄰的實例點非常敏感[2]。如果鄰近的實例點恰巧是噪聲,預測就會出錯。換句話說,k值的減小就意味着整體模型變得複雜,容易發生過擬合。
如果選擇較大的k值,就相當於用較大鄰域中的訓練實例進行預測。其優點是可以減少學習的估計誤差。但缺點是學習的近似誤差會增大。這時與輸入實例較遠的(不相似的)訓練實例也會對預測起作用,使預測發生錯誤。k值的增大就意味着整體的型變得簡單。
如果k=N,那麼無論輸入實例是什麼,都將簡單地預測它屬於在訓練實例中最多的類。這時,模型過於簡單,完全忽略訓練實例中的大量有用信息,是不可取的。在應用中,k值一般取一個比較小的數值。通常採用交叉驗證法來選取最優的k值
分類決策規則:
繞來繞去,沒看明白~~~~
三、代碼:
import numpy as np
import pandas as pd
import math
import matplotlib.pyplot as plt
%matplotlib inline
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from collections import Counter
#對距離度量進行定義
#定義距離度量
def distance_(x1,x2,p=2):
x1=np.array(x1)
x2=np.array(x2)
assert x1.shape==x2.shape
sum_=0
for i in range(x1.shape[0]):
sum_+=math.pow((x1[0]-x2[0]),p)
return math.pow(sum_,1./p)
#製作訓練數據
iris = load_iris() #中文名是安德森鳶尾花卉數據集
df = pd.DataFrame(iris.data, columns=iris.feature_names)
df['label'] = iris.target
df.columns = ['sepal length', 'sepal width', 'petal length', 'petal width', 'label']
df
# 花萼長度 花萼寬度 花瓣長度 花瓣寬度 類別
#數據進行可視化
plt.scatter(df[:50]['sepal length'], df[:50]['sepal width'], c='r',label='0')
plt.scatter(df[50:100]['sepal length'], df[50:100]['sepal width'],c='y' ,label='1')
#plt.scatter(df[100:150]['sepal length'], df[100:150]['sepal width'],c='g' ,label='2')
plt.xlabel('sepal length')
plt.ylabel('sepal width')
plt.legend()
#取數據,並且分成訓練和測試集合
data = np.array(df.iloc[:100, [0, 1, -1]])
X, y = data[:,:-1], data[:,-1]
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)
#定義模型
class KNN:
def __init__(self,num_k,p,X_train,Y_train):
self.p=p
self.k=num_k
self.X_train=X_train
self.Y_train=Y_train
def get_preds(self,input_data):
dist_=np.zeros((self.X_train.shape[0],2))
for i in range(self.X_train.shape[0]):
dist_[i]=distance_(input_data,self.X_train[i],p=2),self.Y_train[i]
#print(dist_[i])
#dist_=dist_[np.lexsort(dist_[:,::-1].T)]
dist_ = dist_[dist_[:,0].argsort()]
res=dist_[:self.k,:]
#print(res)
sortbin=res[:,1].astype(np.int32)
#print(np.argmax(np.bincount(sortbin)))
return np.argmax(np.bincount(sortbin))
#運行模型並eval
model=KNN(num_k=10,p=2,X_train=X_train,Y_train=y_train)
count=0
for i in range(X_test.shape[0]):
pred=model.get_preds(X_test[i])
if pred == y_test[i] :
count+=1
print("acc:",float(float(count)/y_test.shape[0]))