通过sklearn建立分辨性别的模型后,再使用fasttext做同样的事情,对比两个模型的效果。
用sklearn建模的博客链接在此处:链接
fasttext是由facebook出品的一个用于文档识别的模型。属于Neural Network的范畴。
1.Theory
这篇论文介绍了fasttext模型的思想。Bag of Tricks for Efficient Text Classification
下面是自己的一些学习理解(就是个人笔记):
我们使用words建立word vector,再得出prediction的过程中,需要做dimension reduction。fasttext做了一个word embedding的工作。譬如将3000个词,分成每行128个词的短vector,然后组成matrix。
【ANN在word vector到prediction的过程中,要进行dimension reduction。fasttext的word embedding就是做这件事,可以认为是ANN的一层。】
从下到上,如word vector先分割得到中间结果,在将vector中的每个word的值求avg,因为word很多,组合的类型也很多,所以尽管求avg会损失一部分精度,但还是可以用来进行predict,主要还是要起到降维的作用。
在以word vector作为input到得到output的vector的过程中,会有中间层。我们可以给每条线上假设一个weight值,初始值是随机分配的,根据output来看梯度,调整weight值,默认为5-round(可调整),过高可能会出现过拟合(over-fitting),使得模型不general。
fasttext的一个优势:增加了subword的判断,如wings是target word,还会把wing,ings考虑进去,会比svm更加准确。
补充:
fasttext中的相似性:如两个词很相似,那么两个词对应的vector也会比较近。
2.Practice
2.1 配置环境
fasttext在github上给出了官方的权威环境配置要求。
facebookresearch/fastText
环境配置要求如下:
2.2 准备数据
输入格式为__label__class word1 word2 word3 ...
2.3 构建模型
参考fasttext给出的官方文档中,‘python/doc/examples/train_supervised.py‘文档。
构建自己的模型。
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals
from __future__ import division, absolute_import, print_function
from fastText import train_supervised
def print_results(Number, precision, recall):
print("Number\t" + str(Number))
print("Precision@{}\t{:.3f}".format(1, precision))
print("Recall@{}\t{:.3f}".format(1, recall))
if __name__ == "__main__":
train_data = 'train.csv'
valid_data = 'validate.csv'
# train_supervised uses the same arguments and defaults as the fastText cli
model = train_supervised(
input=train_data, epoch=10, lr=1.0, wordNgrams=2, verbose=2, minCount=1,
loss='softmax'
)
# model.save_model("model.bin")
model.quantize(input=train_data, qnorm=True, retrain=True, cutoff=100000)#压缩训练出来的模型,压缩后的结果没差别
#print_results(*model.test(valid_data))
model.save_model("model.ftz")
将训练好的模型文件保存为model.ftz,是一个压缩文件,和model.bin二进制文件本质上没有不同。
2.4 结果分析
由于fasttext提供的分析方法很不好用,所以还是用sklearn中的metrics来对模型预测的结果进行分析。
from sklearn import metrics
from fastText import load_model
import csv
import numpy as np
def convert(prediction):
converted_prediction = []
for item in prediction:
if '__label__men' in item:
converted_prediction.append(0)
elif '__label__women' in item:
converted_prediction.append(1)
return converted_prediction
def process_array(array):
new_array = []
for item in array:
new_array.append(item[0])
return new_array
if __name__ == '__main__':
f = load_model('genderModel.ftz')
validate = []
ground_truth = []
with open('fastText.validate.csv', 'r') as csvfile:
spamreader = csv.reader(csvfile)
for row in spamreader:
row = str(row)[2:-2]
if '__label__women' in row:
row = row.replace('__label__women', '').strip(' ')
validate.append(row)
ground_truth.append(1)
elif '__label__men' in row:
row = row.replace('__label__men', '').strip(' ')
validate.append(row)
ground_truth.append(0)
predicted, array = f.predict(validate)
predicted = convert(predicted)
#array = process_array(array) # how to use ?
predicted = np.asarray(predicted)
accuracy = np.mean(predicted == ground_truth)
man_precision_score = metrics.precision_score(ground_truth, predicted, average='binary', pos_label=0)
women_precision_score = metrics.precision_score(ground_truth, predicted, average='binary', pos_label=1)
man_recall_score = metrics.recall_score(ground_truth, predicted, pos_label=0)
women_recall_score = metrics.recall_score(ground_truth, predicted, pos_label=1)