三、中文分类机器学习解决方案

前言:计算机读不懂文本表述,该怎么办? 回想一下我们是如何进行阅读的?

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句话....

...

②统计词频

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 ...]

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

  • 把是否出现替换成频次
  • 不只记录每个词,我还记录连续的n-gram
    • ”李雷喜欢韩梅梅“ =>("李雷","喜欢","韩梅梅")
    • "韩梅梅喜欢李雷" =>("李雷","喜欢","韩梅梅")
    • "李雷喜欢韩梅梅" =>("李雷","喜欢","韩梅梅","李雷喜欢",”喜欢韩梅梅“)
    • "韩梅梅喜欢李雷" =>("韩梅梅","喜欢","李雷","韩梅梅喜欢","喜欢李雷")
  • 不只是使用频次信息,需要知道词对于句子的重要程度
    • TF-IDF = TF(term frequency) + IDF(inverse document frequency)

⑥上述的表达都是独立表达(没有词与词在含义空间上的分布)

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

  • word-net (把词汇根据关系构成一张网:近义词、反义词、上位词、下位词...)
    • 怎么更新?
    • 个体差异?
  • 希望能够基于海量数据的分布去学习到一种表示
    • nnlm =>词向量
    • word2vec (周边词类似这样一些词,是可以互相替换的,相同的语境)
      • 捕捉的是相关性的词,不是近义词
        • 我 讨厌 你
        • 我 喜欢 你
      • word2vec优化...
      • 用监督学习去调整word2vec的结果(word embedding/词嵌入)
    • 文本预处理
      • 时态语态Normalize
      • 近义词替换
      • stemming
      • ....

1.1.4 分类模型

对向量化的输入去做建模

①NB/LR/SVM...建模

——可以接受特别高纬度的稀疏表示

②MLP/CNN/LSTM

——不适合稀疏高纬度数据输入 => word2vec

1.2 朴素贝叶斯

我们试试用朴素贝叶斯完成一个中文文本分类器,一般在数据量足够,数据丰富度够的情况下,用朴素贝叶斯完成这个任务,准确度还是不错的。

机器学习的算法要取得好的效果,离不开数据。

1.2.1 准备数据

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 去停用词

我们对数据做一些预处理,并把处理过后的数据写入新文件夹避免每次重复工作

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()

#生成训练数据
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)

为了一会儿监测一下分类器的效果如何,我们需要一份训练集一份测试集
所以对原始数据进行切分

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)

下一步要做的就是在降噪数据上抽取出有用的特征,我们对文本抽取词袋模型特征

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的统计特征,比如可以把词库放大一些

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'))

你可能感兴趣的:(三、中文分类机器学习解决方案)