作业要求及项目源码
作业要求:第二周作业 - 结对编程总结
项目源码:黄金点游戏
PSP表格估计项目时间和实际时间
(由于我们没有预估时间,所以只填写了实际时间,现在再事后诸葛亮一样“估计”时间我觉得也无法做到客观)
阶段 | 预估时间(分钟) | 实际时间(分钟) |
---|---|---|
计划:明确需求和其他因素,估计以下项目需要多少时间 | N/A | 0 |
开发:包含下面8项 | N/A | 700 |
—— 需求分析 | N/A | 20 |
—— 生成设计文档 | N/A | 30 |
—— 设计复审 | N/A | 20 |
—— 代码规范 | N/A | 10 |
—— 具体设计 | N/A | 20 |
—— 具体编码 | N/A | 240 |
—— 代码复审 | N/A | 120 |
—— 测试 | N/A | 240 |
报告 | N/A | 20 |
—— 测试报告 | N/A | 0 |
—— 计算工作量 | N/A | 0 |
—— 事后总结 | N/A | 200 |
合计(分钟) | N/A | 900 |
结对编程中的接口设计
由于我们没有设计图形界面,所以也没有涉及Information Hiding, Interface Design。
重要模块接口的设计与实现过程
我们的程序很简单粗暴,核心就是利用统计学的ARIMA模型拟合前25个点,然后预测下一个点。
主要函数依次实现了以下功能:
- def data_transfer(history);把历史数据预处理一下,离上一个黄金点近的放在左边,离黄金点远的放在右边,这么做是为了防止有些队伍随机提交数字,而且打乱随机数和真实预测数据的顺序(但结果表明似乎并没有队伍提交位置顺序不同的随机数)。
- def my_ARIMA(new_history, aaa);对于历史数据中的黄金点,利用arima(p,d,q)去拟合,且令d=1,预测下一个黄金点
- def detect_random(history);对于与处理过的历史数据,判断有没有随机数,且估计出随机数中的大数的期望和概率(如一个组以0.2的概率提交99)
- def predict(info_array);利用随机数信息和ARIMA模型的预测,预测下一个黄金点的值GD,然后以0.3的概率提交一个70,随机项记为RM,另一个提交x,x满足(GD*22+RM+x)/24 * 0.618 = x,(22为其他玩家的数目)
但事实上我们没有注意这个游戏的均值其实是稳定的,因此系数不应该是0.618,而应该是一个动态的数,这个失误让我们第一轮的预测值基本都比真实值低不少。第二轮把系数改为0.997,效果有所改善。我们在测试集上修复完bug就取得了第一名,因此就没有注意到这个问题,比赛结束才发现0.618其实是一个极其关键而且需要动态调整的系数。
Design by Contract
契约式编程的核心思想是编程前每一段代码的功能被确定,他有权利和义务,权利就是可以用assert等语句确定程序等输入是合理的,而given一个合理的输入,程序要能产生正确的输出。assert语句就是contract的体现。
在我们的项目中,我负责了arima部分,队友负责了数据预处理和根据ARIMA模型的值完成预测的工作,因此我们的接口很简单,也没有涉及契约式编程的内容
程序的代码规范、设计规范。程序中的异常处理
如上所述,我和队友的交互就是他给我一个列表,我给他一个ARIMA模型的预测值,因此代码设计大部分是割裂的,我们只统一了一下交互输入和输出的具体格式(list),另外一个跟规范稍微有一点点关系的就是indent用tab,没有用4个空格,用这个是因为我们两个人的python IDE都是用tab,且tab都是4个空格长度。
程序会吐出大量的warning,拟合ARIMA模型可能会出现不收敛的问题,对此我们silence了所有warning,如果ARIMA模型拟合不收敛会尝试下一组(p, q)值。
结对过程
10.12-13:讨论涉及算法
10.14-10.15:实现算法
10.15-10.16:测试,修复bug
合作过程
我们没有选择结对编程,只是一人完成一半工作,没有人充当领航员的角色。
我和同伴的优缺点:
-
同伴的优点:
-- 代码能力强,擅长用简洁的代码实现复杂逻辑。
-- 能想到一些有趣的策略(比如交换提交的两个数)。
-- 熟练使用VS框架,擅长代码管理。 -
同伴的缺点:
-- 会在一些很小的细节上出小bug。 -
我的优点:
-- 会从别人的角度考虑问题,设计策略
-- 看代码细致,能发现一些小bug。
-- 熟悉一些统计学模型 -
我的缺点
-- 代码能力不强,编程速度比队友慢得多
如何说服队友改正缺点:
其实我和队友沟通很顺利,没有出现大的分歧。出bug的事情我会先称赞他的代码能力,然后指出小bug,建议他除了熟练使用ML框架,也要复习一下基本数据类型的操作。最后说bug解决了,我们离出结果又近了一步。
其他收获
我们的方法是基于统计和人为设计策略,而第一轮比赛第一名和第二轮比赛第一名的组都是基于强化学习的策略。最初我们没有选择强化学习是因为我们感觉数据量不够,难以完成强化学习的训练。但事实上通过一系列压缩编码和q-table更新策略,强化学习是可以在这个问题上实现在线学习的。不要人为的草率判断一个算法的可行性,也是我的一个很大的收获。
附一张工作图
附录
7,8,9涉及到图形用户界面,而我们并没有,因此没有写。