根据眼动数据的模板作为KNN聚类的中心点并因此进行数据分类

2023-11-17

from scipy.io import loadmat
import numpy as np
import matplotlib.pyplot as plt

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

实验数据采集分为两个过程,
第一个是眼动校准阶段,要求实验参与者依次观看界面上的数字 0-9,

如下图 3 所示,每个目标 1 个试次,校准阶段共 10 个试次.
所采集的数据作为参与者的模板数据,用于正式阶段的分类.

第二个是正式实验阶段,采集过程连续进行,数据中包含开始和结束的位置索引,每个目标 2 个试次,共 20 个试次.
本题任务是根据采集的眼动数据实现 10 个目标的分类

dict_calib = loadmat("本科课设数据及说明-2021/sub-data/eyedata/calib_data.mat") #校准阶段数据,也就是数据模板
print(dict_calib.keys())
dict_label = loadmat("本科课设数据及说明-2021/sub-data/eyedata/label.mat")
print(dict_label.keys())
dict_online = loadmat("本科课设数据及说明-2021/sub-data/eyedata/online.mat")
print(dict_online.keys())
dict_keys(['__header__', '__version__', '__globals__', 'Left_pre_c', 'Right_pre_c'])
dict_keys(['__header__', '__version__', '__globals__', 'label'])
dict_keys(['__header__', '__version__', '__globals__', 'Left_pre_o', 'Right_pre_o'])

利用校准阶段的眼动数据,对正式实验阶段的眼动数据进行分类,
并计算目标分类的准确率。眼动数据包括左眼和右眼两部分数据,可参见附件数据包:
calib_data.mat 文件包含
Left_pre_c、Right_pre_c; ——校准阶段预处理后的左右眼数据.
online.mat 文件包含
Left_pre_o、Right_pre_o; ——正式阶段预处理后的左右眼数据。
数据维度:试次特征维度

校准阶段的数据标签为[1 2 3 4 5 6 7 8 9 10],正式实验阶段的数据标签为 20 个 1-10 的
数值.

时域采样点
一个试次对应一个指令(即一个目标),特征维度为 X,Y 轴坐标数据,
时域采样点
为一段时间内的眼动数据。如 20,2,40 是指 20 个试次,一眼 XY 两轴坐标数据,40 个时间点.

label = dict_label['label']
label = np.concatenate((label[:,0],label[:, 1]))
label
array([ 1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 10,  9,  8,  7,  6,  5,  4,
        3,  2,  1], dtype=uint8)
  1. 计算模板数据的十个中心坐标(求所有时间点下 XY 坐标轴数据的均值)
calib_data = dict_calib['Left_pre_c']  # (10, 2, 40)
module_coordinate = np.array([(label[0].mean(),label[1].mean()) for label in calib_data])
  1. 计算正式实验阶段的实验数据与模板各类中心的欧式距离,最小距离对应索引即为目标类别
def eucldist_vectorized(modules, coord):
    """
    :param modules: 模板数据  (n,2)
    :param coord: (2)
    :return: 最小值的下标
    """
    """ Calculates the euclidean distance between 2 lists of coordinates. """
    distant = []
    for module in modules:
        distant.append( np.sqrt(np.sum((module - coord)**2)))
    distant = np.array(distant)
    label = distant.argmin()
    return label+1

Left_o, Right_o = dict_online['Left_pre_o'], dict_online['Right_pre_o']  # (20, 2, 40), (20, 2, 40)

Left_o_mean = [[label[0].mean(),label[1].mean()] for label  in Left_o] # 20,2
Right_o_mean = [[label[0].mean(),label[1].mean()] for label  in Right_o] # 20,2

def get_mix_mean(left, right):
    Mix_o_mean = []
    for value in zip(left,right):
        x_mean = np.array([value[0][0],value[1][0]]).mean()
        y_mean = np.array([value[0][1],value[1][1]]).mean()
        Mix_o_mean.append([x_mean,y_mean])

    return np.array(Mix_o_mean)
Mix_o_mean = get_mix_mean(Left_o_mean, Right_o_mean)
print(Mix_o_mean.shape)
(20, 2)

(1)求正式实验阶段目标分类的准确率,左右眼分别计算分类准确率,然后左右眼融
合计算分类准确率(各占 50%)
(2)分析不同时间点 10、20、30、40 条件下的分类准确率,并画出曲线。
(3)GUI 界面呈现校准阶段 10 个试次各自的中心位置(XY 坐标),以及正式实验阶
段 20 个试次目标分类类别,可表格呈现,包括单左眼、单右眼和左右眼融合的分类结果。
另外呈现不同时间点下的分类准确率曲线.

# 求正式实验阶段目标分类的准确率,左右眼分别计算分类准确率,然后左右眼融合计算分类准确率(各占 50%)
def calculate_acc(preds, labels):
    """

    :param preds: 预测
    :param labels: 实际
    :return: acc
    """
    assert len(preds) == len(labels)
    count = 0
    for pred, label in zip(preds,labels):
        if pred == label:
            count +=1
    acc = count / len(preds)
    return acc

pred_left = [eucldist_vectorized(module_coordinate,coord) for coord in Left_o_mean]
pred_right = [eucldist_vectorized(module_coordinate,coord) for coord in Right_o_mean]
pred_mix = [eucldist_vectorized(module_coordinate,coord) for coord in Mix_o_mean]


print(f"pred_left acc is :{calculate_acc(pred_left, label)}")
print(f"pred_right acc is :{calculate_acc(pred_right, label)}")
print(f"pred_mix acc is :{calculate_acc(pred_mix, label)}")
pred_left acc is :0.95
pred_right acc is :0.45
pred_mix acc is :0.7

(2)分析不同时间点 10、20、30、40 条件下的分类准确率,并画出曲线.

此题中不同时间点, 理解为瞬间的准确率?
此处曲线, 横坐标4个点,中坐标 acc

# 40个采样点中取  4个时间点
time = [9, 19, 29, 39] # 数组从0开始,减1
sample = []
for t in time:
    left = Left_o[:,:,t]
    right = Right_o[:,:,t]
    mix = get_mix_mean(left,right)
    sample.append([left, right, mix])
sample = np.array(sample)
print(sample.shape)  # (4, 3, 20, 2)  4 个时间点, 3中类型,20个样本,2是数据维度(坐标)

plot_data = []
# # 计算分类准确率,画出曲线
for temp in sample:
    pred_left_sample = [eucldist_vectorized(module_coordinate,coord) for coord in temp[0]]
    pred_right_sample = [eucldist_vectorized(module_coordinate,coord) for coord in temp[1]]
    pred_mix_sample = [eucldist_vectorized(module_coordinate,coord) for coord in temp[2]]
    left_acc = calculate_acc(pred_left_sample, label)
    right_acc = calculate_acc(pred_right_sample, label)
    mix_acc = calculate_acc(pred_mix_sample, label)
    plot_data.append([left_acc, right_acc, mix_acc])


plt.rcParams['font.family'] = 'SimHei'
plot_data = np.array(plot_data)
plt.plot(plot_data[:,0], color = 'yellow', label='Left acc' )
plt.plot(plot_data[:,1], color = 'blue', label='Right acc' )
plt.plot(plot_data[:,2], color = 'red', label='Mix acc' )
plt.legend(loc='upper right')
plt.xlabel("4个采样点")
plt.ylabel(" Accuracy")
plt.show()
(4, 3, 20, 2)

在这里插入图片描述

(3)GUI 界面呈现校准阶段 10 个试次各自的中心位置(XY 坐标),以及正式实验阶
段 20 个试次目标分类类别,可表格呈现,包括单左眼、单右眼和左右眼融合的分类结果。
另外呈现不同时间点下的分类准确率曲线.

# 校准的中心位置
print(Mix_o_mean.shape)
print(Mix_o_mean)
(20, 2)
[[0.35302685 0.61259491]
 [0.45273939 0.62760038]
 [0.51697524 0.62021255]
 [0.52222001 0.62713213]
 [0.36040243 0.47567411]
 [0.42068609 0.48298781]
 [0.48002522 0.49755144]
 [0.53585174 0.50573368]
 [0.57450059 0.49090094]
 [0.64409662 0.49662821]
 [0.63488904 0.4763542 ]
 [0.58628343 0.46553476]
 [0.54330032 0.47620673]
 [0.481635   0.47012699]
 [0.41486268 0.46960786]
 [0.14540334 0.39104608]
 [0.52493566 0.62729682]
 [0.51115335 0.58661289]
 [0.46328944 0.55657719]
 [0.30149007 0.63653916]]
# 正式实验阶段 20 个试次目标分类类别
print("实际的标签", label)
print("单左眼的分类结果:",pred_left)
print("单右眼的分类结果:",pred_right)
print("左右眼融合的分类结果:",pred_mix)
实际的标签 [ 1  2  3  4  5  6  7  8  9 10 10  9  8  7  6  5  4  3  2  1]
单左眼的分类结果: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 9, 8, 7, 6, 5, 4, 3, 7, 1]
单右眼的分类结果: [1, 2, 3, 3, 6, 7, 8, 9, 9, 10, 10, 10, 9, 8, 7, 5, 3, 3, 3, 1]
左右眼融合的分类结果: [1, 2, 3, 3, 5, 6, 8, 8, 9, 10, 10, 9, 9, 8, 6, 5, 3, 3, 3, 1]

附加的, 完全按照 K 均值的方法进行无监督聚类.

knn_left = Left_o.transpose(1,0,2).reshape(-1,2)
knn_right = Right_o.transpose(1, 0, 2).reshape(-1,2)
knn_mix = []
for value in zip (knn_left,knn_right):
    temp = (value[0][0]+value[1][0]/2,value[0][1]+value[1][1]/2)
    knn_mix.append(temp)
knn_mix = np.array(knn_mix)
knn_mix.shape
(800, 2)
from sklearn.model_selection import train_test_split
from sklearn.cluster import KMeans

cluster = KMeans(n_clusters=10, random_state=0).fit(knn_left)
y_pred = cluster.labels_  # 查看聚好的类
centroid = cluster.cluster_centers_  # 查看质心坐标
print("查看质心坐标:\n",centroid)

inertia = cluster.inertia_  # 查看总距离平方和
print("查看总距离平方和\n",inertia)


def euc(modules, coord):
    """
    :param modules: 模板数据  (n,2)
    :param coord: (2)
    :return: 最小值的下标
    """
    """ Calculates the euclidean distance between 2 lists of coordinates. """
    distant = []
    for module in modules:
        distant.append( np.sqrt(np.sum((module - coord)**2)))
    distant = np.array(distant)

    return distant
print("knn 自聚类的质心坐标与模板中心K均值聚类的欧式距离:\n",euc(centroid,Mix_o_mean))
查看质心坐标:
 [[0.61597146 0.61585092]
 [0.44917144 0.44920044]
 [0.33769204 0.33765738]
 [0.10968668 0.10885209]
 [0.5158853  0.51584852]
 [0.38981738 0.38988691]
 [0.56668034 0.56680314]
 [0.48144118 0.48129547]
 [0.22980181 0.22962997]
 [0.63404646 0.63406013]]
查看总距离平方和
 0.09544180417750626
knn 自聚类的质心坐标与模板中心K均值聚类的欧式距离:
 [0.96247278 0.71574271 1.21515049 2.56087015 0.64113659 0.9494539
 0.75684214 0.64744206 1.83248692 1.05137818]
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

根据眼动数据的模板作为KNN聚类的中心点并因此进行数据分类 的相关文章

随机推荐

  • Java实现CSV读写

    在开发过程中经常需要处理csv文件 我一般是实现一个CSVHelper 封装一些对csv文件的基本操作 代码中直接使用封装好的CSVHelper来读写csv文件就可以了 今天就来记录一下如何通过Java实现封装的csv文件的读写 对于C 实
  • 弱网测试

    来自 https www cnblogs com linxiu 0925 p 9412190 html 什么是弱网测试 弱网测试主要在宽带 丢包 延时的弱网环境中 验证客户端的展示 以及丢包 延时的处理机制 属于健壮性测试的内容 比如弱网下
  • STM32移植U8g2图形库——玩转OLED显示

    之前的文章 介绍过ESP8266在Arduino IDE环境中使用U8g2库 实现OLED上的各种图形显示 本篇 介绍一下U8g2库如何移植到STM32上 进行OLED的图形显示 本次的实验硬件为 STM32 型号为最常见的STM32F10
  • 前事不忘,后事之师——基于相似性进行剩余有效寿命预测的案例讲解

    在上一篇文章中我们讲到了三种机电产品算命方法 相似模型法 退化模型法和生存模型法 这一篇我们将使用相似模型法构建完整的剩余使用寿命 RUL 估计工作流程 该案例来自MATLAB的Similarity Based Remaining Usef
  • JavaScript设计模式(三)——单例模式、装饰器模式、适配器模式

    个人简介 个人主页 前端杂货铺 学习方向 主攻前端方向 正逐渐往全干发展 个人状态 研发工程师 现效力于中国工业软件事业 人生格言 积跬步至千里 积小流成江海 推荐学习 前端面试宝典 Vue2 Vue3 Vue2 3项目实战 Node js
  • SpringBoot快速入门

    SpringBoot快速入门 1 SpringBoot简介 SpringBoot概述 SpringBoot起步依赖 SpringBoot程序启动 入门案例 SpringBoot项目快速启动 2 基础配置 自动提示功能消失解决方案 yaml语
  • docker创建多个mysql集群_Docker在一台服务器上安装和配置Mysql集群

    1 从docker hub下载mysql5 6的镜像 docker pull mysql 5 6 2 使用mysql5 6镜像运行4台mysql服务 用端口号区分 前期准备工作 在本机创建四个目录 分别用了存储4台mysql服务的数据 日志
  • Windows服务器管理(运维)——cmd命令大全

    1 文件和目录操作命令 cd 更改当前目录 dir 列出当前目录中的文件和文件夹 mkdir 创建一个新的文件夹 rmdir 删除一个空的文件夹 copy 复制文件或文件夹 del 删除文件 ren 重命名文件或文件夹 move 移动文件或
  • angular html原理,Angular 4.x ngModel 双向绑定原理揭秘

    在 Angular 4 x 中对于使用 Template Driven 表单场景 如果需要实现表单数据绑定 我们就需要引入 ngModel 指令 该指令用于基于 domain 模型 创建 FormControl 实例 并将创建的实例绑定到表
  • java日志级别

    java中日志级别有7 个级别 severe Warning info config fine finer finest 默认情况只记录前三个级别 另外可以使用Level ALL开启所有的级别记录 或者使用Level OFF关闭所有的级别记
  • android动静态申请IMEI或其他特殊权限(适配11)

    报错原因 今天又是撸代码的一天 人生第一个项目上架闪退被打回 很难受 打开就闪退 后面才恍然大悟 打开APP默认申请获取手机IMEI 测试用的手机被我手动打开了权限 所以一直没有注意这个问题 果然 log报错 java lang Secur
  • pjsip的一个qt写的demo

    msvc版本编译的pjsip的demo 有源码 也有可直接运行的包 本程序解决了pjsip双方互相同时呼叫时会出现的问题 目前只是用来呼叫接听的demo 没有做流媒体传输 https download csdn net download q
  • 【C语言】使用C语言实现静态、动态的通讯录(简单易懂)

    我们在学习结构体之后 就可以尝试去实现通讯录的制作 如果您这边对于结构体还没有太多的认识的话 请先访问这一篇文章 会有利于接下来的学习 自定义类型 带你走进结构体 枚举 联合 小王学代码的博客 CSDN博客 目录 一 通讯录 二 静态通讯录
  • Java自增和自减运算符(++和--)

    在对一个变量做加 1 或减 1 处理时 可以使用自增运算符 或自减运算 或 是单目运算符 放在操作数的前面或后面都是允许的 与 的作用是使变量的值增 1 或减 1 操作数必须是一个整型或浮点型变量 自增 自减运算的含义及其使用实例如表 1
  • Flutter实现倒计时功能,秒数转时分秒,然后倒计时

    Flutter实现倒计时功能 发布时间 2023 05 12 本文实例为大家分享了Flutter实现倒计时功能的具体代码 供大家参考 具体内容如下 有一个需求 需要在页面进行显示倒计时 倒计时结束后 做相应的逻辑处理 实现思路 在Flutt
  • 牛客中等难度3

    HJ70 矩阵乘法计算量估算 描述 矩阵乘法的运算量与矩阵乘法的顺序强相关 例如 A是一个50 10的矩阵 B是10 20的矩阵 C是20 5的矩阵 计算A B C有两种顺序 AB C 或者 A BC 前者需要计算15000次乘法 后者只需
  • 异常处理包装技术

    异常大致可分为两种 受检查异常和非受检查异常 受检查异常是在编译期间就可以检查到的 非受检查异常又分为error和RuntimeException 非受检查异常是可控的 可以人为操作修改的 一般我们针对业务异常 非受检查异常 进行处理 会继
  • 鸿蒙系统是否可以用来做服务器,小米手机也能使用鸿蒙系统?国内厂商使用鸿蒙热情高涨...

    原标题 小米手机也能使用鸿蒙系统 国内厂商使用鸿蒙热情高涨 自从6月2日HarmonyOS 2正式发布以来 国内针对鸿蒙系统的热议一直不减 对于新买的华为手机用户来说 能第一批次使用上国产的手机系统 也确实过了一把瘾 本次手机系统更新 华为
  • Android蓝牙开发教程(三)——蓝牙设备相互通讯

    在上一篇中已经介绍如何连接我们搜索到的蓝牙设备 如果你还没阅读过 建议先看看上一篇文章Android蓝牙开发教程 二 连接蓝牙设备 在上一篇文章中 无论是自动连接还是被动连接 连接成功后 都是将获取到的BluetoothSocket交由连接
  • 根据眼动数据的模板作为KNN聚类的中心点并因此进行数据分类

    from scipy io import loadmat import numpy as np import matplotlib pyplot as plt 实验数据采集分为两个过程 第一个是眼动校准阶段 要求实验参与者依次观看界面上的数