动手学机器学习K近邻算法+习题

K近邻算法

import matplotlib.pyplot as plt
import numpy as np
import os# 读入mnist数据集
m_x = np.loadtxt('mnist_x', delimiter=' ')
m_y = np.loadtxt('mnist_y')# 数据集可视化
data = np.reshape(np.array(m_x[0], dtype=int), [28, 28])
plt.figure()
plt.imshow(data, cmap='gray')# 将数据集分为训练集和测试集
ratio = 0.8
split = int(len(m_x) * ratio)
# 打乱数据
np.random.seed(0)
idx = np.random.permutation(np.arange(len(m_x)))
m_x = m_x[idx]
m_y = m_y[idx]
x_train, x_test = m_x[:split], m_x[split:]
y_train, y_test = m_y[:split], m_y[split:]

delimiter=' '表示使用空格作为分隔符

data = np.reshape(np.array(m_x[0], dtype=int), [28, 28])获取一个图片的像素后变成28x28

idx = np.random.permutation(np.arange(len(m_x)))获取索引后,打乱索引

class KNN:def __init__(self, k, label_num):self.k = kself.label_num = label_num # 类别的数量def fit(self, x_train, y_train):# 在类中保存训练数据self.x_train = x_trainself.y_train = y_traindef get_knn_indices(self, x):# 获取距离目标样本点最近的K个样本点的标签# 计算已知样本的距离dis = list(map(lambda a: distance(a, x), self.x_train))# 按距离从小到大排序,并得到对应的下标knn_indices = np.argsort(dis)# 取最近的K个knn_indices = knn_indices[:self.k]return knn_indicesdef get_label(self, x):# 对KNN方法的具体实现,观察K个近邻并使用np.argmax获取其中数量最多的类别knn_indices = self.get_knn_indices(x)# 类别计数label_statistic = np.zeros(shape=[self.label_num])for index in knn_indices:label = int(self.y_train[index])label_statistic[label] += 1# 返回数量最多的类别return np.argmax(label_statistic)def predict(self, x_test):# 预测样本 test_x 的类别predicted_test_labels = np.zeros(shape=[len(x_test)], dtype=int)for i, x in enumerate(x_test):predicted_test_labels[i] = self.get_label(x)return predicted_test_labels

argsort得到排序后对应的下标,截断k个返回

用下标到self.y_train中提取具体label并计数,然后argmax返回最大值的下标,在这里是标签

from sklearn.neighbors import KNeighborsClassifier # sklearn中的KNN分类器
from matplotlib.colors import ListedColormap# 读入高斯数据集
data = np.loadtxt('gauss.csv', delimiter=',')
x_train = data[:, :2]
y_train = data[:, 2]
print('数据集大小:', len(x_train))# 可视化
plt.figure()
plt.scatter(x_train[y_train == 0, 0], x_train[y_train == 0, 1], c='blue', marker='o')
plt.scatter(x_train[y_train == 1, 0], x_train[y_train == 1, 1], c='red', marker='x')
plt.xlabel('X axis')
plt.ylabel('Y axis')
plt.show()

x_train = data[:, :2]

y_train = data[:, 2]

 

x_train[y_train == 0, 0]:表示选择标签为0的样本点的第一个特征(x轴坐标)

x_train[y_train == 0, 1]:表示选择标签为0的样本点的第二个特征(y轴坐标)

# 设置步长
step = 0.02
# 设置网格边界
x_min, x_max = np.min(x_train[:, 0]) - 1, np.max(x_train[:, 0]) + 1
y_min, y_max = np.min(x_train[:, 1]) - 1, np.max(x_train[:, 1]) + 1
# 构造网格
xx, yy = np.meshgrid(np.arange(x_min, x_max, step), np.arange(y_min, y_max, step))
grid_data = np.concatenate([xx.reshape(-1, 1), yy.reshape(-1, 1)], axis=1)

x、y轴上最大值+1最小值-1得到边界

np.meshgrid()函数生成一个二维数组,其中的每个元素都是一对坐标值,这些坐标值构成了一个网格

np.concatenate() 函数将 xxyy 两个列向量按列方向(axis=1)进行拼接

fig = plt.figure(figsize=(16,4.5))
# K值,读者可以自行调整,观察分类结果的变化
ks = [1, 3, 10] 
cmap_light = ListedColormap(['royalblue', 'lightcoral'])for i, k in enumerate(ks):# 定义KNN分类器knn = KNeighborsClassifier(n_neighbors=k) knn.fit(x_train, y_train)z = knn.predict(grid_data)# 画出分类结果ax = fig.add_subplot(1, 3, i + 1)ax.pcolormesh(xx, yy, z.reshape(xx.shape), cmap=cmap_light, alpha=0.7)ax.scatter(x_train[y_train == 0, 0], x_train[y_train == 0, 1], c='blue', marker='o')ax.scatter(x_train[y_train == 1, 0], x_train[y_train == 1, 1], c='red', marker='x')ax.set_xlabel('X axis')ax.set_ylabel('Y axis')ax.set_title(f'K = {k}')
plt.show()

 z.reshape(xx.shape)z 是对网格数据的预测结果,它是一个一维数组,需要通过 reshape() 函数重新整形为与网格数据相同的形状,这样才能与网格数据对应起来

alpha=0.7:指定了绘制颜色的透明度,这里是0.7,表示颜色相对不透明

# block_size表示向外扩展的层数,扩展1层即3*3
block_size = 1 def read_style_image(file_name, size=block_size):# 读入风格图像, 得到映射 X->Y# 其中X储存3*3像素格的灰度值,Y储存中心像素格的色彩值# 读取图像文件,设图像宽为W,高为H,得到W*H*3的RGB矩阵img = io.imread(file_name) fig = plt.figure()plt.imshow(img)plt.xlabel('X axis')plt.ylabel('Y axis')plt.show()# 将RGB矩阵转换成LAB表示法的矩阵,大小仍然是W*H*3,三维分别是L、A、Bimg = rgb2lab(img) # 取出图像的宽度和高度w, h = img.shape[:2] X = []Y = []# 枚举全部可能的中心点for x in range(size, w - size): for y in range(size, h - size):# 保存所有窗口X.append(img[x - size: x + size + 1, \y - size: y + size + 1, 0].flatten())# 保存窗口对应的色彩值a和bY.append(img[x, y, 1:])return X, Y

L、A、B分别代表亮度、色度和色彩度

LAB颜色空间是一种常用的颜色表示方法,它将颜色分为亮度(L)和两个色度分量(A和B),可以更好地模拟人类视觉系统对颜色的感知。

具体来说,LAB颜色空间有三个通道:

  • L 表示亮度(Lightness),取值范围为0到100,表示黑到白。
  • A 表示从绿色到红色的范围,负值表示绿色,正值表示红色。
  • B 表示从蓝色到黄色的范围,负值表示蓝色,正值表示黄色。

将RGB图像转换为LAB颜色空间的图像可以使得图像在颜色的表达上更加准确和稳定,同时也便于进行一些颜色相关的图像处理任务,比如颜色修正、颜色分割等。

x.append做了一个滑窗

图像中不同位置的像素通常包含了不同的信息,例如边缘、纹理等

图像中的像素通常具有一定的空间相关性,相邻像素之间可能存在一定的关联关系

可以将注意力集中在局部区域,从而更加高效地处理图像

色彩值是AB,所以是 1:

X, Y = read_style_image(os.path.join(path, 'style.jpg')) # 建立映射# weights='distance'表示邻居的权重与其到样本的距离成反比
knn = KNeighborsRegressor(n_neighbors=4, weights='distance')
knn.fit(X, Y)

通过read_style_image得到一个颜色的映射,也就是RGB->LAB

def rebuild(img, size=block_size):# 打印内容图像fig = plt.figure()plt.imshow(img)plt.xlabel('X axis')plt.ylabel('Y axis')plt.show()# 将内容图像转为LAB表示img = rgb2lab(img) w, h = img.shape[:2]# 初始化输出图像对应的矩阵photo = np.zeros([w, h, 3])# 枚举内容图像的中心点,保存所有窗口print('Constructing window...')X = []for x in range(size, w - size):for y in range(size, h - size):# 得到中心点对应的窗口window = img[x - size: x + size + 1, \y - size: y + size + 1, 0].flatten()X.append(window)X = np.array(X)# 用KNN回归器预测颜色print('Predicting...')pred_ab = knn.predict(X).reshape(w - 2 * size, h - 2 * size, -1)# 设置输出图像photo[:, :, 0] = img[:, :, 0]photo[size: w - size, size: h - size, 1:] = pred_ab# 由于最外面size层无法构造窗口,简单起见,我们直接把这些像素裁剪掉photo = photo[size: w - size, size: h - size, :]return photo

将预测的色度值填充到 photo 中对应的位置

当时滑窗余了一部分,这里全切掉

K最近邻(KNN)模型的作用是根据给定的窗口特征 X,预测对应的色度值 pred_ab

对于给定的窗口特征 X,首先计算它与训练集中所有窗口特征的距离,根据距离的大小,选取距离最近的K个邻居,使用这K个最近邻的目标值(在这里是色度值)进行加权平均,其中权重通常与距离成反比关系

习题

1.错误。KNN常使用交叉验证的方法确定K

2.C。K是超参数,人为设置的

3.

  1. 稀疏数据:在数据稀疏的情况下,尤其是在特征空间中存在大量零值时(例如,用户对电影的评分矩阵),曼哈顿距离可能更合适,因为它不会因为零值特征的欧氏距离为零而忽略非零特征之间的差异。

  2. 异常值敏感性:欧氏距离对异常值比较敏感,因为异常值会在高维空间中拉大与其他点的距离。曼哈顿距离由于只考虑各个维度上的绝对差异,因此对异常值的敏感性较低。

改为曼哈顿距离:

def distance(a, b):return np.sum(np.abs(a - b))

                               曼哈顿                                                   欧几里得

4.

  1. 失去局部细节:增大采样窗口会导致对局部细节的损失,因为每个像素点的颜色值是通过周围更大范围的像素值来预测的。这可能会导致图像的局部结构和纹理细节被模糊化。

  2. 计算复杂度增加:随着采样窗口的增大,需要考虑的颜色空间的维度也会增加,从而导致计算复杂度的增加。KNN回归器的训练和预测过程可能会变得更加耗时。

  3. 可能的颜色偏移:采样窗口增大可能会导致对颜色平滑度的过度假设,这可能会导致在图像中出现颜色偏移或色块。特别是对于细节丰富的图像,增大采样窗口可能会产生不自然的结果。

                        block_size为1                                                                block_size为2

5.略

6.

# 创建由多张图像构成的数据集,num表示图像数量
# 返回的X、Y的含义与函数read_style_image相同
def create_dataset(data_dir='vangogh', num=10):# 初始化函数输出X = []Y = []# 读取图像files = np.sort(os.listdir(os.path.join(path, data_dir)))num = min(num, len(files))for file in files[:num]:print('reading', file)X0, Y0 = read_style_image(os.path.join(path, data_dir, file))X.extend(X0)Y.extend(Y0)return X, YX, Y = create_dataset()
knn = KNeighborsRegressor(n_neighbors=4, weights='distance')
knn.fit(X, Y)content = io.imread(os.path.join(path, 'input.jpg'))
new_photo = rebuild(content)
new_photo = lab2rgb(new_photo)fig = plt.figure()
plt.imshow(new_photo)
plt.xlabel('X axis')
plt.ylabel('Y axis')
plt.show()

之前用的一张照片的滑窗训练,现在加个for循环把窗口一起放数组里

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/577766.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

(C++笔试题)选择题+编程题

个人主页:Lei宝啊 愿所有美好如期而遇 选择题 第一道 下面对析构函数的正确描述是() A. 系统不能提供默认的析构函数B. 析构函数必须由用户定义C. 析构函数没有参数D. 析构函数可以设置默认参数 解析: 正确描述析构函数的…

tab切换组件,可横向自适应滑动

示例图&#xff1a; 注&#xff1a;需要引入Jquery <!DOCTYPE html> <html><head><meta charset"utf-8"><title></title><style>.tabs-box {width: 100%;height: auto;}.tab-header-box {display: flex;overflow: hidden…

【AI】『Suno』哎呦不错呦,AI界的周董,快来创作你的歌曲吧!

前言 &#x1f34a;缘由 Suno AI的旋风终于还是吹到了音乐圈 &#x1f3c0;事情起因&#xff1a; 朋友说他练习时长两天半&#xff0c;用Suno发布了首张AI音乐专辑。震惊之余&#xff0c;第一反应是音乐圈门槛也这么低了&#xff0c;什么妖魔鬼怪都可以进军了嘛&#xff01;…

unity学习(77)--多玩家信息交互--不同类型的数据包

明白各个数据包的作用&#xff0c;以及是否正确的发挥作用 1.“120包”&#xff0c;客户端登录时发给服务器的&#xff0c;服务器处理后返回“121包”。 2.“121包” &#xff0c;服务器返回给客户端的&#xff0c;包含登录时所有在线玩家的信息。 客户端也通过createPlayer函…

【Android Studio3.5.2安装以及错误错误解决】

前言 下面是博主在安装Android studio时遇到的一些问题&#xff0c;并且花费很长时间寻找解决方法&#xff0c;经过了血和泪的教训下面将自己在安装过程中遇到的查看的资料贴出来&#xff08;感谢各位大佬的文章帮助本闲狗解答疑惑&#xff0c;此处贴出原文链接&#xff0c;如…

VTK 9.2.6 源码和VTK Examples 编译 Visual Studio 2022

对于编译 VTK 源码和编译详细的说明&#xff1a; VTK 源码编译&#xff1a; 下载源码&#xff1a; 从 VTK 官方网站或者 GitHub 获取源代码。官网目前最近的9.3.0有问题&#xff0c;见VTK 9.3.0 编译问题 Visual Studio 2022去gitlab上选择9.2.6分支进行clone CMake 配置&…

基于Unity+Vue3通信交互的WebGL项目发布实践

基于UnityVue3通信交互的WebGL项目发布实践 实践路线 基于UnityVue3通信交互的WebGL项目发布实践问题背景准备工作解决方案项目实践小目标搭建Unity测试项目 创建Vue3测试项目运行项目验证unity和vue通信功能总结与展望 问题背景 我们最近需要把unity开发的pc项目迁移到web端&…

Manjaro 安装全新 Linux 版微信,从此告别 Wine

目前已经基本上使用 Manjaro 来工作&#xff0c;而工作离不开微信作为日常的工作沟通工具。因为微信官方一直没有 Linux 版本的&#xff0c;所以之前都只能够使用 Wine 版本&#xff0c;然后踩了不少坑&#xff0c;但还算能勉强使用。 最近听说微信终于要发布 Linux 版本的&am…

[flink 实时流基础] flink组件栈以及任务执行与资源划分

文章目录 7. Flink组件栈1. 部署层&#xff08;1&#xff09;Local模式&#xff08;2&#xff09;Cluster模式&#xff08;3&#xff09;Cloud模式 2.运行时3.API层4. 上层工具 8. 任务执行与资源划分1. 再谈逻辑视图到物理执行图2. 任务、算子子任务与算子链3. Slot与计算资源…

YOLOv9改进策略:loss优化 | LRM loss困难样本挖掘,提升难样本、遮挡物、低对比度等检测精度

&#x1f4a1;&#x1f4a1;&#x1f4a1;本文改进内容&#xff1a;LRM loss困难样本挖掘引入到YOLOv9&#xff0c;性能优于Focal Loss &#x1f4a1;&#x1f4a1;&#x1f4a1; LRM loss应用到能够大幅提升小目标、红外小目标、大幅度提升遮挡物性能&#xff0c;性能如下图所…

【51单片机入门记录】Onewire单总线协议 温度传感器DS18B20概述

一、温度传感器DS18B20概述 &#xff08;1&#xff09;数字化温度传感器 美国DALLAS半导体公司的数字化温度传感器DS1820是世界上第一片支持“一线总线”接口的温度传感器。一线总线独特而且经济的特点&#xff0c;使用户可轻松地组建传感器网络&#xff0c;为测量系统的构建…

JSON数据的类型

JSON 代表 JavaScript Object Notation。JSON是开放的标准格式&#xff0c;由key-value对组成。JSON的主要用于在服务器与web应用之间传输数据。 PostgreSQL提供了两种存储JSON数据的类型&#xff1a;json和jsonb&#xff1b; jsonb是json的二进制形式。 json格式写入快&#x…