参考文章: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