fastext 是什么?
Facebook AI Research Lab 发布的一个用于快速进行文本分类和单词表示的库. 优点是很快, 可以进行分钟级训练, 这意味着你可以在几分钟时间内就训练好一个分类模型.
本文主要内容?
使用 fasttext 训练一个效果不错的新闻文本分类器 / 模型.
使用到的技术和环境?
1. python 3.7,fasttext 0.9.1(截至 2020/3/29 最新版本) Windows 10 (实验过程中使用的环境)
2. 1 核 2G 1Mbps 腾讯云服务器 Ubuntu 18.04 (最终的模型产出于此, 如果你手头有 Linux 系统, 那最好不过了)
需要注意什么?
1. 博主并非是专业的 NLP 学习者, 所以以下内容是参考诸多博客, 官方 doc 以及 GitHub 上的项目说明而来, 算是拾人牙慧. 但总结一些坑, 便于后来者食用.
2. 强烈建议使用 Linux or Mac OS 系统来训练, 哪怕你是要在 Windows 下使用 (训练的模型是可以多系统之间通用的, 比如我在 Linux-Ubuntu 中训练, 在 Windows 上可以正常使用). 但是在 Windows 下训练也是可行的, 至少可以通过 python 安装 fasttext 库来使用, 但是会有问题 -- 无法进行自动超参数优化 (至少目前如此).
重要的文档?
官方的文档及博客 GitHub fastext 项目
Let's start
Step1: 准备训练集和测试集
这里的参考训练测试集来自 一位博主博客, 他已经进行过中文分词, 所以可以直接拿来训练.
下载地址 (如果地址失效, 请在博客下方留言评论, 或者尝试联系上方 QQ/Email)
news_fasttext_train.txt 训练集 365M
news_fasttext_test.txt 测试集 310M
如果上述链接失效, 可从下述链接获取:
链接: https://pan.baidu.com/s/1izR-0oUFhZ4v5lrVYFng6A
提取码: n5w6
Step2: 在机器上构建 fasttext
1. Windows 10 os : 过程中发现许多人在安装时遇到了问题, 这里建议直接使用 python pip 工具安装
pip/pip3 install fastext
安装成功后, import 它即可.
2. Linux os : 按照官网教程, 下面照搬过来
命令行键入:
- $ Git clone https://github.com/facebookresearch/fastText.git
- $ cd fastText
- $ make
如果没有 Git 工具, 按照提示安装一下.
Step3 : 进行训练
是的, 你已经可以开始训练了, 而训练.... 也只需要一行命令, 即为简单, 且可以在几分钟内完成.
1. 使用默认参数进行训练:
命令行键入:
$ ./fasttext supervised -input news_fasttext_train.txt -output model_xxxx
其中 - input 后跟训练集的路径, 要修改为自己放置训练集的 path, 如果就放在 fasttext 文件夹下, 那么直接按照上面运行即可.-output 是模型的名字, 训练完成后会产生一个 model_xxxx.bin 的文件, 即是模型, 可以自行设置模型文件名.
2. 自己设定参数进行训练:
命令行键入:
$ ./fasttext supervised -input news_fasttext_train.txt -output model_xxxx -lr 1.0 -epoch 25
上面的命令新增设定了 - lr 学习率和 - epoch 训练集送入的次数, 当然还有其他的参数, 请自行前往官网或者 GitHub 项目查看并设定, 再进行训练.
3. 自动超参数优化
找到最佳超参数对于构建有效模型至关重要. 但是, 手动搜索最佳超参数很困难. 但是, fasttext 可以为你找到对于测试集来说最佳的超参数, 然后使用这些超参数, 再用训练集进行训练. 而使用自动超参数优化, 只需要在命令行中加入 - autotune-validation 测试集 path.
命令行键入:
$ ./fasttext supervised -input news_fasttext_train.txt -output model_xxxx -autotune-validation news_fasttext_test.txt
这样一来, 就可以不用自己费力调参, 直接得到对于测试集来说最佳的模型, 从我使用的情况来看, 确实如此. 下图中, 我展示了两个新闻主题的训练过程中的数据, 最后使用此功能得到了相较此前最好的效果. 证明, 使用自动超参数优化来做, 比自己摸索调参要来的更快, 效果更好.
Step4 : 计算一下评价数据
precision,recall,f1-score , 尤其后者是评价模型优劣的重要数据, 我们来计算一下.
这里要使用到 python 来写脚本:(脚本来自上面博客, 但是在 py3.7 下运行会出错, 我进行了修改)
- # -*- coding: utf-8 -*-
- # @Author : yocichen
- # @Email : yocichen@126.com
- # @File : test.py
- # @Software: PyCharm
- # @Time : 2020/3/27 21:49
- import fasttext
- # 1. 加载模型
- # 模型文件名自行修改
- classifier = fasttext.load_model('Model/model_0328_1854.bin')
- # 2. 读入测试集文件, 进行预处理
- labels_right = []
- texts = []
- with open("Data/news_fasttext_test.txt", encoding='utf-8') as fr:
- for line in fr:
- line = line.rstrip()
- labels_right.append(line.split("\t")[1].replace("__label__", ""))
- texts.append(line.split("\t")[0])
- labels_predict = []
- for t in texts:
- res = classifier.predict(t)
- labels_predict.append(res[0][0].replace('__label__', ''))
- text_labels = list(set(labels_right)) # 训练集中的标签类别
- text_predict_labels = list(set(labels_predict)) # 预测结果中的标签类别
- A = dict.fromkeys(text_labels,0) #预测正确的各个类的数目
- B = dict.fromkeys(text_labels,0) #测试数据集中各个类的数目
- C = dict.fromkeys(text_predict_labels,0) #预测结果中各个类的数目
- for i in range(0,len(labels_right)):
- B[labels_right[i]] += 1
- C[labels_predict[i]] += 1
- if labels_right[i] == labels_predict[i]:
- A[labels_right[i]] += 1
- print('A:', A)
- print('B', B)
- print('C', C)
- # 3. 计算准确率, 召回率, F 值
- for key in B:
- try:
- r = float(A[key]) / float(B[key])
- p = float(A[key]) / float(C[key])
- f = p * r * 2 / (p + r)
- print("%s:\t p:%f\t r:%f\t f:%f" % (key,p,r,f))
- except:
- print("error:", key, "right:", A.get(key,0), "real:", B.get(key,0), "predict:",C.get(key,0))
- python script
运行结果:
Step5 : 实战测试一下
我在各大新闻网站随机摘抄了 20 条新闻 (片段), 其中大部分是财经新闻, 来小小的测试一下我们的分类器 / 模型.
下载地址:
news_sample.txt 新闻片段 9.95kb
链接: https://pan.baidu.com/s/1bURmHsQn_v5UevZqY8vBeg
提取码: numq
stop_words.txt 停用词 17.2kb
链接: https://pan.baidu.com/s/1Qzpk4KAOlI5Wmm7iuIaelQ
提取码: gfda
下面编写脚本来加载上面训练好的模型, 进行简单测试
- # -*- coding: GBK -*-
- # @Author : yocichen
- # @Email : yocichen@126.com
- # @File : predict.py
- # @Software: PyCharm
- # @Time : 2020/3/27 13:15
- import fasttext
- import sys, os
- import jieba
- from preprocess import *
- # 加载模型
- model = fasttext.load_model('Model/model_0328_1854.bin')
- with open('Data/news_sample.txt', encoding='utf-8') as f:
- for line in f:
- handle_text = seg(line.lower().replace('\n', ''), stop_words(), apply=clean_txt)
- res1 = model.predict(handle_text)
- print(res1[0][0].replace('__label__', ''))
predict.py
- import re
- from types import MethodType, FunctionType
- import jieba # 中文分词第三方库, 需要自行安装 pip3 install jieba / 在 pycharm 中安装也可
- # 文本清洗
- def clean_txt(raw):
- fil = re.compile(r"[^0-9a-zA-Z\u4e00-\u9fa5]+")
- return fil.sub(' ', raw)
- # 中文分词, 去通用词, 再连接成字符串
- def seg(sentence, sw, apply=None):
- if isinstance(apply, FunctionType) or isinstance(apply, MethodType):
- sentence = apply(sentence)
- return ' '.join([i for i in jieba.cut(sentence) if i.strip() and i not in sw])
- # 停用词, stop_words.txt 需要下载
- def stop_words():
- with open('Data/stop_words.txt', 'r', encoding='utf-8') as swf:
- return [line.strip() for line in swf]
- # 对某个 sentence 进行处理:
- # content = '上海天然橡胶期价周三再创年内新高, 主力合约突破 21000 元 / 吨重要关口.'
- # res = seg(content.lower().replace('\n', ''), stop_words(), apply=clean_txt)
- # print(res)
preprocess.py
测试结果:
根据人工判断进行比对, 准确率大概在 18-19/20 吧!
到这里, 使用 fastext 训练一个新闻文本分类器, 就结束了, 其实自己的工作并不多, 但是也学到了一些文本分类相关的东西, 愿后来的你也能有所收获!
参考文档
[1] https://www.cnblogs.com/hyserendipity/p/11698606.html
[2] jieba 库使用说明
[3] 利用 Fast-Text 进行中文文本分类 [前期在用这里的训练集, 虽然 f1 很高 0.98, 但实际使用效果并不好, 不推荐]
来源: https://www.cnblogs.com/yocichen/p/12595770.html