博文

目前显示的是 二月, 2017的博文

纯C++的tensorflow trainer

今天写了一个纯C++的tensorflow trainer。大体来讲,main函数里要干这么几件事情:

创建grpc serverload MetaGraph创建session,执行init OP从meta graph得到queue def,创建并运行queue执行training loopsave model 这里的meta graph是用python生成的。主要是因为C++的API还没有把auto gradient做完善。不仅如此,目前用C++构造graph的代码远远比python复杂,没有任何优势。
training loop的跳出方式有两种。 一种是等待抛出out of range错误。这个在C++中可以通过检查run方法的返回值,在python中可以catch异常。 另一种是显式的设置step个数。这种一般需要预先知道有多少training samples。sample_count * iteration_count/mini_batch_size就可以得到max step。这种通常用于需要按iteration调节learning rate的场景。
唔,折腾一半天有啥实际好处呢?我拿alexnet在没有GPU的机器上试了下,performance并没有什么差别。主要是因为对于这样的复杂的网络结构,python层所占的cost很小。我准备明天再在有GPU的机器上试一试看。

mysql jdbc client端也加了一个maxAllowedPacket参数

不知道这是从哪个版本开始的,mysql jdbc client端也加了一个maxAllowedPacket参数。
所以我一再的修改server上的 max_allowed_packet 设置都没有用。

mysql> show global variables like '%packet%';
+--------------------------+------------+
| Variable_name            | Value      |
+--------------------------+------------+
| max_allowed_packet       | 16777216   |
| slave_max_allowed_packet | 1073741824 |
+--------------------------+------------+
2 rows in set (0.00 sec)


java里还是报告

Caused by: com.mysql.cj.jdbc.exceptions.PacketTooBigException: Packet for query is too large (100,152 > 65,535). You can change this value on the server by setting the 'max_allowed_packet' variable.
at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:100)
at com.mysql.cj.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:1983)
at com.mysql.cj.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:1936)
at com.mysql.cj.jdbc.StatementImpl.executeQuery(StatementImpl.java:1422)

FUCK!

解决办法就是client端也得改

tensorflow alexnet performance test

放一些最近做的测试

测试1:
tutorials\image\alexnet\alexnet_benchmark.py:
网络结构:
conv1   [128, 56, 56, 64]
pool1   [128, 27, 27, 64]
conv2   [128, 27, 27, 192]
pool2   [128, 13, 13, 192]
conv3   [128, 13, 13, 384]
conv4   [128, 13, 13, 256]
conv5   [128, 13, 13, 256]
pool5   [128, 6, 6, 256]

batch size=128

E5 1630-v3 4核
 step 0, duration = 1.412
 Forward across 10 steps, 1.334 +/- 0.039 sec / batch
 step 0, duration = 4.181
 Forward-backward across 10 steps, 4.175 +/- 0.170 sec / batch

GTX 970:
 step 0, duration = 0.046
 Forward across 1 steps, 0.046 +/- 0.000 sec / batch
 step 0, duration = 0.137
 Forward-backward across 1 steps, 0.137 +/- 0.000 sec / batch

K20m:
  Forward across 100 steps, 0.093 +/- 0.001 sec / batch
  Forward-backward across 100 steps, 0.253 +/- 0.001 sec / batch


测试2,model/slim下完整的training:
alexnet v2 batch size=128
K20m: 0.35s
gtx 970: 0.2s
E5 1630-v3: 27s

inception v2: batch size=32
K20m: 0.83s
gtx 970: 0.52s


还有些我没贴出来。我觉得会不会是哪里搞错了。。。。太诡异 首先,不同CPU的性能差不多。尤其是20核的居然和普通家用的4核差不多。 其次…

docker 1.13默认会在iptables里drop forward包

我发现我在升级docker 1.13后,我的openvpn就不能用了。经水木Dieken指点,发现这是docker更改了默认行为
https://github.com/docker/docker/pull/28257

解决办法有好几种:

1. 根据自己的情况添加白名单
sudo iptables -I FORWARD -i tun+ -o eth0 -s 192.168.0.0/16 -m conntrack --ctstate NEW -j ACCEPT
sudo iptables -I FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
sudo iptables -t nat -A POSTROUTING -s 192.168.0.0/16 -o eth0  -j MASQUERADE  (这条原本就需要)

2. 把默认规则改回ACCEPT
sudo iptables -P FORWARD ACCEPT

3. 修改sysctl的默认设置
只要sysctl里的ip foward不是docker打开的,docker就不会把默认的drop规则添加进去。

tensorflow distributed runtime初窥

图片
Tensorflow的核心是一个graph execution engine。所以,分布式,对于tensorflow而言,最主要是如何通过多机器的并行来获得对单个graph execution的加速。为了简单,本文只考虑graph是有向无圈图(DAG)这么一种情况。

一些基本概念:Cluster、Server,Device 在这整个分布式系统中,每个endpoint(一般是指ip:port)对应一个Server。一个进程里可以有一个或多个Server。Server和Server之间可以通过TCP(或其它替代协议)进行通信。

一个Tensorflow的Cluster包含多个Job,一个Job包含多个task,每一个task都是一个进程。
Job相当于Server Role。一般是分成"ps"和"worker"两种。
每个task会有1个或多个device, 如"cpu:0"、"gpu:0"。在创建graph的时候,可以指定node被place到哪个device上。tensor在device和device之间的传输由tensorflow distributed runtime自动完成。这就是tensorflow的分布式的核心设计思想。


在单机版的实现中,Tensorflow已经支持用多线程的方式对执行进行加速。那么分布式就是要把多线程变成多进程,把以内存copy、DMA为主的数据传输变成以tcp为载体。它的基本思想是:对DAG中的每条边,如果它的两个顶点不在同一个device上,那么就把这条边切断,替换成一对send/recv节点。于是得到的新图中,每个连通分支一定在同一个device上。然后将每个连通分支发送到对应的机器上去执行。

tensorflow的分布式设计相比于它的前身DistBelief有什么改变和优势呢?

首先,DistBelief里只有两种角色:parameter server和worker。而tensorflow在摒弃parameter server这个概念,它希望把parameter server做的更generic一些。它认为,parameter server也是既需要做运算,也需要做KV存储,所以它和计算梯度的worker并没有本质的不同,只是它比较“被动”。Goo…

Windows下用copy命令合并文件的时候小心末尾的0x1A

把几个文本文件合并成同一个,在Linux下很简单,
cat src*.txt > dest.txt
就可以了。

在Windows下可以用copy命令:

copy src*.txt dest.txt

但是这样复制出来的文件,dest.txt的末尾会多一个0x1A。这个是Windows系统中特有的eof-of-file marker。这个"Feature"害得我debug了好久。

解决办法:
在源文件的后面加/a
在目的文件的后面加/b
同时,如果是在写脚本,别忘了在命令的最后加一个/y。

例子:

copy tmpdir\part* /a out.txt /b /y

神经网络语言模型

什么是统计语言模型?

"A language model is a function that puts a probability measure over strings drawn from some vocabulary" -- 《Introduction to Information Retrieval》

在实际使用中,一般都是n-gram模型。即,根据前n-1个词判断第n个词的出现概率。由于训练集中的样本(strings)是变长的,所以需要在原始的词表中加入两个特殊的token: START 和 STOP。前者用于表示序列的开始,后者用于表示结束。

下面举个tri-gram的例子。对tri-gram来说:

$$ p(x_1,x_2, ... , x_n) = \prod_{i=1}^np(x_i|x_{i-2},x_{i-1})$$

比如对the dog barks这句话来说,
p(the dog barks STOP) = p(the | START, START) * p(dog| START, the) * p(barks| the, dog) * p(STOP | dog, barks)

这里的概率函数p,一般是通过统计或者机器学习的方式得到的。我个人的理解是:统计语言模型并不是为了对人类的某种语言建立一个通用的模型。因为同一个词在不同的文档集中出现的频率差别很大。
其次,样本中没有出现的,不代表它的概率就是0。平滑化,即为这些未出现过的strings赋予一个非0 的概率,在传统的以counting为主的语言模型中扮演着至关重要的角色。

Distributed representation 是20世纪以Hinton 为代表的Connectionism的一个老旧概念。所有的神经网络模型,都可以认为是input的一种Distributed representation。所以我觉得可以先不去考虑这两个词的意思。常与之混淆的是Distributional representation,这个通常指的是空间向量模型(VSM)。