一、KNN近邻算法
-
KNN算法,根据距离进行划分
-
欧式距离
-
-
二维点:点X(1,4),点Y(4,0)
= 5
-
三维点,四维点,计算公式类似的,套用欧式距离
-
image.png
-
图片中分三类
,请问数据
属于哪个类别
-
因为
整体距离
比较近,划分给类别
,人肉眼的判断
-
想计算机之所想,没有眼睛,没有感觉,通过距离,距离远近判断类别
-
KNN k就是找k个最近的邻居,k = 5;4个邻居是红色,1个邻居是绿色的
-
投票 4 > 1 概率 0.8 > 0.2 计算机就根据概率情况进行了类别划分,将
划分到了红色类别
-
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过滤异常值)
原理:

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
网友评论