从论文公式到Python实现:用单元测试校验滑动平均算法

论文中的公式和代码经常各自正确,却没有实现同一个方法。本篇用滑动平均作为教学案例,完整展示"变量定义---公式---Python实现---正常测试---失败测试---论文解释"的核验流程。

示例不是笔匠AI接口,也不代表产品实测。对于"技术章节不知道怎样安排公式、代码和测试"的卡点,笔匠AI论文写作可以按理工科学科与学历配置任务,并将技术内容放进可编辑大纲;得到章节结构后,再用本文流程核验真实实现,最后进入初稿。

1. 环境与问题定义

运行环境:

  • Python 3.10及以上;
  • 仅使用标准库;
  • 不依赖NumPy;
  • 测试命令为 python -m unittest test_moving_average.py -v。

目标:输入长度为 n 的数列 x 和窗口 k,输出每个连续窗口的算术平均值。

当 k=3 时,第一个输出使用 x_1,x_2,x_3,第二个输出使用 x_2,x_3,x_4。输出长度应为 n-k+1。

2. 先把公式约束写完整

滑动平均可表达为:

复制代码
m_t = (1 / k) × Σ x_i
求和范围:i = t-k+1, ..., t
有效下标:t = k, ..., n

仅有公式还不够,必须补充:

  1. x_i 为数值;
  2. k 为正整数;
  3. k 不大于输入长度 n;
  4. 输入不能为空;
  5. 输出顺序与窗口移动顺序一致。

这些约束决定代码的校验分支,也是单元测试的来源。

3. Python实现

新建 moving_average.py:

复制代码
from numbers import Real


def moving_average(values: list[Real], window: int) -> list[float]:
    if not values:
        raise ValueError("values cannot be empty")
    if not isinstance(window, int) or isinstance(window, bool):
        raise TypeError("window must be an integer")
    if window <= 0:
        raise ValueError("window must be greater than 0")
    if window > len(values):
        raise ValueError("window cannot exceed input length")
    if any(not isinstance(value, Real) for value in values):
        raise TypeError("all values must be real numbers")

    return [
        sum(values[start : start + window]) / window
        for start in range(len(values) - window + 1)
    ]

切片 values[start:start+window] 对应公式中的连续求和区间,除以 window 对应 1/k。循环上界保证输出数量为 n-k+1。

4. 正常、边界与失败测试

新建 test_moving_average.py:

复制代码
import unittest

from moving_average import moving_average


class MovingAverageTests(unittest.TestCase):
    def test_normal_windows(self) -> None:
        self.assertEqual(
            moving_average([1, 2, 3, 4], 3),
            [2.0, 3.0],
        )

    def test_window_of_one(self) -> None:
        self.assertEqual(
            moving_average([1, 2], 1),
            [1.0, 2.0],
        )

    def test_window_equals_input_length(self) -> None:
        self.assertEqual(
            moving_average([2, 4, 6], 3),
            [4.0],
        )

    def test_empty_input_fails(self) -> None:
        with self.assertRaises(ValueError):
            moving_average([], 1)

    def test_zero_window_fails(self) -> None:
        with self.assertRaises(ValueError):
            moving_average([1, 2], 0)

    def test_large_window_fails(self) -> None:
        with self.assertRaises(ValueError):
            moving_average([1, 2], 3)


if __name__ == "__main__":
    unittest.main()

运行测试后,预期结果是6个测试通过。这里的"预期"需要在自己的环境中实际执行后才能写成真实结果;本文不把未运行的展示当实测。

5. 用人工计算验证正常样例

输入 [1,2,3,4],窗口 k=3:

复制代码
第一个窗口:(1+2+3)/3 = 2
第二个窗口:(2+3+4)/3 = 3
预期输出:[2.0, 3.0]

单元测试的预期值来自公式和人工计算,而不是复制函数输出。否则代码和测试可能带着同一个错误一起通过。

6. 怎样写进论文

方法章节先说明研究问题、变量、公式和约束;实现章节解释关键映射,不必粘贴全部代码;实验章节记录真实数据、环境、参数和测试结果;附录可保留完整代码或仓库说明。

如果使用笔匠AI组织技术章节,可以从论文题目或开题报告生成可编辑大纲,再把公式定义、实现位置、测试用例和预期输出分别放入方法、实现与实验章节。产品能够连接公式、代码、图表和初稿,但真实代码是否运行、数据是否有效仍需作者验证。

7. 这个示例不能证明什么

它只能证明给定实现符合本文定义的滑动平均行为,不能证明滑动平均适合某项研究,也不能证明结果具有预测、因果或实际应用价值。

如果真实研究涉及缺失值、不规则时间间隔、加权窗口、边界填充或大规模数据性能,就需要重新定义公式、增加实现分支,并补充对应测试。

结论

论文代码验证不能止于"程序能运行"。先定义公式语义和边界,再实现代码,并用独立计算得到的正常样例、边界样例和失败样例进行测试,才能说明公式和程序至少完成了同一项任务。方法变化后,还要同步更新代码、测试、图表和论文结论。

相关推荐
锋行天下6 小时前
langgraph 后端发自定义数据,前端接收方法概括
人工智能·python
benchmark_cc8 小时前
用 QuantDash 读取单只股票五档盘口:抽样、缺失值检查与复现记录
python·数据分析·pandas·量化交易·股票数据·quantdash
曲径海盗9 小时前
【Python 学习第 55 天】列表基础
python·学习笔记·编程入门
专注仿真9 小时前
知识问答模型用到的算法集详解及代码实例
python·算法·代码·大模型训练·控制算法
jyOverQ9 小时前
我写了一个 CSDN Markdown 图片助手:告别本地图片逐张上传
python·工具·csdn
罗西的思考10 小时前
【轻量化复刻大模型 / KIMI K3】AttnRes 模块交互式演示
人工智能·算法·机器学习
刘马想放假12 小时前
CANviz 使用指南|Linux 安装、DBC 解码、实时曲线与 J1939 实战
linux·python·websocket
2601_9679873713 小时前
python判断变量名不要调用任何函数实现
python·函数·语法·判断·变量名
好悬给我拽开线13 小时前
ZILOT 论文解析
算法
卷无止境14 小时前
SALib敏感性分析的python库学习笔记
后端·python