前面几章中,通过卷积实现了文本分类,并且通过使用gensim掌握了对文本进行词向量转换的方法。词嵌入是目前最常见的将文本转换成向量的方法,比较适合较复杂词袋中词组较多的情况。
使用独热编码方法对字符进行表示是一种非常简单的方法,但是由于其使用受限较大,产生的矩阵较为稀疏,因此在实用性上并不是很强,在这里统一推荐使用词嵌入的方式对词进行处理。
有些人可能会有疑问,使用word2vec的形式来计算字符的“字向量”是不是可行?完全可以,并且相对于单纯采用独热编码形式的矩阵来表示,能有更好的表现和准确度。
接下来就以中文为例,介绍字向量。
中文文本处理
中文文本处理相较于英文文本略为复杂,一个非常简单的办法就是讲中文转化成拼音的形式,使用Python提供的拼音库包,
pip install pinyin
使用方法如下,
import pypinyin
def chinese_to_pinyin(string):
pinyin = pypinyin.pinyin(string, heteronym = True)
print(pinyin)
pinyin = pypinyin.lazy_pinyin(string)
print(pinyin)
def main():
chinese_to_pinyin(" ^v^g")
if __name__ == "__main__":
main()
运行结果打印输出如下,
[['zhōng', 'zhòng'], ['wén']]
['zhong', 'wen']
可见,对于多音字,会输出多个候选拼音。
较常见的中文文本处理的方法是使用分词器对文本进行分词处理,将分词后的词数据除去停用词和副词之后制作词嵌入(即词向量化),如下文,
近日,哈尔滨市松北区多名小区业主报料称,一个健身房老板拆穿了承重墙,造成小区整栋居民楼的住户被疏散。该房屋为高层住宅,一共31层,大部分业主都是通过贷款买的房子,而健身房老板拆承重墙的行为,导致200多户居民无家可归。消息一经披露,迅速引发公众关注和热议。
“施工队在3楼给承重墙拆了,已经出现墙体开裂了,闹得业主都人心惶惶。”“普通镐子打不动,这家伙直接上专业的拆迁钩机。”“从建筑学的角度来讲,这楼废了。应力已经重新分配了,结构体系转变了,补回去没用了……这是危害公共安全!”
事发地的居民楼,是松北区裕民街道利民学苑B栋2单元。4月28日当天凌晨一点多,居民楼里240多户业主被紧急疏散。目前,业主们被临时安置到附近的酒店宾馆,当地住建部门和警方已经介入调查。
据悉,涉事的居民楼下,周围有宾馆、网吧、火锅店多家商铺。当地人士称,“那天经过这里,还觉得奇怪,几种大型机器齐上阵,最后把居民楼搞废了。”“有人租了居民楼的三楼,准备开健身房,装修时把承重墙砸穿了。事发当天,租户就被警方控制了。”
下面对上文进行分词并将其转化成词向量的形式。
读取数据
为了演示直接使用字符串作为数据的存储形式。
def vectorize():
string = "近日,哈尔滨市松北区多名小区业主报料称,一个健身房老板拆穿了承重墙,造成小区整栋居民楼的住户被疏散。该房屋为高层住宅,一共31层,大部分业主都是通过贷款买的房子,而健身房老板拆承重墙的行为,导致200多户居民无家可归。消息一经披露,迅速引发公众关注和热议。“施工队在3楼给承重墙拆了,已经出现墙体开裂了,闹得业主都人心惶惶。”“普通镐子打不动,这家伙直接上专业的拆迁钩机。”“从建筑学的角度来讲,这楼废了。应力已经重新分配了,结构体系转变了,补回去没用了……这是危害公共安全!”
事发地的居民楼,是松北区裕民街道利民学苑B栋2单元。4月28日当天凌晨一点多,居民楼里240多户业主被紧急疏散。目前,业主们被临时安置到附近的酒店宾馆,当地住建部门和警方已经介入调查。据悉,涉事的居民楼下,周围有宾馆、网吧、火锅店多家商铺。当地人士称,“那天经过这里,还觉得奇怪,几种大型机器齐上阵,最后把居民楼搞废了。”“有人租了居民楼的三楼,准备开健身房,装修时把承重墙砸穿了。事发当天,租户就被警方控制了。””
import jieba
import re
对于正文文本,首先需要对其进行清洗,去除非标准字符,这里采用re正则表达式对文本进行处理,代码如下,
def vectorize():
string = "近日,哈尔滨市松北区多名小区业主报料称,一个健身房老板拆穿了承重墙,造成小区整栋居民楼的住户被疏散。该房屋为高层住宅,一共31层,大部分业主都是通过贷款买的房子,而健身房老板拆承重墙的行为,导致200多户居民无家可归。消息一经披露,迅速引发公众关注和热议。“施工队在3楼给承重墙拆了,已经出现墙体开裂了,闹得业主都人心惶惶。”“普通镐子打不动,这家伙直接上专业的拆迁钩机。”“从建筑学的角度来讲,这楼废了。应力已经重新分配了,结构体系转变了,补回去没用了……这是危害公共安全!”事发地的居民楼,是松北区裕民街道利民学苑B栋2单元。4月28日当天凌晨一点多,居民楼里240多户业主被紧急疏散。目前,业主们被临时安置到附近的酒店宾馆,当地住建部门和警方已经介入调查。据悉,涉事的居民楼下,周围有宾馆、网吧、火锅店多家商铺。当地人士称,“那天经过这里,还觉得奇怪,几种大型机器齐上阵,最后把居民楼搞废了。”“有人租了居民楼的三楼,准备开健身房,装修时把承重墙砸穿了。事发当天,租户就被警方控制了。”"
import jieba
import re
string = re.sub(r"[a-zA-Z0-9-,。""”“!、()《》【】…]", " ", string)
string = re.sub(r" +", " ", string)
string = re.sub(" ", "", string)
print(string)
运行结果打印输出如下,
近日哈尔滨市松北区多名小区业主报料称一个健身房老板拆穿了承重墙造成小区整栋居民楼的住户被疏散该房屋为高层住宅一共层大部分业主都是通过贷款买的房子而健身房老板拆承重墙的行为导致多户居民无家可归消息一经披露迅速引发公众关注和热议施工队在楼给承重墙拆了已经出现墙体开裂了闹得业主都人心惶惶普通镐子打不动这家伙直接上专业的拆迁钩机从建筑学的角度来讲这楼废了应力已经重新分配了结构体系转变了补回去没用了这是危害公共安全事发地的居民楼是松北区裕民街道利民学苑栋单元月日当天凌晨一点多居民楼里多户业主被紧急疏散目前业主们被临时安置到附近的酒店宾馆当地住建部门和警方已经介入调查据悉涉事的居民楼下周围有宾馆网吧火锅店多家商铺当地人士称那天经过这里还觉得奇怪几种大型机器齐上阵最后把居民楼搞废了有人租了居民楼的三楼准备开健身房装修时把承重墙砸穿了事发当天租户就被警方控制了
可见,文本中的数字、中文标点符号等都特殊字符都已经被删除,而且由于删除特殊字符余留的空格也被一一删除,剩下的是完成的待分文本。
中文文本的清洗与分词
下面使用分词工具对中文文本进行分词处理。Python里,中文的常用分词工具是jieba分词库,代码如下,
def vectorize():
string = "近日,哈尔滨市松北区多名小区业主报料称,一个健身房老板拆穿了承重墙,造成小区整栋居民楼的住户被疏散。该房屋为高层住宅,一共31层,大部分业主都是通过贷款买的房子,而健身房老板拆承重墙的行为,导致200多户居民无家可归。消息一经披露,迅速引发公众关注和热议。“施工队在3楼给承重墙拆了,已经出现墙体开裂了,闹得业主都人心惶惶。”“普通镐子打不动,这家伙直接上专业的拆迁钩机。”“从建筑学的角度来讲,这楼废了。应力已经重新分配了,结构体系转变了,补回去没用了……这是危害公共安全!”事发地的居民楼,是松北区裕民街道利民学苑B栋2单元。4月28日当天凌晨一点多,居民楼里240多户业主被紧急疏散。目前,业主们被临时安置到附近的酒店宾馆,当地住建部门和警方已经介入调查。据悉,涉事的居民楼下,周围有宾馆、网吧、火锅店多家商铺。当地人士称,“那天经过这里,还觉得奇怪,几种大型机器齐上阵,最后把居民楼搞废了。”“有人租了居民楼的三楼,准备开健身房,装修时把承重墙砸穿了。事发当天,租户就被警方控制了。”"
import jieba
import re
string = re.sub(r"[a-zA-Z0-9-,。""”“!、()《》【】…]", " ", string)
string = re.sub(r" +", " ", string)
string = re.sub(" ", "", string)
print(string)
strings = jieba.lcut_for_search(string)
print(strings)
jieba库是一个用于对中文文本进行分词的工具,分词函数如下,
这里使用jieba分词对文本进行分词,之后将分词后的结果以数组的形式存储。运行结果打印输出如下,
Building prefix dict from the default dictionary ...
Loading model from cache /tmp/jieba.cache
Loading model cost 1.741 seconds.
Prefix dict has been built successfully.
['近日', '哈尔', '哈尔滨', '哈尔滨市', '北区', '松北区', '多名', '小区', '业主', '小区业主', '报料', '称', '一个', '健身', '健身房', '老板', '拆穿', '了', '承重', '承重墙', '造成', '小区', '整栋', '居民', '居民楼', '的', '住户', '被', '疏散', '该', '房屋', '为', '高层', '住宅', '高层住宅', '一共', '层', '大部', '部分', '大部分', '业主', '都', '是', '通过', '贷款', '买', '的', '房子', '而', '健身', '健身房', '老板', '拆', '承重', '承重墙', '的', '行为', '导致', '多户', '居民', '无家可归', '消息', '一经', '披露', '迅速', '引发', '公众', '关注', '和', '热议', '施工', '施工队', '在', '楼', '给', '承重', '承重墙', '拆', '了', '已经', '出现', '墙体', '开裂', '墙体开裂', '了', '闹', '得', '业主', '都', '人心', '惶惶', '人心惶惶', '普通', '镐', '子', '打', '不动', '这', '家伙', '直接', '上', '专业', '的', '拆迁', '钩机', '从', '建筑', '建筑学', '的', '角度', '来讲', '这楼', '废', '了', '应力', '已经', '重新', '分配', '重新分配', '了', '结构', '体系', '转变', '了', '补', '回去', '没用', '了', '这', '是', '危害', '公共', '安全', '公共安全', '事发', '地', '的', '居民', '居民楼', '是', '北区', '松北区', '裕民', '街道', '利民', '学苑', '栋', '单元', '月', '日', '当天', '凌晨', '一点', '一点多', '居民', '居民楼', '里', '多户', '业主', '被', '紧急', '疏散', '目前', '业主', '们', '被', '临时', '安置', '到', '附近', '的', '酒店', '宾馆', '酒店宾馆', '当地', '住建', '部门', '和', '警方', '已经', '介入', '调查', '据悉', '涉事', '的', '居民', '楼下', '周围', '有', '宾馆', '网吧', '火锅', '火锅店', '多家', '商铺', '当地', '人士', '称', '那天', '经过', '这里', '还', '觉得', '奇怪', '几种', '大型', '机器', '齐', '上阵', '最后', '把', '居民', '居民楼', '搞', '废', '了', '有人', '租', '了', '居民', '居民楼', '的', '三楼', '准备', '开', '健身', '健身房', '装修', '时', '把', '承重', '承重墙', '砸', '穿', '了', '事发', '当天', '租户', '就', '被', '警方', '控制', '了']
使用gensim构建词向量
使用gensim构建词向量的方法之前几章已经讲解,这里直接使用即可,代码如下,
def vectorize():
string = "近日,哈尔滨市松北区多名小区业主报料称,一个健身房老板拆穿了承重墙,造成小区整栋居民楼的住户被疏散。该房屋为高层住宅,一共31层,大部分业主都是通过贷款买的房子,而健身房老板拆承重墙的行为,导致200多户居民无家可归。消息一经披露,迅速引发公众关注和热议。“施工队在3楼给承重墙拆了,已经出现墙体开裂了,闹得业主都人心惶惶。”“普通镐子打不动,这家伙直接上专业的拆迁钩机。”“从建筑学的角度来讲,这楼废了。应力已经重新分配了,结构体系转变了,补回去没用了……这是危害公共安全!”事发地的居民楼,是松北区裕民街道利民学苑B栋2单元。4月28日当天凌晨一点多,居民楼里240多户业主被紧急疏散。目前,业主们被临时安置到附近的酒店宾馆,当地住建部门和警方已经介入调查。据悉,涉事的居民楼下,周围有宾馆、网吧、火锅店多家商铺。当地人士称,“那天经过这里,还觉得奇怪,几种大型机器齐上阵,最后把居民楼搞废了。”“有人租了居民楼的三楼,准备开健身房,装修时把承重墙砸穿了。事发当天,租户就被警方控制了。”"
import jieba
import re
string = re.sub(r"[a-zA-Z0-9-,。""”“!、()《》【】…]", " ", string)
string = re.sub(r" +", " ", string)
string = re.sub(" ", "", string)
print(string)
strings = jieba.lcut_for_search(string)
print(strings)
import gensim.models
model = gensim.models.word2vec.Word2Vec([strings], vector_size = 50, min_count = 1, window = 3)
print(model.wv["小区业主"])
有一个非常重要的细节需要注意,因为Word2Vec( )需要传入u一个二维数组,而示例文字通过jieba分词的结果是一个一维数组,所以需要人为在strings外加上一个数组符号从而构建一个新的二维数组,否则打印时量后会报错。
代码执行后,等待gensim训练完成后打印一个字符的向量。运行结果打印输出如下,
近日哈尔滨市松北区多名小区业主报料称一个健身房老板拆穿了承重墙造成小区整栋居民楼的住户被疏散该房屋为高层住宅一共层大部分业主都是通过贷款买的房子而健身房老板拆承重墙的行为导致多户居民无家可归消息一经披露迅速引发公众关注和热议施工队在楼给承重墙拆了已经出现墙体开裂了闹得业主都人心惶惶普通镐子打不动这家伙直接上专业的拆迁钩机从建筑学的角度来讲这楼废了应力已经重新分配了结构体系转变了补回去没用了这是危害公共安全事发地的居民楼是松北区裕民街道利民学苑栋单元月日当天凌晨一点多居民楼里多户业主被紧急疏散目前业主们被临时安置到附近的酒店宾馆当地住建部门和警方已经介入调查据悉涉事的居民楼下周围有宾馆网吧火锅店多家商铺当地人士称那天经过这里还觉得奇怪几种大型机器齐上阵最后把居民楼搞废了有人租了居民楼的三楼准备开健身房装修时把承重墙砸穿了事发当天租户就被警方控制了
Building prefix dict from the default dictionary ...
Loading model from cache /tmp/jieba.cache
Loading model cost 1.704 seconds.
Prefix dict has been built successfully.
['近日', '哈尔', '哈尔滨', '哈尔滨市', '北区', '松北区', '多名', '小区', '业主', '小区业主', '报料', '称', '一个', '健身', '健身房', '老板', '拆穿', '了', '承重', '承重墙', '造成', '小区', '整栋', '居民', '居民楼', '的', '住户', '被', '疏散', '该', '房屋', '为', '高层', '住宅', '高层住宅', '一共', '层', '大部', '部分', '大部分', '业主', '都', '是', '通过', '贷款', '买', '的', '房子', '而', '健身', '健身房', '老板', '拆', '承重', '承重墙', '的', '行为', '导致', '多户', '居民', '无家可归', '消息', '一经', '披露', '迅速', '引发', '公众', '关注', '和', '热议', '施工', '施工队', '在', '楼', '给', '承重', '承重墙', '拆', '了', '已经', '出现', '墙体', '开裂', '墙体开裂', '了', '闹', '得', '业主', '都', '人心', '惶惶', '人心惶惶', '普通', '镐', '子', '打', '不动', '这', '家伙', '直接', '上', '专业', '的', '拆迁', '钩机', '从', '建筑', '建筑学', '的', '角度', '来讲', '这楼', '废', '了', '应力', '已经', '重新', '分配', '重新分配', '了', '结构', '体系', '转变', '了', '补', '回去', '没用', '了', '这', '是', '危害', '公共', '安全', '公共安全', '事发', '地', '的', '居民', '居民楼', '是', '北区', '松北区', '裕民', '街道', '利民', '学苑', '栋', '单元', '月', '日', '当天', '凌晨', '一点', '一点多', '居民', '居民楼', '里', '多户', '业主', '被', '紧急', '疏散', '目前', '业主', '们', '被', '临时', '安置', '到', '附近', '的', '酒店', '宾馆', '酒店宾馆', '当地', '住建', '部门', '和', '警方', '已经', '介入', '调查', '据悉', '涉事', '的', '居民', '楼下', '周围', '有', '宾馆', '网吧', '火锅', '火锅店', '多家', '商铺', '当地', '人士', '称', '那天', '经过', '这里', '还', '觉得', '奇怪', '几种', '大型', '机器', '齐', '上阵', '最后', '把', '居民', '居民楼', '搞', '废', '了', '有人', '租', '了', '居民', '居民楼', '的', '三楼', '准备', '开', '健身', '健身房', '装修', '时', '把', '承重', '承重墙', '砸', '穿', '了', '事发', '当天', '租户', '就', '被', '警方', '控制', '了']
[ 0.01282488 -0.01791745 -0.01469664 -0.00351682 0.00341335 -0.00210878
-0.01040556 0.01319773 0.0175558 -0.0148411 0.01962424 0.01471681
-0.01491169 -0.00377307 0.00849714 0.0141305 -0.00733728 -0.01393338
0.00943648 -0.01807544 -0.01169678 -0.00253274 0.01097345 -0.0113619
0.00962926 -0.00086912 0.0053379 0.01280627 0.00282506 0.01542611
-0.00064837 -0.01649615 0.01834944 -0.00972557 0.00942264 -0.00779012
-0.01465465 -0.01304724 0.00937132 -0.00134354 0.00296423 -0.01786045
-0.0102826 -0.01210692 0.01686552 -0.01738032 0.01002714 -0.00171046
0.00039568 0.0175779 ]
完整代码如下,
def vectorize():
string = "近日,哈尔滨市松北区多名小区业主报料称,一个健身房老板拆穿了承重墙,造成小区整栋居民楼的住户被疏散。该房屋为高层住宅,一共31层,大部分业主都是通过贷款买的房子,而健身房老板拆承重墙的行为,导致200多户居民无家可归。消息一经披露,迅速引发公众关注和热议。“施工队在3楼给承重墙拆了,已经出现墙体开裂了,闹得业主都人心惶惶。”“普通镐子打不动,这家伙直接上专业的拆迁钩机。”“从建筑学的角度来讲,这楼废了。应力已经重新分配了,结构体系转变了,补回去没用了……这是危害公共安全!”事发地的居民楼,是松北区裕民街道利民学苑B栋2单元。4月28日当天凌晨一点多,居民楼里240多户业主被紧急疏散。目前,业主们被临时安置到附近的酒店宾馆,当地住建部门和警方已经介入调查。据悉,涉事的居民楼下,周围有宾馆、网吧、火锅店多家商铺。当地人士称,“那天经过这里,还觉得奇怪,几种大型机器齐上阵,最后把居民楼搞废了。”“有人租了居民楼的三楼,准备开健身房,装修时把承重墙砸穿了。事发当天,租户就被警方控制了。”"
import jieba
import re
string = re.sub(r"[a-zA-Z0-9-,。""”“!、()《》【】…]", " ", string)
string = re.sub(r" +", " ", string)
string = re.sub(" ", "", string)
print(string)
strings = jieba.lcut_for_search(string)
print(strings)
import gensim.models
model = gensim.models.word2vec.Word2Vec([strings], vector_size = 50, min_count = 1, window = 3)
print(model.wv["小区业主"])
def main():
vectorize()
if __name__ == "__main__":
main()
对于现实中的工程,可以执行参考而为卷积对文本处理的模型进行计算。
其他文本类型识别
对于普通文本,完成可以通过一系列的清洗和向量化处理将其转化成矩阵的形式,之后通过卷积神经网络对文本进行处理。在上一节中制作了中文向量化的处理,缺乏主题提取、去除停用词等操作。请参考之前的章节,根据需要补全代码。
对于词嵌入构成的矩阵,能否使用之前的模型去处理呢?比如ResNet,以及加上了attention机制的记忆里模型。答案是可以的。
结论
从52章起,到本章止,介绍了对文本的分词、词嵌入向量化等文本分类任务的模型。并且介绍了基于卷积神经网络的文本分类模型,认识到卷积神经网络不仅仅专注于图像特征提取,在文本分类任务里同样可以实现。