三、中文分類機器學習解決方案

前言:計算機讀不懂文本表述,該怎么辦? 回想一下我們是如何進行閱讀的?

1.1 文本分類 = 文本表示 + 分類模型

1.1.1 文本表示: BOW 、N-Gram 、TF-IDF、word2vec、word embedding ELMo

分類模型:NB、LR、SVM、LSTM、CNN等

1.1.2 分類模型:NB/LR/SVM/LSTM(GRU)/CNN

語種判斷:拉丁語系,字母組成的,甚至字母也一樣 => 字母的使用(次序、頻次)不一樣

1.1.3 文本表示

詞袋模型(中文)

①分詞

第1句話[w1 w3 w5 w2 w1 ...]

第2句話[w11 w32 w51 w21 w15]

第3句話....

...

②統(tǒng)計詞頻

w3 count3

w7 count7

wi count_i

...

③構建詞典

選出頻率最高的N個詞

開[1*n]這樣的向量空間

(每個位置是哪個詞)

④映射:把每句話共構建的詞典進行映射

第1句話 [1 0 1 0 1 0 ...]

第2句話[0 0 0 0 0 0 ... 1 , 0 0 1 0 ...]

⑤提升信息的表達充分度:

  • 把是否出現(xiàn)替換成頻次
  • 不只記錄每個詞,我還記錄連續(xù)的n-gram
    • ”李雷喜歡韓梅梅“ =>("李雷","喜歡","韓梅梅")
    • "韓梅梅喜歡李雷" =>("李雷","喜歡","韓梅梅")
    • "李雷喜歡韓梅梅" =>("李雷","喜歡","韓梅梅","李雷喜歡",”喜歡韓梅梅“)
    • "韓梅梅喜歡李雷" =>("韓梅梅","喜歡","李雷","韓梅梅喜歡","喜歡李雷")
  • 不只是使用頻次信息,需要知道詞對于句子的重要程度
    • TF-IDF = TF(term frequency) + IDF(inverse document frequency)

⑥上述的表達都是獨立表達(沒有詞與詞在含義空間上的分布)

喜歡 = 在乎 = “稀罕” = “中意”

  • word-net (把詞匯根據(jù)關系構成一張網(wǎng):近義詞、反義詞、上位詞、下位詞...)
    • 怎么更新?
    • 個體差異?
  • 希望能夠基于海量數(shù)據(jù)的分布去學習到一種表示
    • nnlm =>詞向量
    • word2vec (周邊詞類似這樣一些詞,是可以互相替換的,相同的語境)
      • 捕捉的是相關性的詞,不是近義詞
        • 我 討厭 你
        • 我 喜歡 你
      • word2vec優(yōu)化...
      • 用監(jiān)督學習去調整word2vec的結果(word embedding/詞嵌入)
    • 文本預處理
      • 時態(tài)語態(tài)Normalize
      • 近義詞替換
      • stemming
      • ....

1.1.4 分類模型

對向量化的輸入去做建模

①NB/LR/SVM...建模

——可以接受特別高緯度的稀疏表示

②MLP/CNN/LSTM

——不適合稀疏高緯度數(shù)據(jù)輸入 => word2vec

1.2 樸素貝葉斯

我們試試用樸素貝葉斯完成一個中文文本分類器,一般在數(shù)據(jù)量足夠,數(shù)據(jù)豐富度夠的情況下,用樸素貝葉斯完成這個任務,準確度還是不錯的。

機器學習的算法要取得好的效果,離不開數(shù)據(jù)。

1.2.1 準備數(shù)據(jù)

import jieba 
import panda as pd 
df_technology = pd.read_csv('./origin_data/technology_news.csv',encoding = 'utf-8')
df_technology = df_technology.dropna()

df_car = pd.read_csv('./origrin_data/car_news.csv',encoding = 'utf-8')
df_car = df_car.dropna()

df_entertainment = pd.read_csv('./origin_data/entertainment_news.csv',encoding = 'utf-8')
df_entertainment.dropna()

df_military = pd.read_csv('./origin_data/military_news.csv',encoding = 'utf-8')
df_military.dropna()

df_sports = pd.read_csv('./origin_data/sport_news.csv',encoding = 'utf-8')
df_sports.dropna()

1.2.2 分詞與中文文本處理

1.2.2.1 停用詞梳理

stopwords = pd.read_csv('roigin_data/stopwords.txt',sep = '\t',index_col = False , quoting = 3 , name = ['stopword'],encoding = 'utf-8')

stopwords = stopwords['stopword'].values

1.2.2.2 去停用詞

我們對數(shù)據(jù)做一些預處理,并把處理過后的數(shù)據(jù)寫入新文件夾避免每次重復工作

def preprocess_tex(content_lines , sentence , category , target_path):
    out_f = open(target_path +'/' + category + '.txt' , 'w')
    for line in content_lines:
        try:
            seg = jieba.lcut(line)
            segs = list(filter(lambda x: len(x) >1 ,segs)) 
            segs = list(filter(lambda x: x not in stopwords , segs)) 
            out_f.writer(" ".join(segs) + "\n")
        except:
            print(line)
            continue
    out_f.close()

#生成訓練數(shù)據(jù)
sentence = []
preprocess_text(technology , sentence , 'technology','processed_data')
preprocess_text(car , sentence,'car','processed_data' )
preprocess_text(entertainment , sentence,'entertainment','processed_data')
preprocess_text(military , sentences , 'military' , 'processed_data')
preprocess_text(sports , sentences ,'sports','processed_data')

1.2.2.3 生成訓練集

我們打亂一下順序 生成更可靠的訓練集

import random
random.shuffle(sentence)

為了一會兒監(jiān)測一下分類器的效果如何,我們需要一份訓練集一份測試集
所以對原始數(shù)據(jù)進行切分

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

下一步要做的就是在降噪數(shù)據(jù)上抽取出有用的特征,我們對文本抽取詞袋模型特征

from sklearn.feature_extraction.text import CountVectorizer

vec = CountVectorizer(
    analyzer = 'word' ,
    max_features = 4000
)
vec.fit(x_train)

def get_features(x):
    vec.transform(x)

把分類器import 進來并訓練

from sklearn.navie_bayes import MultinomialNB
classifier = MultinomialNB()
classifier.fit(vec.transfrom(x_train) , y_train)

準確率查看

classifier.score(vec.transfrom(x_test) , y_test)

有沒有辦法把準確率提高一些呢?
我們可以把特征做的更好一些,比如說:我們試試加入2-gram 或者3-gram的統(tǒng)計特征,比如可以把詞庫放大一些

vec = CountVectorizer(
  analyzer = 'word',
  ngram = range(1,4)
  max_features = 20000
)

vec.fit(x_train)
def get_features(x):
    vec.transform(x)

1.2.3 分類訓練

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

1.2.3 交叉驗證

from sklearn.model_selection import StraifiedKFlod
from sklearn.metrics import accuracy_score , precision_score
import numpy as np

def stratifiedkfold_cv(x , y , clf_class ,shuffle = True , n_folds = 5,**kwargs ):
    stratifiedk_fold = StratifiedKFlod(n_splits = n_folds , shuffle = shuffle)
    y_pred = y[:]
    for train_index , test_index in stratifiedk_fold.split(x,y):
        X_train , X_test = x[train_index] , x[test_index]
        y_train = y[train_index]
        clf = clf_class(**kwargs)
        clf.fit(x_train , y_train)
        y_pred[test_index] = clf.predict(X_test)
    return y_pred

NB = MultinomialNB
print(precission_score(y , stratifiedkfold_cv(vec,transform(x) , np.array(y) , NB) , average = 'macro'))
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容