读书笔记-统计学习方法(李航)第三章
发布时间
阅读量:
阅读量
第三章 K 近邻算法
-
3.1 k近邻算法
-
3.2 k近邻模型
-
- 距离度量
- k值的选择
- 决策规则
-
- 实践:
-
手动实现
-
sklearn 实现
3.1 k近邻算法
k近邻是一种基本的分类 和 回归 方法
k近邻法的三个基本要素为:
1:k值的选择
2:距离度量
1:分类决策规则
3.2 k近邻模型
距离度量

k值的选择
1:k值太小:
模型过于复杂(只考虑最近的一个点),过拟合
2:当k参数取值过大时,模型结构过于简单(例如当K的取值等于样本总数N时),导致模型无法有效学习到数据特征。
决策规则
对测试点最近的K个点的类别投票,用多数类别预测 测试点的类别。
实践:
"""
2.给定一个二维空间的数据集T={正实例:(5,4),(9,6),(4,7);负实例:(2,3), (8,1),(7,2)},试基于欧氏距离,找到数据点S(5,3)的最近邻(k=1),并对S点进行分类预测。
(1)用“线性扫描”算法自编程实现。
(2)试调用sklearn.neighbors的KNeighborsClassifier模块,对S点进行分类预测,并对比近邻数k取值不同,对分类预测结果的影响。
(3)思考题:思考“线性扫描”算法和“kd树”算法的时间复杂度。
"""
'\n2.给定一个二维空间的数据集T={正实例:(5,4),(9,6),(4,7);负实例:(2,3), (8,1),(7,2)},试基于欧氏距离,找到数据点S(5,3)的最近邻(k=1),并对S点进行分类预测。\n\n(1)用“线性扫描”算法自编程实现。\n\n(2)试调用sklearn.neighbors的KNeighborsClassifier模块,对S点进行分类预测,并对比近邻数k取值不同,对分类预测结果的影响。\n\n(3)思考题:思考“线性扫描”算法和“kd树”算法的时间复杂度。\n'
手动实现
import numpy as np
x_train = np.array([[5,4],[9,6],[4,7],[2,3],[8,1],[7,2]])
y_train = np.array([1,1,1,0,0,0])
x_test = np.array([[5,3]])
def model(k,x_train,y_train,x_test):
dis2class = dict()
for i in range(y_train.shape[0]):
point = x_train[i]
dis = 0
for j in range(2):
dis += (point[j]-x_test[0][j])**2
dis = dis ** 0.5
dis2class[dis] = y_train[i]
print(dis2class)
dis_list = list(dis2class.keys())
dis_list.sort()
dis_list = dis_list[:k]
print(dis_list)
class_list = [dis2class[diss] for diss in dis_list]
print(class_list)
class_count = dict()
for c in set(class_list):
class_count[class_list.count(c)] = c
print(class_count)
print(max(class_count))
return class_count[max(class_count)]
result = model(1,x_train,y_train,x_test)
print("result = ",result)
{1.0: 1, 5.0: 1, 4.123105625617661: 1, 3.0: 0, 3.605551275463989: 0, 2.23606797749979: 0}
[1.0]
[1]
{1: 1}
1
result = 1
k值过小会造成过拟合,过大则会欠拟合
sklearn 实现
from sklearn.neighbors import KNeighborsClassifier
"""
n_neighbors : 默认值:5
weights : 默认:uniform(权重一样) ; distancs(距离越近权重越大)
algorithm: 默认:auto ; brute(暴力求解即线性扫描) ; kd_tree ; ball_tree (当数据量较小时会自动变成暴力求解)
leaf_size : 默认:30 (叶子节点数量的阈值)
p : 默认是2(即欧氏距离)
metric:默认 mincowski
n_jobs:并行搜索 ,1表示一个进程,-1表示所%alias进程
"""
for k in range(1,6,2):
#构建实例
clf = KNeighborsClassifier(n_neighbors=k,n_jobs=1,)
#训练
clf.fit(x_train,y_train)
#预处
res = clf.predict(x_test)
print("当k值为{}时,测试点的分类结果为:".format(k) ,res)
当k值为1时,测试点的分类结果为: [1]
当k值为3时,测试点的分类结果为: [1]
当k值为5时,测试点的分类结果为: [1]
全部评论 (0)
还没有任何评论哟~
