谷歌SEO

谷歌SEO

Products

当前位置:首页 > 谷歌SEO >

贝叶斯算法真的适合按键动作模式识别吗?

96SEO 2026-02-23 15:04 14


none">基于朴素贝叶斯对按键动作进行模式识别的一次学习实验

贝叶斯算法真的适合按键动作模式识别吗?

之前学习了贝叶斯更新的相关内容,正好现在也在玩开发板,板子上面有几个小的单击按键,一般识别按键动作的做法就很简单,不是中断就是查询,基本都是靠边沿或者电平的状态来进行的,这一套就很无聊,没有实现的欲望,所以想用点不一样的方法。

这就有了本片文章的出现,基于朴素贝叶斯分类,使用滑动窗口捕捉电平序列,提取特征进行模式识别,理想情况下识别效果杠杠的,但是出现边界以及混合的情况,效果一言难尽,目前水平不够,这应该也是后续需要解决的主要问题了。

本文实现的方法基于朴素贝叶斯分类器,主要就是两方面内容:贝叶斯定理条件独立假设,涉及的概念有先验概率后验概率条件概率,其中先验和条件概率都是提前准备好的,可以是主观经验的,也可以是统计量化的,而贝叶斯定理中的条件概率(不是后验概率),又称为似然概率。

这个方法的基本思想是:对于给定的待分类项(就是窗口中的电平序列),求解当这个待分类项出现时,各个已经定义过的模式类别出现的概率,哪个概率最大,那么这个待分类项就属于哪个模式。

  • 定义有哪些模式类别,这些模式边界要明确,不然不容易分析特征
  • 定义这些模式的特征属性,这些属性在不同模式下的表现是不同的,这是识别的关键,对应了贝叶斯定理中的似然概率
  • 这里的窗口是实时更新的窗口,老数据移出,新数据加入,滑动窗口确定电平序列数据的范围,只有处在窗口中的序列数据才会得到特征提取的机会,它的长度与序列的时间长度成比例,也就是说采样频率会影响到窗口时效性。

    它需要考虑的问题是怎么捕捉到完整的信号,对应于滑动的步长,以及特征提取的周期。

  • 滑动窗口采集:使用固定大小的滑动窗口持续采集按键状态数据
  • 特征提取:从窗口数据中提取多个维度的特征
  • 概率计算:基于先验概率和似然概率计算后验概率
  • 模式判断:根据后验概率和阈值确定当前按键模式
  • 为了验证设想的可行性,通过逻辑分析仪记录按键的引脚电平变化,低电平表示按键按下,高电平表示无按键动作,采样率1MHz,时长20s,在后面的实验中,认为序列是连续的,这就是电平序列的来源,具体序列如下图所示:

    data-src="https://fastly.jsdelivr.net/gh/bucketio/img14@main/2026/02/17/1771293682747-d81c3402-eb3d-4b28-adba-763adf4d2ca0.png"

    上面记录的数据可以作为一个样本,我通过观察和测量确定了几种模式,以及一些帮助识别的特征属性,在实验过程中使用python进行了方法验证。

  • 无效:无有效按键动作
  • 单击:单次短暂按键动作
  • 双击:快速连续两次按键动作
  • 长按:持续时间较长的按键动作
  • 动作的实施都是通过一个单按键来进行的,其中单击和双击涉及到电平的较快速变化,是识别的难点

  • 高电平占比:窗口内高电平信号的比例
  • 上升沿数量:信号从低到高的转换次数
  • 下降沿数量:信号从高到低的转换次数
  • 最长连续高电平持续时间:窗口内持续高电平的最长时间
  • 先验概率:初始假设四种模式等概率出现,即每个模式的先验都是0.25。

    并且和一般的贝叶斯方法不同的是,在实现过程中认为先验是不需要更新的,也就是在每一次识别时认为每个模式都是等概率出现的,没有转移概率或者历史因素影响

  • 似然概率:基于特征分布参数计算观测到当前特征的概率,其中的分布参数是根据实际捕捉的序列数据来设计的,概率分布模型采用正态分布来近似,需要均值和标准差,统一使用概率密度表达似然结果

    • 后验概率:使用贝叶斯公式计算各模式的后验概率,先计算提取的特征在每个模式下的联合似然,基于条件独立假设,可以直接相乘,然后计算后验并归一化可得最终的概率表
    • 把逻辑分析仪中的数据导出为csv文件,代码首先实现了 read_sigrok_csv_simple 函数,用于读取

      sigrok

      class="language-python">def read_sigrok_csv_simple(filename):    time_data = []

          signal_data = []    with open(filename, 'r', newline='') as csvfile:        reader = csv.reader(csvfile)        for row in reader:            # 跳过注释行和空行            if not row or row[0].startswith(';'):                continue            # 确保行有两个列            if len(row) >= 2:                try:                    time_val = float(row[0])                    data_val = float(row[1])                    time_data.append(time_val)                    signal_data.append(data_val)                except ValueError:                    # 跳过无法转换为数字的行                    continue    return time_data, signal_data

      文件中的时间戳和信号值,返回两个列表分别存储时间数据和信号数据,通过plot输出采样的数据图如下所示:

      data-src="https://fastly.jsdelivr.net/gh/bucketio/img0@main/2026/02/17/1771293729251-6f4bcd36-9a3b-40e6-beb1-e25327a680c4.png"

      核心实现是 BayesianButtonRecognizer 类,用于实现基于贝叶斯分类的按键模式识别:

      class="language-python">class BayesianButtonRecognizer:    """基于滑动窗口和贝叶斯更新的按键模式识别器"""    def __init__(self, window_size=20, sample_interval=0.01,     threshold=0.7):        """        初始化识别器        Args:            window_size: 滑动窗口大小            sample_interval: 采样间隔(秒)            threshold: 判定阈值        """        self.window_size = window_size        self.sample_interval = sample_interval        self.threshold = threshold        # 滑动窗口存储最近的观测序列        self.window = deque(maxlen=window_size)        # 模式类别        self.modes = ['无效', '单击', '双击', '长按']        # 先验概率 - 初始等可能        self.prior = np.array([0.25, 0.25, 0.25, 0.25])        # 特征提取相关的参数(单位:采样点数)        self.short_press_max = 15  # 短按最大持续时间        self.long_press_min = 30    # 长按最小持续时间          self.double_click_interval = 10  # 双击间隔阈值        # 初始化特征分布参数(基于物理理解预设)        self._init_feature_distributions()        # 特征权重        self.featwight={            "无效":np.array([1.2,0.8,0.8,1.2]),            "单击":np.array([1,1.2,1.2,1]),            "双击":np.array([1,1.2,1.2,0.8]),            "长按":np.array([1.2,0.8,0.8,1.2])        }

      识别器初始化时设置了各模式下特征的概率分布参数:

      class="language-python">def _init_feature_distributions(self):    """初始化各模式下特征的概率分布参数"""    # 高电平占比的分布参数    self.high_ratio_params = {        '无效': 0.05,   # 无效时高电平占比很低        '单击': 0.2,    # 单击时有短暂高电平        '双击': 0.3,    # 双击时高电平占比稍高        '长按': 0.9     # 长按时高电平占比很高    }    # 上升沿数量的分布参数    self.rise_count_params = {        '无效': 0.1,    # 无效时几乎无上升沿        '单击': 1,    # 单击时有1个上升沿        '双击': 2,    # 双击时有2个上升沿          '长按': 0.7     # 长按有1个上升沿    }    # 最长高电平持续时间的分布参数(正态分布:均值,标准差)    self.max_duration_params = {        '无效': (0, 2),     # 无效时持续时间很短        '单击': (0.2, 5),     # 单击中等持续时间        '双击': (0.17, 3),     # 双击每次按下时间短        '长按': (0.9, 10)    # 长按持续时间长    }

      从滑动窗口数据中提取特征,其中高电平占比是通过求序列平均值来获得的,然后边沿计数对应了记录序列跳变数量,最长高电平时间通过记录连续高电平时长获取:

      class="language-python">def extract_features(self, window_data):    """从滑动窗口数据中提取特征"""    if len(window_data) == 0:        return None    data = np.array(window_data)    # 特征1: 高电平占比    high_ratio = np.mean(data)    # 特征2: 上升沿数量(0->1的变化)    rises = 0    for i in range(1, len(data)):        if data[i-1] == 0 and data[i] == 1:            rises += 1    # 特征3: 下降沿数量(1->0的变化)    falls = 0    for i in range(1, len(data)):        if data[i-1] == 1 and data[i] == 0:            falls += 1    # 特征4: 最长连续高电平持续时间    max_duration = 0    current_duration = 0    for val in data:        if val == 1:            current_duration += 1            max_duration = max(max_duration, current_duration)        else:            current_duration = 0    return {        'high_ratio': high_ratio,        'rise_count': rises,         'fall_count': falls,        'max_duration': max_duration    }

      计算给定模式下观测到特征值的似然概率,即条件概率,通过上面定义的分布参数,使用正态分布近似,在python中通过stats.norm.pdf求特征对应每个模式的似然程度,然后基于条件独立的假设,求解联合似然,表示样本对某一模式的最终似然结果:

      class="language-python">def calculate_likelihood(self, features, mode):    """计算给定模式下观测到特征值的似然概率"""    if features is None:        return 1.0  # 无特征时返回中性似然    # 使用概率密度函数计算各特征的似然    likelihoods = []    # 1. 高电平占比的似然    target_ratio = self.high_ratio_params[mode]    # 使用正态分布近似, 标准差根据经验设定    like_ratio = stats.norm.pdf(features['high_ratio'],                               target_ratio, 0.2)    likelihoods.append(like_ratio + 1e-10)  # 避免零    # 2. 上升沿数量的似然    target_rises = self.rise_count_params[mode]    like_rises = stats.norm.pdf(features['rise_count'],     target_rises,0.3)    likelihoods.append(like_rises + 1e-10)    # 3. 下降沿(同上升沿)数量的似然    target_falls = self.rise_count_params[mode]    like_falls = stats.norm.pdf(features['fall_count'],     target_falls,0.3)    likelihoods.append(like_falls + 1e-10)    # 4. 最长持续时间的似然(使用正态分布)    target_dur, std_dur = self.max_duration_params[mode]    target_dur *= self.window_size    like_duration = stats.norm.pdf(features['max_duration'],                                  target_dur, std_dur)    likelihoods.append(like_duration + 1e-10)    # 组合各特征的似然(假设特征条件独立)    total_likelihood = np.prod(np.array(likelihoods))    print("特征在mode[%s]的似然:"%{mode},likelihoods,"最终联合似然:%.    3f"%total_likelihood)    return total_likelihood

      class="language-python">def slide_window(self,io_state):    # 移除最旧的值    self.window.popleft()    # 将新观测值加入滑动窗口    self.window.append(io_state)

      计算完样本对每个模式的似然后,就于先验概率相乘,就得到了后验概率,然后归一化得到最终结果,同时使用阈值判定机制,当最大后验超过判定阈值后,才会识别具体模式,否则就是不确定

      class="language-python">def update_belief(self, io_state):    """根据新观测值更新信念"""    # 提取当前窗口的特征    features = self.extract_features(self.window)    print("特征提取:",features)    # 计算各模式的似然    likelihoods = np.array([self.calculate_likelihood(features,     mode)                           for mode in self.modes])    # 贝叶斯更新: 后验 ∝ 似然 × 先验    unnormalized_posterior = likelihoods * self.prior    evidence = np.sum(unnormalized_posterior)    if evidence > 0:        posterior = unnormalized_posterior / evidence    else:        posterior = self.prior.copy()    # 更新先验(用于下一次迭代)    # self.prior = posterior    # 判断当前模式    best_mode_idx = np.argmax(posterior)    best_prob = posterior[best_mode_idx]    print("后验:",posterior)    if best_prob > self.threshold:        detected_mode = self.modes[best_mode_idx]    else:        detected_mode = '不确定'    return detected_mode, posterior

      因为定义了高电平为有效电平,但实际中低电平,或者说下降沿是按键动作的反应,所以处理数据序列时做了相应的取反处理。

      class="language-python">if __name__ == "__main__":    DeltaT = 0.01

      采样间隔    UnitTime = 1e-06

      原始数据点的时基    SampleInterval = math.floor(DeltaT / UnitTime)    filename = "key_data_20s_all.csv"  # 逻辑分析仪导出的数据    recognizer = BayesianButtonRecognizer(window_size=100,     threshold=0.8)    recognizer.reset()    time_data, signal_data = read_sigrok_csv_simple(filename)    print(f"成功读取数据,共 {len(time_data)} 个数据点")    print(f"时间范围: {time_data[0]}s 到 {time_data[-1]}s")    plt.figure(1)    sample_data = []    res_data = []    sample_num = math.floor(len(signal_data) / SampleInterval)    print("sample size is:",sample_num)    for i in range(sample_num-1):        sample_data.append(int(not signal_data[SampleInterval*i]))        recognizer.slide_window(int(not signal_data        [SampleInterval*i]))        if i%recognizer.window_size==0:            res,postrior=recognizer.update_belief(i)            if(res not in["不确定","无效"]):                res_data.append(res)            print("win[%d]:"%i,res)            plt.plot(recognizer.window)            plt.show()    plt.figure(1)    plt.plot(sample_data)    plt.show()    print(res_data)

      data-src="https://fastly.jsdelivr.net/gh/bucketio/img16@main/2026/02/17/1771293783552-374386fd-51ad-4ecc-90cb-c38b2aa5a203.png"

      上图是一个无效按键样本序列图,保持无效电平,没有边沿变化。

      下图给出了识别的过程和结果:

      data-src="https://fastly.jsdelivr.net/gh/bucketio/img13@main/2026/02/17/1771293803151-94e9e91f-21ff-4ccc-995a-e4dee84ed04b.png"

      可以看到特征提取的信息是正确的,高电平占比为0,边沿计数为0,最长高电平延时为0,在各个模式的似然列表中,给出了对应的似然结果,同时从列数据对比来看,也可以直接从数值上看出样本特征更偏向哪个模式,最终的后验结果,确实是无效模式的概率最高,即判定窗口中的序列为无效。

      单击样本示例:

      data-src="https://fastly.jsdelivr.net/gh/bucketio/img12@main/2026/02/17/1771293891198-b35c3126-6cdb-4e0c-aa8d-866bb50f0abb.png"

      上图是一个单击按键样本序列图,有边沿变化,一个上升沿,一个下降沿,高电平占比大约0.2。

      下图给出了识别的过程和结果:

      data-src="https://fastly.jsdelivr.net/gh/bucketio/img18@main/2026/02/17/1771293913887-243f48a3-b10e-4539-a556-b64928912fe1.png"

      可以看到特征提取的信息是正确的,最终的识别结果也是正确的

      双击样本示例:

      data-src="https://fastly.jsdelivr.net/gh/bucketio/img1@main/2026/02/17/1771293929485-ba56eac4-b956-455e-91a9-60a337f17f6d.png"

      上图是一个双击样本的示例图,可以看到由两个高电平组成,下图给出识别过程和结果:

      data-src="https://fastly.jsdelivr.net/gh/bucketio/img1@main/2026/02/17/1771293960527-ad7cc398-d923-41ef-8d6f-ad712670b32d.png"

      可以看出特征提取信息正确,有两个上升沿和两个下降沿,然后最终的后验概率中也是双击的概率最大,并且超过阈值判定正确。

      边界双击情况示例:

      data-src="https://fastly.jsdelivr.net/gh/bucketio/img16@main/2026/02/17/1771293978238-9f37d07c-3bc9-4da7-9aa1-b1e750afd69f.png"

      上图中可以看出很明显是一个双击的动作,但是由于窗口长度固定的原因,导致一部分序列缺失,下图给出识别结果:

      data-src="https://fastly.jsdelivr.net/gh/bucketio/img13@main/2026/02/17/1771293991565-251bfdcd-4f0c-4384-bad2-ec45caef56a4.png"

      特征提取的信息倒是正确的,识别出下降沿只有1个,在计算似然过程中,相应位置的似然结果也反应了这一点,最终的后验表中可以看到前两个大的概率是单击和双击,但是都没超过阈值,所以判定为不确定

      边界单击情况示例:

      data-src="https://fastly.jsdelivr.net/gh/bucketio/img11@main/2026/02/17/1771294007027-42bf15d6-a5f4-439c-9b7e-9373e29bb1e6.png"

      可以看出这个情况像是单击,但是实际上是一段长按序列,下图给出识别过程:

      data-src="https://fastly.jsdelivr.net/gh/bucketio/img11@main/2026/02/17/1771294043631-9760e86e-65e2-4318-ba9a-a81f8662083f.png"

      特征信息提取是正确的,然后似然结果都偏低,表示不偏向某一个模式,但在最终的后验结果中单击的后验概率异常的高,应该是在归一化过程中,单击概率占比比其他概率大很多导致的,这也是同样的问题,也就是信号完整性缺失导致了误判

      在这次实验中,基于朴素贝叶斯分类方法,通过滑动窗口采集数据、提取多维度特征、计算概率分布和应用贝叶斯更新,学到了不少,也融合了很多内容,算是一次不小的学习体验吧,虽然目前测试下来效果有限,还无法真正用在项目中,也总结了一些不足的地方。

      比如信号完整性保证不了,不同特征属性对不同模式的权重实际并不一致等,这些都是需要解决的问题,虽然对现在的我来说很困难,但探索新方法的过程还是蛮喜欢的,也可能是对现有方法的审美疲劳导致的吧。

      但有一说一,传统的方法,还是简单高效的,也不涉及到什么数学的内容,全凭逻辑加判断就可以搞定了,真是省时省力啊。

      role="contentinfo">

      本文来自博客园,作者:pie_thn,转载请注明原文链接:https://www.cnblogs.com/pie-o/p/19622890

      class="post-meta-container">


      标签: 这也行?按键动作模式识别也能用贝叶斯?

      SEO优化服务概述

      作为专业的SEO优化服务提供商,我们致力于通过科学、系统的搜索引擎优化策略,帮助企业在百度、Google等搜索引擎中获得更高的排名和流量。我们的服务涵盖网站结构优化、内容优化、技术SEO和链接建设等多个维度。

      百度官方合作伙伴 白帽SEO技术 数据驱动优化 效果长期稳定

      SEO优化核心服务

      网站技术SEO

      • 网站结构优化 - 提升网站爬虫可访问性
      • 页面速度优化 - 缩短加载时间,提高用户体验
      • 移动端适配 - 确保移动设备友好性
      • HTTPS安全协议 - 提升网站安全性与信任度
      • 结构化数据标记 - 增强搜索结果显示效果

      内容优化服务

      • 关键词研究与布局 - 精准定位目标关键词
      • 高质量内容创作 - 原创、专业、有价值的内容
      • Meta标签优化 - 提升点击率和相关性
      • 内容更新策略 - 保持网站内容新鲜度
      • 多媒体内容优化 - 图片、视频SEO优化

      外链建设策略

      • 高质量外链获取 - 权威网站链接建设
      • 品牌提及监控 - 追踪品牌在线曝光
      • 行业目录提交 - 提升网站基础权威
      • 社交媒体整合 - 增强内容传播力
      • 链接质量分析 - 避免低质量链接风险

      SEO服务方案对比

      服务项目 基础套餐 标准套餐 高级定制
      关键词优化数量 10-20个核心词 30-50个核心词+长尾词 80-150个全方位覆盖
      内容优化 基础页面优化 全站内容优化+每月5篇原创 个性化内容策略+每月15篇原创
      技术SEO 基本技术检查 全面技术优化+移动适配 深度技术重构+性能优化
      外链建设 每月5-10条 每月20-30条高质量外链 每月50+条多渠道外链
      数据报告 月度基础报告 双周详细报告+分析 每周深度报告+策略调整
      效果保障 3-6个月见效 2-4个月见效 1-3个月快速见效

      SEO优化实施流程

      我们的SEO优化服务遵循科学严谨的流程,确保每一步都基于数据分析和行业最佳实践:

      1

      网站诊断分析

      全面检测网站技术问题、内容质量、竞争对手情况,制定个性化优化方案。

      2

      关键词策略制定

      基于用户搜索意图和商业目标,制定全面的关键词矩阵和布局策略。

      3

      技术优化实施

      解决网站技术问题,优化网站结构,提升页面速度和移动端体验。

      4

      内容优化建设

      创作高质量原创内容,优化现有页面,建立内容更新机制。

      5

      外链建设推广

      获取高质量外部链接,建立品牌在线影响力,提升网站权威度。

      6

      数据监控调整

      持续监控排名、流量和转化数据,根据效果调整优化策略。

      SEO优化常见问题

      SEO优化一般需要多长时间才能看到效果?
      SEO是一个渐进的过程,通常需要3-6个月才能看到明显效果。具体时间取决于网站现状、竞争程度和优化强度。我们的标准套餐一般在2-4个月内开始显现效果,高级定制方案可能在1-3个月内就能看到初步成果。
      你们使用白帽SEO技术还是黑帽技术?
      我们始终坚持使用白帽SEO技术,遵循搜索引擎的官方指南。我们的优化策略注重长期效果和可持续性,绝不使用任何可能导致网站被惩罚的违规手段。作为百度官方合作伙伴,我们承诺提供安全、合规的SEO服务。
      SEO优化后效果能持续多久?
      通过我们的白帽SEO策略获得的排名和流量具有长期稳定性。一旦网站达到理想排名,只需适当的维护和更新,效果可以持续数年。我们提供优化后维护服务,确保您的网站长期保持竞争优势。
      你们提供SEO优化效果保障吗?
      我们提供基于数据的SEO效果承诺。根据服务套餐不同,我们承诺在约定时间内将核心关键词优化到指定排名位置,或实现约定的自然流量增长目标。所有承诺都会在服务合同中明确约定,并提供详细的KPI衡量标准。

      SEO优化效果数据

      基于我们服务的客户数据统计,平均优化效果如下:

      +85%
      自然搜索流量提升
      +120%
      关键词排名数量
      +60%
      网站转化率提升
      3-6月
      平均见效周期

      行业案例 - 制造业

      • 优化前:日均自然流量120,核心词无排名
      • 优化6个月后:日均自然流量950,15个核心词首页排名
      • 效果提升:流量增长692%,询盘量增加320%

      行业案例 - 电商

      • 优化前:月均自然订单50单,转化率1.2%
      • 优化4个月后:月均自然订单210单,转化率2.8%
      • 效果提升:订单增长320%,转化率提升133%

      行业案例 - 教育

      • 优化前:月均咨询量35个,主要依赖付费广告
      • 优化5个月后:月均咨询量180个,自然流量占比65%
      • 效果提升:咨询量增长414%,营销成本降低57%

      为什么选择我们的SEO服务

      专业团队

      • 10年以上SEO经验专家带队
      • 百度、Google认证工程师
      • 内容创作、技术开发、数据分析多领域团队
      • 持续培训保持技术领先

      数据驱动

      • 自主研发SEO分析工具
      • 实时排名监控系统
      • 竞争对手深度分析
      • 效果可视化报告

      透明合作

      • 清晰的服务内容和价格
      • 定期进展汇报和沟通
      • 效果数据实时可查
      • 灵活的合同条款

      我们的SEO服务理念

      我们坚信,真正的SEO优化不仅仅是追求排名,而是通过提供优质内容、优化用户体验、建立网站权威,最终实现可持续的业务增长。我们的目标是与客户建立长期合作关系,共同成长。

      提交需求或反馈

      Demand feedback