0%

Hungry Router - 尝无止尽路由

步入硅器时代的中期,互联网逐渐进行的城市化,已经让原先的博客原住民变成了一座座孤岛。早年间繁荣的航海发现已经变得萧条,浏览世界的工具,也从孤身一人富含冒险勇气的Safari/Explorer,变成了社区群体汇集丰富多元的Chrome。孤岛的生活自由精致,不求浮名,但求同好。

硅矿工匠

Free Mind - Free Mind
徐阿衡 - Shuang
利器 - 创造者和他们的工具
科学空间|Scientific Spaces - 渴望成为一个小飞侠
GeekPlux - Data Visualization & Full-stack programmer @ finance firm, Blogger, Cat lover, Lifelong learner.
王垠的博客 - 当然我在扯淡 - 王垠的博客 - 当然我在扯淡
GENKUN - Recent content on GENKUN
每周记录SEE - 每周记录SEE
Lu Huang’s Blog - Lu Huang’s Blog
图月志 - JJ Ying 的界面设计博客,博主同时也是设计播客 Anyway.FM 的主播
Hi, DIYgod - Hi, DIYgod
中文日志 on Yihui Xie | 谢益辉 - Recent content in 中文日志 on Yihui Xie | 谢益辉
数字移民 - 数字移民是一种生活方式
Chenfan Blog - Do cool things that matter.
细语呢喃 - 技术改变生活
Go Further - Stay Hungry, Stay Foolish
ONES Piece 翻译计划 - 聚焦科技、创投和商业 - ONES Piece是一个由ONES Ventures发起的非营利翻译计划,聚焦科技、创投和商业。
infoier | 设计乘数 - infoier | 设计乘数
piglei - piglei
安妮薇时报 Anyway.News - 由 Anyway.FM 发行,为你提供与设计行业相关的新闻资讯、网摘推荐以及专栏文章等内容。
Be For Web - Be For Web
一稿计划 - Last one

游吟诗稿

一天世界 - 一天世界
城堡阅读周刊 - 由阅读爱好者业余制作,基于 Markdown 排版的网络独立杂志。
刘未鹏 | Mind Hacks - 思维改变生活
GoldenGrape’s Blog - This is a blog site for GoldenGrape.
大破进击 - 大破进击
HuoJu’s BLOG - Recent content on HuoJu’s BLOG
累牍 - 累牍
万有引力之虫 - 在刺猬与狐狸之外,在傻子和英雄之间。 A blog about social movement and others.

播波电台

大内密谈 - 大内密谈
UX Coffee 设计咖 - 设计无处不在。在这个节目里,我们试图通过和设计这个世界的人们交谈,去探寻创造的过程、感受设计的力量。
无业游民 The Unemployable - 生活再丧,也不要和世界失去联系
文化土豆 Culture Potato - 文化土豆 Culture Potato
路书 - 路书
津津乐道 - 用耳朵体验世界
迟早更新 - by ONES Ventures
日谈公园 - 日谈公园
不丧 - Busang Podcast
不可理论 - 带你用理论理解生活
提前怀旧 - 一切未来终将成为过去。欢迎收听《提前怀旧》,一档由任宁和 Rio 主持的科技评论节目。
故事 FM - 用你的声音,讲述你的故事。
硬影像 - 硬影像
博物志 - 博物志
一天世界 - 一天世界,昆乱不挡。不鳥萬如一主理。IPN 出品。
疯投圈 - 疯投圈
时尚怪物 - Fashion Monster 《时尚怪物》是一档探讨文化艺术与奇奇怪怪生活的播客节目,Tianxi、汉洋主持,IPN 出品。
黑水公园 - 黑水公园
剩余价值SurplusValue - 剩余价值SurplusValue (已更名随机波动)
随机波动StochasticVolatility - 是由三位女性媒体人发起的一档泛文化类播客,原剩余价值
字谈字畅 - 用听觉方式扯视觉艺术
捕蛇者说 - 编程、程序员、Python
Anyway.FM 设计杂谈 - 由 UI 设计师 JJ Ying 和 Leon Gao 主播的 podcast,主题包括但不限于视觉设计,入选 2015 年 Apple 最佳播客榜单。Anyway.FM 是两个闷骚男抒发对设计热情的地方、Anyway.FM 是两个老男人吐槽世界的地方、Anyway.FM 也是一对好基友想把自己的见解分享给更多人的地方。

时间和因果性

春节肺炎的群体隔离期间,看了片单里罗列很久的电影,恰好又在书架上看到初中那会特别喜欢的一本书《Hyperspace 超越时空》。这本书算是一本「超空间理论」的科普读物,全书基本奉行「霍金畅销书」理论,全篇没有用一个公式,只是通过举例和类比的文学方式来描述近代物理的一个很争议的「超空间理论」。

除去四大基本力的统一,最有吸引力的就是对「时间」的解读。作为一个抽象又具象的名词,宗教、哲学、文学、艺术领域都又有不同的流派对这个词有所解释。在时间的科幻应用上谈及最多的就是「时间旅行」,这里又可以衍生出很多的假说来描述时间旅行的种种问题。

此前我也作为一个定性分析爱好者,喜欢琢磨「时间旅行」的可解释性。那个时候我最认同的是时间旅行的经历只是可观测性但不可修改的,就像在地球看到几亿光年外的星体,可以通过改变和它的空间距离来看到这个星体的过去和未来。现在的自己认知来看这种自己觉得可解释性最强的假说无疑不够精妙,这种假说下,空间和时间维度还是被揉捏在一起,没有那种正交互相独立的美感。

刷电影片单的过程带了些新的思考,一直以来最容易理解时间维度的方式就是视频,天然有一个可供调整的进度条来切换时间的位置。从这点来看,文学作品也是差不多,书籍的页码同样是自带的「时间进度条」,在电子阅读软件上同样也是这么使用的。不过电影和文学的叙事表达有很多手法,很难有纯线性叙事的作品了,这一点来看,切换的时间轴反而会更容易陷入事件时间的先后错乱中。但这种非线性叙事其实很接近时间旅行,提前或延后知晓在一件事情还没发生或者发生后的场景故事。

就像空间维度上的人可以从A走到B,作为正交的时间轴应该也能修改,像视频剪辑软件那样,把白天的人下一秒就安排在黑夜。但这种粗暴的方式无疑会破坏因果性,无数时间旅行的假说就是为了满足因果性而产生的,大致可以归纳为宿命论和非宿命论。但这些都是认为一件事情发生后会像蝴蝶效应那样导致一件事情发生,只是那件事情的结果,可能会,也可能不会,如同时间旅行前那样。这就是为了体现时间的因果性。但有没有可能时间是没有因果性的,我把叉了苹果的叉子往嘴里伸,然后吃到了牛肉。

我自己其实一直也觉得时间和因果性应该深深地绑定在一起,或者说时间只是因果的产物,但物理上真的是这样吗?鉴于是为了探索脑洞的趣味性,我只是在知乎上看了看现有的讨论。

最直接的问题就是「因果」是建立在「时间」这个概念上的吗? 虽然和我想的时间是不是因果的产物有所差异,但其实探讨的本质是一样的。毫无疑问,这类的问题解读最先要做的是对因果和时间进行定义,不同的定义会延伸出不同的解读结论。但只是作为脑洞探索,分析各类定义的不同结论实在过于繁琐。按照康德的因果观和相对论的时空观解读来看,因果和时间都是光传递的内容,也就是说在得知时间同时也能知道因果的作用。似乎以一种回避的方式讨论了时间和因果的关系,但的确也没办法进行任何的实验来描绘二者的关系。定性的分析成了这类问题的最大的遗憾。

像电影视听表达那样无视前一秒和后一秒的因果性,这是一种免于时空旅行各类悖论的取巧方式。但这种简单粗暴的覆盖像是一种偷懒,实在很难让人相信这是世界运转的规律之一。

中央处理单元-CPU

cpu 的话消费顶级选择当然不止intel 9900k,另一个可以选择的是7月新出的AMD 3900x, 价格两者差不多(4k左右)。从数据上看 3900x的核心和线程数都比较高,(9900k-8核16线程 | 3900x-12核24线程)但一方面是我对amd 的处理器不太了解,主板选择上和内存支持上可能没有太大把握,同时由于本月新品的原因,配套主板的价格特别高。另一方面实际游戏测试表现来看默频下,9900k略胜3900x一筹(平均高出6%),超频下9900k(5ghz)还是略胜3900x(auto)一筹(平均高出5%,但9900k超频空间大很多)。所以游戏娱乐来看现在买9900k还是一个比较好的选择,至于专业视频制作和数据处理3900x因为核心线程的领先表现可能会好一点。

Refer:9900k和3900x游戏性能对比

主板-Motherboard

主板的话 如果不超频的话微星的暗黑版本就够用了,但是m2接口和供电还是寒酸了一点,如果后续要加m2硬盘会少一两个,用微星战神ace的话如果超频的话供电能更稳定一点,i/o和硬盘接口更丰富一点,毕竟现在主板一键超频还是比较容易的,超频不是很复杂。华硕的rog m11h 和 微星 战神 ace差不多,但有rog的灯效和品牌加成,不过如果选择rog 我比较建议再加一点钱到 m11a,rog的顶级供电,可以挑战一波液氮超频。 美观的话rog m11f比较好看
如果选微星暗黑注意下只有结尾带ac的是自带无线网卡和蓝牙的。

Refer:msi carbon | msi ace | rog m11h |rog m11e主板对比

图形处理单元-GPU

gpu的话是十分价钱一分货,一千块一两帧的差距吧,1w左右的看造型选就行了,如果还是比较看中频率的话微星魔龙在这个价位有一点点优势,建议主板和显卡选择同品牌的,这样在软件监控管理上稍微方便一点点。如果主板选了rog,显卡可以选rog的猛禽。

内存-Memory

内存的话有两个方向一个是追求空间的16g双通道,另一个是追求频率的8g双通道,性能上高频率的8g双通道在游戏上表现会好一点(10%以内),一张主板能插四条内存,性能要求高又对空间要求不太高(不跑大数据处理和高分辨率的影视动画制作)4个8gb的绝对够用了,如果空间要求比较大还是16g的内存吧(rog 主板是只有两个内存槽 除了m11e)

硬盘-Disk

硬盘的话不太知道你原来硬盘的型号,主控颗粒还是新硬盘好一点,4k读写能快很多,建议还是用新m2硬盘装个系统500g或者250g的都可以,但500g的性能会好一点。硬盘的话价格高的在跑分上还是比较明显的,但使用感受区别不大。而且硬盘不太保值,换起来又方便,随用随换可能比较好一点。

电源-Power

电源 如果打算5年后下一台电脑接着用的话可以用1000w的电源,质保时限都是ok的,850w其实也够下一台用,但余量不一定够,不过电源用得太久也不一定100%稳定。至于rog的雷神用的是同款海韵电源的带灯贴皮,不过一般机箱电源位都是带仓包起来的,所以带了灯可能也看不见。

散热-CPU Cooler

散热我查了一下,水冷有几个5年损坏全赔的,可以具体问一下客服,就是如果漏夜造成你机箱损伤他们会折旧赔其他部件比如cpu/gpu的钱。9900k的发热量还是比较大的,如果用风冷真的是装一个硕大硕大的散热塔,还得有额外的承重架来支撑一下(不过显卡估计也会需要支撑架),水冷能让机箱整洁一点。不过水冷不太好带到日本,路上颠簸说不定就影响整体密封性了。不管选水冷还是风冷都要注意机箱尺寸,水冷一般机箱描述会写有支持360冷排,风冷的话最好问一下客服猫头鹰或大霜塔能不能装进去,而且还要注意会不会挡住主板的一些接口位置

机箱-Computer Case

机箱 注意支持主板大小是不是支持atx主板,前面板对type-c有没有要求(rog m11h主板不支持机箱前面板的type-c),散热装不装得下,别的就没什么了,主要还是看你对造型的喜好。我个人觉得rog 太阳神这样就还行。但你最好多挑挑,毕竟低头不见抬头见

参考推荐表—9900k+2080ti 7月简单推荐配置
9900k+2080ti 7月简单推荐配置

下载: motrix - 可以作为迅雷部分无法下载资源的备用,部分迅雷服务器可以缓存的资源,速度还是迅雷更快

code展示: Carbon

mac 录屏幕:GIPHY CAPTURE

Markdown: Typora

Mysql gui: sequel pro - mac上非常容易操作的轻量mysql gui,当然大部分情况下python的mysql包就完全够用了

Gist gui:Lepton - 比较好用的gist桌面应用,可惜没有搜索功能

从11月初开始,google-research就陆续开源了bert的各个版本。google此次开源的bert是通过tensorflow高级API—— tf.estimator进行封装(wrapper)的。因此对于不同数据集的适配,只需要修改代码中的processor部分,就能进行代码的训练、交叉验证和测试。

在自己的数据集上运行bert

bert的代码同论文里描述的一致,主要分为两个部分。一个是训练语言模型(language model)的预训练(pretrain)部分。另一个是训练具体任务(task)的fine-tune部分。在开源的代码中,预训练的入口是在run_pretraining.py而fine-tune的入口针对不同的任务分别在run_classifier.pyrun_squad.py。其中run_classifier.py适用的任务为分类任务。如CoLA、MRPC、MultiNLI这些数据集。而run_squad.py适用的是阅读理解(MRC)任务,如squad2.0和squad1.1。预训练是bert很重要的一个部分,与此同时,预训练需要巨大的运算资源。按照论文里描述的参数,其Base的设定在消费级的显卡Titan x 或Titan 1080ti(12GB RAM)上,甚至需要近几个月的时间进行预训练,同时还会面临显存不足的问题。不过所幸的是谷歌满足了issues#2里各国开发者的请求,针对大部分语言都公布了bert的预训练模型。因此在我们可以比较方便得在自己的数据集上进行fine-tune。

下载预训练模型

对于中文而言,google公布了一个参数较小的bert预训练模型。具体参数数值如下所示:

Chinese Simplified and Traditional, 12-layer, 768-hidden, 12-heads, 110M parameters

模型的下载链接可以在github上google的开源代码里找到。对下载的压缩文件进行解压,可以看到文件里有五个文件,其中bert_model.ckpt开头的文件是负责模型变量载入的,而vocab.txt是训练时中文文本采用的字典,最后bert_config.json是bert在训练时,可选调整的一些参数。

修改processor

任何模型的训练、预测都是需要有一个明确的输入,而bert代码中processor就是负责对模型的输入进行处理。我们以分类任务的为例,介绍如何修改processor来运行自己数据集上的fine-tune。在run_classsifier.py文件中我们可以看到,google对于一些公开数据集已经写了一些processor,如XnliProcessor,MnliProcessor,MrpcProcessorColaProcessor。这给我们提供了一个很好的示例,指导我们如何针对自己的数据集来写processor。
对于一个需要执行训练、交叉验证和测试完整过程的模型而言,自定义的processor里需要继承DataProcessor,并重载获取label的get_labels和获取单个输入的get_train_examples,get_dev_examplesget_test_examples函数。其分别会在main函数的FLAGS.do_trainFLAGS.do_evalFLAGS.do_predict阶段被调用。
这三个函数的内容是相差无几的,区别只在于需要指定各自读入文件的地址。以get_train_examples为例,函数需要返回一个由InputExample类组成的listInputExample类是一个很简单的类,只有初始化函数,需要传入的参数中guid是用来区分每个example的,可以按照train-%d'%(i)的方式进行定义。text_a是一串字符串,text_b则是另一串字符串。在进行后续输入处理后(bert代码中已包含,不需要自己完成) text_a和text_b将组合成[CLS] text_a [SEP] text_b [SEP]的形式传入模型。最后一个参数label也是字符串的形式,label的内容需要保证出现在get_labels函数返回的list里。
举一个例子,假设我们想要处理一个能够判断句子相似度的模型,现在在data_dir的路径下有一个名为train.csv的输入文件,如果我们现在输入文件的格式如下csv形式:

1
2
1,你好,您好
0,你好,你家住哪

那么我们可以写一个如下的get_train_examples的函数。当然对于csv的处理,可以使用诸如csv.reader的形式进行读入。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
def get_train_examples(self, data_dir)
file_path = os.path.join(data_dir, 'train.csv')
with open(file_path, 'r') as f:
reader = f.readlines()
examples = []
for index, line in enumerate(reader):
guid = 'train-%d'%index
split_line = line.strip().split(',')
text_a = tokenization.convert_to_unicode(split_line[1])
text_b = tokenization.convert_to_unicode(split_line[2])
label = split_line[0]
examples.append(InputExample(guid=guid, text_a=text_a,
text_b=text_b, label=label))
return examples

同时对应判断句子相似度这个二分类任务,get_labels函数可以写成如下的形式:

1
2
def get_labels(self):
reutrn ['0','1']

在对get_dev_examplesget_test_examples函数做类似get_train_examples的操作后,便完成了对processor的修改。其中get_test_examples可以传入一个随意的label数值,因为在模型的预测(prediction)中label将不会参与计算。

修改processor字典

修改完成processor后,需要在在原本main函数的processor字典里,加入修改后的processor类,即可在运行参数里指定调用该processor。

1
2
3
4
5
6
7
processors = {
"cola": ColaProcessor,
"mnli": MnliProcessor,
"mrpc": MrpcProcessor,
"xnli": XnliProcessor,
"selfsim": SelfProcessor #添加自己的processor
}

运行fine-tune

之后就可以直接运行run_classsifier.py进行模型的训练。在运行时需要制定一些参数,一个较为完整的运行参数如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
export BERT_BASE_DIR=/path/to/bert/chinese_L-12_H-768_A-12 #全局变量 下载的预训练bert地址
export MY_DATASET=/path/to/xnli #全局变量 数据集所在地址

python run_classifier.py \
--task_name=selfsim \ #自己添加processor在processors字典里的key名
--do_train=true \
--do_eval=true \
--dopredict=true \
--data_dir=$MY_DATASET \
--vocab_file=$BERT_BASE_DIR/vocab.txt \
--bert_config_file=$BERT_BASE_DIR/bert_config.json \
--init_checkpoint=$BERT_BASE_DIR/bert_model.ckpt \
--max_seq_length=128 \ #模型参数
--train_batch_size=32 \
--learning_rate=5e-5 \
--num_train_epochs=2.0 \
--output_dir=/tmp/selfsim_output/ #模型输出路径

bert源代码里还有什么

在开始训练我们自己fine-tune的bert后,我们可以再来看看bert代码里除了processor之外的一些部分。
我们可以发现,process在得到字符串形式的输入后,在file_based_convert_examples_to_features里先是对字符串长度,加入[CLS]和[SEP]等一些处理后,将其写入成TFrecord的形式。这是为了能在estimator里有一个更为高效和简易的读入。
我们还可以发现,在create_model的函数里,除了从modeling.py获取模型主干输出之外,还有进行fine-tune时候的loss计算。因此,如果对于fine-tune的结构有自定义的要求,可以在这部分对代码进行修改。如进行NER任务的时候,可以按照bert论文里的方式,不只读第一位的logits,而是将每一位logits进行读取。
bert这次开源的代码,由于是考虑在google自己的TPU上高效地运行,因此采用的estimator是tf.contrib.tpu.TPUEstimator,虽然tpu的estimator同样可以在gpu和cpu上运行,但若想在gpu上更高效得做一些提升,可以考虑将其换成tf.estimator.Estimator,于此同时model_fn里一些tf.contrib.tpu.TPUEstimatorSpec也需要修改成tf.estimator.EstimatorSpec的形式,以及相关调用参数也需要做一些调整。在转换成较普通的estimator后便可以使用常用的方式对estimator进行处理,如生成用于部署的.pb文件等。

issues里一些有趣的内容

从google对bert进行开源开始,issues里的讨论便异常活跃,bert论文第一作者javob devlin也积极地在issues里进行回应,在交流讨论中,产生了一些很有趣的内容。
#95中大家讨论了bert模型在今年ai-challenger比赛上的应用。我们也同样尝试了bert在ai-challenger的mrc赛道的表现。如果简单得地将mrc的文本连接成一个长字符串的形式,可以在dev集上得到79.1%的准确率。如果参考openAI的GPT论文里multi-choice的形式对bert的输入输出代码进行修改则可以将准确率提高到79.3%。采用的参数都是bert默认的参数,而单一模型成绩在赛道的test a排名中已经能超过榜单上的第一名。因此,在相关中文的任务中,bert能有很大的想象空间。
#123中,@hanxiao给出了一个采用ZeroMQ便捷部署bert的service,可以直接调用训练好的模型作为应用的接口。同时他将bert改为一个大的encode模型,将文本通过bert进行encode,来实现句子级的encode。此外,他对比了多GPU上的性能,发现bert在多GPU并行上的出色表现。

总结

总得来说,google此次开源的bert和其预训练模型是非常有价值的,可探索和改进的内容也很多。相关数据集上已经出现了对bert进行修改后的复合模型,如squad2.0上哈工大(HIT)的AoA + DA + BERT以及西湖大学(DAMO)的SLQA + BERT
在感谢google这份付出的同时,我们也可以借此站在巨人的肩膀上,尝试将其运用在自然语言处理领域的方方面面,让人工智能的梦想更近一步。

声明

本文相关工作在©奇点机智工作期间完成,已授权©奇点机智对文章的各类使用。

一、在执行代码时使用 tf.enable_eager_execution() 开启eager模式

二、正向传播支持自定义class类型

  1. 定义的model继承keras.model
  2. init()里定义所用到的layer类型
  3. call()里连接layer,返回output

二、反向传播的使用

  1. 先用tf的api定义loss函数

  2. 用tfe的api调用loss得到梯度grads

    1
    2
    tfe.gradients_function(loss,x)
    tfe.implicit_gradients(loss)

    或者也可以采用GradientTape(y,x)来进行计算可以根据函数y计算变量x的梯

    1
    2
    with tf.GradientTape() as grad_tape:
    grad_tape.gradient(y,x)

    在tf的诸多eager execution样例中里用第二种方法较多

  3. 用tf定义的optimizer优化梯度更新参数

    1
    optimizer.apply_gradients(grad)

三、Eager的输入使用tf.data.Dataset但不支持placeholderstring_input_producer这类在graph模式中使用的输入

四、使用tf.train.Checkpoint()保存模型的checkpoint

五、可以使用tf.contrib.eager.defun对python的函数进行封装转换成图的形式进行运算。用eager的写法可以实现graph的运算速度。

  1. 使用了defun的forward propagation例子如下:

    1
    2
    model.call = tf.contrib.eager.defun(model.call)
    model(x, training=True) # executes a graph, with dropout
  2. 一个使用了defun的back propagation例子如下

    1
    2
    3
    4
    5
    6
    7
    optimizer = tf.train.GradientDescentOptimizer()
    with tf.GradientTape() as tape:
    outputs = model(x)
    gradient = tape.gradient(outputs, model.trainable_variables)
    defun_gradients = tfe.defun(gradient)
    tfe.defun(optimizer.apply_gradients((grad, var) for grad,
    var in zip(gradient,model.trainable_variables)))

    然而此后defun可能会被AutoGraph替代

Refer:Code with Eager Execution, Run with Graphs: Optimizing Your Code with RevNet as an Example

checkpoint增加一些可阅读性的操作

checkpoint的基础使用在官方的手册里描述地比较清楚了。但在进行迁移学习时,需要对一些预训练的权重进行读取,因此如果能可阅读得打印一些变量,可以使得读取过程变得简捷便利。

checkpoint里变量名和权重值

1
2
3
4
5
6
7
8
9
10
11
from tensorflow.python import pywrap_tensorflow
import os
model_dir = 'dir'
file_name = 'ckptfile'

checkpoint_path = os.path.join(model_dir,file_name)
reader = pywrap_tensorflow.NewCheckpointReader(checkpoint_path)
var_to_shape_map = reader.get_variable_to_shape_map()
for key in var_to_shape_map:
print('tensor_name: ',key) #变量名
print(reader.get_tensor(key)) #变量值

在ckpt文件里的变量有两类,一类是进行前馈的权重,另一类是在后馈时的梯度。同时有一些变量并不是此前在构建模型时声明的,而是在实现各类模型api时自动产生的,通常这类变量会根据参数产生W和bias。对于包含多步线性计算的cell即各类RNN的cell而言,W会被整合成一个名为kernel的变量,其tensor大小将根据具体的计算方式生成,如lstm的kernel变量大小为(input_dim+lstm_dim,4*lstm_dim)。

sess里变量读取预训练权重

1
2
3
4
sess.run(tf.global_variables_initializer())
sess.run(tf.local_variables_initializer())
print_variable = [var.name for var in tf.global_variables()]
print(print_variable)

因为ckpt读取变量需要新变量和ckpt里的变量名字完全一致,所以可以通过上述代码查看变量名是否满足条件。

1
2
3
4
5
6
7
variables_to_restore = [var for var in tf.global_variables()
if var.name=='bias:0' or var.name=='kernel:0']
saver = tf.train.Saver(variables_to_restore)
model_dir = 'dir'
file_name = 'ckptfile'
checkpoint_path = os.path.join(model_dir,file_name)
saver.restore(self.sess,checkpoint_path)

通过在saver初始化时传入需要读取的参数,可以控制restore哪些变量。

estimator的简单使用方式

estimator的官方使用方式介绍了使用自定义的estimator的model,没有涉及到从keras的model来使用estimator。
主要的使用方式来自这篇notebook在使用的时候没有遇上太多障碍。
但有一些细节花了一点时间去调试。
比如estimator能按照dataset重复次数dataset.repeat(n)作为epoch,因此如果直接使用dataset.repeat()会在训练时陷入死循环。

model_fn的处理

1
2
3
4
5
6
7
8
9
def model_fn(features, labels, mode):
keras_estimator_obj = tf.keras.estimator.model_to_estimator(
keras_model=base_model,
model_dir=<model_dir>,
config=<run_config>,
)

# pull model_fn that we need (hack)
return keras_estimator_obj._model_fn

通过传递参数是无法打印更多的训练结果,但是可以通过创建一个logging hook来让estimator运行。
In the body of model_fn function for your estimator:

1
2
3
4
5
6
7
8
logging_hook = tf.train.LoggingTensorHook({"loss" : loss, 
"accuracy" : accuracy}, every_n_iter=10)

# Rest of the function

return tf.estimator.EstimatorSpec(
...params...
training_hooks = [logging_hook])

除了self.estimator.train()以外,可以使用tf.estimator.train_and_evaluate()trainevaluate进行更精细地操作。

此外add_metrics(estimator,my_auc)只是把metrics加入到最终结果的输出里,而不是每一次step,对于每一次step需要在EstimatorSpec(training_hook=[logging_hook])里添加logging_hook

多gpu出现的
All hooks must be SessionRunHook instances问题在#issues21444 里解决,等待tf-1.11版本。