[原创] 使用 fastText 做中文文本分类(2)

查看本系列文章合集,请看这里

做好文本预处理,才能输入fastText训练一个效果好的模型出来。

 原文示例
有时我们拿到的源数据是很粗糙的,带有很多会影响模型效果的内容,例如下面这样:

<p>罗望子,是豆科酸豆属唯一的种,是热带乔木,原产于东部非洲,包括马达加斯加落叶森林,但已被引入热带亚洲、拉丁美洲和加勒比海。柽柳是中国海南省三亚的一种城市树木。罗望子最适合生长在温度高、日照长、气候干燥、干湿季节分明的地区。</p><p><img src="http://p0.qhimg.com/t014b83dc78c7cc5000.jpg?size=741x320"/><br /></p><p>罗望子富含糖、乙酸、酒石酸、甲酸、柠檬酸等成分,主要用于调味品、饮料、果酱等食品领域。吃一点罗望子有很多好处。当我们吃罗望子时,罗望子中含有的多糖是一种非常好的抗光物质。当我们吃这种物质时,它可以防止紫外线辐射伤害皮肤。通常吃一点罗望子,饭前吃一点罗望子可以增进食欲,改善我们的饮食质量。在炎热的夏日,吃一点罗望子可以生津止渴,清热解毒,降低中暑的风险。</p><p><img src="http://p1.qhimg.com/t01ecdbbc26c329a78b.jpg?size=533x409"/><br /></p><p>罗望子种子含有丰富的抗氧化物质。多吃罗望子籽可以延缓人体衰老,保持皮肤湿润有光泽。罗望子种子还含有一些清热解毒、消炎的物质,可以帮助我们的人体抵抗一些有害细菌,保护我们的健康。

这里面不仅带有URL、大量的HTML标签,而且还有标点符号等,这些都要清洗掉。

 清除掉HTML标签、URL
这里给出Java版的一个实现(从网上借鉴来的),它们并不完善,但是够用了:

    /**
     * 移除一个字符串中的HTML标签。
     *
     * @param inputStr 输入的字符串。
     * @return 移除了HTML标签之后的字符串。
     */
    private String removeHtmlTags(String inputStr) {
      if (StringUtils.isEmpty(inputStr)) {
        return inputStr;
      }
      return inputStr.replaceAll("<[^>]*>""");
    }

    /**
     * 移除一个字符串中的URL。
     *
     * @param inputStr 输入的字符串。
     * @return 移除了URL之后的字符串。
     */
    private String removeUrl(String inputStr) {
      String urlPattern = "((https?|ftp|gopher|telnet|file|Unsure|http):((//)|(\\\$$)+[\\w\\d:#@%/;$()~_?+-=\\\\.&]*)";
      Pattern p = Pattern.compile(urlPattern, Pattern.CASE_INSENSITIVE);
      Matcher m = p.matcher(inputStr);
      StringBuffer sb = new StringBuffer(inputStr.length());
      while (m.find()) {
        m.appendReplacement(sb, "");
      }
      return sb.length() == 0 ? inputStr : sb.toString();
    }

文章来源:https://www.codelast.com/
以前面的内容为例,依次经过上面两个方法处理后,得到的结果是:

罗望子,是豆科酸豆属唯一的种,是热带乔木,原产于东部非洲,包括马达加斯加落叶森林,但已被引入热带亚洲、拉丁美洲和加勒比海。柽柳是中国海南省三亚的一种城市树木。罗望子最适合生长在温度高、日照长、气候干燥、干湿季节分明的地区。罗望子富含糖、乙酸、酒石酸、甲酸、柠檬酸等成分,主要用于调味品、饮料、果酱等食品领域。吃一点罗望子有很多好处。当我们吃罗望子时,罗望子中含有的多糖是一种非常好的抗光物质。当我们吃这种物质时,它可以防止紫外线辐射伤害皮肤。通常吃一点罗望子,饭前吃一点罗望子可以增进食欲,改善我们的饮食质量。在炎热的夏日,吃一点罗望子可以生津止渴,清热解毒,降低中暑的风险。罗望子种子含有丰富的抗氧化物质。多吃罗望子籽可以延缓人体衰老,保持皮肤湿润有光泽。罗望子种子还含有一些清热解毒、消炎的物质,可以帮助我们的人体抵抗一些有害细菌,保护我们的健康。
这样看上去就干净多了。
文章来源:https://www.codelast.com/
除此之外,还有标点符号,以及一些无用的词需要被除掉,这些词对表达文本的主要含义作用不大,比如“啊”,“嘿”之类的词,它们一般称为停用词(stop words)。我们可以从网上下载到常用的停用词表,比如这个链接。
在对文本进行分词之后,出现在停用词表中的,全都过滤掉。

 分词并去除停用词
Python下比较流行的中文分词器之一是结巴分词

import jieba


my_text = '罗望子,是豆科酸豆属唯一的种,...'



# 分词
segmented_words = jieba.cut(my_text, cut_all=False)  # 精确分词模式



# 去除停用词

for single_word in segmented_words:
    #TODO: 去除停用词

文章来源:https://www.codelast.com/
Java版的结巴分词作者已经不维护了,建议换其他的分词器,比如用户量很大的HanLP。其使用也非常简单,在Maven项目的 pom.xml 中添加:

    <dependency>
      <groupId>com.hankcs</groupId>
      <artifactId>hanlp</artifactId>
      <version>portable-1.7.8</version>
    </dependency>

就可以用了:

import com.hankcs.hanlp.seg.common.Term;
import com.hankcs.hanlp.tokenizer.StandardTokenizer;

String myText = "罗望子,是豆科酸豆属唯一的种,...";

List<Term> termList = StandardTokenizer.segment(myText);
for (Term term : termList) {
    System.out.println(term.word);  // term.word即分出来的每个词
    //TODO: 去除停用词
}

现在得到的是分好的词,并且把停用词等杂七杂八的东西都去掉了,也许对某些情况很糟糕的文本,还会有漏网之鱼,但对一般情况来说基本上够用了。
不同的分词器分出来的词结果不尽相同,这里以Java版为例,得到:

罗 望子 豆科 酸 豆 属 唯一 种 热带 乔木 原产 东部 非洲 包括 马达加斯加 落 叶森林 已 引入 热带 亚洲 拉丁美洲 加勒比海 柽 柳是 中国 海南省 三亚 种 城市 树木 罗 望子 最 适合 生长 温度 高 日照 长 气候 干燥 干湿 季节 分明 地区 罗 望子 富含 糖 乙酸 酒石酸 甲酸 柠檬酸 成分 用于 调味品 饮料 果酱 食品 领域 吃 一点 罗 望子 很多 好处 吃 罗 望子 时 罗 望子 中 含有 多糖 种 好 抗光 物质 吃 物质 时 紫外线 辐射 伤害 皮肤 吃 一点 罗 望子 饭前 吃 一点 罗 望子 增进 食欲 改善 饮食 质量 炎热 夏日 吃 一点 罗 望子 生津止渴 清热 解毒 降低 中暑 风险 罗 望子 种子 含有 抗氧化 物质 吃 罗 望子 籽 延缓 人体 衰老 皮肤 湿润 光泽 罗 望子 种子 还 含有 清热 解毒 消炎 物质 人体 抵抗 有害 细菌 保护 健康
为了清晰展示结果,词与词之间用空格隔开了。
如果对分词结果不满意,比如人名,特殊物品名,可以为分词器添加字典,让分词器识别它们。这些调优的工作就不详述了。
文章来源:https://www.codelast.com/
 文本标注
fastText对训练数据的格式要求是这样的:

__label__健康 罗 望子 豆科 酸 豆 属 唯一 种 热带 乔木 原产 东部 非洲 包括 马达加斯加 落 叶森林 已 引入 热带 亚洲 拉丁美洲 加勒比海 柽 柳是 中国 海南省 三亚 种 城市 树木 罗 望子 最 适合 生长 温度 高 日照 长 气候 干燥 干湿 季节 分明 地区 罗 望子 富含 糖 乙酸 酒石酸 甲酸 柠檬酸 成分 用于 调味品 饮料 果酱 食品 领域 吃 一点 罗 望子 很多 好处 吃 罗 望子 时 罗 望子 中 含有 多糖 种 好 抗光 物质 吃 物质 时 紫外线 辐射 伤害 皮肤 吃 一点 罗 望子 饭前 吃 一点 罗 望子 增进 食欲 改善 饮食 质量 炎热 夏日 吃 一点 罗 望子 生津止渴 清热 解毒 降低 中暑 风险 罗 望子 种子 含有 抗氧化 物质 吃 罗 望子 籽 延缓 人体 衰老 皮肤 湿润 光泽 罗 望子 种子 还 含有 清热 解毒 消炎 物质 人体 抵抗 有害 细菌 保护 健康

每两个字符串之间都用空格隔开,以“__label__”开头的(前后均为双下划线)是后面文本的标签,这里可以有多个标签,比如“__label__健康 __label__生活”,也是用空格分隔开。前面说过,本文以1个标签举例,所以这里只有1个。
这是文本预处理的最后一步,完成之后就可以把数据喂给fastText训练出一个模型啦。
比如说上面分好词的文本,我们要为它标注一个类别(例如“健康”)。
然鹅,我们难道用人工肉眼看的方法来标注吗?并且,类别有哪些,我怎么知道?
就算有一目十行的能力,看瞎我的钛合金狗眼,我一天也标不了10万条数据啊!
欲知解决方法,请看下一篇文章。

文章来源:https://www.codelast.com/
➤➤ 版权声明 ➤➤ 
转载需注明出处:codelast.com 
感谢关注我的微信公众号(微信扫一扫):

wechat qrcode of codelast

发表评论