文章目录

  • 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近邻习题相关推荐

  1. 统计学习方法读书笔记(六)-逻辑斯蒂回归与最大熵模型(迭代尺度法(IIS))

    全部笔记的汇总贴:统计学习方法读书笔记汇总贴 逻辑斯谛回归 (logistic regression )是统计学习中的经典分类方法.最大熵是概率模型学习的一个准则,将其推广到分类问题得到最大熵模型(m ...

  2. 统计学习方法读书笔记(九)-EM算法及其推广

    全部笔记的汇总贴:统计学习方法读书笔记汇总贴 EM算法用于含有隐变量(hidden variable)的概率模型参数的极大似然估计,或极大后验概率估计.EM算法的每次迭代由两步组成:E步,求期望(ex ...

  3. 统计学习方法 读书笔记(五)

    读书笔记仅供个人学习使用 本文主要参考书籍为<统计学习方法>(李航)第二版 参考 Sunning_001的博客 决策树 决策树的定义 if-then 的理解 条件概率分布的理解 决策树学习 ...

  4. 统计学习方法第三章 k近邻法

    文章目录 第三章 k近邻法 k近邻算法 k近邻模型的距离划分 k值的选择 k近邻分类决策规则 第三章 k近邻法 只讨论分类问题的k近邻法 k近邻三个基本要素: k值选择 距离度量 分类决策规则 k近邻 ...

  5. 统计学习方法读书笔记15-逻辑斯蒂回归习题

    文章目录 1.课后习题 2.视频课后习题 1.课后习题 import numpy as np import time import matplotlib.pyplot as plt from mpl_ ...

  6. 统计学习方法笔记(一)-k近邻算法原理及python实现

    k近邻法 k近邻算法 算法原理 距离度量 距离度量python实现 k近邻算法实现 案例地址 k近邻算法 kkk近邻法(kkk-NN)是一种基本分类和回归方法. 算法原理 输入:训练集 T={(x1, ...

  7. 李航《统计学习方法》笔记

    虽然书名是统计学习,但是却是机器学习领域中和重要的一本参考书.当前的机器学习中机器指计算机,但是所运用的方法和知识是基于数据(对象)的统计和概率知识,建立一个模型,从而对未来的数据进行预测和分析(目的 ...

  8. 统计学习方法 学习笔记(1)统计学习方法及监督学习理论

    统计学习方法及监督学习理论 1.1.统计学习 1.1.1.统计学习的特点 1.1.2.统计学习的对象 1.1.3.统计学习的目的 1.1.4.统计学习的方法 1.1.5.统计学习的研究 1.1.6.统 ...

  9. 统计学习方法——李航 笔记

    第一章 概论 统计学习的目标在于:从假设空间中选取最优模型 统计学方法三要素:方法=模型+策略+算法 训练集用来训练模型,验证集用来选择模型,测试集用于对学习方法的评估. 1.输入变量和输出变量均为连 ...

  10. 统计学习方法-李航-第一章:统计学习方法概论-笔记1

    文章目录 0 机器学习分类 0.1 监督学习 0.2 无监督学习 0.3 半监督学习 0.4 强化学习 1 统计学习方法概论 1.1 监督学习的步骤 1.2 统计学习三要素 1.3 模型评估 1.4 ...

最新文章

  1. django--favicon.ico
  2. Cocos2d-精灵的几个常识
  3. android init(system/core/init/init.c)分析
  4. 用3年时间破解学界200多年难题,年仅21岁的天才竟因谈了一场恋爱挂掉了.........
  5. [渝粤教育] 西南科技大学 高频电子线路 在线考试复习资料2021版
  6. 数据可视化分析票房数据报告_票房收入分析和可视化
  7. 计算机网络学习笔记-目录(更新日期:2020.4.8)
  8. git与github学习笔记
  9. 微信短内容要来了!新功能已开启内测申请
  10. javascript实现blob流、base64,file、base64的互相转换
  11. 加速pip下载:更换pip源
  12. AD用SmartPDF导出原理图标号显示不全解决方法
  13. Qt Designer简介
  14. PE格式文件修复过程
  15. MacBook 快捷键
  16. LAMP The requested URL /index.html was not found on this server.
  17. HTML之部分易忘点
  18. 用vue封装分页器,让你的页面简单而不失优雅
  19. php 无法连接redis,无法连接使用 phpredis
  20. AWS S3 in china 地址

热门文章

  1. 14.ThreadLocal
  2. 【转载】关于.NET下开源及商业图像处理(PSD)组件
  3. Bootstrap基础3(表单)
  4. JAVA 编码格式转换工具类
  5. 普通摄像头游戏——飞翔
  6. 目录中带.造成文件上传验证问题
  7. 机器学习(1)——基础概念
  8. STM32F407使用MFRC522射频卡调试及程序移植成功
  9. [bzoj3585] Rmq Problem / mex
  10. 所有子模块都要执行的checkstyle检查