0、踩坑背景

执行Torch-RNN的时候,在LanguageModel.lua中的encode_string函数中,对start_text的各个character进行id映射编码,实现功能类似“北京天安门”-->“5 10 88 32 111”,方便后面的计算。

这个函数会利用一个全局的类似HashMap的table,hashmap中的key是character(char),value是id(int),涉及到一个从hashmap中按照key取值的操作,代码如下:

local idx = self.token_to_idx[token]
assert(idx ~= nil, 'Got invalid idx')

但是每次运行到assert语句时,都会报错,返回的是nil。

我的训练数据集的规模足够大,同时编码正确的情况下,那么我就需要从几个方面debug:

  • 这个字典table文件压根没数据(本文测试的内容)
  • token确实在table中未命中

我对 self.token_to_idx 这个table类型的变量的大小,进行打印的时候,采用了多种方式:

print(table.getn(self.token_to_idx))
print(table.maxn(self.token_to_idx))
print(#self.token_to_idx)

但是输出都为0,奇了怪了,我用如下语句打印这个table,是有值的:

for k,v in pairs(self.token_to_idx) do
print(k,v)
end

--------------------------------------------------------------------

那么这是为什么呢?明明table不为空,取table size的时候都是0?

1、lua中的table是什么,各种size函数的区别?

在上一篇《Torch-RNN运行过程中的坑 [0](一些基础概念)》中,我们了解到了lua的introduction中有一句:

自动内存管理;只提供了一种通用类型的表(table),用它可以实现数组,哈希表,集合,对象;

也就是说lua中的数组和hashmap两种数据类型是合并的,美其名曰通用类型的表。

table的API本篇不研究,抛一个链接:Lua table(表),我们先研究一下咱们碰到的问题,即如何取table的真实size。

下面有四种方法(均在Lua 5.14下进行):

  • table.getn(t)

返回table中元素的个数。给出一个调用例子:

> t1 = {, , , };
> print(table.getn(t1)) > t2 = {[]=,[]=,[]=,[]=};
> print(table.getn(t2))

这不正和我们的要求吻合嘛,继续试试:

> t3 = {[]=,[]=,[]=,[]=};
> print(table.getn(t2))
--第4个元素下标为6,非连续 > t4 = {[]=,[]=,nil,[]=};
> print(table.getn(t4))
--有nil,长度异常 > t5 = {[]=,[""]=,nil,[]=};
> print(table.getn(t5))
--有nil,长度异常 > t6 = {[]=,[""]=,[]=};
> print(table.getn(t6))
--1后面没有2,没连续上 > t7 = {[]=,[""]=,[]=};
> print(table.getn(t7))
--即使1和2两个index没有写连上,但是table首先排序后,计数为2 > t8 = {[""]=,[""]=,[""]=};
> print(table.getn(t8))
--hashmap型长度异常

好像出问题了,在index不连续的情况下、在含有nil的情况下、有hashmap、数组与hashmap混搭等情况下getn返回的结果都不正常。

----------------------------------------------------------------------------------------------------------

lua的table长度问题中,作者提出了table可以存储两种类型,一种是list类型(数组,key必为正整数),另外一种是record类型(hashmap,key为非正整数),getn函数统计的是连续的key为正整数的数目,所以我们看头两个例子是输出正常的。

所以没必要记这个规律,除了上面几个例子,getn肯定还有一些其他的规律没发现,不过记住这个getn函数要在有序正整数key的size计数时,输出才是正确的。。。

  • table.maxn(t)

Lua中的table函数库中总结的很好,在这里引用一下:

table.maxn()函数返回指定table中所有正数key值中最大的key值. 如果不存在key值为正数的元素, 则返回0. 此函数不限于table的数组部分.

  下面的例子也搬运一下:

> tbl = {[] = "a", [] = "b", [] = "c", [] = "z"}
> print(#tbl)
-- 因为26和之前的数字不连续, 所以不算在数组部分内
> print(table.maxn(tbl))
26 > tbl[91.32] = true
> print(table.maxn(tbl))
91.32
  • #t

  #方法取size,经测试,效果上应该与getn()方法一毛一样。从1开始,连续整数key的元素个数(必须从1开始计数,结果才正常)。再抛几个例子,希望看官不要花眼。。。

> t5 = {[]=,[]=,[""]=,[]=};
> print(#t5)
--1和2连续 > t5 = {[]=,[]=,[""]=,[]=};
> print(#t5)
--从1开始计数,下一个就是9了,不连续 > t5 = {[]=,[]=,[""]=,[]=};
> print(#t5)
--没从1开始计数,非常遗憾
  • for遍历cnt++

  那么难道没有API可以对hashmap计数了吗?让我这个Java流选手写Lua情何以堪。。。最后找了一位同学同样的疑问,它使用了for循环对key-value计数。。。

function count(ht)
local n = ;
for _, v in pairs(ht) do
n = n + ;
end
return n;
end

2、重点来啦,那么解决问题的方法?

相信大家看完文章,答案自然成竹于胸,也是很尴尬。那就是:

Lua中“hashmap型”table的元素计数,还得用for循环cnt++的方法。。。。

3、结论与感慨

该踩的坑还是得踩啊。。。

Torch-RNN运行过程中的坑 [1](读取Lua非空table,size为0)的更多相关文章

  1. Torch-RNN运行过程中的坑 [2](Lua的string sub函数,读取中文失败,乱码?)

    0.踩坑背景 仍然是torch-rnn/LanguageModel.lua文件中的一些问题,仍然是这个狗血的LM:encode_string函数: function LM:encode_string( ...

  2. Torch-RNN运行过程中的坑 [0](一些基础概念)

    0.Lua & LuaJIT简介 Lua 是一种轻量小巧的脚本语言,用标准C语言编写并以源代码形式开放, 其设计目的是为了嵌入应用程序中,从而为应用程序提供灵活的扩展和定制功能. Lua 是巴 ...

  3. HOWTO - Basic MSI安装包在安装运行过程中如何获取完整源路径

    有朋友问到如何在一个Windows Installer安装包中获取安装包源路径,就是在安装包运行过程中动态获取*.msi所在完整路径. 这个问题分两类,如果我们的安装包只是一个*.msi安装文件,那么 ...

  4. ionic 运行过程中动态切换API服务器地址

    ionic 运行过程中动态切换API服务器地址 keywords: ionic,phonegap,cordova,网络制式,动态切换,变更,API,服务器地址,$resource,localstora ...

  5. (转)在.NET程序运行过程中,什么是堆,什么是栈?什么情况下会在堆(栈)上分配数据?它们有性能上的区别吗?“结构”对象可能分配在堆上吗?什么情况下会发生,有什么需要注意的吗?

    转自:http://www.cnblogs.com/xiaoyao2011/archive/2011/09/09/2172427.html 在.NET程序运行过程中,什么是堆,什么是栈? 堆也就是托管 ...

  6. Jmeter运行过程中如何让Fiddler同时可以抓获到服务器的应答报文

    在默认情况下,Jmeter运行过程中,Fiddler是抓不到对应的应答报文的. 但是,在某些时候,我们希望分析Jmeter执行失败的原因,想了解Jmeter获取到的应答报文是否有问题,就需要同服务器返 ...

  7. 程序运行过程中遇到“ORA-03114: not connected to ORACLE”的问题解决

    c#,winform程序,数据批量入oracle库时用到DataAdaper的.FillSchema函数,如:da.FillSchema(dt2, SchemaType.Mapped); 程序运行一段 ...

  8. 菜鸟帮你跳过openstack配置过程中的坑

    一:前言 对于一个以前做java全栈工程师而言,而且没学过Linux,很少用虚拟机(还是在大学的时候简单的用过),去配置openstack我想我入的坑肯定比有基础的一定要多,躺在每个坑中徘徊思索的时间 ...

  9. 菜鸟帮你跳过openstack配置过程中的坑[文末新添加福利]

    一:前言 对于一个以前做java全栈工程师而言,而且没学过Linux,很少用虚拟机(还是在大学的时候简单的用过),去配置openstack我想我入的坑肯定比有基础的一定要多,躺在每个坑中徘徊思索的时间 ...

随机推荐

  1. Android数据库之基本概念(上)

    1.Android数据库简单介绍 Android通过结合使用SQLite数据库和Content Provider,提供了结构化数据的持久功能. SQLite数据库能够通过一种结构化的.易于管理的方法来 ...

  2. IOS 开发学习33 使用sqlite3

    sqlite3 命令行简单使用 sqlite3 路径 //打开数据库路径连接 select * from sqlite_master where type="table"; //显 ...

  3. Vue 表单

    1.v-model v-model不再关心初始化的value值. <!DOCTYPE html> <html lang="zh"> <head> ...

  4. C#中怎样获取当前路径的几种方法

    String apppath = System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase; //获取整个文件路径名 a ...

  5. Android双向seekbar

    ※效果 watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/disso ...

  6. Spring Boot(二)Application events and listeners

    一.自定义监听器: 1.创建: META-INF/spring.factories 2.添加: org.springframework.context.ApplicationListener=com. ...

  7. .NET Remoting与Socket、Webservice和WCF的比较及优势 (转)

    1:Socket VS Remoting 使用socket无疑是效率最高的.但是,在复杂的接口环境下,Socket的开发效率也是最低的.故在兼顾开发效率的情况下,可以使用Remoting来代替Sock ...

  8. sharepoint admin svc must be running in order to create deployment timer job 若要创建计时器作业,必须执行SVC

    sharepoint admin svc must be running in order to create deployment timer job 若要创建计时器作业.必须执行SVC       ...

  9. unity3d贴图2D

    在GUI上绘制图片步骤如下: 1.定义一个2D图片纹理变量: public Texture2D pic; 2.关联变量和贴图的关系: 在布局界面选中MainCamera,找到右侧属性列表中的pic选项 ...

  10. 设置phpcms v9黄页模块作为首页方法

    如果我们根据需要,想把黄页作为单独的网站,我们可以用模块化安装,并且首页设置,那么仿站网就说说详细的步骤.首先,我们需要安装最新版本的phpcms V9其次,下载黄页模块,然后进行根目录的替换.再次, ...