KNN算法实战:肿瘤预测(距离的权重)
样本数据:0代表为良性肿瘤,1代表恶性肿瘤
raw_data_x =[
[3.393533211,2.331273381],
[3.110073483,1.781539638],
[1.343808831,3.368360954],
[3.582294042,4.679179110],
[2.280362439,2.866990263],
[7.423436942,4.696522875],
[5.745051997,3.533989803],
[9.172168622,2.511101045],
[7.792783481,3.424088941],
[7.939820817,0.791637231]
]
raw_data_y = [0,0,0,0,0,1,1,1,1,1]
按照我们昨天的思路,做一个肿瘤预测的案例(数据为虚拟数据)
导入需要用到的库
from sklearn import neighbors
import numpy as np
import matplotlib.pyplot as plt
加载数据
raw_data_x =[
[3.393533211,2.331273381],
[3.110073483,1.781539638],
[1.343808831,3.368360954],
[3.582294042,4.679179110],
[2.280362439,2.866990263],
[7.423436942,4.696522875],
[5.745051997,3.533989803],
[9.172168622,2.511101045],
[7.792783481,3.424088941],
[7.939820817,0.791637231]
]
raw_data_y = [0,0,0,0,0,1,1,1,1,1]
# 上面的数据是python的list类型,需要转换为numpy的 ndarray 类型
x_train = np.array(raw_data_x)
y_train = np.array(raw_data_y)
选择模型,创建模型对象
参数 3 是指根据离未知样本最近的已知样本类型的数量
即,根据未知样本附近最近的 3 个样本类型来进行预测
这里的距离指的是欧几里得距离,即我们初中所学的一个公式:
sklearn 中默认的是欧几里得距离
|AB| = sqrt((X1-X2)**2 + (Y1-Y2)**2)
# sqrt表示开方,如 sqrt(9) = 3
创建 KNN模型的对象,通过该对象可以调用封装好的KNN相关方法
knn = neighbors.KNeighborsClassifier(3)
为了便于更加直观的理解,简单的可视化一下样本点的大概位置
plt.scatter(x_train[y_train==0,0],x_train[y_train==0,1],color='b')
plt.scatter(x_train[y_train==1,0],x_train[y_train==1,1],color='r')
plt.show()
训练模型
knn.fit(x_train,y_train)
预测数据
x_predict = [[5.2,3.5]]
y_predict = knn.predict(x_predict)
print(y_predict)
# 预测结果
# [0]
因为训练模型时使用的是矩阵,即二维数据
所以即使我们只预测一个样本,也需要构建一个矩阵
即 [[5.3,5]]
y_predict 就是预测出来的结果,0 代表的就是良性肿瘤
可视化展示
不管模型预测的结果是什么,我们先来看一下未知样本点的大概位置
plt.scatter(x_train[y_train==0,0],x_train[y_train==0,1],color='b')
plt.scatter(x_train[y_train==1,0],x_train[y_train==1,1],color='r')
# 先将未知样本的位置使用紫色显示出来
plt.scatter(5.2,3.5,color='purple')
plt.show()
很明显,我们可以看到,该样本点附近最近的三个样本情况:
左边两个良性肿瘤,右边一个恶性肿瘤
在不考虑距离的权重时,三个样本点就会开始投票:良性2票,恶性1票
所以,预测出来的结果就是0:良性
plt.scatter(x_train[y_train==0,0],x_train[y_train==0,1],color='b')
plt.scatter(x_train[y_train==1,0],x_train[y_train==1,1],color='r')
# 因为上面已经知道预测结果为0,所以直接指定其颜色为蓝色
plt.scatter(5.2,3.5,color='b')
plt.show()
很明显,[ 5 , 3.5 ] 位置上附近最近的三个样本点中,有两个良性,一个恶性
所以将该位置预测为良性。
但是,从这张图片上很明显可以看出,该位置和其右边的恶性肿瘤的距离非常近,离其左边的两个良性肿瘤非常远,如果让我们人为的来判断,认为它是恶性肿瘤的可能性是不是应该更大呢?
这是因为啊,sklearn 中的KNN算法,默认是只考虑附近样本类型的数量,而不考虑距离的权重。
考虑距离的权重,也就是距离预测样本点越近的样本投的票越有话语权。
就像在我们的现实世界中,我们和最经常一起学习或者共事的人的相似度越高。
考虑距离权重
现在,我们修改一下代码,将其设置为考虑距离的权重
我们只需要修改一行代码即可,其他代码不变
knn_clf = neighbors.KNeighborsClassifier(3,weights='distance')
与上面的代码相比,增加了一个参数 weights = distance
再次执行上面训练模型,预测样本的代码
# 训练模型
knn_clf.fit(x_train,y_train)
# 预测样本数据
x_predict = [[5.2,3.5]]
# 开始预测
y_predict = knn_clf.predict(x_predict)
print(y_predict)
# 预测结果
# [1]
可以看到,在考虑距离权重的情况下,该样本点就被预测为了恶性肿瘤。
看一下最终的结果:
plt.scatter(x_train[y_train==0,0],x_train[y_train==0,1],color='b')
plt.scatter(x_train[y_train==1,0],x_train[y_train==1,1],color='r')
# 因为上面已经知道预测结果为0,所以直接指定其颜色为蓝色
plt.scatter(5.2,3.5,color='r')
plt.show()