在写论文的时候了解到有fasttext这种文本分类方法,也看了很多别人的博客,但感觉使用这种方法的人并不是很多,或者使用的版本有些旧。本文会介绍下Windows下最新的fasttext版本以及如何进行文本分类
以下是本篇文章正文内容,下面案例可供参考
fasttext简介
fasttext是2016年facebook开源的一款高效词表示和文本分类工具。它是一个浅层的神经网络模型,类似于word2vec的CBOW,主要用途就是两个——词向量化和文本分类。
Windows下安装
代码如下(示例):
pip install fasttext
版本
2019年6月25官网发布了Windows下的最新版本,这个版本将原来的官方版fastText和非官方版fasttext合并,现在最新版本fasttext在github repository和 pypi.org都可以找到。
新版特色
保留了官方API和顶层函数(例如train_unsupervised和train_supervised)以及返回的numpy对象。 从非正式API中删除了cbow,skipgram和supervised函数。 并且将非官方API中的好主意带到了官方API中。 特别是,我们喜欢WordVectorModel这类很python的方法。
主要函数及用法
如果是文本分类用到的函数就是 train_supervised
import fasttext
model = fasttext.train_supervised('data.train.txt')
这里data.train.txt是一个文本文件,每行包含一个训练语句以及标签。 默认情况下,我们假设标签是带有字符串__label__前缀的string.
该函数主要参数如下:
input # training file path (required)
lr # learning rate [0.1]
dim # size of word vectors [100]
ws # size of the context window [5]
epoch # number of epochs [5]
minCount # minimal number of word occurences [1]
minCountLabel # minimal number of label occurences [1]
minn # min length of char ngram [0]
maxn # max length of char ngram [0]
neg # number of negatives sampled [5]
wordNgrams # max length of word ngram [1]
loss # loss function {ns, hs, softmax, ova} [softmax]
bucket # number of buckets [2000000]
thread # number of threads [number of cpus]
lrUpdateRate # change the rate of updates for the learning rate [100]
t # sampling threshold [0.0001]
label # label prefix ['__label__']
verbose # verbose [2]
pretrainedVectors # pretrained word vectors (.vec file) for supervised learning []
#可以用训练好的词向量
文本分类
数据集
import pandas as pd
import numpy as np
from sklearn import metrics
from sklearn import model_selection
from sklearn.naive_bayes import BernoulliNB
import jieba
from xgboost import plot_importance,plot_tree
import xgboost as xgb
import fasttext
import time
df = pd.read_csv('D:word data/ChnSentiCorp_htl_all.csv',encoding='utf-8')
df = df.dropna()
print(df.dtypes)
df.head()
数据处理
分词和去除停用词
def filter_stopwords(txt):
sent = jieba.lcut(txt)
words = []
for word in sent:
if(word in stopwords):
continue
else:
words.append(word)
return ' '.join(words)
def get_custom_stopwords(stop_words_file):
with open(stop_words_file,encoding="utf8") as f:
stopwords = f.read()
stopwords_list = stopwords.split('\n')
custom_stopwords_list = [i for i in stopwords_list]
return custom_stopwords_list
stop_words_file = 'D:/data/stoplist.txt'
stopwords = get_custom_stopwords(stop_words_file)
文本格式处理
df['cut_review'] = df.review.apply(filter_stopwords)
df['label'] = '__label__'+ df['label'] #fasttext需要将分类标签添上'__label__'前缀
#且要求每行输出如下中间用分隔符分开,而','分隔符是不行的
df['res'] = df['label'] + ' ' + df['cut_review']
划分数据集并保存为txt文件
由于train_supervised中input参数只接受文件路径,划分数据集为训练集和测试集后保存为text文件
sentences = df['res']
sentences_train,sentences_test = train_test_split(sentences,test_size = 0.3)
sentences_train = sentences_train.values.tolist()
sentences_test = sentences_test.values.tolist()
def writeData(sentences,fileName):
print("writing data to fasttext format...")
out=open(fileName,'w',encoding='utf-8')
for sentence in sentences:
out.write(sentence+"\n")
print("done!")
fileName = 'D:word data/ChnSentiCorp_htl_train.txt'
writeData(sentences_train,fileName)
fileName = 'D:word data/ChnSentiCorp_htl_test.txt'
writeData(sentences_test,fileName)
二分类
ts = time.time()
model = fasttext.train_supervised('D:word data/ChnSentiCorp_htl_train.txt')
time.time() - ts
# 0.2246713638305664
#模型评估
def print_results(N, p, r):
print("N\t" + str(N))
print("P@{}\t{:.3f}".format(1, p))
print("R@{}\t{:.3f}".format(1, r))
print_results(*model.test('D:word data/ChnSentiCorp_htl_test.txt'))
# N2330
# [email protected] precsion 这可能是正样本比例偏高导致的
# [email protected] recall
调参
#考虑word ngram 并改损失函数为负采样的损失函数
ts = time.time()
model = fasttext.train_supervised('D:word data/ChnSentiCorp_htl_train.txt',wordNgrams = 2,loss = 'ns')
time.time() - ts
# 0.2246713638305664
#模型评估
def print_results(N, p, r):
print("N\t" + str(N))
print("P@{}\t{:.3f}".format(1, p))
print("R@{}\t{:.3f}".format(1, r))
print_results(*model.test('D:word data/ChnSentiCorp_htl_test.txt'))
# N2330
#效果并没有提高
和朴素贝叶斯比较
#导入数据并处理
df = pd.read_csv('D:word data/ChnSentiCorp_htl_all.csv',encoding='utf-8')
df = df.dropna()
df['cut_review'] = df.review.apply(filter_stopwords)
X = df['cut_review']
y = df.label
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=22)
#词向量化 只考虑每个单词出现的频率;然后构成一个特征矩阵,每一行表示一个训练文#本的词频统计结果
from sklearn.feature_extraction.text import CountVectorizer
vect = CountVectorizer(max_df = 0.8,
min_df = 3,
token_pattern=u'(?u)\\b[^\\d\\W]\\w+\\b',
stop_words=frozenset(stopwords))
from sklearn.naive_bayes import MultinomialNB
nb = MultinomialNB()
X_train_vect = vect.fit_transform(X_train)
nb.fit(X_train_vect, y_train)
train_score = nb.score(X_train_vect, y_train)
print(train_score)
# 0.895363811976819
#模型评估
pred = nb.predict(X_test_vect)
y_test
X_test_vect = vect.transform(X_test)
metrics.precision_score(y_test,nb.predict(X_test_vect)),metrics.recall_score(y_test,pred)
# (0.8984088127294981, 0.9157829070492826)
# 朴素贝叶斯效果还是好一些的
小节
本文仅仅简单介绍了fasttext的使用,可能数据集比较小,又是简单的二分类任务,fasttext优势并没有展现出来,之后会用更大的训练集和多分类任务进行测试。