统计学习方法读书笔记7-K近邻习题
文章目录
- 1.课本课后习题
- 2.视频课后习题
- 1.KNN自编程
- 2.sklearn实现
1.课本课后习题
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.colors import ListedColormap
from sklearn.neighbors import KNeighborsClassifier# 实例点
x = np.array([[0.5, 0.9], [0.7, 2.8], [1.3, 4.6], [1.4, 2.8], [1.7, 0.8], [1.9, 1.4], [2, 4], [2.3, 3], [2.5, 2.5], [2.9, 2],[2.9, 3], [3, 4.5], [3.3, 1.1], [4, 3.7], [4, 2.2], [4.5, 2.5], [4.6, 1], [5, 4]])# 类别
y = np.array([0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0])# 设置二维网格的边界
x_min, x_max = 0, 6
y_min, y_max = 0, 6# 设置不同类别区域的颜色
cmap_light = ListedColormap(['#FFFFFF', '#BDBDBD'])# 生成二维网格
h = .01
xx, yy = np.meshgrid(np.arange(x_min, x_max, h), np.arange(y_min, y_max, h))# 这里的参数n_neighbors就是k近邻法中的k
knn = KNeighborsClassifier(n_neighbors=2)
knn.fit(x, y)# ravel()实现扁平化,比如将形状为3*4的数组变成1*12
# np.c_()在列方向上连接数组,要求被连接数组的行数相同
Z = knn.predict(np.c_[xx.ravel(), yy.ravel()])
Z = Z.reshape(xx.shape)plt.figure()# 设置坐标轴的刻度
plt.xticks(tuple([x for x in range(6)]))
plt.yticks(tuple([y for y in range(6) if y != 0]))# 填充不同分类区域的颜色
# Z与cmap相互对应
plt.pcolormesh(xx, yy, Z, cmap=cmap_light)# 设置坐标轴标签
plt.xlabel('$x^{(1)}$')
plt.ylabel('$x^{(2)}$')# 绘制实例点的散点图
plt.scatter(x[:, 0], x[:, 1], c=y)plt.show()
k=2
k=1
总体来说,k值的减小意味着整体模型变得复杂,容易发生过拟合;k值的增大意味着整体模型变得简单,可以减少学习的估计误差,但是学习的近似误差会增大。通常采用交叉验证法来选取最优的k值。关于k值的选择可以参考书本上3.2.3章节。
2.视频课后习题
k近邻算法的模型复杂度主要体现在k值上
k值比较小时,容易造成过拟合
k值比较大时,容易造成欠拟合
1.KNN自编程
#!usr/bin/env python
# -*- coding:utf-8 _*-
"""
@author: liujie
@software: PyCharm
@file: KNN自编程.py
@time: 2020/10/21 12:58
"""
# KNN-线性扫描import numpy as np
# 计数函数
from collections import Counter
import matplotlib.pyplot as pltclass KNN():# 所需参数初始化def __init__(self,x_train,y_train,k=3):self.k = kself.x_train = x_trainself.y_train = y_traindef predict(self,x_test):# 计算欧式距离-二范数dist_list = [(np.linalg.norm(x_test-self.x_train[i],2),self.y_train[i])for i in range(self.x_train.shape[0])]# dist_list = [(np.sqrt(np.sum(np.square(x_test-self.x_train[i]))), self.y_train[i])# for i in range(len(self.x_train.shape[0]))]# 对所有距离进行排序-sort函数,不过只需要前k个,但这是全部排序,浪费了时间dist_list.sort(key=lambda x:x[0])# 取前k个最小距离对应的类别y_list = [dist_list[i][-1] for i in range(self.k)]# 对上述k的点的分类进行统计# Counter是一个计数函数,针对序列中出现次数最多的元素,其中most_common()可直接给出答案y_count = Counter(y_list).most_common()return y_count[0][0]def draw(X_train,y_train,X_new):# 正负实例点初始化X_po=np.zeros(X_train.shape[1])X_ne=np.zeros(X_train.shape[1])# 区分正、负实例点# np.vstack垂直(按照行顺序)的把数组给堆叠起来。for i in range(y_train.shape[0]):if y_train[i]==1: # 正例X_po=np.vstack((X_po,X_train[i]))else: # 负例X_ne=np.vstack((X_ne,X_train[i]))# 实例点绘图plt.plot(X_po[1:,0],X_po[1:,1],"g*",label="1")plt.plot(X_ne[1:, 0], X_ne[1:, 1], "rx", label="-1")plt.plot(X_new[:, 0], X_new[:, 1], "bo", label="test_points")# 测试点坐标值标注# plt.annotate()函数用于标注文字for xy in zip(X_new[:, 0], X_new[:, 1]):plt.annotate("test{}".format(xy),xy)# 设置坐标轴plt.axis([0,10,0,10])plt.xlabel("x1")plt.ylabel("x2")# 显示图例plt.legend()# 显示图像plt.show()def main():# 训练数据x_train = np.array([[5,4],[9,6],[4,7],[2,3],[8,1],[7,2]])y_train = np.array([1,1,1,-1,-1,-1])# 测试数据x_test = np.array([[5,3]])# 绘图draw(x_train,y_train,x_test)# 不同的k对分类结果的影响for k in range(1,6,2):# 构建KNN实例clf = KNN(x_train,y_train,k=k)# 对测试数据进行分类预测y_predict = clf.predict(x_test)print('k={},被分类为: {}'.format(k,y_predict))if __name__ == '__main__':main()
k=1,被分类为: 1
k=3,被分类为: -1
k=5,被分类为: -1
线性扫描优化版本思路:- 多数据处理for循环多进程- 距离用列表排序,浪费时间与空间用堆这个数据结构
# 线性扫描优化版本:
# 1.多数据处理:for循环,多进程
# 2.距离改用堆这个结构import numpy as np
# Counter是一个计数函数
from collections import Counter
# 多进程
from concurrent import futures
import matplotlib.pyplot as plt
# 导入堆模块
import heapq
import timeclass KNN:def __init__(self, X_train, y_train, k=3):# 所需参数初始化self.k = k # 所取k值self.X_train = X_trainself.y_train = y_train# 堆操作def predict_single(self, x_new):# 计算与前k个样本点欧氏距离,距离取负值是把原问题转化为取前k个最大的距离dist_list = [(-np.linalg.norm(x_new - self.X_train[i], ord=2), self.y_train[i], i)for i in range(self.k)]# 利用前k个距离构建堆heapq.heapify(dist_list)# 遍历计算与剩下样本点的欧式距离for i in range(self.k, self.X_train.shape[0]):dist_i = (-np.linalg.norm(x_new - self.X_train[i], ord=2), self.y_train[i], i)# 若dist_i 比 dis_list的最小值大,则用dis_i替换该最小值,执行下堆操作# 最小堆if dist_i[0] > dist_list[0][0]:heapq.heappushpop(dist_list, dist_i)# 若dist_i 比 dis_list的最小值小,堆保持不变,继续遍历else:continuey_list = [dist_list[i][1] for i in range(self.k)]# [-1,1,1,-1...]# 对上述k个点的分类进行统计y_count = Counter(y_list).most_common()# {1:n,-1:m}return y_count[0][0]# 用多进程实现并行,处理多个值的搜索def predict_many(self, X_new):# 导入多进程with futures.ProcessPoolExecutor(max_workers=4) as executor:# 建立多进程任务tasks = [executor.submit(self.predict_single, X_new[i]) for i in range(X_new.shape[0])]# 驱动多进程运行done_iter = futures.as_completed(tasks)# 提取运行结果res = [future.result() for future in done_iter]return resdef draw(X_train, y_train, X_new):# 正负实例点初始化X_po = np.zeros(X_train.shape[1])X_ne = np.zeros(X_train.shape[1])# 区分正、负实例点# np.vstack垂直(按照行顺序)的把数组给堆叠起来。for i in range(y_train.shape[0]):if y_train[i] == 1: # 正例X_po = np.vstack((X_po, X_train[i]))else: # 负例X_ne = np.vstack((X_ne, X_train[i]))# 实例点绘图plt.plot(X_po[1:, 0], X_po[1:, 1], "g*", label="1")plt.plot(X_ne[1:, 0], X_ne[1:, 1], "rx", label="-1")plt.plot(X_new[:, 0], X_new[:, 1], "bo", label="test_points")# 测试点坐标值标注# plt.annotate()函数用于标注文字for xy in zip(X_new[:, 0], X_new[:, 1]):plt.annotate("test{}".format(xy), xy)# 设置坐标轴plt.axis([0, 10, 0, 10])plt.xlabel("x1")plt.ylabel("x2")# 显示图例plt.legend()# 显示图像plt.show()def main():start = time.time()# 训练数据X_train = np.array([[5, 4],[9, 6],[4, 7],[2, 3],[8, 1],[7, 2]])y_train = np.array([1, 1, 1, -1, -1, -1])# 测试数据X_new = np.array([[5, 3], [9, 2]])# 绘图draw(X_train, y_train, X_new)# 不同的k(取奇数)对分类结果的影响for k in range(1, 6, 2):# 构建KNN实例clf = KNN(X_train, y_train, k=k)# 对测试数据进行分类预测y_predict = clf.predict_many(X_new)print("k={},被分类为:{}".format(k, y_predict))end = time.time()print("用时:{}s".format(round(end - start), 2))if __name__ == "__main__":main()
# 难理解-对于树的构造不熟
# 构建kd树,搜索待预测点所属区域
from collections import namedtuple
import numpy as np# 建立节点类
class Node(namedtuple("Node","location left_child right_child")):def __repr__(self):return str(tuple(self))# kd tree类
class KdTree():def __init(self,k=1,p=2):self.k=kself.p=pself.kdtree=None#构建kd treedef _fit(self,X,depth=0):try:k=X.shape[1]except IndexError as e:return None# 这里可以展开,通过方差选择axisaxis=depth % kX=X[X[:,axis].argsort()]median=X.shape[0]//2try:X[median]except IndexError:return Nonereturn Node(location=X[median],left_child=self._fit(X[:median],depth+1),right_child=self._fit(X[median+1:],depth+1))def _search(self,point,tree=None,depth=0,best=None):if tree is None:return bestk=point.shape[1]# 更新 branchif point[0][depth%k]<tree.location[depth%k]:next_branch=tree.left_childelse:next_branch=tree.right_childif not next_branch is None:best=next_branch.locationreturn self._search(point,tree=next_branch,depth=depth+1,best=best)def fit(self,X):self.kdtree=self._fit(X)return self.kdtreedef predict(self,X):res=self._search(X,self.kdtree)return resdef main():KNN=KdTree()X_train=np.array([[5,4],[9,6],[4,7],[2,3],[8,1],[7,2]])KNN.fit(X_train)X_new=np.array([[5,3]])res=KNN.predict(X_new)print(res)if __name__=="__main__":main()
2.sklearn实现
import numpy as np
from sklearn.neighbors import KNeighborsClassifierdef main():# 训练数据x_train = np.array([[5,4],[9,6],[4,7],[2,3],[8,1],[7,2]])y_train = np.array([1,1,1,-1,-1,-1])# 测试数据x_test = np.array([[5,3]])# 绘图# draw(x_train,y_train,x_test)# 不同的k对分类结果的影响for k in range(1,6,2):# 构建KNN实例clf = KNeighborsClassifier(n_neighbors=k,weights='distance',n_jobs=-1)# 训练模型clf.fit(x_train,y_train)# 预测-二维数据y_predict = clf.predict(x_test)# 属于不同分类的概率print(clf.predict_proba(x_test))print('k={},被分类为: {}'.format(k,y_predict))if __name__ == '__main__':main()
[[0. 1.]]
k=1,被分类为: [1]
[[0.43837481 0.56162519]]
k=3,被分类为: [1]
[[0.45986872 0.54013128]]
k=5,被分类为: [1]
当只考虑样本数N的影响时:
线性扫描:计算N个距离O(N)
kd tree : 二叉树搜索O(logN)随着维度d的增加,kd tree效率下降,实际上当维度d接近N时,二者效率相当
统计学习方法读书笔记7-K近邻习题相关推荐
- 统计学习方法读书笔记(六)-逻辑斯蒂回归与最大熵模型(迭代尺度法(IIS))
全部笔记的汇总贴:统计学习方法读书笔记汇总贴 逻辑斯谛回归 (logistic regression )是统计学习中的经典分类方法.最大熵是概率模型学习的一个准则,将其推广到分类问题得到最大熵模型(m ...
- 统计学习方法读书笔记(九)-EM算法及其推广
全部笔记的汇总贴:统计学习方法读书笔记汇总贴 EM算法用于含有隐变量(hidden variable)的概率模型参数的极大似然估计,或极大后验概率估计.EM算法的每次迭代由两步组成:E步,求期望(ex ...
- 统计学习方法 读书笔记(五)
读书笔记仅供个人学习使用 本文主要参考书籍为<统计学习方法>(李航)第二版 参考 Sunning_001的博客 决策树 决策树的定义 if-then 的理解 条件概率分布的理解 决策树学习 ...
- 统计学习方法第三章 k近邻法
文章目录 第三章 k近邻法 k近邻算法 k近邻模型的距离划分 k值的选择 k近邻分类决策规则 第三章 k近邻法 只讨论分类问题的k近邻法 k近邻三个基本要素: k值选择 距离度量 分类决策规则 k近邻 ...
- 统计学习方法读书笔记15-逻辑斯蒂回归习题
文章目录 1.课后习题 2.视频课后习题 1.课后习题 import numpy as np import time import matplotlib.pyplot as plt from mpl_ ...
- 统计学习方法笔记(一)-k近邻算法原理及python实现
k近邻法 k近邻算法 算法原理 距离度量 距离度量python实现 k近邻算法实现 案例地址 k近邻算法 kkk近邻法(kkk-NN)是一种基本分类和回归方法. 算法原理 输入:训练集 T={(x1, ...
- 李航《统计学习方法》笔记
虽然书名是统计学习,但是却是机器学习领域中和重要的一本参考书.当前的机器学习中机器指计算机,但是所运用的方法和知识是基于数据(对象)的统计和概率知识,建立一个模型,从而对未来的数据进行预测和分析(目的 ...
- 统计学习方法 学习笔记(1)统计学习方法及监督学习理论
统计学习方法及监督学习理论 1.1.统计学习 1.1.1.统计学习的特点 1.1.2.统计学习的对象 1.1.3.统计学习的目的 1.1.4.统计学习的方法 1.1.5.统计学习的研究 1.1.6.统 ...
- 统计学习方法——李航 笔记
第一章 概论 统计学习的目标在于:从假设空间中选取最优模型 统计学方法三要素:方法=模型+策略+算法 训练集用来训练模型,验证集用来选择模型,测试集用于对学习方法的评估. 1.输入变量和输出变量均为连 ...
- 统计学习方法-李航-第一章:统计学习方法概论-笔记1
文章目录 0 机器学习分类 0.1 监督学习 0.2 无监督学习 0.3 半监督学习 0.4 强化学习 1 统计学习方法概论 1.1 监督学习的步骤 1.2 统计学习三要素 1.3 模型评估 1.4 ...
最新文章
- django--favicon.ico
- Cocos2d-精灵的几个常识
- android init(system/core/init/init.c)分析
- 用3年时间破解学界200多年难题,年仅21岁的天才竟因谈了一场恋爱挂掉了.........
- [渝粤教育] 西南科技大学 高频电子线路 在线考试复习资料2021版
- 数据可视化分析票房数据报告_票房收入分析和可视化
- 计算机网络学习笔记-目录(更新日期:2020.4.8)
- git与github学习笔记
- 微信短内容要来了!新功能已开启内测申请
- javascript实现blob流、base64,file、base64的互相转换
- 加速pip下载:更换pip源
- AD用SmartPDF导出原理图标号显示不全解决方法
- Qt Designer简介
- PE格式文件修复过程
- MacBook 快捷键
- LAMP The requested URL /index.html was not found on this server.
- HTML之部分易忘点
- 用vue封装分页器,让你的页面简单而不失优雅
- php 无法连接redis,无法连接使用 phpredis
- AWS S3 in china 地址