引子
深度学习的研究,调参是躲不开的话题,动辄几天甚至几周的训练暂且不表,很多时候,我们遇到的模型跑完一次训练只需要十几分钟,刚开始“炼丹”可能会热血冲头,非要等到结果出来,一看不好就立刻调参再炼一轮。但是这样做首先是很没效率的,其次也很不系统,容易让代码越改越乱,实验结果也越来越难以回顾(别问我怎么知道的。
自动训练脚本,就是设计好之后自动枚举各个参数进行训练并且保存实验结果的代码。这样的技术其实很容易实现,不过笔者这里更想分享自动化训练意识。
自动化训练的好处。一来,程序员的浪漫不就是让代码简化我们的工作,避免重复劳动吗!二来,这样的方式会迫使你提前规划好所有超参数的位置,以及可能的值,从而加深你对网络架构的理解。三来,自动化训练更容易估计时间,且不必每次训练结束后手动调参,效率更高。四来,自动化训练可以通过代码进行简单的数据分析和可视化,实验结果更直观。
本文真的不是什么硬核技术贴,更多是为了分享这样的训练方式。因而只简单介绍两种方式,以及实现上的核心部分(这些方式其实内部也有些小坑,笔者改进后会更新的。至于为什么是“其一”呢?我相信肯定有更多的更好的自动化训练技术的,可以后来填坑,小伙伴们如果愿意分享也可以在评论区留言。
通过python代码实现
- 将模型封装到一个函数中,每次训练前通过参数列表传入超参数的值,返回特定的网络
def getModel(hyperparameters):
"""参数是超参数列表,返回模型"""
# 生成一个网络
return model
- 在主程序中循环进行训练,每次训练前调用getModel获取新的模型
if __name__ == "__main__":
for hyperparameter1 in [1, 0.1, 0.01]:
model = getModel()
model.train()
- 可以在模型训练结束时保存模型参数,方便复现。这时超参数的取值正好可以作为命名的一部分用来区分。
'model_{}_{}.h5'.format(hyperparameter1, hyperparameter2)
- 收集到的结果也可以分类存储到不同的列表中,在全部训练结束后进行集中打印。
通过.sh脚本实现
.sh脚本是linux系统的脚本,相信很多小伙伴都是在实验室的服务器上进行实验的,因而介绍.sh脚本,实际上windows的脚本也是一样的做法。
这种方法的思路是通过shell脚本执行预先写进去的python命令行指令,实现这种方式首先需要了解命令行向python程序传参的方式,以及shell的简单用法。
- python传参,直接看实例
#/usr/bin/python
import sys
print sys.argv[0]
print sys.argv[1]
print sys.argv[2]
print sys.argv[3]
执行指令:python argv.py 1 2 3
输出:
argv.py # 注意!argv[0]固定是python文件的名字
1
2
3
- shell可以只用最简单的用法,直接在其中写入待执行的shell指令。例如:新建一个文件auto.sh,打开auto.sh在其中输入:
python train.py
然后用chmod赋予文件可执行的权限,具体:
chmod a+x auto.sh
最后执行auto.sh
./auto.sh
auto.sh执行时会按顺序执行其中写好的指令。
- 看到这里相信大家已经明白原理了。命令行指令可以传参给python程序 and shell脚本可以顺序执行python命令行指令。结论:在shell脚本中写入若干行传参数给python程序的命令,用来修改网络结构,shell脚本顺序执行这些指令,实现自动化训练。
- shell指令“>”可以将本要输出到终端的字符重定向到其他位置,比如一个文件。实例:
echo hello > test
指令将生成一个名为test的文件(如果没有的话),本该直接回显的hello将被写入这个文件。这样就可以在实验跑完之后通过查看test中的内容检查训练过程。