第7課:動手實戰(zhàn)基于 ML 的中文短文本分類

文本分類悟民,屬于有監(jiān)督學(xué)習(xí)中的一部分厕氨,在很多場景下都有應(yīng)用,下面通過小數(shù)據(jù)的實例汹粤,一步步完成中文短文本的分類實現(xiàn)命斧,整個過程盡量做到少理論重實戰(zhàn)。

enter image description here

開發(fā)環(huán)境玄括,我們選擇

  1. Windows 系統(tǒng)
  2. Python 3.6
  3. Jupyter Notebook

本文使用的數(shù)據(jù)是我曾經(jīng)做過的一份司法數(shù)據(jù)冯丙,需求是對每一條輸入數(shù)據(jù),判斷事情的主體是誰遭京,比如報警人被老公打,報警人被老婆打泞莉,報警人被兒子打哪雕,報警人被女兒打等來進行文本有監(jiān)督的分類操作。

整個過程分為以下幾個步驟

  • 語料加載
  • 分詞
  • 去停用詞
  • 抽取詞向量特征
  • 分別進行算法建模和模型訓(xùn)練
  • 評估鲫趁、計算 AUC 值
  • 模型對比

基本流程如下圖所示

enter image description here

下面開始項目實戰(zhàn)斯嚎。

1. 首先進行語料加載,在這之前挨厚,引入所需要的 Python 依賴包堡僻,并將全部語料和停用詞字典讀入內(nèi)存中。

第一步疫剃,引入依賴庫钉疫,有隨機數(shù)庫、jieba 分詞巢价、pandas 庫等:

    import random
    import jieba
    import pandas as pd

第二步牲阁,加載停用詞字典,停用詞詞典為 stopwords.txt 文件壤躲,可以根據(jù)場景自己在該文本里面添加要去除的詞(比如冠詞城菊、人稱、數(shù)字等特定詞):

    #加載停用詞
    stopwords=pd.read_csv('stopwords.txt',index_col=False,quoting=3,sep="\t",names=['stopword'], encoding='utf-8')
    stopwords=stopwords['stopword'].values

第三步碉克,加載語料凌唬,語料是4個已經(jīng)分好類的 csv 文件,直接用 pandas 加載即可漏麦,加載之后可以首先刪除 nan 行客税,并提取要分詞的 content 列轉(zhuǎn)換為 list 列表:

    #加載語料
    laogong_df = pd.read_csv('beilaogongda.csv', encoding='utf-8', sep=',')
    laopo_df = pd.read_csv('beilaogongda.csv', encoding='utf-8', sep=',')
    erzi_df = pd.read_csv('beierzida.csv', encoding='utf-8', sep=',')
    nver_df = pd.read_csv('beinverda.csv', encoding='utf-8', sep=',')
    #刪除語料的nan行
    laogong_df.dropna(inplace=True)
    laopo_df.dropna(inplace=True)
    erzi_df.dropna(inplace=True)
    nver_df.dropna(inplace=True)
    #轉(zhuǎn)換
    laogong = laogong_df.segment.values.tolist()
    laopo = laopo_df.segment.values.tolist()
    erzi = erzi_df.segment.values.tolist()
    nver = nver_df.segment.values.tolist()

2. 分詞和去停用詞。

第一步唁奢,定義分詞霎挟、去停用詞和批量打標(biāo)簽的函數(shù),函數(shù)包含3個參數(shù):content_lines 參數(shù)為語料列表麻掸;sentences 參數(shù)為預(yù)先定義的 list酥夭,用來存儲分詞并打標(biāo)簽后的結(jié)果;category 參數(shù)為標(biāo)簽 :

    #定義分詞和打標(biāo)簽函數(shù)preprocess_text
    #參數(shù)content_lines即為上面轉(zhuǎn)換的list
    #參數(shù)sentences是定義的空list,用來儲存打標(biāo)簽之后的數(shù)據(jù)
    #參數(shù)category 是類型標(biāo)簽
    def preprocess_text(content_lines, sentences, category):
        for line in content_lines:
            try:
                segs=jieba.lcut(line)
                segs = [v for v in segs if not str(v).isdigit()]#去數(shù)字
                segs = list(filter(lambda x:x.strip(), segs))   #去左右空格
                segs = list(filter(lambda x:len(x)>1, segs)) #長度為1的字符
                segs = list(filter(lambda x:x not in stopwords, segs)) #去掉停用詞
                sentences.append((" ".join(segs), category))# 打標(biāo)簽
            except Exception:
                print(line)
                continue 

第二步熬北,調(diào)用函數(shù)疙描、生成訓(xùn)練數(shù)據(jù),根據(jù)我提供的司法語料數(shù)據(jù)讶隐,分為報警人被老公打起胰,報警人被老婆打,報警人被兒子打巫延,報警人被女兒打效五,標(biāo)簽分別為0、1炉峰、2畏妖、3,具體如下:

    sentences = []
    preprocess_text(laogong, sentences,0)
    preprocess_text(laopo, sentences, 1)
    preprocess_text(erzi, sentences, 2)
    preprocess_text(nver, sentences, 3)

第三步疼阔,將得到的數(shù)據(jù)集打散戒劫,生成更可靠的訓(xùn)練集分布,避免同類數(shù)據(jù)分布不均勻:

    random.shuffle(sentences)

第四步婆廊,我們在控制臺輸出前10條數(shù)據(jù)迅细,觀察一下:

    for sentence in sentences[:10]:
        print(sentence[0], sentence[1])  #下標(biāo)0是詞列表,1是標(biāo)簽

得到的結(jié)果如圖所示:

enter image description here

3. 抽取詞向量特征淘邻。

第一步茵典,抽取特征,我們定義文本抽取詞袋模型特征:

    from sklearn.feature_extraction.text import CountVectorizer
    vec = CountVectorizer(
        analyzer='word', # tokenise by character ngrams
        max_features=4000,  # keep the most common 1000 ngrams
    )

第二步列荔,把語料數(shù)據(jù)切分敬尺,用 sk-learn 對數(shù)據(jù)切分,分成訓(xùn)練集和測試集:

    from sklearn.model_selection import train_test_split
    x, y = zip(*sentences)
    x_train, x_test, y_train, y_test = train_test_split(x, y, random_state=1256)

第三步贴浙,把訓(xùn)練數(shù)據(jù)轉(zhuǎn)換為詞袋模型:

    vec.fit(x_train)

4. 分別進行算法建模和模型訓(xùn)練砂吞。

定義樸素貝葉斯模型,然后對訓(xùn)練集進行模型訓(xùn)練崎溃,直接使用 sklearn 中的 MultinomialNB:

    from sklearn.naive_bayes import MultinomialNB
    classifier = MultinomialNB()
    classifier.fit(vec.transform(x_train), y_train)

5. 評估蜻直、計算 AUC 值。

第一步袁串,上面步驟1-4完成了從語料到模型的訓(xùn)練概而,訓(xùn)練之后,我們要用測試集來計算 AUC 值:

    print(classifier.score(vec.transform(x_test), y_test))

得到的結(jié)果評分為:0.647331786543囱修。

第二步赎瑰,進行測試集的預(yù)測:

    pre = classifier.predict(vec.transform(x_test))

6. 模型對比。

整個模型從語料到訓(xùn)練評估步驟1-5就完成了破镰,接下來我們來看看餐曼,改變特征向量模型和訓(xùn)練模型對結(jié)果有什么變化压储。

(1)改變特征向量模型

下面可以把特征做得更強一點,嘗試加入抽取 2-gram3-gram 的統(tǒng)計特征源譬,把詞庫的量放大一點集惋。

    from sklearn.feature_extraction.text import CountVectorizer
    vec = CountVectorizer(
        analyzer='word', # tokenise by character ngrams
        ngram_range=(1,4),  # use ngrams of size 1 and 2
        max_features=20000,  # keep the most common 1000 ngrams
    )
    vec.fit(x_train)
    #用樸素貝葉斯算法進行模型訓(xùn)練
    classifier = MultinomialNB()
    classifier.fit(vec.transform(x_train), y_train)
    #對結(jié)果進行評分
    print(classifier.score(vec.transform(x_test), y_test))

得到的結(jié)果評分為:0.649651972158,確實有一點提高踩娘,但是不太明顯刮刑。

(2)改變訓(xùn)練模型

使用 SVM 訓(xùn)練:

    from sklearn.svm import SVC
    svm = SVC(kernel='linear')
    svm.fit(vec.transform(x_train), y_train)
    print(svm.score(vec.transform(x_test), y_test))

使用決策樹、隨機森林养渴、XGBoost雷绢、神經(jīng)網(wǎng)絡(luò)等等:

    import xgboost as xgb  
    from sklearn.model_selection import StratifiedKFold  
    import numpy as np
    # xgb矩陣賦值  
    xgb_train = xgb.DMatrix(vec.transform(x_train), label=y_train)  
    xgb_test = xgb.DMatrix(vec.transform(x_test)) 

在 XGBoost 中,下面主要是調(diào)參指標(biāo)厚脉,可以根據(jù)參數(shù)進行調(diào)參:

    params = {  
            'booster': 'gbtree',     #使用gbtree
            'objective': 'multi:softmax',  # 多分類的問題习寸、  
            # 'objective': 'multi:softprob',   # 多分類概率  
            #'objective': 'binary:logistic',  #二分類
            'eval_metric': 'merror',   #logloss
            'num_class': 4,  # 類別數(shù),與 multisoftmax 并用  
            'gamma': 0.1,  # 用于控制是否后剪枝的參數(shù),越大越保守傻工,一般0.1、0.2這樣子孵滞。  
            'max_depth': 8,  # 構(gòu)建樹的深度中捆,越大越容易過擬合  
            'alpha': 0,   # L1正則化系數(shù)  
            'lambda': 10,  # 控制模型復(fù)雜度的權(quán)重值的L2正則化項參數(shù),參數(shù)越大坊饶,模型越不容易過擬合泄伪。  
            'subsample': 0.7,  # 隨機采樣訓(xùn)練樣本  
            'colsample_bytree': 0.5,  # 生成樹時進行的列采樣  
            'min_child_weight': 3,  
            # 這個參數(shù)默認(rèn)是 1,是每個葉子里面 h 的和至少是多少匿级,對正負(fù)樣本不均衡時的 0-1 分類而言  
            # 假設(shè) h 在 0.01 附近蟋滴,min_child_weight 為 1 葉子節(jié)點中最少需要包含 100 個樣本。  
            'silent': 0,  # 設(shè)置成1則沒有運行信息輸出痘绎,最好是設(shè)置為0\.  
            'eta': 0.03,  # 如同學(xué)習(xí)率  
            'seed': 1000,  
            'nthread': -1,  # cpu 線程數(shù)  
            'missing': 1 
        }  

總結(jié)

上面通過真實司法數(shù)據(jù)津函,一步步實現(xiàn)中文短文本分類的方法,整個示例代碼可以當(dāng)做模板來用孤页,從優(yōu)化和提高模型準(zhǔn)確率來說尔苦,主要有兩方面可以嘗試:

  1. 特征向量的構(gòu)建,除了詞袋模型行施,可以考慮使用 word2vec 和 doc2vec 等允坚;
  2. 模型上可以選擇有監(jiān)督的分類算法、集成學(xué)習(xí)以及神經(jīng)網(wǎng)絡(luò)等蛾号。

如有侵權(quán)請聯(lián)系QQ:758230255刪除

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末稠项,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子鲜结,更是在濱河造成了極大的恐慌展运,老刑警劉巖活逆,帶你破解...
    沈念sama閱讀 219,427評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異乐疆,居然都是意外死亡划乖,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,551評論 3 395
  • 文/潘曉璐 我一進店門挤土,熙熙樓的掌柜王于貴愁眉苦臉地迎上來琴庵,“玉大人,你說我怎么就攤上這事仰美∶缘睿” “怎么了?”我有些...
    開封第一講書人閱讀 165,747評論 0 356
  • 文/不壞的土叔 我叫張陵咖杂,是天一觀的道長庆寺。 經(jīng)常有香客問我,道長诉字,這世上最難降的妖魔是什么懦尝? 我笑而不...
    開封第一講書人閱讀 58,939評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮壤圃,結(jié)果婚禮上陵霉,老公的妹妹穿的比我還像新娘。我一直安慰自己伍绳,他們只是感情好踊挠,可當(dāng)我...
    茶點故事閱讀 67,955評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著冲杀,像睡著了一般效床。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上权谁,一...
    開封第一講書人閱讀 51,737評論 1 305
  • 那天剩檀,我揣著相機與錄音,去河邊找鬼闯传。 笑死谨朝,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的甥绿。 我是一名探鬼主播字币,決...
    沈念sama閱讀 40,448評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼共缕!你這毒婦竟也來了洗出?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,352評論 0 276
  • 序言:老撾萬榮一對情侶失蹤图谷,失蹤者是張志新(化名)和其女友劉穎翩活,沒想到半個月后阱洪,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,834評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡菠镇,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,992評論 3 338
  • 正文 我和宋清朗相戀三年冗荸,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片利耍。...
    茶點故事閱讀 40,133評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡蚌本,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出隘梨,到底是詐尸還是另有隱情程癌,我是刑警寧澤,帶...
    沈念sama閱讀 35,815評論 5 346
  • 正文 年R本政府宣布轴猎,位于F島的核電站嵌莉,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏捻脖。R本人自食惡果不足惜锐峭,卻給世界環(huán)境...
    茶點故事閱讀 41,477評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望可婶。 院中可真熱鬧只祠,春花似錦、人聲如沸扰肌。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,022評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽曙旭。三九已至,卻和暖如春晶府,著一層夾襖步出監(jiān)牢的瞬間桂躏,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,147評論 1 272
  • 我被黑心中介騙來泰國打工川陆, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留剂习,地道東北人。 一個月前我還...
    沈念sama閱讀 48,398評論 3 373
  • 正文 我出身青樓较沪,卻偏偏與公主長得像鳞绕,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子尸曼,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,077評論 2 355

推薦閱讀更多精彩內(nèi)容