MPI 学习笔记

参考资料:

消息传递接口(MPI)维基百科

MPI_TUTORIAL

MPI 在大规模机器学习领域的前景如何?

因为要和平台组对接工作以及写我们自己的BN同步…所以来了解一下MPI相关…感谢平台组@gyz 菊苣提供指导。

下面写一些自己的理解 ^_^

OVERVIEW

MPI是一个跨语言的通讯协议,用于并行相关

MPI不是一种具体的语言实现,而是一种标准或者说接口,类比sql在关系型数据库中的地位,具体用的时候我们是用某个特定的实现,例如openmpi或者mpich2

对于机器学习问题,MPI很适合用在超算上…

下面随便补一些我认为需要了解的:

 communicator 是一个进程的group,该group里的所有进程可以相互通信。

在这组进程中,每个进程有一个唯一的rank,通信按照rank进行(做身份标识的作用?

MPI支持的通信方式有point-to-point 和 collective 两种,也就是点对点和广播

下面分别介绍这两种方式。

Blocking point-to-point communication

Blocking  communication 就是阻塞通信

阻塞通信是指消息发送方的send调用需要接受方的recv调用的配合才可完成

对于非阻塞通信,不必等到通信操作完全完成便可以返回,该通信操作可以交给特定的通信硬件去完成,在该通信硬件完成该通信操作的同时,处理机可以同时进行计算操作,这样便实现了计算与通信的重叠。通过计算与通信的重叠,可以大大提高程序执行的效率。这一方法和通过异步I/O实现I/O与计算的重叠思路是完全一样的。

MPI Send and Receive

 

 

 

 

 

 

 

 

 

 

tensorflow input pipline 学习笔记

参考资料:

tf_doc_Reading data

TENSORFLOW INPUT PIPELINE EXAMPLE

tensorflow:理解tensorflow中的输入管道

第二个参考资料是第一个的翻译版本,翻译的水平一般,建议看原文,不是很长。

下面是我挑了文章中重点的部分+自己的理解。

TL;DR;

一个适用于不是很大的数据集的pipline input 的例子。

Load Data in Tensorflow

input pipline 可以理解称一种load data的方式。 一般有两种方式load data,一种是比较传统的,使用feed 的方式。如果数据集比较大,这种方式就不适用了,因为这种方式需要将数据全部导入到memory中。因此tf提供了pipline input的读入数据的方式。

input pipline 会处理 csv file,解码文件格式,重构数据结构,打乱数据顺序,做数据扩充或者其他预处理,然后使用线程(threads)将数据导进batch.

Load the Label Data

确保使用正确的dataset,csv文件路径。

然后处理 得到train和test 的label

由于我们只是读数据而没有真的打算训练,所以没有使用one-hot的编码方式,而是直接将(本来也是由数字字符组成的)字符串,转化成int.

Do Some Optional Processing on Our String Lists

Start Building the Pipeline

确保tensor的 dtype和list中的数据的type相匹配。

Lets Partition the Data

这是一个可选的步骤。可能由于我们的数据集比较大,我们先把它分成train set 和 test set

A visualization of the dynamic partition function in tensorflow.

 

Build the Input Queues and Define How to Load Images

 

使用slice_input_producer 切分 tensor,得到一个个的实例(?),然后使用线程 queue them up.

shuffle表示是否打乱数据,此处我们不打乱。

Group Samples into Batches

单个sample训练效率会很低,通常的做法是将若干个samples合成一个batch一起训练。每个batch中samples的个数就是所谓的batch_size

到目前为止我们只是描述了pipline大致的样子,但是tensorflow还不知道我们image数据的shape.  在使用tf.train_batch将samples合成若干个batch之前,我们需要首先定义image

tensor 的 shape

Run the Queue Runners and Start a Session

 

到目前为止我们已经构建好了input pipline.但是为了将pipline 启动,我们还需要使用线程,线程将加载queue,将数据导入tensorflow objects.

 

如下面的输出所示,tensorflow 不会关心epoch(全部数据过了一遍叫一个epoch)的数值,所以需要你自己手动统计。

Complete Code for this example

 

 

 

tensorflow 合并模型

在这里存个备份,还有些问题没有解决。

raise ValueError(“GraphDef cannot be larger than 2GB.”)

记录一些思路好了。现在是没有生成.meta文件,爆掉应该是因为所有的变量都加载到了默认图里。

也就是说我处理完checkpoint 0 之后开始处理checkpoint1,但是checkpoint0的那些变量还是存在的…所以越来越多?

目前有两个想法,第一个想法是是受TensorFlow极简教程:创建、保存和恢复机器学习模型  中启发,用多个saver,每个saver指定要搞的图(但是这样好像要每个checkpoint都是不同的saver才有意义?)

第二个想法是,每次save完变量之后,将图恢复成默认状态(可以把图中所有变量清空。。

 

想法二大失败:

会遇到if self.stack[-1] is not default: │
IndexError: list index out of range   的问题。。

根据 reset_default_graph awkwardly breaks graph nesting        

中提到了。。。reset_default_graph本身就不舍被设计成放在graph中清空变量用的。。。然后tf的代码也写得很不友好。。。没有 指明这个错误的原因。。。

For historical context,  tf.reset_default_graph() was never designed to be used with  with g.as_default(): context managers. I think the proper fix here is to make  tf.reset_default_graph() fail with an informative error message when used inside a  with g.as_default(): context. I think this could be done by checking that  ops._default_graph_stack is empty before resetting.

 

嘛。。先不管了。。。据数据那边说已经够用了。下面是最终版本,没有合并动量,因为对验证没有作用。

 

20170822update:去掉了卷基层的动量,添加了一些超参

 

tensorflow:tf.shape(a)和a.get_shape()区别

 

相同点:都可以得到tensor a的尺寸

不同点:tf.shape()中a 数据的类型可以是tensor, list, array

a.get_shape()中a的数据类型只能是tensor,且返回的是一个元组(tuple)

 

tensorflow checkpoint 学习笔记

参考资料:

What is the TensorFlow checkpoint meta file?

TensorFlow: Restoring variables from from multiple checkpoints

合并模型的时候发现.meta一直在累加,而其他数据文件没有改变。因此来探究一下checkpoint的几个文件的含义。

This file contains a serialized  MetaGraphDef protocol buffer. The  MetaGraphDef is designed as a serialization format that includes all of the information required to restore a training or inference process (including the  GraphDef that describes the dataflow, and additional annotations that describe the variables, input pipelines, and other relevant information). For example, the  MetaGraphDef is used by TensorFlow Serving to start an inference service based on your trained model. We are investigating other tools that could use the  MetaGraphDef for training.

Assuming that you still have the Python code for your model, you do not need the  MetaGraphDefto restore the model, because you can reconstruct all of the information in the  MetaGraphDef by re-executing the Python code that builds the model. To restore from a checkpoint, you only need the checkpoint files that contain the trained weights, which are written periodically to the same directory.

提到了.meta文件包含了恢复训练的所有信息。。。主要是为了其他工具可以快速恢复训练?

如果还是用python的话,恢复checkpoint没有必要使用.meta文件。

  • meta file: describes the saved graph structure, includes GraphDef, SaverDef, and so on; then apply  tf.train.import_meta_graph('/tmp/model.ckpt.meta'), will restore  Saver and  Graph.
  • index file: it is a string-string immutable table(tensorflow::table::Table). Each key is a name of a tensor and its value is a serialized BundleEntryProto. Each BundleEntryProto describes the metadata of a tensor: which of the “data” files contains the content of a tensor, the offset into that file, checksum, some auxiliary data, etc.
  • data file: it is TensorBundle collection, save the values of all variables.

 

Checkpoint

checkpoint文件可以理解成一个table,每次save之后会被更新,内容是最近一次的checkpoint文件名。

restore的时候,会先去checkpoint里看到最新的checkpoint文件是什么,然后只加载最新的。

 

tensorflow variable 学习笔记

参考资料:

programmers_guide/variables

tf/Variable

之前感觉对tensorflow 的variable的理解不是很深刻…跑个模型啥的倒不会有什么问题,但是涉及分布式,模型并行之类的,感觉有些地方还是要理解得仔细一点比较好。

OVERVIEW

variable的目的是将状态可持久化。

Unlike  tf.Tensor objects, a  tf.Variable exists outside the context of a single session.run call.

通俗地说就是,variable可以用来存储一个可持久化的tensor

一些op允许读取或者修改tensor的值,这些修改是跨session可见的,也就是说,对于用variable可持久化过的tensor,多个worker(多卡之间)之间可以看到相同的值

Creating a Variable

创建变量可以通过调用tf.get_variable function的方法实现。这个函数要求指明变量名称,这个名称会被作为标识该变量的key。

tf.get_variable也允许变量复用,意思是用之前创建过的有相同名字的变量,创建当前的变量。

Variable collections

由于在不同的部分创建了的变量可能有是够想一起访问,所以我们需要一个简单的能访问一个集合的变量的方法。tensorflow提供了collecetions,可以理解成python list,

是一个存储tensor,variable或者其他实例的容器。

默认情况下,tf.variable被收集到如下两个collcetions:

  • tf.GraphKeys.GLOBAL_VARIABLES:放置可以被多个设备共享的variable(从名字中的GLOBAL也可以看出来…)
  • tf.GraphKeys.TRAINABLE_VARIABLES:用来放置用来计算梯度的variable

如果不想训练某个variable,那么将它加入名字叫tf.GraphKeys.LOCAL_VARIABLES 的默认collection…

下面是一个将名字叫my_local的variable加入tf.GraphKeys.LOCAL_VARIABLES的例子

一个等价写法是,将trainable属性设置为False

当然自定义collcetion也是可以的,名字可以是任何字符串。

Device placement

variable和op一样,也可以放在指定的设备上。

在分布式tensorflow中,variable放在合适的设备上非常重要,如果不慎将variable 放在了 worker(GPU device)而不是PS(CPU device)上,将会严重减慢训练速度

基于这样的原因,我们提供replica_device_setter,来自动将variable放置在ps上…默认是轮盘转的放置策略

Initializing variables

在使用一个变量之前,必须先进行初始化。如果你用原生tensorflow,那初始化一般要手动显示完成。如果是使用slim,keras之类,variable的初始化一般是自动完成的。

Explicit initialization is otherwise useful because it allows you not to rerun potentially expensive initializers when reloading a model from a checkpoint as well as allowing determinism when randomly-initialized variables are shared in a distributed setting.

另一方面,明确地初始化可以保证你不会多次运行计算代价可能很昂贵的初始化操作,当你reload一个模型时。

一次性初始化所有变量可以使用tf.global_variables_initializer(),运行
session.run(tf.global_variables_initializer())
这个操作会把tf.GraphKeys.GLOBAL_VARIABLES 中的所有变量初始化。

也可以手动初始化特定变量,

还可以得到当前没有被初始化的变量有那些(这样就可以只初始化仍然没有初始化的变量,避免重复初始化,减小计算代价。

需要注意的是,tf.global_variables_initializer()初始化所有变量时并没有固定的顺序,所以如果你的某个variable的值依赖于另一个variable的值,那么就很可能出错。

Any time you use the value of a variable in a context in which not all variables are initialized (say, if you use a variable’s value while initializing another variable), it is best to use  variable.initialized_value() instead of  variable:

任何时候如果你处于一个不是所有变量都被初始化 的环境,最后使用myvar.initialized_value()来替代myvar

Using variables

variable可以直接看做tensor

对变量赋值可以使用assign,assign_add或者tf.variable class中的方法

Saving and Restoring

 

保存和恢复一个模型的最容易的方法就是使用tf.train.Saver object. 该object包含save和restore两个op,

使用save 或者 restore  op来保存或者恢复图中全部,或者指定的varibales

如果想在图外面恢复一个模型的checkpoint,必须先用tf.train.import_meta_graph将checkpoint中的metafile(以meta为后缀)的文件导入

这样会返回一个Saver object,然后才能执行resotre op

Checkpoint Files

 

tensorflow将variable存储为二进制文件的形式,通俗地说,就是map variable names to tensor values

当你创建了Saver object 之后,你可以选择为你保存进checkpoint files 文件的变量起一个名字。默认情况下,变量被使用tf.Variabel.name的名字。

如果想检查checkpoint 中的variable,可以使用inspect_checkpoint库,尤其是其中的print_tensors_in_checkpoint_file 函数。

Saving Variables

下面是一个如何使用Saver object 中的save操作来保存变量的例子

Restoring Variables

注意从checkpoint文件中恢复variables的时候没有必要初始化

下面是一个使用saver object 的restore op的例子:

Choosing which Variables to Save and Restore

如果tf.train.Saver()中不传入任何参数就会默认处理所有变量。

我们可以传入一些变量名,表示处理特定的变量。例子如下:

需要注意的是:

  • Saver object可以有任意多个,同一个变量也可以被任意多个Saver object save
  • restore的时候如果只是restore了一部分变量,其余的变量记得要初始化

Sharing variables

暂时用不上,有空补吧,困了orz

 

 

 

20170819近况

一转眼…暑假就要结束了…

秋招似乎也可以告一段落了…

投了蛮多的,但是昨天突然发现我用gmail邮箱发邮件有概率发不出去。。所以我也不知道到底哪些简历根本没有发出去orz

先是做了拼多多的笔试,感觉数据有点问题,390/400,没能AK有点不爽。还没面…

cvte的笔试….面了cpp和中央研究院的视觉计算…还不知道结果…面试官略菜….

奶茶厂广告部数据组(?的面试…本来说有两面,一面我也回答得不算差…结果一面之后说我技能不match他们的工作,不用二面了.。。。

看了下貌似是数据挖掘岗….听我讲了半个小时的dl cv…. 大概是我讲的太投入了orz

百度网页搜索部…rank算法工程师…因为有之前的实习记录,所以直接三面美滋滋….和面试官很聊得来…嗯…应该是拿到了…

阿里…投的cv岗位没理我…被阿里云捞了简历…还没面

sensetime给了offer…..还是比较满意的orz。。

其实好早之前基本确定了,但是仍然投了很多其他厂,一个是想体验一下秋招,一个大概是想拿到更高的offer去argue一个更好的package…

但是好像…没什么必要了….已经很满意了orz(其实是基本拿不到什么能去argue的offer了…  还是要知足常乐啊…

之后 的面试大厂还是会尝试一下(?如果工作紧就不尝试了。。。。

从2月初第一家 的hyperal到现在面了这么多家…

唯一印象深刻的就是实习时某价值观厂交叉面面试官,是非常糟糕的一次体验。

我被传达到的信息是“我厂天下第一,你连高star 的cpp项目都没有也敢来申请实习?快滚”…

感觉面试官非常不尊重人,一生黑倒不至于,但是没什么好印象就是了。对于这种大厂,惹不起,还是躲得起的…

不过还是很想拿到他们的offer,这样就可以也拒他们一次了..超记仇.jpg …感觉最近特别流行拒绝该厂offer呢2333…我也想体验一下。

 

tensorflow Session 学习笔记

tensorflow-session官方文档

说下我自己的理解:

session中文一般叫会话,可以理解成op执行时候需要的一层虚拟化的封装。

op必须在session中才能执行。

tensor也是在tensor中才可以存在(tf.variable和tensor几乎是一回事,只是tf.variable的会话不要求session,也可以理解成tf.variable在session中就成了tensor.

需要注意的是session一般会占据资源,所以在使用完记得释放,或者写成with的形式(看到with总想叫成开域语句…感觉暴露年龄orz

下面这两种形式是等价的:

session本身有一些配置,我们使用configproto:

allow_soft_placement的作用是自动选择可用的设备(如果指定的设备不可用(?)),防止指定的设备不可用而挂掉的情况。

log_device_placement :To find out which devices your operations and tensors are assigned to.

 

 

 

 

 

leetcode 146. LRU Cache(list+unordered_map)

请实现最近最少使用缓存(Least Recently Used (LRU) cache)类,需要支持 get,
set,操作。
get 操作,给出 key,获取到相应的 value (value 为非负数),如果不存在返回-1,
如果存在此 key 算作被访问过。
set 操作,设置 key,如果 key 存在则覆盖之前的 value (此时相当于访问过一次)。
如果 key 不存在,需要进行插入操作,如果此时已经 key 的数量已经到达 capacity,
这样需要淘汰掉最近最少使用(也就是上次被使用的时间距离现在最久的)的那
一项。

要求get和set的时间复杂度都是O(1)

 

使用tensorboard 生成 graph的方法

tf的文档真的是…其实就一句话啊orz

使用上还是多参考CS20SI比较好orz

CS20SI-slides2

python只获取当前目录下的文件夹及文件名

如果需要遍历文件夹下的所以文件,可以使用os.walk()方法。

举个列处当前目录所有文件夹的例子:

 

参考资料

Distributed Tensorflow : Cannot assign a device for operation save

是在使用分布式tensorflow遇到的一个错误

报错如下:

InvalidArgumentError (see above for traceback): Cannot assign a device for operation ‘save/Rest│| 2 GeForce GTX 1080 On | 0000:08:00.0 Off | N/A |
oreV2_888’: Operation was explicitly assigned to /job:worker/task:0/device:CPU:0 but available │| 24% 39C P8 12W / 180W | 0MiB / 8114MiB | 0% Default |
devices are [ /job:localhost/replica:0/task:0/cpu:0, /job:localhost/replica:0/task:0/gpu:0 ]. Make sure the device specification refers to a valid device.

其中看到Distributed Tensorflow : Cannot assign a device for operation. 中提到,可能的两个原因是:

I have mostly seen the “cannot assign a device for operation …” error in the case of people using GPU without specifying allow_soft_placement=True but in my case I am using just CPUs.

I have seen another instance of this error when users were not specifying server.target as the device of a session,thereby creating a local session but this is not the case in my code.

 

 

分布式tensorflow 设备分配 学习笔记

 

 

replica_device_setter_TF官网文档

由于看到这个函数很是激动。。。感觉这个东西也是蛮重要的。。之前完全手动分配累死辣。。。

所以单独写一篇,主要是翻译replica_device_setter的文档,之后和分布式 tensorflow 设备分配相关的内容也会放在这里

tf.train.replica_device_setter

函数原型

用法

device functions是用在tf.device(device_function) 中来自动向op objects 分配设备的。

设备的作用域优先级从内向外(类似变量的作用域

目前可以设置的域的关键字有(job, task, cpu/gpu)

如果cluster没有被定义,并且ps_tasks为0,那么该函数返回一个no-op(no-op应该就是operation界的null类型)

默认情况下,只有变量的op会被放在ps上,放置策略是在 所有ps tasks上用 Round-robin

该策略也可以自定义,参考GreedyLoadBalancingStrategy

例子

参数

  • ps_tasks: Number of tasks in the  ps job. Ignored if  cluster is provided.
  • ps_device: String. Device of the  ps job. If empty no  ps job is used. Defaults to  ps.
  • worker_device: String. Device of the  worker job. If empty no  worker job is used.
  • merge_devicesBoolean. If  True, merges or only sets a device if the device constraint is completely unset. merges device specification rather than overriding them.
  • clusterClusterDef proto or  ClusterSpec.
  • ps_ops: List of strings representing  Operation types that need to be placed on  ps devices. If  None, defaults to  ["Variable"].
  • ps_strategy: A callable invoked for every ps  Operation (i.e. matched by  ps_ops), that takes the  Operation and returns the ps task index to use. If  None, defaults to a round-robin strategy across all  ps devices.

 

 

 

其他

allow_soft_placement:session的一个属性,可以用来防止指定的设备不存在而导致无法运行的情况。设置为true会自动选择存在的设备。

 

 

python join 和 split的常用使用方法

python处理字符串果然厉害…怪不得今年面头条的那个字符串处理的题…没有竞赛经历的同学都能分分钟用py秒掉。。而我(以为语言选了就不能再改)去写c艹。。。写了一年
令人窒息的操作.jpg

参考资料: python join 和 split的常用使用方法