1. 問題背景
在電商平臺中,不少用戶都會基於本身的購物體驗對商品進行評分和評論.但有些用戶只給出了評論而沒有評分,沒有了評分的量化標準,這給商家進行數據運營與選品決策帶來了困難.如何根據商品評論估計出相對應的評分,這是情感分析的問題,咱們能夠用fastText文本分類器來快速解決.
2. fastText簡介
fastText是FAIR(Facebook AI Research)於2016年開源的一個詞向量與文本分類工具,主要優勢是可以取得與深度神經網絡相媲美的分類精度,同時訓練速度比深度神經網絡快幾個數量級,節約了不小的訓練成本,果真是名副其實fastText.
3. fastText安裝html
$ git clone https://github.com/facebookresearch/fastText.git $ cd fastText $ sudo python setup.py install
4. 準備數據
下載Yelp商品評論數據(JSON格式)
Yelp是美國著名商戶點評網站,提供了470萬的用戶評論數據以做科學研究.Yelp採用的是五星級評分,用戶評分和評論的例子以下:
python
下載解壓後會獲得數據reviews.json(大約5.3G),每行是個json對象,格式以下:git
{ "review_id": "abc123", "user_id": "xyz123", "business_id": "1234", "stars": 5, "date":" 2019-01-01", "text": "This restaurant is great!", "useful":0, "funny":0, "cool":0 }
可是fastText要求輸入的數據須要有個標籤前綴__label__YOURLABEL,因此咱們要對reviews.json的數據進行預處理,像上面的評論要轉換爲github
__label__5 This restaurant is great!
5. 數據預處理json
import json from pathlib import Path import re import random reviews_data = Path("yelp_dataset") / "review.json" training_data = Path("fasttext_dataset_training.txt") test_data = Path("fasttext_dataset_test.txt") # What percent of data to save separately as test data percent_test_data = 0.10 def strip_formatting(string): string = string.lower() string = re.sub(r"([.!?,'/()])", r" \1 ", string) return string with reviews_data.open() as input, \ training_data.open("w") as train_output, \ test_data.open("w") as test_output: for line in input: review_data = json.loads(line) rating = review_data['stars'] text = review_data['text'].replace("\n", " ") text = strip_formatting(text) fasttext_line = "__label__{} {}".format(rating, text) if random.random() <= percent_test_data: test_output.write(fasttext_line + "\n") else: train_output.write(fasttext_line + "\n")
將上面代碼保存爲dataPre.py,運行後會獲得按照9:1比例隨機劃分的訓練數據和測試數據(fasttext_dataset_training.txt & fasttext_dataset_test.txt)
6. 訓練模型網絡
import fasttext model = fasttext.train_supervised(input="fasttext_dataset_training.txt") model.save_model("model_reviews.bin ")
訓練模型並保存模型爲model_reviews.bin
dom
7. 測試模型ide
import fasttext 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)) model = fasttext.load_model("model_reviews.bin") print_results(*model.test('fasttext_dataset_test.txt'))
運行後獲得測試結果精確率是69.6%,仍是有很大的提高空間的
8. 優化模型
在以前的模型訓練中是不考慮單詞的順序的,每一個單詞在句子中是獨立的,但實際情形不是這樣的,每每須要考慮上下文,這個時候咱們能夠用參數wordNgrams來進行改進,把N個單詞捆綁在一塊兒進行訓練.考慮到時間成本,咱們取wordNgrams=2.工具
import fasttext model = fasttext.train_supervised(input="fasttext_dataset_training.txt", lr=1.0, epoch=25, wordNgrams=2) model.save_model("model_reviews.bin") 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('fasttext_dataset_test.txt'))
精確率爲69.8%,只提升了0.2%,模型仍須要優化啊測試
咱們隨機找幾個評論預測一下星級評分
import fasttext model = fasttext.load_model("model_reviews.bin") sent = input("Please input:") test = model.predict(sent) s = float('%.4f' % test[1]) if test[0] =="('__label__1.0',)": print("Star rating:☆ \nConfidence: % s%%" % (s*100)) elif test[0] =="('__label__2.0',)": print("star rating:☆☆ \nConfidence: % s%%" % (s*100)) elif test[0] =="('__label__3.0',)": print("star rating:☆☆☆ \nConfidence: % s%%" % (s*100)) elif test[0] =="('__label__4.0',)": print("star rating:☆☆☆☆ \nConfidence: % s%%" % (s*100)) else: print("star rating:☆☆☆☆☆ \nConfidence: % s%%" % (s*100))