美文网首页
(十)KNN---K Nearest Neighbors(最近的

(十)KNN---K Nearest Neighbors(最近的

作者: 羽天驿 | 来源:发表于2020-04-07 08:36 被阅读0次

一、KNN近邻算法

  • KNN算法,根据距离进行划分

  • 欧式距离

  • d = \sqrt{\sum\limits_{i=1}^n(x_i - y_i)^2}

  • 二维点:点X(1,4),点Y(4,0)d = \sqrt{(1 - 4)^2 + (4 - 0)^2} = 5

  • 三维点,四维点,计算公式类似的,套用欧式距离

  • image.png
  • 图片中分三类w_1 红色圆圈,w_2 蓝色三角,w_3 绿色的方块,请问数据X_u属于哪个类别

  • 因为X_u 整体距离w_1 比较近,划分给类别w_1,人肉眼的判断

  • 想计算机之所想,没有眼睛,没有感觉,通过距离,距离远近判断类别

  • KNN k就是找k个最近的邻居,k = 5;4个邻居是红色,1个邻居是绿色的

  • 投票 4 > 1 概率 0.8 > 0.2 计算机就根据概率情况进行了类别划分,将X_u划分到了红色类别

  • 5个最近的邻居,怎么找的?

    • 计算计算所有点的距离(穷举),排序,找到最近的5个邻居
    • 计算机,计算速度非常快的。
    • image.png
  • 绿色的这个球,划分到哪个类别呢???

  • KNN算法,有一定的缺陷:

    • k取不同值,得到的结果,可能会不同
    • k = 3,找最近3个邻居2个邻居是红色三角,1个邻居蓝色方块 2 > 1 67% > 33% 所以选择红色三角
    • k = 5,3个邻居是蓝色方块,2个邻居是红色三角,3>2 60% > 40%,此时,绿色球划分到蓝色的方块。
  • KNN

    • knn计算时,时间复杂度和空间复杂度,比较大,for循环遍历,计算,耗时操作
    • knn算法不适合,数据量特别大的案例
    • knn会因为k选择,不同,结果略有差异,k值参数,调整,筛选,从而选择合适的k值

二、代码的实现

(一、KNN实现鸢尾花的分类)

import numpy as np

from sklearn.neighbors import KNeighborsClassifier #分类

from sklearn import datasets

from sklearn.model_selection import train_test_split

from sklearn.metrics import accuracy_score#准确率计算
d:\python3.7.4\lib\importlib\_bootstrap.py:219: RuntimeWarning: numpy.ufunc size changed, may indicate binary incompatibility. Expected 192 from C header, got 216 from PyObject
  return f(*args, **kwds)
X,y = datasets.load_iris(True)

# 没有给定划分的比例,默认的比例,test_size = 0.25
# 默认参数,很重要信息
X_train,X_test,y_train,y_test = train_test_split(X,y,random_state = 0)
knn = KNeighborsClassifier(n_neighbors=6)

# 算法,原理,比较难的,使用,比较简单
knn.fit(X_train,y_train)#训练,使用简单

y_ = knn.predict(X_test)

print('算法预测的类别\n',y_)
print('真实的累呗是:\n',y_test)

# 三种准确率,计算公式,本质上来说,一回事儿!
print('准确率:',(y_ == y_test).mean())
print('另一种方式准确率:',accuracy_score(y_test,y_))
print('第三种准确率:',knn.score(X_test,y_test))
算法预测的类别
 [2 1 0 2 0 2 0 1 1 1 2 1 1 1 1 0 1 1 0 0 2 1 0 0 2 0 0 1 1 0 2 1 0 2 2 1 0
 2]
真实的累呗是:
 [2 1 0 2 0 2 0 1 1 1 2 1 1 1 1 0 1 1 0 0 2 1 0 0 2 0 0 1 1 0 2 1 0 2 2 1 0
 1]
准确率: 0.9736842105263158
另一种方式准确率: 0.9736842105263158
第三种准确率: 0.9736842105263158

分类算法:逻辑斯蒂回归、KNN

回归算法:线性回归、Ridge、Lasso、ElasticNet……

逻辑斯蒂回归本质上根据概率大小进行划分

KNN 怎样划分,根据概率进行划分

knn.predict_proba(X_test)
array([[0.        , 0.        , 1.        ],
       [0.        , 1.        , 0.        ],
       [1.        , 0.        , 0.        ],
       [0.        , 0.        , 1.        ],
       [1.        , 0.        , 0.        ],
       [0.        , 0.        , 1.        ],
       [1.        , 0.        , 0.        ],
       [0.        , 1.        , 0.        ],
       [0.        , 1.        , 0.        ],
       [0.        , 1.        , 0.        ],
       [0.        , 0.16666667, 0.83333333],
       [0.        , 1.        , 0.        ],
       [0.        , 0.83333333, 0.16666667],
       [0.        , 1.        , 0.        ],
       [0.        , 0.66666667, 0.33333333],
       [1.        , 0.        , 0.        ],
       [0.        , 0.83333333, 0.16666667],
       [0.        , 1.        , 0.        ],
       [1.        , 0.        , 0.        ],
       [1.        , 0.        , 0.        ],
       [0.        , 0.16666667, 0.83333333],
       [0.        , 1.        , 0.        ],
       [1.        , 0.        , 0.        ],
       [1.        , 0.        , 0.        ],
       [0.        , 0.16666667, 0.83333333],
       [1.        , 0.        , 0.        ],
       [1.        , 0.        , 0.        ],
       [0.        , 1.        , 0.        ],
       [0.        , 1.        , 0.        ],
       [1.        , 0.        , 0.        ],
       [0.        , 0.        , 1.        ],
       [0.        , 1.        , 0.        ],
       [1.        , 0.        , 0.        ],
       [0.        , 0.33333333, 0.66666667],
       [0.        , 0.        , 1.        ],
       [0.        , 1.        , 0.        ],
       [1.        , 0.        , 0.        ],
       [0.        , 0.16666667, 0.83333333]])

(二、KNN实现癌症的分类)

import numpy as np

import pandas as pd

from sklearn.neighbors import KNeighborsClassifier

from sklearn.model_selection import train_test_split
### 提前发现,早起发现,治疗效果,最好的!
# 569 样本,32代表32列,特征、属性
# 人看到的感受到的,都是宏观
# 微观,无法感受,设备,放大镜,显微镜,光学显微镜(200万倍)
#早起癌症,宏观,没有感觉,微观已然变化,精密设备, 采集的人体微观数据
# 生物学测量,指标
# 无论专业,计算机都可以进行研究。
data = pd.read_csv('./cancer.csv',sep = '\t')

y = data['Diagnosis']
X = data.iloc[:,2:]
display(y.head(),X.head())
0    M
1    M
2    M
3    M
4    M
Name: Diagnosis, dtype: object
# 统计类比出现的次数 
y.value_counts()
B    357
M    212
Name: Diagnosis, dtype: int64
X_train,X_test,y_train,y_test = train_test_split(X,y,random_state = 1024)

使用模型,删选最优的参数

score = []
# for循环可以帮助,筛选最合适的参数
for k in np.arange(2,30):
    knn = KNeighborsClassifier(n_neighbors= k)

    knn.fit(X_train,y_train)

    s = knn.score(X_test,y_test)
    score.append([k,s])
score = pd.DataFrame(score,columns=['k','accuracy'])
acc = score['accuracy']
index = acc.idxmax()

print('最合适的邻居数量:',score['k'][index])
最合适的邻居数量: 13
knn = KNeighborsClassifier(n_neighbors=13,weights='distance')

knn.fit(X_train,y_train)

knn.score(X_test,y_test)
0.9370629370629371
# 曼哈顿距离
knn = KNeighborsClassifier(n_neighbors=13,weights='uniform', p =1)

knn.fit(X_train,y_train)

knn.score(X_test,y_test)
0.9440559440559441
%%time
# 曼哈顿距离
# algorithm='brute' 如何找最近的邻居 暴力方式,寻找,for循环
knn = KNeighborsClassifier(n_neighbors=13,algorithm='brute',weights='uniform', p =1)

knn.fit(X_train,y_train)

print(knn.score(X_test,y_test))
0.9440559440559441
Wall time: 19.9 ms
%%time
# 曼哈顿距离
# algorithm='brute' 如何找最近的邻居 暴力方式,寻找,for循环
# 数据量小的时候,方式影响不大!
# 参数调整,上限94.4%!!
knn = KNeighborsClassifier(n_neighbors=13,algorithm='kd_tree',weights='uniform', p =1)

knn.fit(X_train,y_train)

print(knn.score(X_test,y_test))
0.9440559440559441
Wall time: 20.9 ms

再想要提升准确率,调整算法参数,已经不行了

调整数据,算法烹饪工具,数据---->食材

数据清洗!!!

X.head()

第一种归一化(标准化)操作,最大值最小值归一化

X1 = (X - X.min())/(X.max() - X.min())
score = 0
for i in range(1000):
    X_train,X_test,y_train,y_test = train_test_split(X1,y)
    # 归一化,效果,特别明显!
    knn = KNeighborsClassifier()
    knn.fit(X_train,y_train)
    score += knn.score(X_test,y_test)/1000    
print('-----------------',score)
----------------- 0.9671818181818205

第二种,Z-score归一化

X2 = (X - X.mean())/X.std()
X2.std()# 使用Z-score归一化,返回的结果标准差是1
score = 0
for i in range(1000):
    X_train,X_test,y_train,y_test = train_test_split(X2,y)
    # 归一化,效果,特别明显!
    knn = KNeighborsClassifier()
    knn.fit(X_train,y_train)
    score += knn.score(X_test,y_test)/1000
print('+++++++++++++++++++++',score)
+++++++++++++++++++++ 0.9648251748251779

第三种归一化,sigmoid

# sigmoid这个中归一化,不适合所给定癌症数据
sigmoid = lambda x : 1/(1 + np.e**(-x))
X3 = sigmoid(X)
score = 0
for i in range(1000):
    X_train,X_test,y_train,y_test = train_test_split(X3,y)
    # 归一化,效果,特别明显!
    knn = KNeighborsClassifier()
    knn.fit(X_train,y_train)
    score += knn.score(X_test,y_test)/1000
print('***************************',score)
*************************** 0.9023636363636356
X3

pandas中交叉表

# 使用 最大值,最小值归一化
# scaler 缩放 ,使用最大值,最小值方法,将属性进行缩放
# preprocessing 预处理,算法,训练之前,将数据进行操作,处理,预热
from sklearn.preprocessing import MinMaxScaler
scaler = MinMaxScaler()
X1.head()
# 第一种归一化方法,最小值最大值归一化
# 自己写的方法返回的结果X1和使用sklearn中提供的方法,返回的结果完全相同
X4 = scaler.fit_transform(X)
X4
array([[0.52103744, 0.0226581 , 0.54598853, ..., 0.91202749, 0.59846245,
        0.41886396],
       [0.64314449, 0.27257355, 0.61578329, ..., 0.63917526, 0.23358959,
        0.22287813],
       [0.60149557, 0.3902604 , 0.59574321, ..., 0.83505155, 0.40370589,
        0.21343303],
       ...,
       [0.45525108, 0.62123774, 0.44578813, ..., 0.48728522, 0.12872068,
        0.1519087 ],
       [0.64456434, 0.66351031, 0.66553797, ..., 0.91065292, 0.49714173,
        0.45231536],
       [0.03686876, 0.50152181, 0.02853984, ..., 0.        , 0.25744136,
        0.10068215]])
knn = KNeighborsClassifier()
X_train,X_test,y_train,y_test = train_test_split(X4,y)
knn.fit(X_train,y_train)
y_ = knn.predict(X_test)
print('算法预测:\n',y_)
print('真实结果:\n',y_test.values)
算法预测:
 ['B' 'M' 'B' 'M' 'B' 'M' 'B' 'B' 'B' 'M' 'B' 'B' 'M' 'M' 'B' 'M' 'B' 'B'
 'B' 'B' 'B' 'M' 'M' 'B' 'B' 'M' 'B' 'B' 'B' 'B' 'M' 'B' 'B' 'M' 'B' 'M'
 'B' 'B' 'M' 'B' 'M' 'B' 'B' 'B' 'B' 'B' 'B' 'M' 'B' 'B' 'M' 'B' 'B' 'M'
 'B' 'B' 'M' 'B' 'M' 'M' 'B' 'M' 'M' 'M' 'M' 'B' 'B' 'B' 'M' 'B' 'B' 'M'
 'M' 'B' 'M' 'B' 'B' 'B' 'M' 'B' 'M' 'B' 'B' 'M' 'M' 'M' 'M' 'B' 'B' 'M'
 'B' 'B' 'B' 'B' 'B' 'B' 'B' 'B' 'M' 'B' 'B' 'B' 'B' 'B' 'M' 'B' 'B' 'M'
 'B' 'B' 'M' 'B' 'B' 'B' 'B' 'M' 'M' 'B' 'B' 'M' 'M' 'M' 'B' 'M' 'B' 'B'
 'B' 'M' 'B' 'M' 'M' 'M' 'B' 'M' 'M' 'B' 'B' 'M' 'B' 'B' 'M' 'M' 'B']
真实结果:
 ['B' 'M' 'B' 'M' 'B' 'M' 'B' 'B' 'B' 'B' 'B' 'B' 'M' 'M' 'B' 'M' 'B' 'B'
 'B' 'B' 'B' 'M' 'M' 'B' 'B' 'M' 'B' 'B' 'B' 'B' 'M' 'B' 'B' 'M' 'B' 'M'
 'B' 'B' 'M' 'B' 'M' 'B' 'B' 'B' 'B' 'B' 'B' 'M' 'B' 'B' 'M' 'B' 'B' 'M'
 'B' 'M' 'M' 'B' 'M' 'M' 'B' 'M' 'M' 'M' 'M' 'B' 'B' 'B' 'M' 'B' 'B' 'M'
 'M' 'B' 'M' 'B' 'B' 'B' 'M' 'B' 'M' 'B' 'B' 'M' 'M' 'M' 'M' 'B' 'B' 'M'
 'B' 'B' 'B' 'M' 'B' 'B' 'B' 'B' 'M' 'B' 'B' 'B' 'B' 'B' 'M' 'B' 'B' 'M'
 'M' 'B' 'M' 'B' 'M' 'B' 'B' 'M' 'M' 'B' 'B' 'M' 'M' 'M' 'B' 'M' 'B' 'B'
 'M' 'M' 'B' 'M' 'M' 'M' 'B' 'M' 'M' 'B' 'B' 'M' 'B' 'B' 'M' 'M' 'B']
X_test.shape
(143, 30)
# 交叉表,可以对,要对比的数据,进行查看
pd.crosstab(index = y_test,columns=y_,rownames=['确诊'],colnames=['预测'],margins=True)

(三、3sigma过滤异常值)
原理:


image.png
import numpy as np

from sklearn.neighbors import KNeighborsClassifier

# Z-score标准化 == StandardScaler (std)
from sklearn.preprocessing import StandardScaler,MinMaxScaler

import pandas as pd
d:\python3.7.4\lib\importlib\_bootstrap.py:219: RuntimeWarning: numpy.ufunc size changed, may indicate binary incompatibility. Expected 192 from C header, got 216 from PyObject
  return f(*args, **kwds)
d:\python3.7.4\lib\importlib\_bootstrap.py:219: RuntimeWarning: numpy.ufunc size changed, may indicate binary incompatibility. Expected 192 from C header, got 216 from PyObject
  return f(*args, **kwds)
data = pd.read_csv('./cancer.csv',sep = '\t')

X = data.iloc[:,2:]

y = data.iloc[:,1]
scaler = StandardScaler()

X = scaler.fit_transform(X)
X
array([[ 1.09706398, -2.07333501,  1.26993369, ...,  2.29607613,
         2.75062224,  1.93701461],
       [ 1.82982061, -0.35363241,  1.68595471, ...,  1.0870843 ,
        -0.24388967,  0.28118999],
       [ 1.57988811,  0.45618695,  1.56650313, ...,  1.95500035,
         1.152255  ,  0.20139121],
       ...,
       [ 0.70228425,  2.0455738 ,  0.67267578, ...,  0.41406869,
        -1.10454895, -0.31840916],
       [ 1.83834103,  2.33645719,  1.98252415, ...,  2.28998549,
         1.91908301,  2.21963528],
       [-1.80840125,  1.22179204, -1.81438851, ..., -1.74506282,
        -0.04813821, -0.75120669]])
# 3sigma准则,我们可以调整,根据数据,调整倍数
# 找异常值
cond = np.abs(X - X.mean(axis = 0)) > 4*X.std(axis = 0)
print(cond.sum())
cond = cond.any(axis = 1)
print(cond.sum())
X2 = X[cond]
X2.shape
67
34





(34, 30)
# 3sigma准则,我们可以调整,根据数据,调整倍数
# 找正常值
cond = np.abs(X - X.mean(axis = 0)) < 4*X.std(axis = 0)
cond = cond.all(axis = 1)
X1 = X[cond]
y1 = y[cond]
X1.shape
(535, 30)

数据X1和y1,就是经过数据清洗之后的数据,里面没有异常值了

from sklearn.model_selection import train_test_split
score = 0
for i in range(1000):
    X_train,X_test,y_train,y_test = train_test_split(X1,y1)

    knn = KNeighborsClassifier()

    knn.fit(X_train,y_train)

    score += knn.score(X_test,y_test)/1000
print('数据清洗:',score)
# 比,不进行数据清洗,好
数据清洗: 0.9643805970149184

相关文章

网友评论

      本文标题:(十)KNN---K Nearest Neighbors(最近的

      本文链接:https://www.haomeiwen.com/subject/jruruhtx.html