1. 程式人生 > >機器學習 之 決策樹(Decision Tree)文字演算法的精確率

機器學習 之 決策樹(Decision Tree)文字演算法的精確率

目錄

背景

最近的專案中,用到了很多機器學習的演算法,每個機器學習的演算法在不同的樣本下的精準率是不同的。為了驗證每個演算法在每種不同樣本數量的能力,就做了一下實驗,本文講的是決策樹在文字演算法中的精準率。

效果圖

先看一下沒有任何調參的情況下的效果吧!
在這裡插入圖片描述
通過以上資料可以看出決策樹在樣本數量較低的情況下還不錯,在樣本數量在5000的時候效果還可以,但是到達20000的時候,準確率已經在70%左右了。

整體流程

1、先把整體樣本讀到記憶體中

2、把整體樣本按照8:2的比例,分為80%的訓練集,20%的測試集

3、然後“訓練集”的樣本 先分詞,然後轉換為詞向量

4、接著把訓練集的樣本和標籤統一的傳入 “決策樹”的演算法中,得到擬合後的模型

5、把“測試集”的樣本 先分詞,然後得到詞向量

6、把測試集得出的詞向量丟到擬合後的模型中,看得出的結果

7、把結果轉換為準確率的形式,最後做成表格形式以便觀看

這裡應該多跑幾遍不同樣本,然後把結果取平均值,每次的結果還是稍有不同的。

這裡用詞向量,而不是TF-IDF預處理後的向量

這裡我們直接取得詞向量,而不是經過TF-IDF處理過的詞向量。如果處理過,效果會不如現在的好。

TF-IDF(詞頻-逆文字頻率),前面的TF也就是常說到的詞頻,我們之前做的向量化也就是做了文字中各個詞的出現頻率統計,並作為文字特徵,這個很好理解。關鍵是後面的這個IDF,即“逆文字頻率”如何理解。有些句子中的詞,比如說“的”,幾乎所有句子都會出現,詞頻雖然高,但是重要性卻應該比 主語、賓語等低。IDF就是來幫助我們來反應這個詞的重要性的,進而修正僅僅用詞頻表示的詞特徵值。
概括來講, IDF反應了一個詞在所有文字中出現的頻率,如果一個詞在很多的文字中出現,那麼它的IDF值應該低

加了TF-IDF處理後的效果:
在這裡插入圖片描述

經過TF-IDF處理後的效果比不處理效果還差。所以,這裡就不經過TF-IDF處理了哈。
以下原始碼中,如果加TF-IDF處理,只需要在jiabaToVector()函式中增加True這個引數就OK了

    vector_train = jiabaToVector(m_text_train, False, True)
    ...
    ...
    vector_test = jiabaToVector(m_text_test, True, True)

原始碼

import jieba
import datetime
# 向量\測試集\訓練集\得分比對
from sklearn.model_selection  import train_test_split
from sklearn.feature_extraction.text import TfidfTransformer
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.metrics import accuracy_score
#決策樹
from sklearn import tree

m_count = [1000,3000,5000,8000,10000,15000,20000]

# all
m_list_allText = []
m_list_allL4ID = []
# 內容的訓練集、測試集
m_text_test = []
m_text_train = []
m_label_test = []
m_label_train = []

m_map_all = []


# 讀取檔案裡面資料,獲取標籤和內容
def getFile(filename, count):
    with open(filename, 'r' ,encoding='utf-8') as fp:
        global m_list_allL4ID,m_list_allText
        m_list_allL4ID = []
        m_list_allText = []
        for i in range(count):
            text = fp.readline()
            if ":" in text:
                L4ID = text.split(":")[-2]
                Msg = text.split(":")[-1]
                m_list_allL4ID.append(L4ID)
                m_list_allText.append(Msg)

# 隨機分為 測試集 和 訓練集 2-8分
def randomTestAndTrain():
    # 生成訓練集和測試集
    global m_text_test, m_text_train, m_label_test, m_label_train
    m_text_train, m_text_test, m_label_train, m_label_test = train_test_split(m_list_allText, m_list_allL4ID, test_size=0.2, random_state=1)

def jiabaToVector(list, isTest, isTFIDF = False):
    tmp_list = []
    for sentence in list:
        tmp_list.append(" ".join(jieba.cut(sentence.strip())))
    # 利用TFIDF生成詞向量
    transformer = TfidfTransformer()
    if isTest:
        if isTFIDF:
            tfidf = transformer.fit_transform(vectorizer.transform(tmp_list))
        else:
            tfidf = vectorizer.transform(tmp_list)
    else:
        if isTFIDF:
            tfidf = transformer.fit_transform(vectorizer.fit_transform(tmp_list))
        else:
            tfidf = vectorizer.fit_transform(tmp_list)
    return tfidf


# 建立預設引數的決策樹
def predict_4(X, Y):
    clf = tree.DecisionTreeClassifier()
    clf = clf.fit(X, Y)
    return clf

def test(count):
    # getFile("./rg_test.train", count)
    getFile("./rg_train_20190102_20181227114134.train", count)
    # print("獲取全部已知資料的label和text")

    # 隨機分為 測試集 和 訓練集 2-8分
    randomTestAndTrain()

    global vectorizer
    # 全域性向量
    vectorizer = CountVectorizer()

    # 生成訓練向量
    vector_train = jiabaToVector(m_text_train, False)

    # 資料大小
    lenall = len(m_list_allText)
    # print("總集大小:", lenall)
    print("總集大小:", lenall)

    # 訓練
    startT_Train = datetime.datetime.now()
    clf = predict_4(vector_train, m_label_train)
    endT_Train = datetime.datetime.now()
    print("訓練Time:", (endT_Train - startT_Train).microseconds)

    # 生成測試向量
    vector_test = jiabaToVector(m_text_test, True)

    # 測試
    startT = datetime.datetime.now()
    result = clf.predict(vector_test)
    endT = datetime.datetime.now()
    print("測試Time:", (endT - startT).microseconds)

    # 計算百分比
    percent = accuracy_score(result, m_label_test)
    print("準確率:", round(percent, 3))

    map_all = {}
    map_all["精確率"]=round(percent, 3)
    map_all["資料量"]=lenall
    map_all["訓練時間/us"]=(endT_Train - startT_Train).microseconds
    map_all["測試時間/us"]=(endT - startT).microseconds
    m_map_all.append(map_all)

if __name__ =="__main__":
    print ("-- 開始 --")
    for testC in m_count:
        test(testC)
    print ("-- 結束 --")

    # 打印表格
    print("資料量\t準確度\t訓練時間/us\t測試時間/us")
    for key in m_map_all:
        print("%d\t%f\t%d\t%d"%(key["資料量"],key["精確率"],key["訓練時間/us"],key["測試時間/us"]))