機器學習 之 決策樹(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"]))