背景
给定一串文字,它是否代表一个地址? 一般地址里有xx路,xx街之类的,这些字符都是地址串的很强的特征。
但是如果仅靠这样,还是不够,比如:延安路发生重大交通事故,很明显不是地址串。 这类问题直觉上是更适合用语言模型来捕获地址的常用说法。借助tensorflow,我们可以很容易训练一个这样的模型。
训练数据
本模型中,使用了100w+个地址串,加上全国省市区县的组合(特别规整的xx省xx市xx县). 覆盖了大部分地址串的样例
北京朝阳区朝阳北路101号朝阳大悦城6楼(近星河湾)
汕头金平区汕樟立交桥底金华街口(近金华小学)
绥化肇东市利民南路
长春经济开发区临河街天地十二坊C29栋(近肯德基)
六盘水钟山区人民中路220号
宁波河头路83、87、91号
上海杨浦区殷行路752号(城达集贸市场大门口)
衢州江山市鹿溪南路鹿溪广场北侧鹿溪大厦2幢11—16号
模型输入
语言模型可以是基于字的,也也可以是基于词的,基于字的,对中文而已,也有几千个不同的字。 基于词就更大了。
基于词的则还另外需要借助分词器,分好词,而且分词也可能损失精度。 基于字的相对模型简单点,容错也更强。
我们训练的采用基于字的语言模型。这样我们对输入的地址串先按Unicode分割,然后只保留出现频率超过1的作为字典。另外,我们地址串中假设最长50个字符,要不然每段(50个)单独处理。 考虑到我们训练时采用的字符不一定能覆盖所有在线测试时的字符,如果不在字典中,字典会把它映射到id为0。 但是字符串末尾还需要特殊表示下,以区分这种不在字典里的情况,我们对每个串末尾加上来表示结尾
Label & Loss
字语言模型的本质就是给定上下文, 计算下一个位置出现的字符的概率分布,训练的时候,我们给出的地址串,隐含的给出了每个timestep的标注输出值。
一般语言模型的损失函数是困惑度,这里采用的是类似的,把每一步的交叉熵加总起来,由于timestep是固定的,这样相当于把困惑度近似放大了timestep*batch_size倍.
训练代码
这样整个训练代码其实很短,如下:
在线使用
线上代码使用c++调用的,而python训练出来的模型变量和计算图是分开存储的,我们使用tensorflow自带的工具tensorflow/python/tools/freeze_graph.py来把这些合并在一个模型文件中,然后我们C++代码中载入模型。 计算某个句子的困惑度时先把句子按Unicode字符切分,填充好input以及target对应的tensor,然后运行指定的计算节点,获取loss,计算困惑度,这里我们对困惑度做了简单归一化,困惑度越低分值越接近1,反之越接近0。