词向量源码解析:(5.3)ngram2vec源码解析之corpus2vocab
来源:互联网 发布:odds ends相机数据 编辑:程序博客网 时间:2024/06/05 06:06
在hyperwords工具包中,我们看到了用python几行代码就可以建立一个词典。相对于C用几百行实在是方便太多了。但是hyperwords中建立词典的过程却没有考虑主机的内存情况。建立词典的过程中很容易出现内存不够的情况。在word2vec和GloVe中都有ReduceVocab这样的函数,在建立词典中扔掉一些低频词。这样做的会导致最后的词典不全,但是在实际应用中没有什么问题。word2vec和GloVe中虽然有ReduceVocab,但是没有内存的监控,使得我们需要凭借经验去决定ReduceVocab的时机。
ngram2vec中的corpus2vocab对内存进行了监控,能让我们利用有限的内存得到尽可能完整的词典。这个代码会在内存快要不够的时候reduce词典。根据经验这个机制还是比较重要的。比如当我们引入ngram特征甚至其他更加复杂的特征的时候。词典的大小会非常的大,远远超过了内存的大小。这时我们需要能充分的利用内存,尽量能正确的去掉低频单词。下面看一下代码,这个代码考虑了ngram特征。getNgram函数从句子中的某个位置读取n元组(ngram)。
def getNgram(tokens, pos, gram): #uni:gram=1 bi:gram=2 tri:gram=3//tokens是单词列表,pos是我们要从列表的位置读取token,gram表示我们读取几元组
if pos < 0://首先读取的ngram不能越界
return None
if pos + gram > len(tokens):
return None
token = tokens[pos]//ngram的第一个单词
for i in xrange(1, gram)://ngram后几个单词,用@$连接
token = token + "@$" + tokens[pos + i]
return token
然后看一下main函数的变量。getsizeof()函数能得到变量占用的内存,不过对于词典这样的数据结构,其中的字符串占用的内存是不算在getsizeof(vocab),我们需要单独对字符串占用的内存进行统计。
ngram = int(args['--ngram'])//考虑到几阶的ngram
memory_size = float(args['--memory_size']) * 1000**3//内存的字节数1g=1000*3byte
min_count = int(args['--min_count'])//低频词阈值
vocab = {} # vocabulary (stored by dictionary)//词典
reduce_thr = 1 # remove low-frequency words when memory is insufficient//reduce机制,内存满了以后先去掉频数为1的,再满的话去掉频数为2的
memory_size_used = 0 # size of memory used by keys & values in dictionary (not include dictionary itself) //估计的目前词典中字符串占用的内存大小
下面开始构建词典,比hyperwords复杂一些,因为我们考虑了内存不足的情况。但是代码和C语言比也简单多了。
with open(args['<corpus>']) as f:
tokens_num = 0
print str(tokens_num/1000**2) + "M tokens processed."
for line in f:
print "\x1b[1A" + str(tokens_num/1000**2) + "M tokens processed."//用来打印处理的单词个数
tokens = line.strip().split()//对一行分词
tokens_num += len(tokens)
for pos in xrange(len(tokens)): //对一行tokens中每个位置遍历
for gram in xrange(1, ngram+1)://在每个位置上面考虑ngram
token = getNgram(tokens, pos, gram)//得到ngram
if token is None :
continue
if token not in vocab ://如果ngram不在词典中,就要加入词典,可能导致内存不够
memory_size_used += getsizeof(token)
vocab[token] = 1
if memory_size_used + getsizeof(vocab) > memory_size * 0.8: #reduce vocabulary when memory is insufficient//内存不够就需要reduce,0.8是经验值,占用总内存等于字符串占用内存加上词典占用内存
reduce_thr += 1//reduce的阈值提高1,后面是代码是大于等于,我们删掉频数为reduce_thr-1以及以下的单词
vocab_size = len(vocab)
vocab = {w: c for w, c in vocab.iteritems() if c >= reduce_thr}//reduce代码用python就一行,把低频词扔掉
memory_size_used *= float(len(vocab)) / vocab_size #estimate the size of memory used//因为去掉了很多单词,所以重新估计字符串占用的内存大小
else:
vocab[token] += 1//如果在词典中就频数加1
最后对词典去掉低频词以及排序以及写到磁盘,代码很简洁,如果内存大小,可能导致reduce_thr大于预设的min_count。这也是没有办法的事情,已经很充分的利用了内存了
vocab = {w: c for w, c in vocab.iteritems() if c >= min_count} #remove low-frequency words by pre-specified threshold//去掉低频词
vocab = sorted(vocab.iteritems(), key=lambda item: item[1], reverse=True) #sort vocabulary by frequency in descending order//按照词频排序,可能会用到更多的内存
save_count_vocabulary(args['<output>'], vocab)//调用统一的接口去写词典
- 词向量源码解析:(5.3)ngram2vec源码解析之corpus2vocab
- 词向量源码解析:(5.1)ngram2vec源码解析
- 词向量源码解析:(5.12)ngram2vec源码解析小结
- 词向量源码解析:(5.2)ngram2vec源码解析之uni_uni
- 词向量源码解析:(5.4)ngram2vec源码解析之corpus2pairs
- 词向量源码解析:(5.5)ngram2vec源码解析之pairs2vocab
- 词向量源码解析:(5.6)ngram2vec源码解析之pairs2counts
- 词向量源码解析:(5.7)ngram2vec源码解析之counts2shuf等
- 词向量源码解析:(5.8)ngram2vec源码解析之counts2ppmi等
- 词向量源码解析:(5.9)ngram2vec源码解析之word2vecf.py
- 词向量源码解析:(5.10)ngram2vec源码解析之glovef.py
- 词向量源码解析:(5.11)ngram2vec源码解析之中文analogy数据集
- 词向量源码解析:(6.6)fasttext源码解析之词向量1
- 词向量源码解析:(6.7)fasttext源码解析之词向量1
- 词向量源码解析:(2.1)word2vec源码解析
- 词向量源码解析:(2.7)word2vec源码解析小结
- 词向量源码解析:(3.1)GloVe源码解析
- 词向量源码解析:(3.6)GloVe源码解析小结
- 二项分布(Binomial Distribution)
- Java书单
- android studio生成签名导打包的方法
- HTML5 本地存储、新的JS-API
- linux 查看和修改PATH环境变量的方法
- 词向量源码解析:(5.3)ngram2vec源码解析之corpus2vocab
- Servlet处理用户请求和响应(二)
- DBA_FREE_SPACE查询慢的原因及解决方法
- 保研的事终于结束了,接下来就安安心心沉下来做做东西,玩玩游戏吧。
- jstl标签库常见用法
- 开发系统关键字
- odoo8 or openerp 通过xml id获取数据库id
- python项目依赖生成requirements.txt
- 【数据挖掘笔记四】数据仓库和联机分析处理