也就是构造一棵Huffman Tree,输入是按照词汇频次由高到低排序的

采用层次SoftMax的做法,是为了使得训练和预测时候的softmax输出加速,原有multinomal softmax,是和

训练词汇量|V|成正比的,而现在由于二叉树的特性,变成了log(|V|),也就是平均每个预测只做log(|V|)次

的binary的softmax。当然还有另外一种不采用HSTree的方法也就是nce(Noise Contrastive Estimation),后面再分析。

 
 

由于</s>会被统计,这里为了模拟这个,用</s>代替了 "我"

[root@cq01-forum-rstree01.cq01.baidu.com faster-rnnlm]# cat shijiebei.txt

</s> 喜欢 观看 巴西 足球 世界杯

</s> 喜欢 观看 巴西 足球

</s> 喜欢 观看 巴西 足球

</s> 喜欢 观看 巴西

</s> 喜欢 观看 巴西

</s> 喜欢 观看

</s> 喜欢

喜欢

[root@cq01-forum-rstree01.cq01.baidu.com faster-rnnlm]# pwd

/home/users/chenghuige/other/faster-rnnlm.debug/faster-rnnlm

 
 

(gdb) p vocab

$63 = (const Vocabulary &) @0x7fffffffdb60: {static kWordOOV = 4294967295, words_ = std::vector of length 6, capacity 8 = {{freq = 15, word = 0x6ae1c0 "</s>"}, {freq = 8,

word = 0x6aea30 "\317\262\273\266"}, {freq = 6, word = 0x6ae4a0 "\271\333\277\264"}, {freq = 5, word = 0x6aead0 "\260\315\316\367"}, {freq = 3, word = 0x6aeaf0 "\327\343\307\362"}, {freq = 1,

word = 0x6aeba0 "\312\300\275\347\261\255"}}, hash_impl_ = 0x6ae780}

(gdb) n

203         for (int branch = 0; branch < ARITY; ++branch) {

(gdb) n

204         if (next_leaf_node >= 0 && weight[next_leaf_node] < weight[next_inner_node]) {

(gdb) c

Continuing.

 
 

Breakpoint 6, HSTree::CreateHuffmanTree (vocab=..., layer_size=5) at hierarchical_softmax.cc:222

222         return new HSTree(vocab.size(), layer_size, children);

(gdb) p children

$64 = std::vector of length 10, capacity 10 = {5, 4, 6, 3, 2, 1, 7, 8, 0, 9}

(gdb) p weight

$65 = std::vector of length 13, capacity 13 = {15, 8, 6, 5, 3, 1, 4, 9, 14, 23, 38, 0, 0}

 
 

Breakpoint 7, HSTree::Tree::Tree (this=0x6aedf0, leaf_count=6, children=std::vector of length 10, capacity 10 = {...}) at hierarchical_softmax.cc:165

165        }

(gdb) p Tree

$66 = {void (HSTree::Tree * const, int, const std::vector<int, std::allocator<int> > &)} 0x418718 <HSTree::Tree::Tree(int, std::vector<int, std::allocator<int> > const&)>

(gdb) p *this

$67 = {leaf_count_ = 6, root_node_ = 10, tree_height_ = 4, children_ = std::vector of length 10, capacity 10 = {5, 4, 6, 3, 2, 1, 7, 8, 0, 9}, path_lengths_ = std::vector of length 6, capacity 6 = {

2, 4, 4, 4, 5, 5}, points_ = std::vector of length 246, capacity 246 = {10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,

0, 10, 9, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 9, 8, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,

0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 9, 7, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 9, 7, 6,

4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0...}, branches_ = std::vector of length 240, capacity 240 = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,

0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,

0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,

0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0...}}

 
 

仿照写了一个简化版的
这个看起来更清楚一些

//主要输出接口是根据wordId来定位 路径上面的node和branch

class HuffmanTree

{

public:

//默认假定输入的freqs是从大到小排好序的 needSort = false

//@TODO 对应 NumBranch不是2 比如3叉huffman 要检查叶子数目是否ok

HuffmanTree(const vector<int64>& freqs, int numBranchces = 2)

:_numBranches(numBranchces),

_numLeaves(freqs.size()),

_numInterNodes(freqs.size() - 1),

_numNodes(_numLeaves + _numInterNodes),

_childs(_numBranches, _numInterNodes),

_root(_numNodes - 1),

_weight(freqs.begin(), freqs.end()),

_nodePaths(_numLeaves),

_branchPaths(_numLeaves)

{

Init();

Build();

}

 
 

int NumBranches() const

{

return _numBranches;

}

 
 

bool IsLeaf(int node) const

{

return node < _numLeaves;

}

 
 

int Root() const

{

return _root;

}

 
 

int NumLeaves() const

{

return _numLeaves;

}

 
 

size_t size() const

{

return _numLeaves;

}

 
 

const vector<int>& NodePaths(int node) const

{

return _nodePaths[node];

}

 
 

const vector<int>& BranchPaths(int node) const

{

return _branchPaths[node];

}

 
 

int Height() const

{

return _height;

}

 
 

protected:

private:

void Init()

{

_weight.resize(_numNodes, std::numeric_limits<int64>::max());

}

 
 

int InterNodeIndex(int index) const

{

return _numLeaves + index;

}

 
 

void Build()

{

int minLeafIndex = _numLeaves - 1;

int minInterIndex = _numLeaves;

 
 

vector<int> parents(_numNodes);

vector<int> branches(_numNodes);

//每次选取_numBranches个最小的节点,并将它们的和按照顺序

for (int interIndex = 0; interIndex < _numInterNodes; interIndex++)

{

int64 weight = 0;

int index = InterNodeIndex(interIndex);

for (int branch = 0; branch < _numBranches; branch++)

{

if (minLeafIndex >= 0 && _weight[minLeafIndex] <= _weight[minInterIndex])

{

weight += _weight[minLeafIndex];

_childs[branch][interIndex] = minLeafIndex;

parents[minLeafIndex] = index;

branches[minLeafIndex] = branch;

minLeafIndex--;

}

else

{

weight += _weight[minInterIndex];

_childs[branch][interIndex] = minInterIndex;

parents[minInterIndex] = index;

branches[minInterIndex] = branch;

minInterIndex++;

}

}

_weight[index] = weight;

}

 
 

for (int leafNode = 0; leafNode < _numLeaves; leafNode++)

{

for (int node = leafNode; node != _root; node = parents[node])

{

_nodePaths[leafNode].push_back(parents[node]);

_branchPaths[leafNode].push_back(branches[node]);

}

if (_branchPaths[leafNode].size() > _height)

{

_height = _branchPaths[leafNode].size();

}

std::reverse(_nodePaths[leafNode].begin(), _nodePaths[leafNode].end());

std::reverse(_branchPaths[leafNode].begin(), _branchPaths[leafNode].end());

}

}

 
 

private:

int _numBranches = 2;

 
 

//@TODO 目前都是只考虑int 后面考虑改为 WordIndex ? unsigned

int _numLeaves;

int _numInterNodes;

int _numNodes;

int _root;

int _height = 0;

 
 

//存储所有node的weight最开始存储所有叶子节点从大到小排列,然后存储内部节点从小到大排列,root节点就是最后一个节点

//保持和faster-rnnlm中策略一致

vector<int64> _weight;

ufo::Matrix<int> _childs;

 
 

//记录每一个叶子节点对应从root到它自身路径的所有节点,不包括它自己

vector<vector<int> > _nodePaths;

//记录每一个叶子节点对应从root到它自身的所有路径的branch标记 比如 010100

vector<vector<int> > _branchPaths;

};

 
 

测试程序

TEST(huffmantree, func)

{

vector<int64> vec = { 15, 8, 6, 5, 3, 1 };

HuffmanTree tree(vec);

Pvec(tree._weight);

for (int i = 0; i < tree.NumBranches(); i++)

{

Pval(i);

Pvec(tree._childs[i]);

}

 
 

for (size_t i = 0; i < tree.size(); i++)

{

Pval(i);

Pvec(tree.NodePaths(i));

Pvec(tree.BranchPaths(i));

}

Pval(tree.Height());

}

 
 

测试结果

[root@cq01-forum-rstree01.cq01.baidu.com ds]# pwd

/home/users/chenghuige/rsc/app/search/sep/anti-spam/gezi/test/ds

[root@cq01-forum-rstree01.cq01.baidu.com ds]# ./test_huffmantree

[==========] Running 1 test from 1 test case.

[----------] Global test environment set-up.

[----------] 1 test from huffmantree

[ RUN ] huffmantree.func

I1109 16:06:23.855368 26257 test_huffmantree.cc:32] tree._weight --- 11

I1109 16:06:23.855466 26257 test_huffmantree.cc:32] 0 15

I1109 16:06:23.855478 26257 test_huffmantree.cc:32] 1 8

I1109 16:06:23.855484 26257 test_huffmantree.cc:32] 2 6

I1109 16:06:23.855489 26257 test_huffmantree.cc:32] 3 5

I1109 16:06:23.855494 26257 test_huffmantree.cc:32] 4 3

I1109 16:06:23.855499 26257 test_huffmantree.cc:32] 5 1

I1109 16:06:23.855504 26257 test_huffmantree.cc:32] 6 4

I1109 16:06:23.855509 26257 test_huffmantree.cc:32] 7 9

I1109 16:06:23.855515 26257 test_huffmantree.cc:32] 8 14

I1109 16:06:23.855520 26257 test_huffmantree.cc:32] 9 23

I1109 16:06:23.855525 26257 test_huffmantree.cc:32] 10 38

I1109 16:06:23.855530 26257 test_huffmantree.cc:35] i --- [0]

I1109 16:06:23.855538 26257 test_huffmantree.cc:36] tree._childs[i] --- 5

I1109 16:06:23.855543 26257 test_huffmantree.cc:36] 0 5

I1109 16:06:23.855550 26257 test_huffmantree.cc:36] 1 6

I1109 16:06:23.855554 26257 test_huffmantree.cc:36] 2 2

I1109 16:06:23.855559 26257 test_huffmantree.cc:36] 3 7

I1109 16:06:23.855563 26257 test_huffmantree.cc:36] 4 0

I1109 16:06:23.855569 26257 test_huffmantree.cc:35] i --- [1]

I1109 16:06:23.855574 26257 test_huffmantree.cc:36] tree._childs[i] --- 5

I1109 16:06:23.855579 26257 test_huffmantree.cc:36] 0 4

I1109 16:06:23.855584 26257 test_huffmantree.cc:36] 1 3

I1109 16:06:23.855589 26257 test_huffmantree.cc:36] 2 1

I1109 16:06:23.855594 26257 test_huffmantree.cc:36] 3 8

I1109 16:06:23.855599 26257 test_huffmantree.cc:36] 4 9

I1109 16:06:23.855604 26257 test_huffmantree.cc:41] i --- [0]

I1109 16:06:23.855610 26257 test_huffmantree.cc:42] tree.NodePaths(i) --- 1

I1109 16:06:23.855615 26257 test_huffmantree.cc:42] 0 10

I1109 16:06:23.855620 26257 test_huffmantree.cc:43] tree.BranchPaths(i) --- 1

I1109 16:06:23.855626 26257 test_huffmantree.cc:43] 0 0

I1109 16:06:23.855631 26257 test_huffmantree.cc:41] i --- [1]

I1109 16:06:23.855636 26257 test_huffmantree.cc:42] tree.NodePaths(i) --- 3

I1109 16:06:23.855641 26257 test_huffmantree.cc:42] 0 10

I1109 16:06:23.855646 26257 test_huffmantree.cc:42] 1 9

I1109 16:06:23.855651 26257 test_huffmantree.cc:42] 2 8

I1109 16:06:23.855656 26257 test_huffmantree.cc:43] tree.BranchPaths(i) --- 3

I1109 16:06:23.855662 26257 test_huffmantree.cc:43] 0 1

I1109 16:06:23.855667 26257 test_huffmantree.cc:43] 1 1

I1109 16:06:23.855672 26257 test_huffmantree.cc:43] 2 1

I1109 16:06:23.855677 26257 test_huffmantree.cc:41] i --- [2]

I1109 16:06:23.855682 26257 test_huffmantree.cc:42] tree.NodePaths(i) --- 3

I1109 16:06:23.855687 26257 test_huffmantree.cc:42] 0 10

I1109 16:06:23.855692 26257 test_huffmantree.cc:42] 1 9

I1109 16:06:23.855697 26257 test_huffmantree.cc:42] 2 8

I1109 16:06:23.855702 26257 test_huffmantree.cc:43] tree.BranchPaths(i) --- 3

I1109 16:06:23.855707 26257 test_huffmantree.cc:43] 0 1

I1109 16:06:23.855711 26257 test_huffmantree.cc:43] 1 1

I1109 16:06:23.855716 26257 test_huffmantree.cc:43] 2 0

I1109 16:06:23.855721 26257 test_huffmantree.cc:41] i --- [3]

I1109 16:06:23.855726 26257 test_huffmantree.cc:42] tree.NodePaths(i) --- 3

I1109 16:06:23.855731 26257 test_huffmantree.cc:42] 0 10

I1109 16:06:23.855736 26257 test_huffmantree.cc:42] 1 9

I1109 16:06:23.855741 26257 test_huffmantree.cc:42] 2 7

I1109 16:06:23.855746 26257 test_huffmantree.cc:43] tree.BranchPaths(i) --- 3

I1109 16:06:23.855751 26257 test_huffmantree.cc:43] 0 1

I1109 16:06:23.855756 26257 test_huffmantree.cc:43] 1 0

I1109 16:06:23.855762 26257 test_huffmantree.cc:43] 2 1

I1109 16:06:23.855767 26257 test_huffmantree.cc:41] i --- [4]

I1109 16:06:23.855770 26257 test_huffmantree.cc:42] tree.NodePaths(i) --- 4

I1109 16:06:23.855775 26257 test_huffmantree.cc:42] 0 10

I1109 16:06:23.855780 26257 test_huffmantree.cc:42] 1 9

I1109 16:06:23.855785 26257 test_huffmantree.cc:42] 2 7

I1109 16:06:23.855790 26257 test_huffmantree.cc:42] 3 6

I1109 16:06:23.855795 26257 test_huffmantree.cc:43] tree.BranchPaths(i) --- 4

I1109 16:06:23.855800 26257 test_huffmantree.cc:43] 0 1

I1109 16:06:23.855805 26257 test_huffmantree.cc:43] 1 0

I1109 16:06:23.855810 26257 test_huffmantree.cc:43] 2 0

I1109 16:06:23.855814 26257 test_huffmantree.cc:43] 3 1

I1109 16:06:23.855819 26257 test_huffmantree.cc:41] i --- [5]

I1109 16:06:23.855824 26257 test_huffmantree.cc:42] tree.NodePaths(i) --- 4

I1109 16:06:23.855829 26257 test_huffmantree.cc:42] 0 10

I1109 16:06:23.855834 26257 test_huffmantree.cc:42] 1 9

I1109 16:06:23.855839 26257 test_huffmantree.cc:42] 2 7

I1109 16:06:23.855844 26257 test_huffmantree.cc:42] 3 6

I1109 16:06:23.855849 26257 test_huffmantree.cc:43] tree.BranchPaths(i) --- 4

I1109 16:06:23.855854 26257 test_huffmantree.cc:43] 0 1

I1109 16:06:23.855859 26257 test_huffmantree.cc:43] 1 0

I1109 16:06:23.855865 26257 test_huffmantree.cc:43] 2 0

I1109 16:06:23.855870 26257 test_huffmantree.cc:43] 3 0

I1109 16:06:23.855875 26257 test_huffmantree.cc:45] tree.Height() --- [4]

[ OK ] huffmantree.func (0 assertion, 0 ms)

[----------] 1 test from huffmantree (0 ms total)

 
 

[----------] Global test environment tear-down

[==========] 1 test from 1 test case ran. (0 assertion total, 0 ms total)

[ PASSED ] 1 test.

 
 

Faster-rnnlm代码分析2 - HSTree的构造的更多相关文章

  1. tensorflow faster rcnn 代码分析一 demo.py

    os.environ["CUDA_VISIBLE_DEVICES"]=2 # 设置使用的GPU tfconfig=tf.ConfigProto(allow_soft_placeme ...

  2. tensorflow笔记:多层LSTM代码分析

    tensorflow笔记:多层LSTM代码分析 标签(空格分隔): tensorflow笔记 tensorflow笔记系列: (一) tensorflow笔记:流程,概念和简单代码注释 (二) ten ...

  3. angular代码分析之异常日志设计

    angular代码分析之异常日志设计 错误异常是面向对象开发中的记录提示程序执行问题的一种重要机制,在程序执行发生问题的条件下,异常会在中断程序执行,同时会沿着代码的执行路径一步一步的向上抛出异常,最 ...

  4. wifi display代码 分析

    转自:http://blog.csdn.net/lilian0118/article/details/23168531 这一章中我们来看Wifi Display连接过程的建立,包含P2P的部分和RTS ...

  5. JQuery html API支持解析执行Javascript脚本功能实现-代码分析

    JQuery html用法(功能类似innerHTML) 开发中需要使用Ajax技术来更新页面局部区域, 使用的方法是ajax获取html代码段(字符串),然后将这个html代码段作为参数,传入目标D ...

  6. lighttpd与fastcgi+cgilua原理、代码分析与安装

    原理 http://www.cnblogs.com/skynet/p/4173450.html 快速通用网关接口(Fast Common Gateway Interface/FastCGI)是通用网关 ...

  7. 虚拟机创建流程中neutron代码分析(二)

    前言: 当nova服务发送了创建port的restful调用信息之后,在neutron服务中有相应的处理函数来处理调用.根据restful的工作原理,是按照 paste.ini文件中配置好的流程去处理 ...

  8. Hive metastore整体代码分析及详解

    从上一篇对Hive metastore表结构的简要分析中,我再根据数据设计的实体对象,再进行整个代码结构的总结.那么我们先打开metadata的目录,其目录结构: 可以看到,整个hivemeta的目录 ...

  9. (五) vivi代码分析

    目录 vivi代码分析 初始化注册 使用open/read/ioctl 系统调用分析 ioctl流程一览 总结 title: vivi代码分析 date: 2019/4/23 19:30:00 toc ...

随机推荐

  1. event相关

    event.button 事件属性可返回一个整数,指示当事件被触发时哪个鼠标按键被点击. event.keyCode  事件属性可返回一个整数,指示当事件被触发时哪个键盘按键被点击. <scri ...

  2. javascript中数组concat()join()split()

    concat() 方法用于连接两个或多个数组. 该方法不会改变现有的数组,而仅仅会返回被连接数组的一个副本. 所以 <script type="text/javascript" ...

  3. hdu1455 dfs+剪枝

    Sticks Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Subm ...

  4. ubuntu查看端口占用

    查看端口号 sudo netstat -ltnp | 结束进程 sudo kill pid

  5. 【架构】linkerd:来自Twitter为微服务而生的开源RPC解决方案

    大家要如何以规模化方式运维微服务应用程序?实践当中会出现哪些问题,我们又该如何加以解决?在大规模与非预测性工作负载场景当中,我们需要满足哪些条件才能运行一款大型微服务应用程序,而又能够确保不必受到功能 ...

  6. JavaScript——特殊点总结

    首先,== equality 等同,=== identity 恒等. ==, 两边值类型不同的时候,要先进行类型转换,再比较. ===,不做类型转换,类型不同的一定不等. 下面分别说明: 先说 === ...

  7. POJ 2676

    http://poj.org/problem?id=2676 深搜的题目. 题意呢就是一个数独的游戏,应该都知道规则. 思路:我的思路很简单,就是用数组来判断某个数字是否可以使用,而每一个数字都由三个 ...

  8. 方法重写和方法重载;this关键字和super关键字

    1:方法重写和方法重载的区别?方法重载能改变返回值类型吗? 方法重写: 在子类中,出现和父类中一模一样的方法声明的现象. 方法重载: 同一个类中,出现的方法名相同,参数列表不同的现象. 方法重载能改变 ...

  9. 用C#读取txt文件的方法

    1.使用FileStream读写文件 文件头: using System;using System.Collections.Generic;using System.Text;using System ...

  10. ASM:《X86汇编语言-从实模式到保护模式》第10章:32位x86处理器的编程架构

    ★PART1:32位的x86处理器执行方式和架构 1. 寄存器的拓展(IA-32) 从80386开始,处理器内的寄存器从16位拓展到32位,命名其实就是在前面加上e(Extend)就好了,8个通用寄存 ...