利用shell脚本快速高效地对文本分类进行数据预处理

上一篇博文概括地介绍了文本分类时数据预处理涉及到的一些操作,本篇博文将结合本人正在做的一个课程作业,介绍如何利用shell脚本来快速高效地实现文本分类数据预处理中的部分操作。

shell脚本语言在某些方面有着不可比拟的优势,用四个字来概括,就是“短小精悍”。它能利用极少的命令来完成一些复杂的工作,尤其是与sed、awk等脚本工具结合起来使用时,表现出了在文本处理方面超强的处理能力,因此它是每个学习linux或者是涉及到大规模文本处理的学习者必备的知识技能。下面就将详细介绍如何利用shell脚本来进行文本数据预处理。

1. 文档切分

课程作业中给的数据集是一个人民日报语料库,语料库中是人民日报在1998年1月份刊登的各种类型的文章,有新闻、散文、诗歌、评论等等。文章与文章之间用空行隔开。语料库的格式如下所示:

19980101-02-013-001/m [胜利/nz 海上/s 油田/na]nt 产/v!0-3 油/n 创/v 新高/n
19980101-02-013-002/m 本报/r 济南/ns 十二月/t 三十一日/t 电/n 截至/v 一九九七年/t 十二月/t 三十一日/t ,/w [胜利/nz 海上/s 油田/na]nt 全年/n 共/d 生产/v 原油/n 一百五十万零一百/m 吨/q ,/w 超/v 计划/n 一百/m 吨/q 。/w 与/p 上年/t 同期/d 相比/v ,/w 海上/s 油田/n 的/u 年产/vn 能力/n 增加/v 了/u 五十万/m 吨/q 。/w

19980101-02-014-001/m 延安/ns 供水/vn 工程/n 建成/v 通水/v
19980101-02-014-002/m 本报/r 西安/ns 十二月/t 三十一日/t 电/n 十二月/t 二十八日/t ,/w 革命/vn 圣地/n 延安/ns 供水/vn 工程/n 正式/ad 建成/v 通水/v ,/w 延安/ns 市区/s 的/u 缺水/vn 问题/n!0-1 得到/v 根本/a 解决/vn 。/w

19980101-02-015-001/m 大连港/ns 年/q 吞吐量/n 超/v 七千万/m 吨/q
19980101-02-015-002/m 本报/r 大连/ns 十二月/t 三十一日/t 电/n 记者/n 张/nr 书政/nr 报道/v :/w 截至/v 十二月/t 二十八日/t 十八时/t ,/w 大连港/ns 年/q 吞吐量/n 突破/v 七千万/m 吨/q ,/w 比/p 上年/t 同期/d 增加/v 六百万/m 吨/q 。/w

………………

其中每一篇文章中的段落开头都用“年月日-**-文章号-段号”组成,语料库已经完成了切词操作并对每个字词进行了语义标引。下面第一步要做的就是将每篇文章从语料库中分离开来。可以使用如下的awk脚本程序:

BEGIN {
FS = "\n";
RS=””;
DIRPATH = "../documents"; #directory path
}

{
FILENAME = DIRPATH "/" NR ".txt"
print > FILENAME
}

用如上的脚本是完全可行的,但是由于本人的一些错误,导致运行结果不正确,因此换用了另外一种切分方式,如下所示:

#To seperate the input file into individual files

#set the initial parameters
BEGIN {
i = 0;
FS = "\n";
DIRPATH = "../documents"; #directory path
}

#if the first field matches the given regrex, then a new file starts
#redirect the file data to a new file named with i
#
$1 ~ /^[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][0-9]-001/{
i++;
FILENAME = DIRPATH "/" i ".txt";
print > FILENAME;
next;
}

#redirect the rest of the file data to the new file
#
{
print >> FILENAME;
}

#
END {
print "There are" i "documents";
}

执行程序命令:“awk –f split.awk sourcefile > /dev/null “,程序运行结果是在documents目录下生成了889个txt文件,说明语料库中共有889篇文章,切分后的结果如下所示:

QQ截图未命名

上图只是documents目录视图的一部分,打开5.txt,文件显示的是一篇完整的文章内容,内容如下:

19980101-01-005-001/m 挂/v 起/v 红灯/n 迎/v 新年/t (/w 图片/n )/w
19980101-01-005-002/m 元旦/t 来临/v ,/w 安徽省/ns 合肥市/ns 长江路/ns 悬挂/v 起/v 3300/m 盏/q 大/a 红灯笼/n ,/w 为{wei4}/p 节日/n 营造/v 出/v!C-C “/w 千/m 盏/q 灯笼/n 凌空/vd 舞/v ,/w 十/m 里/q 长街/n 别样/r 红/a ”/w 的/u 欢乐/a 祥和/a 气氛/n 。/w (/w 新华社/nt 记者/n 戴/nr 浩/nr 摄/Vg )/w
19980101-01-005-003/m (/w 传真/n 照片/n )/w

2. 去停用词

在所给定的语料库中,有很多字符是无意义的,如语义标引、中英文数字、单字、标点符号、括号说明等等,这些词对表征一篇文档是无意义的,因此必须将其从文档中去除。

sed脚本在文本过滤方面非常的方便,因此本人使用sed脚本程序对文档进行了过滤。sed脚本程序如下所示:

s/\/[a-zA-Z]\{1,\}//g #remove symantics

s/[a-zA-Z0-9-]\{1,\}//g #remove digits and other alphabets

s/(.*)//g #remove nosense annotation

s/[][“”、;:,。()/?!—!《》’『』]//g #remove punctuation marks

s/{.*}//g #remove {wei4}

s/[0123456789]//g #remove full-width digits

s/[一二三四五六七八九十]\{2\}//g #remove chinese digits
s/ *[一二三四五六七八九十] *//g

s/ */ /g #merge blank spaces to one blank space

对单篇文档的过滤效果如下所示:

话剧 沧海横流 在 京 上演
本报 讯部 反映 民族英雄 郑 成功 收复 台湾 的 历史 话剧 沧海横流 近日 在 京 上演
这部 由 福建 人民 艺术 剧院 创作 演出 的 大型 历史 话剧 再现 了 在 收复 台湾 这大 的 历史 背景 下 郑 成功 与 其 属下 施 琅 的 关系 冲突 揭示 了 两 人 之间 既 矛盾 又 统一 的 关系 表现 了 人 的 本质 力量 与 社会关系 的 冲突
中共中央 统战部 及 北京 市委 等 有关 领导 观看 了 演出 宗 素华

可以看出基本上将所有明显的无意义词都去除了,但是经过检查,在其它文档中还是有个别特殊的字符没有去除,另外全角的字母还没有去除,但是这些对后续的结果没有什么影响。

为了实现全部文档的过滤,编写如下的shell脚本程序:

#! /bin/bash

i=0;

for doc in `ls ../documents`
do
echo $doc
i=$(($i+1));
sed -f clean.sed "../documents/"$doc > "../doc-cleaned/"$i".txt"
done

程序运行结果是在doc-cleaned文件夹中生成了对原文件对应的过滤后的889个文件。

3. 单词分行、去单字行、去空行、词频统计

使用如下命令即可完成对某一篇过滤后的文档进行第3步中的全部操作:

sed 's/ */\n/g' doc-cleaned/3.txt | sed '/^$/d' | sed '/^.$/d' | sort | uniq -c | sort –nr

其中sed 's/ */\n/g' doc-cleaned/3.txt 表示将文本中的每个单词单独用一行来表示。“|”表示管道,即前面的输出是后面的输入。 sed '/^$/d' 表示去掉空行。sed '/^.$/d' 表示去掉单字符行。sort表示对每行按字母顺序排列。uniq -c 表示去掉文本中重复的行(词)并统计词重复的个数。sort –nr表示按词频由大到小排序。

程序运行示例结果如下所示(只显示了部分结果):

21 中国
12 发展
7 继续
7 我们
7 世纪
6 国际
6 人民
5 经济
5 建设
5 国家
5 合作
5 世界
4 通过
4 进一步
4 改革
4 希望
4 和平
4 台湾
4 共同
3 香港
3 这些
3 澳门
3 方针
3 新年
3 实现
3 外交
3 同胞
3 各国
3 历史
3 充满
3 保持
3 两岸
2 顺利
2 面临
2 重要
2 理论
2 道路

为了完成对整个文档集的处理,编写如下shell脚本程序:

#! /bin/bash

i=0;

for doc in `ls ../doc-cleaned/`
do
((i++));
sed 's/ */\n/g' "../doc-cleaned/"$doc|sed '/^$/d'|sed '/^.$/d'|sort|uniq -c|sort -nr > "../processed/"$i".txt"
done

执行该shell脚本程序即可完成对整个过滤后的文档集的词频统计处理,运行结果将在processed文件夹下生成对应的词频统计文件。

==============================================================================

至此为此,文本分类的数据预处理工作能够用脚本完成的都已经完成了,当然最后还可以写一个shell脚本来完成如上预处理的整套操作,而不用对每一步都运行一次脚本。其实还可以运用脚本做其它一些操作,如依照中文停用词表对文本进一步进行特征提炼,还可以对每个文档进行总词数统计等等。有兴趣的读者可以自己尝试一下。

下一步就是用其它编程语言来对processed文件夹下的文件进行操作了…

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值