首頁 > 軟體

Python實現基於Fasttext的商品評論資料分類的操作流程

2022-06-01 14:01:55

在以往的文字分型別的任務中,基本的流程主要是就是:

  • 文字資料載入
  • 資料淨化
  • 分詞
  • 向量化
  • 分類模型訓練
  • 效能評估

這裡面比如向量化和模型搭建是獨立的兩個節點,可以自由地進行設計,當然了也是一份工作量,今天使用的fasttext更像是一個整合的庫,把向量化和分類一起做掉了,這個對於使用層面來講就更方便了一些,不過也並不是絕對的,一般經驗來說,封裝程度越高的庫對於個性化的開發越不友好,但是如果僅僅只是使用一下就行,能夠實現自己的功能這樣的想法的話倒是可以使用這種型別的庫的,總之,沒有絕對的最優,只有適合自己的模型。

本文主要也是基於具體的應用來體驗fasttext,整體流程如下:

為了清晰展示流程,這裡我用不同的顏色來標識不同的功能部分:

綠色部分為資料採集部分,這部分由於部分原因無法開放到這裡

藍色部分為資料處理部分,這部分主要完成原始資料的清洗分詞等工作

黃色部分主要是範例化呼叫fasttext提供的模型來完成分類評估等工作

首先看下原始資料樣例如下:

{
    '_id': '4c671f75cc20b28264c30c2ef158f32b',
    'guid': 'b2422b96a015b85d9a47c83e65f01987',
    'content': 'iPhone13收到了,很喜歡的蘋果手機,一直都是蘋果的忠實粉絲。13手機外觀真的太驚豔了,最新款的手機就是不一樣,非常的好看!午夜色也是很驚豔的,是我很喜歡的顏色。外觀設計非常的好看,小巧精緻,很喜歡iPhone的產品。新款的相機非常好,拍攝效果強大,很適合愛美的女生拍照。拍視訊的電影模式也是非常驚豔,真的太棒了,濾鏡自帶美顏效果,非常特別!前置攝像頭也有亮點,優化升級,升級後的畫素真的超棒!萌萌的攝像頭,手機大小合適,握著手感很舒服。螢幕非常細膩,通透,螢幕很喜歡!新一代執行速度快了很多,系統非常流暢,螢幕120hz重新整理率。電池也還不錯,正常使用,續航能力還是挺久的,玩遊戲也不會發燙。買了套裝一年延保的,感覺還是很不錯的!A15速度還是很快的,加上iOS15的加持,手機很流暢,使用了一週了,手機各方面都很不錯!',
    'creationTime': '2021-11-2907: 13: 51',
    'isDelete': False,
    'isTop': False,
    'userImageUrl': 'misc.360buyimg.com/user/myjd-2015/css/i/peisong.jpg',
    'topped': 0,
    'replies': [
        {
            'id': 946189091,
            'commentId': 16739194625,
            'content': '謝謝您對本店的支援,我們會不斷的努力,爭取做的更好,我們成長的路上有您的支援,我們表示感謝,歡迎再次光臨。祝您生活愉快,閤家安康!',
            'pin': 'jd_oMFlwVDJJjkA',
            'userClient': 98,
            'userImage': 'misc.360buyimg.com/user/myjd-2015/css/i/peisong.jpg',
            'ip': '115.207.85.31',
            'productId': 10039695828478,
            'replyList': [
                
            ],
            'nickname': 'jd_oMFlwVDJJjkA',
            'creationTime': '2021-11-2910: 10: 54',
            'parentId': 0,
            'targetId': 0,
            'venderShopInfo': {
                'id': 10706414,
                'appName': '//mall.jd.com/index-10706414.html',
                'title': '京東之家官方旗艦店',
                'venderId': 10955089
            }
        }
    ],
    'replyCount': 28,
    'score': 5,
    'imageStatus': 1,
    'usefulVoteCount': 28,
    'userClient': 4,
    'discussionId': 1006752884,
    'imageCount': 8,
    'anonymousFlag': 1,
    'plusAvailable': 201,
    'mobileVersion': '10.2.4',
    'mergeOrderStatus': 2,
    'productColor': '128G午夜色',
    'productSize': '套裝五:搭配店鋪延保一年',
    'textIntegral': 40,
    'imageIntegral': 40,
    'status': 1,
    'referenceId': '10039695828478',
    'referenceTime': '2021-11-0802: 31: 34',
    'nickname': 'z***a',
    'replyCount2': 39,
    'userImage': 'misc.360buyimg.com/user/myjd-2015/css/i/peisong.jpg',
    'orderId': 0,
    'integral': 80,
    'productSales': '[
        
    ]',
    'referenceImage': 'jfs/t1/124476/38/25971/146827/622b14cfEec332c92/75f5bf4417c1fd1d.jpg',
    'referenceName': '【12期免息可選】Apple蘋果iPhone13(A2634)全網通5G手機128G綠色套裝一:搭配90天品勝碎屏保障',
    'firstCategory': 9987,
    'secondCategory': 653,
    'thirdCategory': 655,
    'aesPin': None,
    'days': 21,
    'afterDays': 0,
    'comp_con': 'iPhone13收到了很喜歡的蘋果手機一直都是蘋果的忠實粉絲13手機外觀真的太驚豔了最新款的手機就是不一樣非常的好看午夜色也是很驚豔的是我很喜歡的顏色外觀設計非常的好看小巧精緻很喜歡iPhone的產品新款的相機非常好拍攝效果強大很適合愛美的女生拍照拍視訊的電影模式也是非常驚豔真的太棒了濾鏡自帶美顏效果非常特別前置攝像頭也有亮點優化升級升級後的畫素真的超棒萌的攝像頭手機大小合適握著手感很舒服螢幕非常細膩通透螢幕很喜歡新一代執行速度快了很多系統非常流暢螢幕120hz重新整理率電池也還不錯正常使用續航能力還是挺久的玩遊戲也不會發燙買了套裝一年延保的感覺還是很不錯的A15速度還是很快的加上iOS15的加持手機很流暢使用了一週了手機各方面都很不錯',
    'label': 1,
    'cut_li': [
        'iPhone',
        '13',
        '收到',
        '喜歡',
        '蘋果',
        '手機',
        '一直',
        '蘋果',
        '忠實',
        '粉絲',
        '13',
        '手機',
        '外觀',
        '真的',
        '太',
        '驚豔',
        '最新款',
        '手機',
        '非常',
        '好看',
        '午夜',
        '色',
        '驚豔',
        '喜歡',
        '顏色',
        '外觀設計',
        '非常',
        '好看',
        '小巧',
        '精緻',
        '喜歡',
        'iPhone',
        '產品',
        '新款',
        '相機',
        '非常',
        '拍攝',
        '效果',
        '強大',
        '適合',
        '愛美',
        '女生',
        '拍照',
        '拍',
        '視訊',
        '電影',
        '模式',
        '非常',
        '驚豔',
        '真的',
        '太棒了',
        '濾鏡',
        '自帶',
        '美顏',
        '效果',
        '非常',
        '特別',
        '前置',
        '攝像頭',
        '亮點',
        '優化',
        '升級',
        '升級',
        '畫素',
        '真的',
        '超棒',
        '萌',
        '攝像頭',
        '手機',
        '大小',
        '合適',
        '握',
        '手感',
        '舒服',
        '螢幕',
        '非常',
        '細膩',
        '通透',
        '螢幕',
        '喜歡',
        '新一代',
        '執行',
        '速度',
        '快',
        '很多',
        '系統',
        '非常',
        '流暢',
        '螢幕',
        '120hz',
        '重新整理率',
        '電池',
        '不錯',
        '正常',
        '使用',
        '續航',
        '能力',
        '挺久',
        '玩遊戲',
        '不會',
        '發燙',
        '買',
        '套裝',
        '一年',
        '延保',
        '感覺',
        '不錯',
        'A15',
        '速度',
        '很快',
        '加上',
        'iOS15',
        '加持',
        '手機',
        '流暢',
        '使用',
        '一週',
        '手機',
        '方面',
        '不錯'
    ],
    'cut_con': 'iPhone13收到喜歡蘋果手機一直蘋果忠實粉絲13手機外觀真的太驚豔最新款手機非常好看午夜色驚豔喜歡顏色外觀設計非常好看小巧精緻喜歡iPhone產品新款相機非常拍攝效果強大適合愛美女生拍照拍視訊電影模式非常驚豔真的太棒了濾鏡自帶美顏效果非常特別前置攝像頭亮點優化升級升級畫素真的超棒萌攝像頭手機大小合適握手感舒服螢幕非常細膩通透螢幕喜歡新一代執行速度快很多系統非常流暢螢幕120hz重新整理率電池不錯正常使用續航能力挺久玩遊戲不會發燙買套裝一年延保感覺不錯A15速度很快加上iOS15加持手機流暢使用一週手機方面不錯',
    'label_con': '__label__1,
    iPhone13收到喜歡蘋果手機一直蘋果忠實粉絲13手機外觀真的太驚豔最新款手機非常好看午夜色驚豔喜歡顏色外觀設計非常好看小巧精緻喜歡iPhone產品新款相機非常拍攝效果強大適合愛美女生拍照拍視訊電影模式非常驚豔真的太棒了濾鏡自帶美顏效果非常特別前置攝像頭亮點優化升級升級畫素真的超棒萌攝像頭手機大小合適握手感舒服螢幕非常細膩通透螢幕喜歡新一代執行速度快很多系統非常流暢螢幕120hz重新整理率電池不錯正常使用續航能力挺久玩遊戲不會發燙買套裝一年延保感覺不錯A15速度很快加上iOS15加持手機流暢使用一週手機方面不錯'
}

之後對原始資料進行解析處理:

# 文字去重
con_li = []
data_clear = []
for item in data:
    if item["content"] not in con_li:
        con_li.append(item["content"])
        data_clear.append(item)
print("文字去重過濾條數:%s" % (len(data) - len(data_clear)))
print("剩餘評論個數:", len(con_li))  # 剩餘評論個數

def clean_txt(raw):
    """
    提取清洗
    """
    fil = re.compile(r"[^0-9a-zA-Zu4e00-u9fa5]+")
    return fil.sub(" ", raw)
compress_num = 0
for i, item in enumerate(data_clear):
    temp_com = item["content"]
    compress_com = clean_txt(temp_com)
    if compress_com != temp_com:
        compress_num += 1
    item["comp_con"] = compress_com
    data_clear[i] = item
print("data_clear_legnth: ", len(data_clear))
for one in data_clear[:3]:
    print("one: ", one)

接著對清洗處理好的資料記性分詞和資料組裝:

# 進行結巴分詞
stop_words = []
with open("cn_stopwords.txt", "r", encoding="utf-8") as f:
    stop_words = f.readlines()
stop_words = [sw.strip() for sw in stop_words]
stop_words.append("n")
data_li = []
for i, item in enumerate(data_final):
    cut_li = list(jieba_fast.cut(item["comp_con"]))
    cut_clear_li = [c.strip() for c in cut_li if c.strip() and c not in stop_words]
    item["cut_li"] = cut_clear_li
    cut_con = " ".join(cut_clear_li)
    item["cut_con"] = cut_con
    label_con = "__label__%s , %s" % (item["label"], item["cut_con"])
    item["label_con"] = label_con
    data_li.append(label_con)
    data_final[i] = item
print("data_final_legnth: ", len(data_final))
for one in data_final[:3]:
    print("one: ", one)

處理後的資料如下:

雖然說看著有些奇怪,尤其是: __label__,但是這個沒辦法,fasttext需要的標準資料格式就是這個樣子的。

之後就可以進行模型訓練了,核心實現如下:

def train_model(ipt=None, opt=None, model="", dim=100, epoch=5, lr=0.5, loss="softmax"):
    np.set_printoptions(suppress=True)
    classifier = fasttext.train_supervised(
        ipt, label="__label__", dim=dim, epoch=epoch, lr=lr, wordNgrams=4, loss=loss
    )
    """
          訓練一個監督模型, 返回一個模型物件
          @param input:           訓練資料檔案路徑
          @param lr:              學習率
          @param dim:             向量維度
          @param ws:              cbow模型時使用
          @param epoch:           次數
          @param minCount:        詞頻閾值, 小於該值在初始化時會過濾掉
          @param minCountLabel:   類別閾值,類別小於該值初始化時會過濾掉
          @param minn:            構造subword時最小char個數
          @param maxn:            構造subword時最大char個數
          @param neg:             負取樣
          @param wordNgrams:      n-gram個數
          @param loss:            損失函數型別, softmax, ns: 負取樣, hs: 分層softmax
          @param bucket:          詞擴充大小, [A, B]: A語料中包含的詞向量, B不在語料中的詞向量
          @param thread:          執行緒個數, 每個執行緒處理輸入資料的一段, 0號執行緒負責loss輸出
          @param lrUpdateRate:    學習率更新
          @param t:               負取樣閾值
          @param label:           類別字首
          @param verbose:         ??
          @param pretrainedVectors: 預訓練的詞向量檔案路徑, 如果word出現在資料夾中初始化不再隨機
          @return model object
        """
    classifier.save_model(opt)
    return classifier

這裡同樣實現了對於模型結果的評估方法:

def cal_precision_and_recall(file="test.txt"):
    """
    計算每個標籤 的precision和recall
    """
    precision = defaultdict(int, 1)
    recall = defaultdict(int, 1)
    total = defaultdict(int, 1)
    with open(file, encoding="utf-8") as f:
        for line in f:
            label, content = line.split(",", 1)
            total[label.strip().strip("__label__")] += 1
            labels2 = classifier.predict([content.strip()])
            pre_label, sim = labels2[0][0][0], labels2[1][0][0]
            recall[pre_label.strip().strip("__label__")] += 1
            if label.strip() == pre_label.strip():
                precision[label.strip().strip("__label__")] += 1
    print("{:<10} {:<30}".format("precision", str(precision.dict)))
    print("{:<10} {:<30}".format("recall", str(recall.dict)))
    print("{:<10} {:<30}".format("total", str(total.dict)))
    for sub in precision.dict:
        pre = precision[sub] / total[sub]
        rec = precision[sub] / recall[sub]
        F1 = (2 * pre * rec) / (pre + rec)
        print(
            f"{sub.strip('__label__')}  t   precision: {str(pre)}  t   recall: {str(rec)}  t   F1: {str(F1)}"
        )

執行結果如下所示:

到此這篇關於Python實現基於Fasttext的商品評論資料分類的文章就介紹到這了,更多相關Python Fasttext商品評論內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com