K nearest neighbour
K-近邻算法采用测量不同特征值之间的距离方法进行分类。
优点:精度高、对异常值不敏感、无数据输入假定。
缺点:时间复杂度高、空间复杂度高。
适用数据范围:数值型和标称型。
一、K-近邻算法(KNN)举例
1)工作原理
存在一个样本数据集合,也称作训练样本集,并且样本集中每个数据都存在标签,即我们知道样本集中每一数据
与所属分类的对应关系。输人没有标签的新数据后,将新数据的每个特征与样本集中数据对应的
特征进行比较,然后算法提取样本集中特征最相似数据(最近邻)的分类标签。一般来说,我们
只选择样本数据集中前K个最相似的数据,这就是K-近邻算法中K的出处,通常*K是不大于20的整数。
最后 ,选择K个最相似数据中出现次数最多的分类,作为新数据的分类*。
2)算法实例
回到前面电影分类的例子,使用K-近邻算法分类爱情片和动作片。有人曾经统计过很多电影的打斗镜头和接吻镜头,下图显示了6部电影的打斗和接吻次数。假如有一部未看过的电影,如何确定它是爱情片还是动作片呢?我们可以使用K-近邻算法来解决这个问题。
首先我们需要知道这个未知电影存在多少个打斗镜头和接吻镜头,上图中问号位置是该未知电影出现的镜头数图形化展示,具体数字参见下表。
即使不知道未知电影属于哪种类型,我们也可以通过某种方法计算出来。首先计算未知电影与样本集中其他电影的距离,如图所示。
现在我们得到了样本集中所有电影与未知电影的距离,按照距离递增排序,可以找到K个距
离最近的电影。假定k=3,则三个最靠近的电影依次是California Man、He’s Not Really into Dudes、Beautiful Woman。K-近邻算法按照距离最近的三部电影的类型,决定未知电影的类型,而这三部电影全是爱情片,因此我们判定未知电影是爱情片。
3)欧几里得距离(Euclidean Distance)
欧氏距离是最常见的距离度量,衡量的是多维空间中各个点之间的绝对距离。公式如下:
二、在scikit-learn库中使用k-近邻算法
分类问题:from sklearn.neighbors import KNeighborsClassifier
回归问题:from sklearn.neighbors import KNeighborsRegressor
三、简单示例(分类)
给出一组数据(身高、体重、鞋子尺码)判断性别
分析:这是一个使用K-临近算法(KNN)的分类问题
1)创建训练数据(特征和结果)
1.训练样本的特征
注意:这里的特征需要和结果一一对应
'''
X_train:训练样本的特征(一列值)
y_train:训练样本的结果(标签)
'''
# 传入训练数据
# 身高,体重, 鞋码
X_train = np.array([
[177,73,42],
[150,44,36],
[177,63,41],
[160,52,35],
[165,70,40],
[179,80,44],
[156,40,36],
[155,50,36]
])
# 一一传入训练数据的样本结果
y_train = np.array(['male','female','male','female','male','male','female','female'])
2)创建 获取分类的模型
KNeighborsClassifier(n_neighbors=5)
功能:实现k近邻投票的分类器。
# n_neighbors:获取最近的几个 默认是5个
knn_c = KNeighborsClassifier(n_neighbors=5)
3)模型训练
knn.fit(X, y)
功能:将训练数据的特征和结果传入进行训练
以X为训练数据,y为目标值 拟合模型
'''
参数 X 是训练数据的特征
参数 y 是训练数据的结果(标签)
'''
knn_c.fit(X_train,y_train)
4)模型测试
knn.predict(X)
功能:通过训练好的模型将测试数据传入,返回测试结果
为提供的数据预测类标签
knn_c.predict([
[190,100,45],
[150,35,32]
])
array(['male', 'female'], dtype='<U6')
5)得出结果
返回测试结果与实际数据符合实际情况,这就是K-近邻算法(KNN)处理分类问题
四、机器学习–鸢尾花(分类)
机器学习常用库sklearn
scikit-learning 提供数据样本,可以供我们研究机器学习模型
# 机器学习里面包含的数据集
from sklearn import datasets
1)获取训练数据(特征和结果)
使用load方法加载数据可以加载很多可供我们使用的数据
这里我们使用鸢尾花数据
iris_data = datasets.load_iris()
iris_data
#这里返回数据较多,我们拿出部分分析
# data:鸢尾花样本,该样本有四个特征,表示 花萼长度 花萼宽度 花瓣长度 花瓣宽度
# target:表示鸢尾花的种类 0(setosa) 1(versicolor) 2(virginica)
{'data': 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],
。。。
[6.5, 3. , 5.2, 2. ],
[6.2, 3.4, 5.4, 2.3],
[5.9, 3. , 5.1, 1.8]]),
'target': 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]),}
#还有一些描述的信息
我们获取的iris_data
是一个字典类型的数据
1. 获取训练样本特征
data = iris_data.data #训练样本的值
feature = iris_data.feature_names #训练样本的值对应的名称
2. 获取训练样本结果
target = iris_data.target # 所有样本的目标值
target_names = iris_data.target_names # 目标值对应的名称
3. 将得到的数据绘制图形
DataFrame(data).plot()
画图研究前两个特征和分类之间的关系
(二维散点图只能展示两个维度)
1、这里截取前两个特征来展示
X_train = data[:,0:2] # 训练样本的特征
y_train = target # 训练样本的结果
#目前取得样本特征和结果依旧是一一对应的关系
2、展示特征和结果之间的关系
花萼长度为x, 花萼宽度为y 对所有样本进行定位
我们使用点的颜色对其进行分类,散点图参数c可以传入一个数组,数组我们可以用样本的值使传入的x, y对应的点得颜色与值一一对应,这样就将图中的点分为三类区分开
plt.scatter(X_train[:,0],X_train[:,1],c=y_train)
plt.xlabel('sepal length') #设置x轴的标签
plt.ylabel('sepal width') #设置y轴的标签
2)创建 获取分类的模型
创建分类模型
knn_c = KNeighborsClassifier(n_neighbors=5)
3)模型训练
将训练数据样本特征和结果放入模型训练
knn_c.fit(X_train,y_train)
4)模型测试
将测试数据传入训练模型,返回训练结果
knn_c.predict([
[4.5,4.0],
[7.5,3.0],
[5.25,2.25]
])
array([0, 2, 1])
4)测试结果分析
测试数据的预测结果与实际结果相同
5)创造测试数据,测试模型结果
1、创造测试数据
先取到x轴线的范围和y轴的范围取到
# 为了全面,将数据的范围稍微扩大一点
xmin = X_train[:,0].min()-0.5
xmax = X_train[:,0].max()+0.5
ymin = X_train[:,1].min()-0.5
ymax = X_train[:,1].max()+0.5
将x轴的数据和y轴的数据每隔 0.01 取一份
# x轴范围内要取遍
x = np.arange(xmin,xmax,0.01)
# y轴范围内也要取遍
y = np.arange(ymin,ymax,0.01)
#我们拿到坐标轴的数据之后,我们要拿到每个点的坐标
拿到每个点对应的x,y坐标
xx,yy = np.meshgrid(x,y) # 将画布上所有的点取遍
xx.flatten(),yy.flatten() # 将矩阵扁平化
(array([3.8 , 3.81, 3.82, ..., 8.38, 8.39, 8.4 ]),
array([1.5, 1.5, 1.5, ..., 4.9, 4.9, 4.9]))
# 把对应位置的两个内容取出来 变成新的列表
X_test = np.c_[xx.flatten(),yy.flatten()] # 将平面上所有的点取遍 并 用来作为测试数据
array([[3.8 , 1.5 ],
[3.81, 1.5 ],
[3.82, 1.5 ],
...,
[8.38, 4.9 ],
[8.39, 4.9 ],
[8.4 , 4.9 ]])
2、使用刚刚训练好的模型进行预测
y_ = knn_c.predict(X_test) #预测后返回预测结果值
3、绘制测试结果图形
根据特征绘制样本的两个特征 X_test[:,0],X_test[:,1]
根据模型预测的结果 y_
绘制样本的颜色
plt.scatter(X_test[:,0],X_test[:,1],c=y_)
4、将训练数据和自己创建的测试数据作比较
把真实的训练数据也画到图上
plt.scatter(X_test[:,0],X_test[:,1],c=y_)
plt.scatter(X_train[:,0],X_train[:,1],c=y_train,cmap=cmap0) #这里的cmap给color设置颜色
5、为图像制定颜色
需要导入
from matplotlib.colors import ListedColormap
cmap0 = ListedColormap(['red','green','blue'])
# 将cmap0传入上面的图的效果
五、预测趋势(回归)
导包
from sklearn.neighbors import KNeighborsRegressor
1)生成训练样本数据
1、种子生成器
功能:固定随机数,多次执行,产生相同的随机数
np.random.seed(0)
np.random.seed(0)
np.random.random()
nd = np.random.rand(40,1) # 样本 40行1列
nd
2、对生成的训练数据排序np.sort
np.sort() 默认对最内层的数据进行排序 现在要对每一行进行排序 让样本从小到大排列
设置 np.sort(nd,axis=0)
对nd进行排序 然后放大5倍数
X_train = 5*np.sort(nd,axis=0)
3、训练数据值
结果集 是一个一维数组,所以在这里要将他改变
y_train = np.sin(X_train).flatten()
2)绘制训练数据
plt.scatter(X_train,y_train)
3)添加噪声
给y_train添加一些噪声 让x和y的关系不要那么明确
我们的训练数据为 40 行一列的数据,我们每隔4个给加一个随机噪声
1、制造噪声
noise = np.random.random(size=10)/2
noise
array([0.2343256 , 0.48838054, 0.30242276, 0.36963179, 0.0195939 ,
0.14140348, 0.06009828, 0.1480701 , 0.05936386, 0.15899159])
2、添加噪声
每隔4个加一个噪声
y_train[::4] += noise
2、添加噪声后的图形
plt.scatter(X_train,y_train)
4)生成模型
from sklearn.neighbors import KNeighborsRegressor
# 获取模型
knn = KNeighborsRegressor(n_neighbors=30)
5)训练数据
把训练数据传入模型,
x:训练样本特征
y:训练样本值
'''
# X_train是多行数据 有几个样本就有几行 有几个特征就有几列
# y_train 是一个一维的数组 里面直接装着结果值
'''
knn.fit(X_train,y_train)
6)创建测试数据
把x范围内的值取遍 然后用机器学习模型获取y_
这里的样本数据为一列,所以绘图时不用调整坐标(相对于上面鸢尾花来说)。
xmin = X_train.min()
xmax = X_train.max()
X_test = np.arange(xmin,xmax,0.01)
7)测试样本值
注意,有一个特征,传入的样本值应该为n行1列
y_ = knn.predict(X_test.reshape(-1,1))
8)绘图显示数据
plt.plot(X_test,y_,color='green',label='predict') #设置颜色和图标
plt.scatter(X_train,y_train,label='real',color='k')
plt.legend() #显示图标
六、人类动作识别
1) 数据保存np.save(保存路径, 数据)
1)保存*.npy数据文件np.save
nd = np.array([1,2,3])
nd
# np.save方法可以把数据保存到本地 参数 1.是路径 2.是数据
np.save('./test',nd) #这里可以不输入文件后缀
2)加载*.npy数据文件np.load(”文件路径”)
np.load('./test.npy')
array([1, 2, 3])
2) 导入训练集和测试集
1、导入数据
X_train = np.load('./data/x_train.npy')
y_train = np.load('./data/y_train.npy')
2、查看数据信息
X_train.shape
(7352, 561) #数据有 7352行,561列
y_train.size
7352
Series(y_train).unique()
array([5, 4, 6, 1, 3, 2], dtype=int64)
'''
这里训练结果集代表的运动类型
1:'walking', #走
2:'walking upstairs', #上楼
3:'walking downstairs', #下楼
4:'sitting', #坐着
5:'standing', #站着
6:'laying' #躺着
'''
3、画图查看各个特征的图形
我们随机抽查 第100,200,300,400,500,600个样本查看训练样本的结果
n = 100
y_train[n]
labels[y_train[n]]
'walking'
------------------------
n = 200
y_train[n]
labels[y_train[n]]
'standing'
------------------------
n = 300
y_train[n]
labels[y_train[n]]
'walking downstairs'
------------------------
n = 400
y_train[n]
labels[y_train[n]]
'sitting'
------------------------
n = 500
y_train[n]
labels[y_train[n]]
'walking upstairs'
------------------------
n = 600
y_train[n]
labels[y_train[n]]
'laying'
我们可以看出抽取的这 6 个数据将全部类型的取出来,我们将这6个训练样本绘图展示观察
plt.figure(figsize=(20,10)) #设置画布大小
for i in [1,2,3,4,5,6]:
axes = plt.subplot(3,2,i) #创建子画布
axes.plot(X_train[i*100],color=colors[i-1]) #在子画布上画图
axes.set_title(labels[y_train[i*100]]) 设置子画布的标题
3) 训练模型
1、创建训练模型
knn = KNeighborsClassifier(n_neighbors=5)
2、训练数据
传入训练数据与训练结果
knn.fit(X_train,y_train)
3、
4、
4) 模型预测
y_ = knn.predict(X_test)
array([5, 5, 5, ..., 2, 2, 1], dtype=int64)
5) 预测准确率
1、自己计算
将预测值与测试值相等,得出预测正确的个数
y_ == y_test # 获取的是布尔值的序列 相等的是True 不想等是False
array([ True, True, True, ..., True, True, False])
测试结果个数与预测结果个数
(y_ == y_test).sum()
2657
y_test.size
2947
两者相乘
(y_ == y_test).sum() / y_test.size
0.9066847641669494
2、KNN自带方法
机器学习模型 给我们提供了 打分的方法
# 参数 1.是测试集的特征数据 2.是测试集的真实结果
# 把测试集的特征数据传入后 机器学习模型 会 计算得到预测结果y_
# 然后和传入的真是结果 y_test 对比 返回准确率
knn.score(X_test,y_test)