帖子

目前显示的是 二月, 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的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的分布式设计相比于它的前身DistBelief有什么改变和优势呢?

首先,DistBelief里只有两种角色:parameter server和worker。而tensorflow在摒弃parameter server这个概念,它希望把parameter server做的更generic一些。它认为,parameter server也是既需要做运算,也需要做KV存储,所以它和计算梯度的worker并没有本质的不同,只是它比较“被动”。Google希望,当想尝试一个新的优化算法时,如FTRL、Adam,不必去改parameter server的code。

于是在tensorflow中,就变成了:有一个进程负责分配任务和存储到其它节点,而其它节点负责执行收到的任务。那个分配任务的就是master节点。其它的slave节点就是传统意义上的parameter server。被分配的任务是Partial graph execution。存储是variable。整个计算流程由master节点来drive。再往上层来讲,假如你采用了training data partition,那么,每个data partition都应对应一个master节点。每个master节点都对应一个tensorflow session。每个slave节点可以同时支撑来自多个master的多个session。

Tensorflow中的session有两个实现,GrpcSession和DirectSession。前者是给分布式用的,后者是给单机用的。


一个GrpcSession的执行环境中包含一个m…

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)。