當前位置:
首頁 > 知識 > 復旦中文文本分類過程

復旦中文文本分類過程

文本分類系統(python 3.5)

中文語言的文本分類技術和流程,主要包括下面幾個步驟:

1. 預處理:去除文本雜訊信息,例如HTML標籤,文本格式轉換,檢測句子邊界

2. 中文分詞:使用中文分詞器為文本分詞,並去除停用詞

3. 構建詞向量空間:統計文本詞頻,生成文本的詞向量空間

4. 權重策略——TF-IDF:使用TF-IDF發現特徵詞,並抽取為反映文檔主題的特徵

5. 分類詞:使用演算法訓練分類器

6. 評價分類結果

1. 預處理

a. 選擇處理文本的範圍

b. 建立分類文本語料庫

訓練集語料已經分好類的文本資源

測試集語料待分類的文本語料,可以使訓練集的一部分,也可以是外部來源的文本語料

c. 文本格式轉化:使用Python的lxml庫去除html標籤

d. 檢測句子邊界:標記句子的結束

2. 中文分詞

分詞是將連續的字序列按照一定的規範重新組合成詞序列的過程,中文分詞即將一個漢字序列(句子)切分成一個個獨立的單詞,中文分詞很複雜,從某種程度上並不完全是一個演算法問題,最終概率論解決了這個問題,演算法是基於概率圖模型的條件隨機場(CRF)

分詞是自然語言處理中最基本,最底層的模塊,分詞精度對後續應用模塊的影響很大,文本或句子的結構化表示是語言處理中最核心的任務,目前文本的結構化表示分為四大類:詞向量空間、主體模型、依存句法的樹表示、RDF的圖表示。

下面給出中文分詞的示例代碼:

# -*- coding: utf-8 -*-

import os

import jieba

def savefile(savepath, content):

fp = open(savepath, "w",encoding="gb2312", errors="ignore")

fp.write(content)

fp.close()

def readfile(path):

fp = open(path, "r", encoding="gb2312", errors="ignore")

content = fp.read()

fp.close()

return content

# corpus_path = "train_small/" # 未分詞分類預料庫路徑

# seg_path = "train_seg/" # 分詞後分類語料庫路徑

corpus_path = "test_small/" # 未分詞分類預料庫路徑

seg_path = "test_seg/" # 分詞後分類語料庫路徑

catelist = os.listdir(corpus_path) # 獲取改目錄下所有子目錄

for mydir in catelist:

class_path = corpus_path + mydir + "/" # 拼出分類子目錄的路徑

seg_dir = seg_path + mydir + "/" # 拼出分詞後預料分類目錄

if not os.path.exists(seg_dir): # 是否存在,不存在則創建

os.makedirs(seg_dir)

file_list = os.listdir(class_path)

for file_path in file_list:

fullname = class_path + file_path

content = readfile(fullname).strip() # 讀取文件內容

content = content.replace("
", "").strip() # 刪除換行和多餘的空格

content_seg = jieba.cut(content)

savefile(seg_dir + file_path, " ".join(content_seg))

print("分詞結束")

為了後續生成詞向量空間模型的方便,這些分詞後的文本信息還要轉換成文本向量信息並對象化,利用了Scikit-Learn庫的Bunch數據結構,具體代碼如下:

import os

import pickle

from sklearn.datasets.base import Bunch

#Bunch 類提供了一種key,value的對象形式

#target_name 所有分類集的名稱列表

#label 每個文件的分類標籤列表

#filenames 文件路徑

#contents 分詞後文件詞向量形式

def readfile(path):

fp = open(path, "r", encoding="gb2312", errors="ignore")

content = fp.read()

fp.close()

return content

bunch=Bunch(target_name=[],label=[],filenames=[],contents=[])

# wordbag_path="train_word_bag/train_set.dat"

# seg_path="train_seg/"

wordbag_path="test_word_bag/test_set.dat"

seg_path="test_seg/"

catelist=os.listdir(seg_path)

bunch.target_name.extend(catelist)#將類別信息保存到Bunch對象

for mydir in catelist:

class_path=seg_path+mydir+"/"

file_list=os.listdir(class_path)

for file_path in file_list:

fullname=class_path+file_path

bunch.label.append(mydir)#保存當前文件的分類標籤

bunch.filenames.append(fullname)#保存當前文件的文件路徑

bunch.contents.append(readfile(fullname).strip())#保存文件詞向量

#Bunch對象持久化

file_obj=open(wordbag_path,"wb")

pickle.dump(bunch,file_obj)

file_obj.close()

print("構建文本對象結束")

3. 向量空間模型

由於文本在儲存未向量空間是維度較高,為節省儲存空間和提高搜索效率,在文本分類之前會自動過濾掉某些字詞,這些字或詞被稱為停用詞,停用此表可以到點這裡下載。

4. 權重策略:TF-IDF方法

如果某個詞或短語在一篇文章中出現的頻率高,並且在其他文章中很少出現,那麼認為這個詞或者短語具有很好的類別區分能力,適合用來分類。

再給出這部分代碼之前,我們先來看詞頻和逆向文件頻率的概念

詞頻(TF):指的是某一個給定的詞語在該文件中出現的頻率。這個數字是對詞數的歸一化,以防止它偏向長的文件,對於某一個特定文件里的詞語來說,它的重要性可表示為:分子是該詞在文件中出現的次數,分母是在文件中所有字詞的出現次數之和

逆向文件頻率(IDF):是一個詞語普遍重要性的度量,某一特定詞語的IDF,可以由總文件數目除以包含該詞語的文件的數目,再將得到的商取對數:|D|是語料庫中的文件總數,j是包含詞語的文件數目,如果該詞語不在語料庫中,就會導致分母為零,因此一般情況下分母還要額外再加上1之後計算詞頻和逆向文件頻率的乘積,某一特定文件內的高詞語頻率,以及該詞語在整個文件集合中的低文件頻率,可以產生出高權重的TF-IDF,因此TF-IDF傾向於過濾掉常見的詞語,保留重要的詞語。代碼如下:

import os

from sklearn.datasets.base import Bunch

import pickle#持久化類

from sklearn import feature_extraction

from sklearn.feature_extraction.text import TfidfTransformer#TF-IDF向量轉換類

from sklearn.feature_extraction.text import TfidfVectorizer#TF-IDF向量生成類

def readbunchobj(path):

file_obj=open(path,"rb")

bunch=pickle.load(file_obj)

file_obj.close()

return bunch

def writebunchobj(path,bunchobj):

file_obj=open(path,"wb")

pickle.dump(bunchobj,file_obj)

file_obj.close()

def readfile(path):

fp = open(path, "r", encoding="gb2312", errors="ignore")

content = fp.read()

fp.close()

return content

path="train_word_bag/train_set.dat"

bunch=readbunchobj(path)

#停用詞

stopword_path="train_word_bag/hlt_stop_words.txt"

stpwrdlst=readfile(stopword_path).splitlines()

#構建TF-IDF詞向量空間對象

tfidfspace=Bunch(target_name=bunch.target_name,label=bunch.label,

filenames=bunch.filenames,tdm=[],vocabulary={})

#使用TfidVectorizer初始化向量空間模型

vectorizer=TfidfVectorizer(stop_words=stpwrdlst,sublinear_tf=True,max_df=0.5)

transfoemer=TfidfTransformer()#該類會統計每個詞語的TF-IDF權值

#文本轉為詞頻矩陣,單獨保存字典文件

tfidfspace.tdm=vectorizer.fit_transform(bunch.contents)

tfidfspace.vocabulary=vectorizer.vocabulary_

#創建詞袋的持久化

space_path="train_word_bag/tfidfspace.dat"

writebunchobj(space_path,tfidfspace)

5.使用樸素貝葉斯分類模塊

常用的文本分類方法有kNN最近鄰法,樸素貝葉斯演算法和支持向量機演算法,一般而言:

kNN演算法原來最簡單,分類精度尚可,但是速度最快

樸素貝葉斯演算法對於短文本分類的效果最好,精度很高

支持向量機演算法的優勢是支持線性不可分的情況,精度上取中

上文代碼中進行操作的都是訓練集的數據,下面是測試集(抽取字訓練集),訓練步驟和訓練集相同,首先是分詞,之後生成詞向量文件,直至生成詞向量模型,不同的是,在訓練詞向量模型時需要載入訓練集詞袋,將測試集產生的詞向量映射到訓練集詞袋的詞典中,生成向量空間模型,代碼如下:

import os

from sklearn.datasets.base import Bunch

import pickle#持久化類

from sklearn import feature_extraction

from sklearn.feature_extraction.text import TfidfTransformer#TF-IDF向量轉換類

from sklearn.feature_extraction.text import TfidfVectorizer#TF-IDF向量生成類

from TF_IDF import space_path

def readbunchobj(path):

file_obj=open(path,"rb")

bunch=pickle.load(file_obj)

file_obj.close()

return bunch

def writebunchobj(path,bunchobj):

file_obj=open(path,"wb")

pickle.dump(bunchobj,file_obj)

file_obj.close()

def readfile(path):

fp = open(path, "r", encoding="gb2312", errors="ignore")

content = fp.read()

fp.close()

return content

#導入分詞後的詞向量bunch對象

path="test_word_bag/test_set.dat"

bunch=readbunchobj(path)

#停用詞

stopword_path="train_word_bag/hlt_stop_words.txt"

stpwrdlst=readfile(stopword_path).splitlines()

#構建測試集TF-IDF向量空間

testspace=Bunch(target_name=bunch.target_name,label=bunch.label,

filenames=bunch.filenames,tdm=[],vocabulary={})

#導入訓練集的詞袋

trainbunch=readbunchobj("train_word_bag/tfidfspace.dat")

#使用TfidfVectorizer初始化向量空間

vectorizer=TfidfVectorizer(stop_words=stpwrdlst,sublinear_tf=True,

max_df=0.5,vocabulary=trainbunch.vocabulary)

transformer=TfidfTransformer();

testspace.tdm=vectorizer.fit_transform(bunch.contents)

testspace.vocabulary=trainbunch.vocabulary

#創建詞袋的持久化

space_path="test_word_bag/testspace.dat"

writebunchobj(space_path,testspace)

下面執行多項式貝葉斯演算法進行測試文本分類並返回精度,代碼如下:

import pickle

from sklearn.naive_bayes import MultinomialNB # 導入多項式貝葉斯演算法包

def readbunchobj(path):

file_obj = open(path, "rb")

bunch = pickle.load(file_obj)

file_obj.close()

return bunch

# 導入訓練集向量空間

trainpath = "train_word_bag/tfidfspace.dat"

train_set = readbunchobj(trainpath)

# d導入測試集向量空間

testpath = "test_word_bag/testspace.dat"

test_set = readbunchobj(testpath)

# 應用貝葉斯演算法

# alpha:0.001 alpha 越小,迭代次數越多,精度越高

clf = MultinomialNB(alpha=0.001).fit(train_set.tdm, train_set.label)

# 預測分類結果

predicted = clf.predict(test_set.tdm)

total = len(predicted);rate = 0

for flabel, file_name, expct_cate in zip(test_set.label, test_set.filenames, predicted):

if flabel != expct_cate:

rate += 1

print(file_name, ": 實際類別:", flabel, "-->預測分類:", expct_cate)

# 精度

print("error_rate:", float(rate) * 100 / float(total), "%")

6.分類結果評估

機器學習領域的演算法評估有三個基本指標:

召回率(recall rate,查全率):是檢索出的相關文檔數與文檔庫中所有相關文檔的比率,衡量的是檢索系統的查全率,召回率=系統檢索到的相關文件/系統所有相關的文件綜述。

準確率(Precision,精度):是檢索出的相關文檔數於檢索出的文檔總數的比率,衡量的是檢索系統的查准率,準確率=系統檢索到的相關文件/系統所有的檢索到的文件數。

準確率和召回率是相互影響的,理想情況下是二者都高,但是一般情況下準確率高,召回率就低;召回率高,準確率就低

import numpy as np

from sklearn import metrics

#評估

def metrics_result(actual,predict):

print("精度:".format(metrics.precision_score(actual,predict)))

print("召回:".format(metrics.recall_score(actual,predict)))

print("f1-score:".format(metrics.f1_score(actual,predict)))

metrics_result(test_set.label,predicted

-今晚直播預告-


喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 AI講堂 的精彩文章:

重磅!2018中國區塊鏈Top100強公司榜單發布!
AI對你影響有多大?3成受訪者感受到對自己工作的威脅

TAG:AI講堂 |