(微信硬广)
现如今,微信已经成为每个中国人接入社会的重要接口,我们用微信在地铁上看鸡汤、在商场使用电子支付、瘫在沙发上刷朋友圈、谈恋(划掉)。总之,微信几乎包办了我们生活中的一切,让人产生一种错觉,在不久的未来手机上只需要装微信一个软件就够了。
为了证明人类社会的下一阶段是微信主义,我们先定一个小目标:用微信控制深度学习训练。
一般来说,想要监控深度学习训练,只能用ssh或者tensorboard,用手机操作毕竟很麻烦,如果微信能把监控深度学习也包办了岂不是妙哉?
在命令行时代,使用图形界面就是逼格;在图形界面时代,使用命令行就是逼格。玩的就是个潮!
现在已经实现了包括被动监控、主动查询、远程关机/停止训练等多项功能。
效果展示:<img src="https://pic3.zhimg.com/v2-58e7eb85ff458ef32676bfaebd12b336_b.jpg" data-rawwidth="271" data-rawheight="528" class="content_image" width="271">
与手机微信间的通信主要由littlecodersh/ItChat实现。
欢迎fork这个项目的GitHub:QuantumLiu/wechat_callback,为了方便阅读(添乱)我硬着头皮加了双语注释。
我很惭愧,只做了一点微小的工作,希望能抛砖引玉,得到各位的支持一起完善这个项目。
一、主要功能介绍
- 实时监控:在每个epoch结束后,自动发送本epoch训练信息以及两张分别代表所有batch和epoch信息的图表至文件传输助手。<img src="https://pic2.zhimg.com/v2-831242df7b0e827349b989f3544ec741_b.jpg" data-rawwidth="452" data-rawheight="727" class="origin_image zh-lightbox-thumb" width="452" data-original="https://pic2.zhimg.com/v2-831242df7b0e827349b989f3544ec741_r.jpg">

- 主动查询:在训练开始后的任意时刻,发送特定格式的指令,可获得指定查询项的信息。目前支持batch和epoch的各个指标的信息、显卡状态信息。<img src="https://pic3.zhimg.com/v2-49068b597a12701bdc14255f5246c20a_b.jpg" data-rawwidth="277" data-rawheight="177" class="content_image" width="277">
<img src="https://pic1.zhimg.com/v2-e02ef05e38637d1d960ce2b8a9826afc_b.jpg" data-rawwidth="800" data-rawheight="600" class="origin_image zh-lightbox-thumb" width="800" data-original="https://pic1.zhimg.com/v2-e02ef05e38637d1d960ce2b8a9826afc_r.jpg">
<img src="https://pic1.zhimg.com/v2-4f0f3930d45675a52a26388016b8e220_b.png" data-rawwidth="268" data-rawheight="402" class="content_image" width="268">

- 远程指令:当你觉得训练已经收敛,或者同实验室的人催你停止训练时,优雅地终止训练甚至关机就变得很重要了。keras的fit方法中,可以通过在callback设置
来实现在当前epoch结束时终止训练,否则只能Ctrl+c暴力停止。利用本插件,可以使用特殊格式的指令来指定停止epoch、立刻停止训练,甚至关机和取消关机。<img src="https://pic2.zhimg.com/v2-3ebdb24148b69a81d8a56845dd592239_b.jpg" data-rawwidth="271" data-rawheight="156" class="content_image" width="271">self.model.stop_training = True
<img src="https://pic4.zhimg.com/v2-c4b84327845a56d410c350c684c6c5c3_b.jpg" data-rawwidth="277" data-rawheight="243" class="content_image" width="277">
<img src="https://pic4.zhimg.com/v2-b74707d717a7258151583ef782cc94f7_b.jpg" data-rawwidth="275" data-rawheight="99" class="content_image" width="275"> 
二、试一试!
- 准备工作
git clone https://github.com/QuantumLiu/wechat_callback.git
cd wechat_callback
需要用到的库:
itchat,keras,numpy,scipy,matplotlib,_thread(py3)确保nvidia-smi可用,如果windows的cmd里找不到命令,请手动将nvidia-smi.exe所在位置添加进环境变量。<img src="https://pic4.zhimg.com/v2-0f6e5592c1d3bc856ba89714f83c7253_b.png" data-rawwidth="504" data-rawheight="520" class="origin_image zh-lightbox-thumb" width="504" data-original="https://pic4.zhimg.com/v2-0f6e5592c1d3bc856ba89714f83c7253_r.png">
2.运行测试脚本
python wechat_test.py
解析:
在wechat_test.py的开头,首先import wechat_utils
import wechat_utils #will login automaticly
#wechat_utils.sendmessage()isthe callback class
#wechat_utils.sendmessage()是keras的回调类,fit时传入callbacklist
在wechat_utils.py中:
# Automaticly login when imported
#在被import时自动登录
#==============================================================================
itchat.auto_login(enableCmdQR=0.5,hotReload=True)
itchat.dump_login_status()#dump
可以看到,当wechat_utils被import时会调用itchat.auto_login(),不出意外的话,将会在命令行显示二维码,需要使用手机微信扫码登录你的微信账号。<img src="https://pic1.zhimg.com/v2-db7803105b2b988dce28e705a607be70_b.jpg" data-rawwidth="183" data-rawheight="141" class="content_image" width="183">
在测试脚本里我使用numpy.random来生成训练数据,搭建了一个多层的FC网络
model = Sequential()
model.add(Dense(2048, input_dim=784))
model.add(Activation('relu'))
for i in range(9):
model.add(Dense(2048))
model.add(Activation('relu'))
model.add(Dense(1,activation='sigmoid'))
x=np.random.rand(nb_sample,dim)
y=np.random.randint(2,size=(nb_sample,1))
调用插件非常简单,只需要在fit时把wechat_utils.sendmessage()这个keras的Callback类传入Callbacklist。
model.fit(x=train_x,y=train_y,batch_size=batch_size,nb_epoch=60,validation_data=(val_x,val_y),callbacks=[wechat_utils.sendmessage()])
于是训练开始,手机会收到如下反馈:<img src="https://pic3.zhimg.com/v2-eb5b0faac4a8de732f55eaa40cd25926_b.jpg" data-rawwidth="266" data-rawheight="102" class="content_image" width="266">我们可以向它发送查询指令,指令一般包括
我们可以向它发送查询指令,指令一般包括关键词和参数
以获取图表为例,包含以下任意关键词将被识别为获取图表指令:
[u'获取图表','Show me the figure']
参数则用{}或[]来指定,所有的指令均支持不指定参数,获取图表的默认参数是查询所有信息,例如<img src="https://pic3.zhimg.com/v2-49068b597a12701bdc14255f5246c20a_b.jpg" data-rawwidth="277" data-rawheight="177" class="content_image" width="277">
‘Show me the figure’触发了指令,{batches}表示查询batches级别信息,[loss hinge]表示查询loss和hinge指标(一般的,同一属性参数用空格隔开)
同理,['GPU','gpu',u'显卡']是gpu状态查询的关键词,用[]指定参数,如图,查询了gpu的显存和温度。GPU参数是根据nvidia-smi的预置参数确定的,全部都是大写,具体可查询属性请看GitHub的readme或者阅读源码。
<img src="https://pic1.zhimg.com/v2-4f0f3930d45675a52a26388016b8e220_b.png" data-rawwidth="268" data-rawheight="402" class="content_image" width="268">
新增进度查询,关键词[u'进度','Progress']。 <img src="https://pic4.zhimg.com/v2-32299755d14f02e2bc44c6459e0b01b7_b.jpg" data-rawwidth="273" data-rawheight="298" class="content_image" width="273">默认将保存每个batch的训练日志至本地,可通过制定参数savelog和fexten来指定是否保存日志以及生成的图片、日志、权重文件的后缀名。
默认将保存每个batch的训练日志至本地,可通过制定参数savelog和fexten来指定是否保存日志以及生成的图片、日志、权重文件的后缀名。
wechat_utils.sendmessage(savelog=True,fexten='TEST')
关机指令关键词是[u'关机','Shut down','Shut down the computer',u'别浪费电了',u'洗洗睡吧'],使用{sec}和[name]指定等待时间和保存文件名,文件名不包括.h5。默认保存模型,如果不想保存,可以在消息中包含[u'不保存模型',"don't save"]比如:
Shut down now{120},don't save
取消关机只需要包含[u'取消','cancel','aaaa']就可以了,也就是说如果着急的话打一串a发过去也是可以的~<img src="https://pic4.zhimg.com/v2-c4b84327845a56d410c350c684c6c5c3_b.jpg" data-rawwidth="277" data-rawheight="243" class="content_image" width="277">
立刻停止训练的关键词是['Stop now',"That's enough",u'停止训练',u'放弃治疗'](《西部世界》看多了)<img src="https://pic4.zhimg.com/v2-cd39572b6d842dfb99376fb8d5beb04f_b.jpg" data-rawwidth="242" data-rawheight="162" class="content_image" width="242">指定停止epoch的关键词是‘Stop at’,参数可以直接用整数表示,不需要[]。
指定停止epoch的关键词是‘Stop at’,参数可以直接用整数表示,不需要[]。<img src="https://pic1.zhimg.com/v2-ed6c231df6d40be22e2215172abd0d98_b.jpg" data-rawwidth="242" data-rawheight="151" class="content_image" width="242">
三、总结
这个项目从有想法算起到写注释、开GitHub、写知乎不过两天半,做的很匆忙也很粗糙,特别是画图的细节和多线程的处理。
我只是一名大一学生(休学ing),水平十分有限,恳请各位多加指点,提高我的姿势水平,如果这个项目能给你带来一点点便利或者灵感,那么我将感到十分荣幸与欣慰。
好了!运行keras代码然后约妹子去看电影吧!
再次感谢@Coldwings的原创创意。

<img src="https://pic1.zhimg.com/v2-4f0f3930d45675a52a26388016b8e220_b.png" data-rawwidth="268" data-rawheight="402" class="content_image" width="268">
<img src="https://pic4.zhimg.com/v2-c4b84327845a56d410c350c684c6c5c3_b.jpg" data-rawwidth="277" data-rawheight="243" class="content_image" width="277">
