參考文章:python
KNN算法,也叫K近鄰算法,是一種是一種基本分類和迴歸方法。算法
KNN算法的原理:給定一個訓練數據集,對新的輸入實例,在訓練數據集中找到與該實例最鄰近的K個實例,這K個實例的多數屬於某個類,就把該輸入實例分類到這個類中。數組
根據以往的經驗,腫瘤良性惡性和腫瘤發現時間之間的關係如上圖所示。其中紅色表示良性,藍色表示惡性。如今有這麼一個病人,他的腫瘤發現時間如圖上綠色(紅綠色盲症的朋友們,對不住~~~)所示,那麼他更有多是良性仍是惡性呢?bash
核心:物以類聚,人以羣分app
原則:少數服從多數機器學習
KNN算法的核心就是計算待預測點附近的K個點,求他們中佔比最大的分類。學習
因此,KNN算法的求解步驟應該是:spa
任務: 經過給定的x點,預測它的y值3d
import numpy as np
import matplotlib.pyplot as plt
raw_data_x = [[3.9353233211,2.331273381],
[3.11007483,1.23792372380],
[1.9723425435,3.234256432],
[2.36675576541,4.23347654],
[7.45465765877655,4.236588767]]
raw_data_y =[0,0,1,1,1]
X_train = np.array(raw_data_x)
y_train = np.array(raw_data_y)
複製代碼
準備工做完成,咱們如今有兩個數組,能夠進行繪製散點圖。rest
代碼:
plt.scatter(X_train[y_train==0,0],X_train[y_train==0,1],color='g')
plt.scatter(X_train[y_train==1,0],X_train[y_train==1,1],color='r')
plt.show()
複製代碼
回車後,能夠看到散點圖以下:
OK。如今咱們加入咱們要進行預測的點。
# 定義一個點,假設這是咱們要進行猜想的點
x= np.array([8.0293657928,3.8928785])
複製代碼
繪圖在圖上:
plt.scatter(X_train[y_train==0,0],X_train[y_train==0,1],color='g')
plt.scatter(X_train[y_train==1,0],X_train[y_train==1,1],color='r')
plt.scatter(x[0],x[0],color='b')
plt.show()
複製代碼
接下來,咱們要進行計算預測的點和圖上各個點的距離。依據咱們偉大的歐拉公式:
接下來,反手就是算:
from math import sqrt
distance=[]
for x_train in X_train:
d = sqrt(np.sum((x_train - x) ** 2))
distance.append(d)
distance
複製代碼
固然,更有經驗的小朋友確定知道上面這段代碼能夠簡寫成:
# 更簡便的寫法
distance = [sqrt(np.sum((x_train -x)** 2)) for x_train in X_train]
複製代碼
反正渣渣我是不懂~~
回車後,咱們能夠看到運算結果:
結果計算出來後,咱們要進行排序,並返回它的預測結果:
# 進行排序,並返回索引
nearest = np.argsort(distance)
k = 3
# 獲取每一個索引對應的y值
topK_y =[y_train[i] for i in nearest]
topK_y
複製代碼
獲得結果:
接下來,咱們要預測,預測,也就是說看看當前的點和獲得哪些點的票數最多,因此咱們須要進行投票統計啦。
from collections import Counter
votes = Counter(topK_y)
votes
複製代碼
獲得結果:
從圖中能夠看到,1有3票,0有2票,很明顯,預測點的y值頗有多是1,而不是0。 固然,咱們可讓程序本身輸出預測值:
predict_y = votes.most_common(1)[0][0]
predict_y
複製代碼
結果:
能夠看到,結果是1,跟咱們預測的同樣~~
# 定義了一個方法,kNN_classify
def kNN_classify(k,X_train,y_train,x):
# k要大於1,小於矩陣的大小
assert 1 <= k <= X_train.shape[0], "k must be valid"
# x,y的大小要相同
assert X_train.shape[0] == y_train.shape[0],\
"the size of X_train must equal to the siz of y_train"
# 待預測矩陣要和x相同
assert X_train.shape[1] == x.shape[0],\
"the feature number of x must be equal to X_train"
# 計算各個點到待預測點的距離
distances = [sqrt(np.sum((x_train-x) ** 2)) for x_train in X_train]
# 排序,返回索引
nearest = np.argsort(distances)
topK_y = [y_train[i] for i in nearest[:k]]
votes = Counter[topK_y]
# 返回預測的y值
return votes.most_common(1)[0][0]
複製代碼
%run kNN_function/kNN.py
# 引入咱們上節課的數據
raw_data_x = [[3.9353233211,2.331273381],
[3.11007483,1.23792372380],
[1.9723425435,3.234256432],
[2.36675576541,4.23347654],
[7.45465765877655,4.236588767]]
raw_data_y =[0,0,1,1,1]
# 這是咱們要進行猜想的點
x= np.array([8.0293657928,3.8928785])
predict_y = kNN_classify(6,X_train,y_train,x)
#打印預測的y值
predict_y
複製代碼
至此,咱們已經完成了的KNN算法的封裝。
在看scikit-learn的KNN算法以前,先來看一下什麼是機器學習。
機器學習就是 輸入訓練集進行訓練,而後輸出模型,經過模型來對樣例進行預測的過程。
However,對於kNN算法來講,訓練集就是模型。這一點是kNN算法跟其餘算法不太同樣的地方。
爲何這裏要插播機器學習的東西呢?
由於等會咱們就會看到,scikit-learn中封裝的各類機器學習算法,暴露出現的方法無非就是這幾個:
OK,回到正題。
scikit-learn中封裝了KNN算法,叫KNeighborsClassifier
。接下來來學習該如何調用它。
from sklearn.neighbors import KNeighborsClassifier
kNN_classifier = KNeighborsClassfier(n_neighbors = 6)
#進行訓練,輸出模型,這個模型會保存在這個kNN_classifier對象中
kNN_classifier.fit(X_train,y_train)
#基於模型進行預測
#這裏要進行reshape 是由於編譯器會進行警告,你們能夠換成predict(x)看一下警告內容
y_predict = kNN_classifier.predict(x.reshape([1,-1])
# y_predict是一個數組,裏面保存了預測的結果,由於咱們只要預測一個值,因此咱們取第0個
y_predict[0]
# 至此,調用過程結束
複製代碼
爲何要再封裝一次KNN算法?由於,爲了更好的理解scikit-learn中算法的封裝思想,提升代碼質量呀~~
咱們剛剛封裝算法是用面向過程的思想寫的,而是scikit-learn中kNN算法是用面向對象的思想寫的,如今咱們來改造一下。
import numpy as np
from math import sqrt
from collections import Counter
class KNNClassifier:
def _init(self, k):
"""初始化KNN分類器"""
assert k >= 1, "k must be valid"
self.k = k
self._X_train = None
self._y_train = None
def fit(self, X_train, y_train):
"""根據訓練集X_train和y_train訓練kNN分類器"""
assert X_train.shape[0] == y_train.shape[0], \
"the size of X_train must equal to the siz of y_train"
assert X_train.shape[1] == x.shape[0], \
"the feature number of x must be equal to X_train"
"""咱們前面說過,kNN模型比較特殊,它的模型就是它的訓練集,因此這裏直接賦值了~"""
self._X_train = X_train
self._y_train = y_train
return self
def predict(self, X_predict):
"""給定待預測數據集X_predict,返回表示X_predict的結果向量"""
assert self._X_train is not None and self._y_train is not None,\
"must fit before predict!"
assert X_predict.shape[1] == self._X_train.shape[1],\
"the feature number of X_predict must be equal to X_train"
y_predict = [self._predict(x) for x in X_predict]
return np.array(y_predict)
def predict(self,x):
"""給定單個帶預測數據x,返回x的預測結果值"""
assert x.shape[0]== self._X_train.shape[1],\
"the feature number of x must be equal to train"
distances = [sqrt(np.sum(x_train - x) ** 2 for x_train in self._X_train)]
nearest = np.argsort(distances)
topK_y = [self._y_train[i] for i in nearest[:self.k]]
votes = Counter(topK_y)
return votes.most_common(1)[0][0]
def _repr_(self):
return "KNN(k=%d)" %self.k
複製代碼
接下來,老規矩,驗證一下:
%run kNN/kNN.py
knn_clf = KNNClassifier(k=6)
knn_clf.fit(x_train,y_train)
y_predict = knn_clf.predict(x_predict)
y_predict[0]
複製代碼
em ~~~~ 累了,不想寫了。先這樣吧,下次再更。
哈?你問我啥時更?我也不知道,看心情,略略略O(∩_∩)O