KNN算法

参考文章:python

目录

一.KNN算法

1.1 什么是KNN算法

KNN算法,也叫K近邻算法,是一种是一种基本分类和回归方法。算法

KNN算法的原理:给定一个训练数据集,对新的输入实例,在训练数据集中找到与该实例最邻近的K个实例,这K个实例的多数属于某个类,就把该输入实例分类到这个类中。数组

根据以往的经验,肿瘤良性恶性和肿瘤发现时间之间的关系如上图所示。其中红色表示良性,蓝色表示恶性。如今有这么一个病人,他的肿瘤发现时间如图上绿色(红绿色盲症的朋友们,对不住~~~)所示,那么他更有多是良性仍是恶性呢?bash

  • 取K = 3,也就是离它最近的3个点,发现都是蓝色,那么很不幸的,这位同志颇有可能患有恶性肿瘤。

1.2 KNN算法的核心和原则

核心:物以类聚,人以群分app

原则:少数服从多数机器学习

二. KNN算法实现

2.1 KNN算法实战

KNN算法的核心就是计算待预测点附近的K个点,求他们中占比最大的分类。学习

因此,KNN算法的求解步骤应该是:spa

  • 计算全部点距离待预测点(咱们叫作x)的距离
  • 取出距离最近的k个点
  • 计算各个分类的占比
  • 取出占比最大的那个分类

任务: 经过给定的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,跟咱们预测的同样~~

2.2 本身封装KNN算法

  • 建立一个kNN.py文件,定义KNN算法
# 定义了一个方法,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]
复制代码
  • 到Jupyter Notebook中调用封装的方法
%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算法的封装。

2.3 scikit-learn中KNN算法的封装

在看scikit-learn的KNN算法以前,先来看一下什么是机器学习。

机器学习就是 输入训练集进行训练,而后输出模型,经过模型来对样例进行预测的过程。

However,对于kNN算法来讲,训练集就是模型。这一点是kNN算法跟其余算法不太同样的地方。

为何这里要插播机器学习的东西呢?

由于等会咱们就会看到,scikit-learn中封装的各类机器学习算法,暴露出现的方法无非就是这几个:

  • fit(参数) -> 训练模型
  • predict(参数) -> 预测结果
  • score() -> 衡量算法准确度

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]

# 至此,调用过程结束
复制代码

2.4 本身再封装一次KNN算法

为何要再封装一次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

相关文章
相关标签/搜索