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:快速的文本分類器

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