深度学习统计分析与数据挖掘

KNN 代码实现

2019-12-23  本文已影响0人  zidea

KNN 模型(K-Nearest Neighbor)

Easy-Steps-to-Understanding.jpg

KNN 算法的一个最吸引人的特点是简单易懂,由于模型在较少训练时间内就可以达到一个不错效果,所以被应用到一些数据集的即时分析,这也是 KNN 的优点。因为 KNN 不需要带有参数的模型进行训练,所以 KNN 是无参数的模型,可以用于分类和回归。

算法

其中 K 表示在新样本点附近(距离)选取 K 个样本数据,通过在 K 个样本进行投票来判断新增样本的类型。

A 和 B 两点间距离需要满足以下条件

距离(模)

\cos(x,y) = \frac{x^T y}{||x||_2 ||y||_2}

代码实现

接下来就是程序员最感兴趣的部分,coding 了,对于程序员总是喜欢自己实现一下,这样才会相信。这里参考 sklearn 的 api 来设计模型提供 fit 和 predict

# coding=utf-8

class KNN:
    def __init__(self,k=3):
        self.k = k
    # 训练数据
    def fit(X,y):
        pass
    
    def predict(self,X):
        pass
import numpy as np
from sklearn import datasets
from sklearn.model_selection import train_test_split
from matplotlib.colors import ListedColormap
cmap = ListedColormap(['#FF0000','#00FF00','#0000FF'])

iris = datasets.load_iris()
X,y = iris.data, iris.target
X_train, X_test, y_train, y_test = train_test_split(X,y,test_size=0.2,random_state=1234)

print(X_train.shape)
print(X_train[0])

这里数据集九四 iris 经典数据集,因为经典也就不再多说了。输出一下数据集数据结构和样本值

(120, 4)
[5.1 2.5 3.  1.1]
cmap = ListedColormap(['#FF0000','#00FF00','#0000FF'])

iris = datasets.load_iris()
X,y = iris.data, iris.target
X_train, X_test, y_train, y_test = train_test_split(X,y,test_size=0.2,random_state=1234)

print(X_train.shape)
print(X_train[0])

print(y_train.shape)
print(y_train)

plt.figure()
plt.scatter(X[:,0],X[:,1],c=y,cmap=cmap,edgecolors='k',s=20)
plt.show()

为更直观观察数据分布我们 matlibplot 将其以图形方式现实处理啊,不同颜色表示不同类别,用样本前两个特征作为 x 轴和 y 轴

iris_scatter.png
class KNN:
    def __init__(self,k=3):
        self.k = k
    # 训练数据
    def fit(self,X,y):
        self.X_train = X
        self.y_train = y
    # 预测
    def predict(self,X):
        predicted_labels = [self._predict(x) for x in X]
        return np.array(predicted_labels)

    
    # 
    def _predict(self,x):
        pass

这里我们定义计算两个点距离采用欧式距离来衡量样本间的距离

def euclidean_distance(x1,x2):
    return np.sqrt(np.sum((x1-x2)**2))
    

def predict(self,X):
    predicted_labels = [self._predict(x) for x in X]
    return np.array(predicted_labels)

    # 
    def _predict(self,x):
        # 计算距离
        distances = [euclidean_distance(x,x_train) for x_train in self.X_train]
        # 获取 k 邻近样本和标签
        k_indices = np.argsort(distances)[:self.k]
        k_nearest_labels = [self.y_train[i] for i in k_indices]
        # 通过投票进行分类
        most_common = Counter(k_nearest_labels).most_common(1)

有关 Counter 方法如何使用,说起来可能有点不好解释,还是用代码来说明更加直观易于理解

a = [1,1,1,3,5,6,7,7,8]
from collections import Counter
most_common = Counter(a).most_common(1)
print(most_common)
[(1, 3)]

从 code 运行结果不难看出,most_common 就是计算出现,返回一个 tuple 结构的数据第一个值是在数组 a 中哪一个数出现次数最多,这样就是 1 第二个数表示 1 一共在数组 a 中出现几次。

class KNN:
    def __init__(self,k=3):
        self.k = k
    # 训练数据
    def fit(self,X,y):
        self.X_train = X
        self.y_train = y
    # 预测
    def predict(self,X):
        predicted_labels = [self._predict(x) for x in X]
        return np.array(predicted_labels)

    
    # 
    def _predict(self,x):
        # 计算距离
        distances = [euclidean_distance(x,x_train) for x_train in self.X_train]
        # 获取 k 邻近样本和标签
        k_indices = np.argsort(distances)[:self.k]
        k_nearest_labels = [self.y_train[i] for i in k_indices]
        # 通过投票进行分类
        most_common = Counter(k_nearest_labels).most_common(1)
        return most_common[0][0]

这里说一说 predict 方法,这里做法就是依次计算预测样本到每一个数据集样本点距离,然后按大小排序后取前 k 样本,然后在 k 个距离其附近样本点所属标签出现次数做多标签作为其标签来决定这个样本属于那个分类。

最后来验证之前的代码是否有效,最好方法就是运行一下。

from knn_model import KNN
clf = KNN(k=3)
clf.fit(X_train,y_train)
predictions = clf.predict(X_test)

acc = np.sum(predictions == y_test) / len(y_test)
print(acc)
上一篇 下一篇

猜你喜欢

热点阅读