1. 程式人生 > >利用決策樹對微信公眾號文字進行分類

利用決策樹對微信公眾號文字進行分類

問題背景

公眾平臺的公眾號每天都會發布大量文章,通過群發圖文的形式向用戶每天推送內容。由於公眾號面向的使用者群體、專注的領域不同,圖文內容也差異很大。一些公眾號主要釋出時事政治內容,而另外一些公眾號主要釋出遊戲的視訊與周邊等。識別公眾號的內容對公眾平臺的運營與新場景應用發揮重要作用,其中對公眾號文字的挖掘能力是一個基礎能力。本次題目選擇時尚類公眾號的文章,關注化妝個護領域,要求根據給出的文章內容(已分詞)識別出該文章是否向用戶推薦化妝個護相關的商品。

知識背景:

  (一)、文字預處理

1.資料清洗:對於爬蟲爬取的HTML原始文字,需要進行資料清洗過濾掉標籤文字。

2.分詞(只針對中文文字):對於中文文字資料,比如一條中文的句子,詞語詞之間是連續的,而資料分析的最小單位粒度我們希望是詞語,所以我們需要進行分詞工作,這樣就給下一步的工作做準備。

3.詞性標註(可選):詞性標註POS的目的是為了讓句子在後面的處理中融入更多的有用的語言資訊。不過對於一些文字處理任務,這一步不是必須的。

4.去停用詞:停用詞stopword是指那些對文字特徵沒有任何貢獻作用的詞語,例如一些語氣助詞和一些標點符號。在一些文字也能針對性的去掉一些詞,如形容詞

 (二)、構造文字特徵

        將文字符號轉換成或者表示成能讓學習模型能夠處理的資料型別,也就是將文字符號串轉變為數字,更確切的說是向量陣列:矩陣。一般使用的方法有詞袋(count,tf-idf)和詞向量(word2vec,glove)。

 (三)、特徵選擇

        在文字挖掘與文字分類的有關問題中,常採用特徵選擇方法。原因是文字的特徵一般都是單詞(term),具有語義資訊,使用特徵選擇找出的k維子集,仍然是單詞作為特徵,保留了語義資訊,而特徵提取則找k維新空間,將會喪失了語義資訊。

常用方法有DF(Document Frequency),MI(Mutual Information),IG(Information Gain),CHI(Chi-square,也就是卡方),WLLR(Weighted Log Likelihood Ration)等。

 (四)、學習模型訓練

        將文字表示為廣義特徵資料結構以後,將特徵放入學習模型,然後用於測試資料集的預測,得到結果。本次作業使用決策樹模型進行文字分類。

        模型評估,評價指標通常由準確率,AUC和F1。

        AUC:ROC全稱是“受試者工作特徵”(Receiver Operating Characteristic)。ROC曲線的面積就是AUC(Area Under the Curve)。AUC用於衡量“二分類問題”機器學習演算法效能(泛化能力)。

        F1:F1分數可以看作是模型準確率召回率的一種加權平均,它的最大值是1,最小值是0。

(五)詞袋模型原理

    Bag-of-words模型是資訊檢索領域常用的文件表示方法。

在資訊檢索中,BOW模型假定對於一個文件,忽略它的單詞順序和語法、句法等要素,將其僅僅看作是若干個詞彙的集合,文件中每個單詞的出現都是獨立的,不依賴於其它單詞是否出現。(是不關順序的)

Wikipedia[1]上給出瞭如下例子:

John likes to watch movies.

Mary likes too.John also likes to watch football games.

根據上述兩句話中出現的單詞, 我們能構建出一個字典 (dictionary):

{"John": 1, "likes": 2, "to": 3, "watch": 4, "movies": 5, "also": 6, "football": 7, "games": 8, "Mary": 9, "too": 10}

該字典中包含10個單詞, 每個單詞有唯一索引, 注意它們的順序和出現在句子中的順序沒有關聯. 根據這個字典, 我們能將上述兩句話重新表達為下述兩個向量:

[1, 2, 1, 1, 1, 0, 0, 0, 1, 1]

[1, 1, 1, 1, 0, 1, 1, 1, 0, 0]

這兩個向量共包含10個元素, 其中第i個元素表示字典中第i個單詞在句子中出現的次數. 因此BoW模型可認為是一種統計直方圖 (histogram). 在文字檢索和處理應用中, 可以通過該模型很方便的計算詞頻.但是從上面我們也能夠看出,在構造文件向量的過程中可以看到,我們並沒有表達單詞在原來句子中出現的次序

適用場景:

現在想象在一個巨大的文件集合D,裡面一共有M個文件,而文件裡面的所有單詞提取出來後,一起構成一個包含N個單詞的詞典,利用Bag-of-words模型,每個文件都可以被表示成為一個N維向量。變為N維向量之後,很多問題就變得非常好解了,計算機非常擅長於處理數值向量,我們可以通過餘弦來求兩個文件之間的相似度,也可以將這個向量作為特徵向量送入分類器進行主題分類等一系列功能中去。

(6)決策樹原理

    分類決策樹模型是一種描述對例項進行分類的樹形結構。決策樹由結點和有向邊組成。結點有兩種型別:內部節點和葉節點,內部節點表示一個特徵或屬性,葉節點表示一個類。分類的時候,從根節點開始,對例項的某一個特徵進行測試,根據測試結果,將例項分配到其子結點;此時,每一個子結點對應著該特徵的一個取值。如此遞歸向下移動,直至達到葉結點,最後將例項分配到葉結點的類中。通俗點說就是一個if-then的過程。常見的決策樹有ID3、C4.5、CART等。

處理過程:

由於文字已經過已經過分詞處理,所以接下來的工作就比較簡單。思路如下:把文字用詞袋模型表示出來,經過特徵選擇,降低每個文字向量的維度,然後通過訓練集(train.tsv)訓練出一個決策樹模型,對測試集(test.tsv)進行分類。

結果:


改進之處:

可以看到,利用python中sklearn的決策樹進行分類,準確只有大概72%,不是特別的高。如果想提高準確率,可以從以下幾個方面入手:

1、增加訓練集的資料量。決策樹是一種有監督學習,訓練集的資料量越大,得到的模型就越完善,進行分類時就越準確。

2、構造文字特徵的時候,利用TF-IDF(詞頻-逆文件頻率)值作為權重,這樣得到的詞袋模型就更加準確,我使用的利用TF(詞頻)作為權重,這樣勢必會受到一些詞頻高,但與文章主題內容不相關的詞語影響,在決策樹進行訓練時會產生錯誤的劃分。

3、使用更完善的決策樹,如GDBT、xgboost決策樹。xgboost決策樹是n顆cart決策樹互相作用得到的一種決策樹模型。

原始碼:

# -*- coding: utf-8 -*-
import pandas as pd
import os,sys
import numpy as np
import jieba
from sklearn.externals import joblib
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn import tree

train ="trian.tsv"

train_df = pd.read_csv(r"train.tsv", sep="\t")

test_df = pd.read_csv(r'test2.tsv', sep="\t")
train_df_X = train_df.content.values.tolist()  # to list
train_df_y = train_df.label.values.tolist()
test_df_X = test_df.content.values.tolist()
test_df_y = test_df.label.values.tolist()


def preprocess_text(content_lists, sentences, label_lists):
    for i in range(0, len(content_lists)):
        line = content_lists[i]
        label = label_lists[i]
        try:
            segs = line.split("|")
            segs = [v for v in segs if not str(v).isdigit()]  # 去數字
            segs = list(filter(lambda x: x.strip(), segs))  # 去左右空格
            segs = list(filter(lambda x: len(x) > 1, segs))  # 長度為1的字元
            sentences.append((" ".join(segs), label))
        except Exception:
            print(line)
            continue

# 生成訓練資料


sentences_train = []
preprocess_text(train_df_X, sentences_train, train_df_y)
# 生成測試資料
sentences_test = []
preprocess_text(test_df_X, sentences_test, test_df_y)

x_train, y_train = zip(*sentences_train)
x_test, y_test = zip(*sentences_test)

vec = CountVectorizer(
    analyzer='word',  # tokenise by character ngrams
    max_features=3500, )
vec.fit(x_train)
vec.fit(x_test)


clf = tree.DecisionTreeClassifier(criterion="entropy", min_samples_split=4)
clf = clf.fit(vec.transform(x_train), y_train)
os.chdir("E:\\Users\\Administrator\\PycharmProjects\\untitled1\\model_save")
joblib.dump(clf,'model_save/train_mode1.m')#儲存決策樹模型,下次直接呼叫即可
clf=joblib.load('model_save/train_mode1.m')#呼叫決策樹模型

print(clf.score(vec.transform(x_test), y_test))#輸出準確率