0、踩坑背景

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

function LM:encode_string(s)
local encoded = torch.LongTensor(#s)
for i = , #s do
local token = s:sub(i, i)
local idx = self.token_to_idx[token]
assert(idx ~= nil, 'Got invalid idx')
encoded[i] = idx
end
return encoded
end

上篇文章Torch-RNN运行过程中的坑 [1](读取Lua非空table,size为0)就在这部分测试table是不是空,填了个坑。

在填坑过程中,发现for...in pair table打印出的字典是没有问题的,但是上述encode_string函数的token竟然是乱码,每次从字典table中命中不了,每次返回的都是nil。

查了console编码,是没有问题的(UTF-8)。这是咋回事哩?

1、Lua中的string sub函数切分中文

我们捋一下整个工程,

第一步使用preprocess.py对文本文件转为json和hdf5文件,值得一提的是,json中使用Unicode存储字典文件;

第二步train.lua中对json和hdf5文件进行训练;

第三步sample.lua中对checkpoint和start_text进行抽样。

由于是对start_text进行character拆分时乱码,我们肯定首先对encode_string函数中的s:sub(i, i)函数进行debug。

这个sub函数首先在lua console中看看它到底返回的是啥:

> s1='a1b2c3'

> print(s1:sub(,))
a --lua中从1开始计数,和java substring和python slice不同的是,start/end index它都包含
> print(s1:sub(,))
a1
> print(s1:sub(,))
b2c3 > print(s1:sub(,))
b2c3 --lua还是比较智能,越界也没有报错,比java更脚本化一些
> print(s1:sub(,))
a1b2c3 > print(s1:sub(-,))
--脚本语言都有的负数下标

大概有个了解,就是java中的substring嘛,有些细节不一样。真的是这样吗?见下:

> s2='1a新华'
> print(s2:sub(,))
1a --前俩字母,正常
> print(s2:sub(,))
1a --WTF?这就尴尬了,我的汉字呢
> print(s2:sub(,))
1a --???
> print(s2:sub(,))
1a新 --???一个“新”字占了3个字节
> print(s2:sub(,))

> print(s2:sub(,))

> print(s2:sub(,))

> print(s2:sub(,))
新华 --???“华”字也是占了三个字节
> print(s2:sub(,))
新华
> print(string.len(s2))
--这。。。正常length 4的是8?

这“1a新华”四个字的length Lua给我输出个8,让我这个java选手情何以堪。。。。

好奇害死猫,尝试在python console下,也输出的是8,看来此处必有蹊跷。嗯。

2、各种字符编码的区别与联系?

一个汉字占了3个字符,学过计组的同学醒醒了,当年老师敲黑板的重点就是这个。。。

这里首先抛出ruanyf十年前写的一篇的浅显易懂的文章 《字符编码笔记:ASCII,Unicode和UTF-8》。太通俗易懂了,我这里简要搬运下。。。

总结一下考点:

首先,ASCII码是1byte,8bit,最多可以表示2^8=256种字符,表示英文字符绰绰有余。

但是,以中文为代表的各国优秀博大精深语言(文中说汉字有10W+),渐渐走进了国际化道路,当年定制ASCII码的同志们发现1byte根本表示不了这么多字符。

于是,我国1980年推出了简体中文GB2312(1995年推出的GBK的前身),两个字节byte表示一个汉字。

再后来,1990年,各国都开发了各自的编码,这时候一个伟大的联盟组织、非营利机构统一码联盟承担了Unicode(万国码、国际码、统一码、单一码)的标准制定,该机构致力于让Unicode方案替换既有的字符编码方案。每个国家的字符都有对应的编码区间,终于实现了同一个世界,同一套编码。。。

但是Unicode还是有些小瑕疵,没有大量推广使用,这时候UTF-8左右Unicode的一种实现方式,闪亮登场。

文中还有一些大小端、BIG-5、UTF-8 BOM方面的考点,感兴趣的同学可以点链接。

3、有点跑题,咱们的问题怎么解决,切分中文string乱码?

如果单纯的string全都是中文,那还好办了,直接三个三个切分就成,如果混合字符串呢?例如“1a新华”这样的。

这时候就要对编码区间进行判断了。

function LM:encode_string(s)
local encoded = torch.LongTensor(#s)
local i =
-- cause 中文在UTF8中存储占位3个字节,而英文仍然是1个字节[ascii]
for token in s.gmatch(s, "[%z\1-\127\194-\244][\128-\191]*") do
local idx = self.token_to_idx[token]
assert(idx ~= nil, 'Got invalid idx')
encoded[i] = idx
i = i+
end
return encoded
end

按照博文lua 含中文的字符串处理--分离字符、计算字符数、截取指定长度 中对regex的解释是:

  1. --[[
  2. UTF8的编码规则:
  3. 1. 字符的第一个字节范围: 0x00—0x7F(0-127),或者 0xC2—0xF4(194-244); UTF8 是兼容 ascii 的,所以 0~127 就和 ascii 完全一致
  4. 2. 0xC0, 0xC1,0xF5—0xFF(192, 193 和 245-255)不会出现在UTF8编码中
  5. 3. 0x80—0xBF(128-191)只会出现在第二个及随后的编码中(针对多字节编码,如汉字)
  6. ]]

这样就不会出现问题了~

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

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

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

  2. Torch-RNN运行过程中的坑 [1](读取Lua非空table,size为0)

    0.踩坑背景 执行Torch-RNN的时候,在LanguageModel.lua中的encode_string函数中,对start_text的各个character进行id映射编码,实现功能类似“北京 ...

  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. C#中StreamReader读取中文出现乱码

    转自yhrun原文C#中StreamReader读取中文出现乱码 原因是自Windows 2000之后的操作系统在文件处理时默认编码采用Unicode 所以.NET文件的默认编码也是Unicode.除 ...

  9. [转]C#中StreamReader读取中文出现乱码

    摘自:C#中StreamReader读取中文出现乱码 原因是自Windows 2000之后的操作系统在文件处理时默认编码采用Unicode所以.NET文件的默认编码也是Unicode.除非另外指定,S ...

随机推荐

  1. FFMpeg框架代码阅读

    http://blog.csdn.net/wstarx/article/details/1572393 FFMPEG源码分析(二) http://www.cnblogs.com/qingquan/ar ...

  2. django2自动发现项目中的url

    根据路飞学城luffycity.com 的crm项目修改的 1 url入口:rbac/urls.py urlpatterns = [ ... # 批量操作权限 re_path(r'^multi/per ...

  3. Spring-1 之入门

    (一)简单对象Spring  XML配置说明 使用Spring (Spring 3.0) 实现最简单的类映射以及引用,属性赋值: 1.1.新建类UserModel: 1 2 3 4 5 6 7 8 9 ...

  4. ionic 项目使用百度地图插件(cordova-qdc-baidu-location)

    现在我们使用'Weizhe He'提供的cordova-qdc-baidu-location来尝试创建简单的定位app. Stpe1:创建一个项目 Stpe2:申请百度地图API秘钥     应用类型 ...

  5. centos7(vmware install) 安装EMQ注意事项 ---控制台远程访问

    若想远端访问控制台,需打开对于端口 TCP 服务端口占用 EMQ 2.0 消息服务器默认占用的 TCP 端口包括: 1883 MQTT 协议端口 8883 MQTT/SSL 端口 8083 MQTT/ ...

  6. 深度学习之Matlab 转C++在iOS上測试CNN手型识别

    1 前言 在上一篇Blog.我介绍了在iOS上执行CNN的一些方法. 可是,一般来说.我们须要一个性能强劲的机器来跑CNN,我们仅仅只是须要将得到的结果用于移动端. 之前在Matlab使用UFLDL的 ...

  7. IDirect3DDevice9::SetTexture的stage参数

    HRESULT IDirect3DDevice9::SetTexture(DWORD Stage, IDirect3DBaseTexture9 *pTexture) 其中Stage并不是“阶段”的意思 ...

  8. Mac 學習系列之Python Challenge 11-20

    11.给你一个正整数列表 L, 如 L=[2,8,3,50], 输出L内全部数字的乘积末尾0的个数, 如例子L的结果为2.(提示:不要直接相乘,数字非常多,可能溢出) Answer: n_2 = 0 ...

  9. 如何改变iframe滚动条的样式?

    如何改变iframe滚动条的样式? web前端开发 css javascript iframe html RayLiao 2014年11月19日提问 · 2014年11月20日更新 关注 关注 收藏 ...

  10. 李洪强和你一起学习前端之(3)Css基础和选择器

    大家好! 经过了前面的学习,是不是对前端的学习有了初步的了解.虽然我之前有iOS开发的经验,现在接触一门新的语言,对我来说 有一定的优势,但是一门技术对于谁来说都是公平的,我承认,我在接触新知识的时候 ...