K-近邻算法(KNN)[原理/分类/回归]

K-近邻算法(KNN)

K nearest neighbour

1、k-近邻算法原理

简单地说,K-近邻算法采用测量不同特征值之间的距离方法进行分类。

  • 优点:精度高、对异常值不敏感、无数据输入假定。
  • 缺点:时间复杂度高、空间复杂度高。
  • 适用数据范围:数值型和标称型。

工作原理

存在一个样本数据集合,也称作训练样本集,并且样本集中每个数据都存在标签,即我们知道样本集中每一数据 与所属分类的对应关系。输人没有标签的新数据后,将新数据的每个特征与样本集中数据对应的 特征进行比较,然后算法提取样本集中特征最相似数据(最近邻)的分类标签。一般来说,我们 只选择样本数据集中前K个最相似的数据,这就是K-近邻算法中K的出处,通常K是不大于20的整数。 最后 ,选择K个最相似数据中出现次数最多的分类,作为新数据的分类

欧几里得距离(Euclidean Distance)

欧氏距离是最常见的距离度量,衡量的是多维空间中各个点之间的绝对距离。公式如下:

2、在scikit-learn库中使用k-近邻算法

  • 分类问题:from sklearn.neighbors import KNeighborsClassifier

  • 回归问题:from sklearn.neighbors import KNeighborsRegressor

0)一个最简单的例子

身高、体重、鞋子尺码数据对应性别

  • 导包【基本包】
import numpy as np
import pandas as pd

from pandas import Series,DataFrame
  • 导入数据集
df = pd.read_excel('../data/movies.xlsx',sheet_name=1)
df

  • 导包【K近邻分类包】
# KNN neighbor
from sklearn.neighbors import KNeighborsClassifier
  • 训练
knn = KNeighborsClassifier(n_neighbors=3)

# fit训练
# X数据
# y目标值
# 监督学习
knn.fit(df[['武打镜头','接吻镜头']],df['分类情况'])
Out:
KNeighborsClassifier(algorithm='auto', leaf_size=30, metric='minkowski',
           metric_params=None, n_jobs=1, n_neighbors=3, p=2,
           weights='uniform')
  • 引入未知电影类型
df.columns
Out: Index(['电影名称', '武打镜头', '接吻镜头', '分类情况'], dtype='object')

# 红海行动
X = [['红海行动',88,80,'?']]

df1 = DataFrame(X,columns = ['电影名称', '武打镜头', '接吻镜头', '分类情况'])
df1

  • 预测
# predict 预测
knn.predict(df1[['武打镜头','接吻镜头']])
Out: array(['动作片'], dtype=object)

# 
knn.predict_proba(df1[['武打镜头','接吻镜头']])
Out: array([[1., 0.]])

1)用于分类

导包,机器学习的算法KNN、数据蓝蝴蝶

# sklearn google 基础的算法模型
import sklearn.datasets as datasets

# iris
iris = datasets.load_iris()

data = iris['data']
target = iris['target']
# data 机器学习的数据,4个特征:花萼长、宽;花瓣长、宽
display(data,target)
Out:
array([[5.1, 3.5, 1.4, 0.2],
       [4.9, 3. , 1.4, 0.2],
       [4.7, 3.2, 1.3, 0.2],
       [4.6, 3.1, 1.5, 0.2],
…………
array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
       2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
       2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2])

获取训练样本

  • 导包
# fit----->train训练
# predict ---->test测试预测
from sklearn.model_selection import train_test_split
  • 划分训练样本和测试样本
​X_train,X_test,y_train,y_test = train_test_split(data,target,test_size =0.1)

# 135个数据交个算法,进行训练
display(X_train.shape,y_train.shape)
Out:
(135, 4)
(135,)

# 保留了15个数据,进行测试,看看算法准确率
display(X_test.shape,y_test.shape)
Out:
(15, 4)
(15,)

定义KNN分类器

from sklearn.neighbors import KNeighborsClassifier
knn = KNeighborsClassifier(n_neighbors=5)

# 数据交给算法
# 监督学习数据---->目标值
knn.fit(X_train,y_train)


# 使用算法,进行预测
y_ = knn.predict(X_test)
y_
Out: array([2, 1, 2, 0, 1, 1, 0, 1, 2, 1, 0, 0, 1, 2, 0])

y_test
Out: array([2, 1, 2, 0, 1, 1, 0, 1, 2, 1, 0, 0, 2, 2, 0])

(y_ == y_test).sum()/15
Out: 0.9333333333333333

2)用于回归

回归用于对趋势的预测

导包

# 函数获取,趋势的预测
# 天气,台风,不是分类,而是回归问题
# 股票的走势,都是回归问题
from sklearn.neighbors import KNeighborsRegressor

sin举栗子

生成样本数据

x = np.linspace(0,2*np.pi,100)

y = np.sin(x)

display(x.shape,y.shape)
Out:
(100,)
(100,)

plt.scatter(x,y)

生成测试数据的结果

np.random.randn(34)
Out:
array([ 1.28118601,  0.3453964 ,  1.50628327, -0.09737965, -0.10653015,
        0.95822035, -1.12873865,  1.30905796, -1.45678685,  1.62889653,
        1.23044502, -1.32255869, -1.0312438 ,  0.70538199,  0.22468141,
        0.41579311, -0.77095849, -1.03628613,  0.58898504,  0.36642575,
        1.50056469,  0.13296536, -0.53085029,  2.10401869,  0.98017388,
       -0.5055233 , -1.61119514, -0.14615836,  0.6363189 , -0.5552644 ,
        2.35988872,  0.08326823, -0.67072616,  0.41070691])

# 添加噪声
y[::3] += np.random.randn(34)*0.2

plt.scatter(x,y)

使用算法进行训练

knn = KNeighborsRegressor(n_neighbors=5)

knn.fit(x.reshape(-1,1),y)
Out:
KNeighborsRegressor(algorithm='auto', leaf_size=30, metric='minkowski',
          metric_params=None, n_jobs=1, n_neighbors=5, p=2,
          weights='uniform')

使用测试数据带入训练好的模型进行预测

# 分类,一般会有目标值,
# 回归------>回归曲线----->目标值
# 分类,真实情况,根据数据求解类别
X_test = np.linspace(0,2*np.pi,1000).reshape(-1,1)

y_ = knn.predict(X_test)

绘图显示数据

plt.plot(X_test,y_,color = 'green')

plt.scatter(x,y,color = 'red')

圆举栗子

# 预测台风 100公里设置检测点 20点
# 交给计算机,进行训练
# 预测,0 ~ 2000每一个位置的风速情况

生成数据集

X = np.linspace(0,2*np.pi,100)

# y 目标值,圆上的点(sin,cos)

y1 = np.sin(X)
y2 = np.cos(X)

# display(y1,y2)

y = np.concatenate([y1.reshape(-1,1),y2.reshape(-1,1)],axis = 1)

plt.scatter(y[:,0],y[:,1])
plt.axis('equal')

制造噪点

y[::4] += np.random.randn(25,2)*0.2

plt.scatter(y[:,0],y[:,1])
plt.axis('equal')

算法训练

knn = KNeighborsRegressor(n_neighbors=5)

knn.fit(X.reshape(-1,1),y)

# 台风100点 ---->目标,间隔50公里0,50,100,150,200
# 25公里 66公里
X_test = np.linspace(0,2*np.pi,2000).reshape(-1,1)

y_ = knn.predict(X_test)

y_.shape
Out: (2000, 2)

绘制图形

# 绘制图形
plt.scatter(y[:,0],y[:,1],color = 'red')

plt.plot(y_[:,0],y_[:,1],color = 'green')

plt.axis('equal')

在scikit-learn库中 make_blobs------------test------------------

导包

from sklearn.datasets import make_blobs
import matplotlib.pyplot as plt
%matplotlib inline

make_blobs数据集

data,target = make_blobs(100,centers=1,cluster_std=0.1,center_box=(-0.5,0.5))
plt.scatter(data[:,0],data[:,1])

新建另一个数据集

c = np.linspace(0,2*np.pi,100)

x = 2*np.sin(c) +np.random.randn(100)*0.2
y = 2*np.cos(c) + np.random.randn(100)*0.2

plt.scatter(x,y)

联结数据集

# axis = 1横轴拼接
data2 = np.concatenate([x.reshape(-1,1),y.reshape(-1,1)],axis = 1)

plt.scatter(data2[:,0],data2[:,1])

data.shape
Out: (100, 2)
data2.shape
Out: (100, 2)

# axis = 0 纵轴拼接
X = np.concatenate([data,data2],axis = 0)

plt.scatter(X[:,0],X[:,1])

------------------------------------------------------------------------------------------------------

------------------------------------------------------------------------------------------------------

猜你喜欢

转载自blog.csdn.net/Dorisi_H_n_q/article/details/82593808
今日推荐