FastText在商品分类下的应用(第十届服创大赛全国三等奖)

昨天第十届服务外包创新创业大赛公布了全国三等奖和晋级决赛的名单,获得了三等奖。这基本上结束了我个人本科阶段的比赛,因为马上就要去IBM实习了。这篇文章一方面是对这次比赛进行一个总结,另一方面也是想将FastText的使用给大家介绍一下,因为国内资料较少。
首先声明:我对Python的了解完全是因为要参加这次比赛了解到Python在机器学习和数据处理等方面的优势才选择学习的,因此只学习了基本的语法,可以根据自己想做的事情在网上查询相关的代码实现,所以关于代码有任何的改进意见欢迎指出,但不接受批评。此外,在机器学习方面的内容也是我在选了这道题目之后才进行了解的,完成题目的过程和思路可能有些问题,欢迎指出并优化。
最后,这也是我写的第一篇非记录式的文章,如果对促进你的工作或学习起到了作用,请给我点赞:)

任务介绍

来自不同网上零售平台的商品500万个,其中有50万个带有商品的标签信息,剩余的450万个无标签信息。建立一种分类模型,利用50万个商品包含的标签信息,对剩余的450万个商品进行合理的标签判定。
赛方提供的数据集格式如下:

# train.tsv
ITEM_NAME	TYPE
腾讯QQ黄钻三个月QQ黄钻3个月季卡官方自动充值可查时间可续费	本地生活--游戏充值--QQ充值

# test.tsv
ITEM_NAME
腾讯QQ蓝钻贵族34个月直充

题目完成过程

大致过了一遍Python的基础教程和机器学习有监督分类相关的算法之后。首先尝试了一些简单的分类算法,如朴素贝叶斯,随机森林,K-means,支持向量机等,但是效果都不太好,有的算法准确率还可以但是训练时间过长,综合来看只有贝叶斯效果好一些,但是只停在了70%左右。后来无意中了解到了FastText,看了介绍和其它博主的文章后决定尝试一下。
* 如果需要Python的学习资料请与我联系

FastText介绍以及环境搭建问题

简介

FastText是Facebook在2016年开源的一个词向量与文本分类工具,典型应用场景是“带监督的文本分类问题”。FastText结合了自然语言处理和机器学习中最成功的理念。这些包括了使用词袋以及n-gram袋表征语句,还有使用子字(subword)信息,并通过隐藏表征在类别间共享信息,另外采用了一个softmax层级(利用了类别不均衡分布的优势)来加速运算过程。
FastText最惊艳的地方在于,和最前沿深度神经网络模型相比,它在分类精度等指标毫不逊色的情况下,把训练和推断速度降低了几个数量级。Facebook的报告指出,在普通多核CPU上,10亿词的文本训练时间小于10分钟,50万句子分到31.2万类别用时小于1分钟。
在这里插入图片描述
* 这些是我从网上抄下来的,原理啥的咱也不懂,只会用一用

使用

由于FastText库目前仅支持Linux/MacOS(好像已经有人用Java实现了,但是为了使用pandas、sklearn等库还是安装了ubuntu双系统)
fastText安装参考:fasttext – 安装 & 使用
FastText分类模型要求输入的数据集在标签前加上特殊的标识符(默认为“label”),例如,“商品名称 __label__商品类别”。因此对数据格式进一步处理后,训练集中的数据形如下:

光 云彩 长方形 钢化 玻璃 微波炉 保鲜盒 红色 __label__厨具锅具--厨房配件--保鲜盒

* 在学习使用FastText的时候主要就是没有明白FastText要求的文本格式是什么样的,看别人的博客好像也没有具体的描述这里强调一下
* 这里分词工具使用的是jieba的精确模式,在实际应用中,可以根据数据集调整分词词库(这也是我当时没有想到的一个优化的点)
这里介绍几个我使用了的函数:

# 训练模型
classifier = fasttext.supervised('train.txt','model',label_prefix = '__label__')
# 加载模型
classifier = fasttext.load_model("classifier.model.bin", label_prefix="__label__")
# 测试准确率,这个txt文件是带有标签的,一般会从train里面分出来20%左右来验证模型
result = classifier.test('test.txt')
print("准确率:", result.precision)
# 预测类别,不包含预测可能性,k default 1
print classifier.predict(texts,k)
# 预测类别,包含预测概率,k default 1
print classifier.predict_proba(tests,k) 

详细参数和方法介绍参考 fasttext-- API 文档 & 参数说明

过程代码

01 取出train中的商品名称和类别

import csv

csv.register_dialect('mydialect',delimiter='\t',quoting=csv.QUOTE_ALL)
train_item = open('../data/train_item.tsv', 'w', encoding='utf-8')
train_name = open('../data/train_type.tsv', 'w', encoding='utf-8')

with open('../data/train.tsv',encoding='utf-8') as csvfile:
    file_list = csv.reader(csvfile,'mydialect')
    for line in file_list:
        train_item.write(line[0] + '\n')
        train_name.write(line[1]+'\n')
    print('将训练集的两列内容取出并保存到train_item.tsv和train_type.tsv中')

csv.unregister_dialect('mydialect')

02 数据预处理

import jieba
import csv
import datetime
import itertools
import re
import logging
import pandas as pd
from sklearn.utils import shuffle

start_time = datetime.datetime.now()
def savefile(savepath, content):
    fp = open(savepath, "w", encoding='utf-8', errors='ignore')
    fp.write(content)
    fp.close()

print('----数据预处理开始')

# 读取数据集并划分
csv.register_dialect('mydialect', delimiter='\t', quoting=csv.QUOTE_ALL)
train_item = open('../data/train_item.tsv', 'w', encoding='utf-8')
train_type = open('../data/train_type.tsv', 'w', encoding='utf-8')

with open('../data/train.tsv', encoding='utf-8') as csvfile:
    file_list = csv.reader(csvfile, 'mydialect')
    for line in file_list:
        train_item.write(line[0] + '\n')
        train_type.write(line[1] + '\n')
csv.unregister_dialect('mydialect')
print('----数据集初始化结束')

# 分词
jieba.setLogLevel(logging.INFO)
with open('../data/train_item.tsv', encoding='utf-8') as train_items:
    seged_train_item = [
        re.sub('[a-zA-Z0-9’!"#$%&\'()()*+,-./:;<=>?@,。?★、…【】《》?“”‘’![\\]^_`{|}~]+', '', ' '.join(jieba.cut(r))) for r in
        train_items.readlines()]
with open('../data/test.tsv', encoding='utf-8') as train_items:
    seged_test = [
        re.sub('[a-zA-Z0-9’!"#$%&\'()()*+,-./:;<=>?@,。?★、…【】《》?“”‘’![\\]^_`{|}~]+', '', ' '.join(jieba.cut(r))) for r in
        train_items.readlines()]
savefile('../data/seged_train_item.tsv', ''.join(seged_train_item))
savefile('../data/seged_test.tsv', ''.join(seged_test))
print('----分词去停用词结束')

with open("../data/train_type.tsv", encoding='utf-8') as f:
    train_type = [r.rstrip('\n').replace('\t', '') for r in f.readlines()]
with open("../data/seged_train_item.tsv", encoding='utf-8') as f:
    seged_train_item = [r.rstrip('\n').replace('\t', '') for r in f.readlines()]
result = itertools.zip_longest(seged_train_item, train_type, fillvalue=' ')
with open("../data/train_added_label.txt", "w", encoding='utf-8') as f:
    [f.write('\t__label__'.join(r) + "\n") for r in result]
print('----合并训练集结束')

data = pd.read_csv('../data/train_added_label.txt', sep='\t', encoding='utf-8', header=0)
data = shuffle(data)
train_shuffled = data.head(450000)
test_shuffled = data.tail(49946)
train_shuffled.to_csv('../data/train_shuffled.txt', sep='\t', index=False)
test_shuffled.to_csv('../data/test_shuffled.txt', sep='\t', index=False)
end_time = datetime.datetime.now()
print('数据预处理结束,总耗时:', (end_time - start_time).seconds / 60, 'min')

03 fastText

# coding=utf-8
import fasttext
import datetime
import pandas as pd
from sklearn.utils import shuffle
from sklearn.metrics import confusion_matrix
start_time = datetime.datetime.now()
print('程序开始')

data = pd.read_csv('../data/train_added_label.txt', sep='\t', encoding='utf-8', header=0)
data = shuffle(data)
data.to_csv('../data/train_shuffled.txt',sep='\t',index=False)

classifier = fasttext.supervised('../data/train_shuffled.txt', '../model/classifier.model',loss='hs',word_ngrams=2,bucket= 2000000,lr=0.5)
pre_time = datetime.datetime.now()
print('预测结束,耗时:', (pre_time - start_time).seconds, 's')

result = classifier.test('../data/test_shuffled.txt')
test_time = datetime.datetime.now()
print('测试结束,耗时:', (test_time - pre_time).seconds, 's')

print("准确率:", result.precision)

end_time = datetime.datetime.now()
print('程序结束,共耗时:', (end_time - start_time).seconds, 's')

* 涉及到赛方的成果保密要求,不能公开所有代码和文档,这里只是展示了部分代码和fasttext的使用样例,更多代码已经上传至 Github,记得star哦

总结

总的来说这次参加服创大赛锻炼了自己的很多能力(队友不太积极,从头到尾都是自己做),能在180多支队伍中获奖已经很不容易了,未来加油。如果你在阅读过程中有疑问请私信我或在文章下留言,我当天就会回复。

参考:
微博短文本下fastText的应用
使用fasttext完成文本处理及文本预测
FastText:快速的文本分类器

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章