手写算法实现 之 KNN K近邻算法
Posted 风信子的猫Redamancy
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了手写算法实现 之 KNN K近邻算法相关的知识,希望对你有一定的参考价值。
【手写算法实现】 之 KNN K近邻算法
k k k-近邻(k-Nearest Neighbors) 的思想是给定测试样本,基于某种距离度量(⼀般使⽤欧⼏⾥德距离) 找出训练集中与其最靠近的 k k k 个训练样本,然后基于这 k k k 个“邻居” 的信息来进⾏预测(“物以类聚”)。
算法步骤:
- 根据给定的距离度量,在训练集中找出与 x x x 最近邻的 k k k 个点,涵盖这 k k k 个点的x 的邻域记作 N k ( x ) N_k(x) Nk(x)。
- 在 N k ( x ) N_k(x) Nk(x) 中根据分类决策规则,如多数表决决定x 的类别y。
可见,决定了 k k k 近邻模型的三个基本要素——距离度量、k 值的选择、分类决策规则。
距离度量
在KNN中,使用不同的距离度量,所得到的最近邻点是不一样的。
- ⼀般使⽤欧⼏⾥德距离
- 相关度(如⽪尔逊相关系数)
- 曼哈顿距离**(Manhattan Distance) **
欧式距离 L 2 ( x i , x j ) = ( ∑ k = 1 n ∣ x i ( k ) − x j ( k ) ∣ 2 ) 1 2 曼哈顿距离 L 1 ( x i , x j ) = ( ∑ k = 1 n ∣ x i ( k ) − x j ( k ) ∣ ) 切比雪夫距离 L ∞ ( x i , x j ) = m a x k = 1 n ∣ x i ( k ) − x j ( k ) ∣ \\text欧式距离\\ \\ \\ \\ \\ L_2(x_i,x_j)=(\\sum_k=1^n|x_i^(k)-x_j^(k)|^2)^\\frac 12\\\\ \\text曼哈顿距离\\ \\ \\ \\ \\ \\ L_1(x_i,x_j)=(\\sum_k=1^n|x_i^(k)-x_j^(k)|)\\\\ \\text切比雪夫距离\\ \\ \\ \\ \\ \\ L_\\infty(x_i,x_j)=\\mathopmax\\limits_k=1^n|x_i^(k)-x_j^(k)| 欧式距离 L2(xi,xj)=(k=1∑n∣xi(k)−xj(k)∣2)21曼哈顿距离 L1(xi,xj)=(k=1∑n∣xi(k)−xj(k)∣)切比雪夫距离 L∞(xi,xj)=k=1maxn∣xi(k)−xj(k)∣
k 值的选择
-
当选择⽐较⼩的 k k k 值的时候,表⽰使⽤较⼩领域中的样本进⾏预测,训练误差会减⼩,但是会导致模型变得复杂,容易导致过拟合。
-
当选择较⼤的 k k k 值的时候,表⽰使⽤较⼤领域中的样本进⾏预测,训练误差会增⼤,同时会使模型变得简单,容易导致⽋拟合。
分类决策规则
-
多数表决法:每个邻近样本的权重是⼀样的,最终预测的结果为出现类别最多的那个类。
y = a r g m a x c j ∑ x i ∈ N k ( x ) I ( y i = c j ) y=argmax_c_j\\sum_x_i\\in N_k(x)I(y_i=c_j) y=argmaxcjxi∈Nk(x)∑I(yi=cj)
其中 I I I 是指示函数 -
加权多数表决法:每个邻近样本的权重是不⼀样的,⼀般情况下采⽤权重和距离成反⽐的⽅式来计算,最终预测结果是出现权重最⼤的那个类别。
手写自定义实现
########-----KNN------#########
class KNN():
def __init__(self, k=10):
self._k = k
def fit(self, X, y):
self._unique_labels = np.unique(y)
self._class_num = len(self._unique_labels)
self._datas = X
self._labels = y.astype(np.int32)
# 多数表决法
def predict(self, X):
# 欧式距离计算
dist = np.sum(np.square(X), axis=1, keepdims=True) - 2 * np.dot(X, self._datas.T)
dist = dist + np.sum(np.square(self._datas), axis=1, keepdims=True).T
# 取最大距离的k个
dist = np.argsort(dist)[:,:self._k]
return np.array([np.argmax(np.bincount(self._labels[dist][i])) for i in range(len(X))])
# 得到score,也就是准确率 accuracy
def score(self, X, y):
y_pred = self.predict(X)
accuracy = np.sum(y == y_pred, axis=0) / len(y)
return accuracy
iris数据集测试
def create_data():
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']
data = np.array(df.iloc[:100, :])
return data[:,:-1], data[:,-1]
用自定义 KNN 模型
# 用自定义 KNN 模型
model = KNN()
model.fit(X_train, y_train)
# 测试数据
print(model.score(X_test, y_test))
1.0
从sklearn 包中调用neighbors 测试
# 从sklearn 包中调用neighbors 测试
from sklearn import neighbors
skl_model = neighbors.KNeighborsClassifier()
# 训练数据集
skl_model.fit(X_train, y_train)
# 测试数据
print(skl_model.score(X_test, y_test))
1.0
完整代码
import numpy as np
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.datasets import load_iris
########-----KNN------#########
class KNN():
def __init__(self, k=10):
self._k = k
def fit(self, X, y):
self._unique_labels = np.unique(y)
self._class_num = len(self._unique_labels)
self._datas = X
self._labels = y.astype(np.int32)
# 多数表决法
def predict(self, X):
# 欧式距离计算
dist = np.sum(np.square(X), axis=1, keepdims=True) - 2 * np.dot(X, self._datas.T)
dist = dist + np.sum(np.square(self._datas), axis=1, keepdims=True).T
# 取最大距离的k个
dist = np.argsort(dist)[:,:self._k]
return np.array([np.argmax(np.bincount(self._labels[dist][i])) for i in range(len(X))])
# 得到score,也就是准确率 accuracy
def score(self, X, y):
y_pred = self.predict(X)
accuracy = np.sum(y == y_pred, axis=0) / len(y)
return accuracy
def create_data():
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']
data = np.array(df.iloc[:100, :])
return data[:,:-1], data[:,-1]
if __name__ == '__main__':
# iris 数据集测试
X, y = create_data()
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3)
print(X_train[0], y_train[0])
# 用自定义 KNN 模型
model = KNN()
model.fit(X_train, y_train)
# 测试数据
print(model.score(X_test, y_test))
# 从sklearn 包中调用neighbors 测试
from sklearn import neighbors
skl_model = neighbors.KNeighborsClassifier()
# 训练数据集
skl_model.fit(X_train, y_train)
# 测试数据
print(skl_model.score(X_test, y_test))
以上是关于手写算法实现 之 KNN K近邻算法的主要内容,如果未能解决你的问题,请参考以下文章