NLP实战01:从简单做起手把手教你一步步Python实现中文文本(新闻文本)分类

NLP实战01:从简单做起手把手教你一步步Python实现中文文本(新闻文本)分类

文章目录

*
NLP实战01:从简单做起手把手教你一步步Python实现中文文本(新闻文本)分类
1.前言
2.数据集介绍
3.预处理数据

+ 3.1 读取数据
+ 3.2 处理数据
+ 3.2.1 如何处理超多文字的新闻文本
4.构建模型并训练数据

1.前言

NLP自然语言处理一直是人工智能,数据科学的热门分类,博主在去年参加的某学会的主题也是自然语言处理相关,自然语言处理由于是对一维上的文本,音频等方面进行处理,信息量更加的少,同时中文文本分类,相对英文,中文更加繁杂单词与单词之间不存在间隔,划分也是一段难事,本文的契机是作者最近参加的中国大学生软件杯需要对近几个月的中文互联网新闻文本进行分类处理,要求在5秒内快速得出新闻文本分类,于是在经过一段时间的折腾,暂时有了不错的进展,权且记录一下。

2.数据集介绍

该数据集收容了最近几个月中文互联网上的中文新闻,他们被提前划分为十个种类,如图,财经,房产,教育,科技,

军事,汽车,体育,娱乐,其他共十种以sheets子表的方式存储在一个xlsx中

NLP实战01:从简单做起手把手教你一步步Python实现中文文本(新闻文本)分类

同时该数据集的特点,就是新闻的文本的长度都非常的长这点 是毋庸置疑的,区别于一般的中文分类,博主曾经看过的文本分类数据集,长度也就大概十几个字,在这里长度甚至会达到上千。所以本次我们的新闻处理任务的难点,有一个很严重的问题就是数据过长,这点如何处理,博主在后面会介绍。

; 3.预处理数据

3.1 读取数据

对于这样一个拥有多个子表的数据,大家可能很容易就想到pandas库,但是如果我们直接采取pandas读取xlsx的方法,

read_excel只会默认将第一个子表的数据,然而显然我们需要的是全部十个子表的数据,这里我们就需要借助xlrd库的方法,获取excel表的sheet的信息。


excel_name = '文本.xlsx'
wb = xlrd.open_workbook(excel_name)
sheets = wb.sheet_names()

data = DataFrame()
for i in range(len(sheets)):
    df = pd.read_excel(excel_name, sheet_name=i)
    data = data.append(df)

值得提醒的是该部分代码是在windows上运行的,在后期博主为了加速训练将代码部署在linux服务器上运行时,报错xlrd不支持excel格式读取,根据博主查找资料获得的信息的话应该是在linux下不支持excel格式读取,所以,这里我们可以直接提前获取sheets的长度,然后直接运行后面这一段代码来读取数据,也是可以的

data = DataFrame()
for i in range(len(sheets)):
    df = pd.read_excel(excel_name, sheet_name=i)
    data = data.append(df)

3.2 处理数据

对于如何处理数据,这里我们需要明确一下,在处理数据,我们最终的目的是什么。计算机是完全不知道语言意思的,人工智能发展到现在,其实都是完全没有智能的(博主个人观点),一个个图像识别,人脸识别的模型其实是数据的转换(用这个观点来理解AI可能更好一点),比如对于二维图片,我们是将图片转换为数据上的一个个像素值,拼凑成一个整体然后让计算机记住拥有这样像素值组合的图片是某种特定的分类。那么对于,我们的文本,我们现在拥有了新闻的文本内容,我们要将新闻文本从计算机完全无法理解的字符转换成数符行,将该新闻对应的分类也转成数据型。这就是我们数据转换的步骤。

那么,我们先从最简单的开始,转换我们的标签:

label_transfer={'体育': 0, '体育焦点': 0, '军事': 2,
                '娱乐': 3, '房产': 4, '教育': 5, '汽车': 6, '游戏': 7, '科技': 8, '财经': 9, '其他': 1}

def apply_transfer(label):
    return label_transfer.get(label)
new_data=data.channelName.apply(apply_transfer)

del data['channelName']
data['channelName']=new_data
data.head()

展示效果如下,可以看到标签数据全部被我们转换成了int整形,我们的数据处理完成了一部分

NLP实战01:从简单做起手把手教你一步步Python实现中文文本(新闻文本)分类

那么接下来,我们开始对文本进行处理,将每个中文单词变成数据形式(这是有一种专门研究的学科称为词嵌入),好像很困难?这里我一开始的想法是,

1.我们将每个句子切割为一个个的单词,那么句子被变成了一个个的单词序列,对于这样的序列我们制作一个字典比如

[‘我’,’喜欢’,’你’],我们将他转换成[0,1,2]看似逻辑很简单,但是有件事却是我们不得不思考的,在中文新闻文本类一篇新闻拥有上百甚至上千单词,将所有新闻文本的单词制作成一个大字典,最后的长度肯达到数十万以及百万(总共14137条数据),那么我们的词嵌入的数据差距就会很大(这对于模型的训练将是巨大的阻碍,同时我们的代码,要制作出一个这么长的字典,过于消耗内存),在硬件训练考虑方面(很现实,深度学习是要考虑硬件,吾日三省吾身,有钱买显卡吗,有原价显卡卖吗,想要的显卡显存够吗),该种方案的代价我们不能接受

但经过后面查阅资料发现,一直在做NLP的前辈已经预见到了这种问题,提供了一种已经提前训练好的word2vec–用于进行词嵌入的库,他可以非常简单的将文本的字符数据转换成高维向量,我们再将该数据直接输入RNN即可完成分类任务,那么接下来我们就主要介绍这种方法

3.2.1 如何处理超多文字的新闻文本

这里我在上篇博客(如何使用python处理中文文本–近几个月的新闻数据分析社会热点并创造词云图_theworld666的博客-CSDN博客)也有提到过,我们可以提前使用别人早已训练好的中文文本切割模型jieba库,但是由于新闻文本内部仍然存在很多根本无意义的字符,那么对于这样的数据我们肯定是要先提前清洗数据,所以我们这里编写文字处理函数如下:

import re
import jieba.posseg as pseg
def word_slice(lines):
    corpus = []
    corpus.append(lines.strip())
    stripcorpus = corpus.copy()
    for i in range(len(corpus)):
        stripcorpus[i] = re.sub("@([\s\S]*?):", "", corpus[i])
        stripcorpus[i] = re.sub("\[([\S\s]*?)\]", "", stripcorpus[i])
        stripcorpus[i] = re.sub("@([\s\S]*?)", "", stripcorpus[i])
        stripcorpus[i] = re.sub(
            "[\s+\.\!\/_,$%^*(+\"\']+|[+——!,。?、~@#¥%......&*()]+", "", stripcorpus[i])

        stripcorpus[i] = re.sub("[^\u4e00-\u9fa5]", "",
                                stripcorpus[i])
        stripcorpus[i] = re.sub("原标题", "", stripcorpus[i])
        stripcorpus[i] = re.sub("回复", "", stripcorpus[i])
        stripcorpus[i] = re.sub("(完)", "", stripcorpus[i])

    onlycorpus = []
    for string in stripcorpus:
        if(string == ''):
            continue
        else:
            if(len(string) < 5):
                continue
            else:
                onlycorpus.append(string)
    cutcorpusiter = onlycorpus.copy()
    cutcorpus = onlycorpus.copy()
    wordtocixing = []
    for i in range(len(onlycorpus)):
        cutcorpusiter[i] = pseg.cut(onlycorpus[i])
        cutcorpus[i] = ""
        for every in cutcorpusiter[i]:
            cutcorpus[i] = (cutcorpus[i] + " " + str(every.word)).strip()
            wordtocixing.append(every.word)
    return wordtocixing
fp = open('text2.txt', "w+", encoding='utf-8')
lenx=[]
for string in content:
    if not isinstance(string,str):
        continue
    lines=word_slice(string)
    lenx.append(len(lines))
    for line in lines:
        fp.write(line)
        fp.write(' ')
    fp.write('\n')
fp.close()

这里最终形成的text2.txt样式如下:

NLP实战01:从简单做起手把手教你一步步Python实现中文文本(新闻文本)分类

那么我们接下来使用word2CVec库:

from gensim.models import word2vec
from gensim.models import Word2Vec
sentences=word2vec.Text8Corpus('text2.txt')
model = Word2Vec(sentences, min_count=1)
model.save('words_models')

这里我们需要提前保存模型,这点是非常需要注意的,即因为该库提供的word2vec形成的模型参数是随机初始化的,我们为了保证每次训练模型的一致性,同时为了节省时间,导入提前保存好的数据,在多次断点训练中,也是最好的选择。

接下来我们正式开始将字符数据转换成高维向量:

model1=Word2Vec.load('words_models')
word_vectors=model1.wv

def pad(x, maxlength=4500):
    x1 = np.zeros((maxlength,100))
    if len(x)==0:
        return x1
    x1[:len(x)] = x
    x1=np.array(x1).reshape(4500,100)
    return x1

def apply_text_trainsfer(text,data):
    text=word_slice(text)

    vec=[word_vectors[w] for w in text if w in word_vectors]
    vec=pad(vec)

    return vec,data

这里我们之所以编写成函数是因为博主的思想是想利用tensorflow提供的dataset数据结构来完成边加载边训练的方式,这样有个好处就是如果不采取这个方式,直接将所有文本转化成向量,那么内存占用是巨大的,不利于训练(博主在深度学习中由于使用GPU训练从而学到的硬件知识,深切的感觉到了计算机组成原理的有用。。。。),所以我们编写函数如下:

new_text=data.content.values
new_data=new_data.values
data_text=[]
for text in new_text:
    data_text.append(text)
data_text=np.array(data_text)
print(data_text.shape)

data_train=tf.data.Dataset.from_tensor_slices((data_text,new_data))
data_train=data_train.shuffle(14632)

data_train=data_train.map(apply_text_trainsfer)
data_train=data_train.batch(32).shuffle(100)

4.构建模型并训练数据

在前面,我们完成了数据的处理,最终我们的数据被全部压入进一个dataset的数据结构。有了数据之后,我们便开始搭建模型,这里我个人喜欢用tensorflow配合keras搭建模型,这里我们使用RNN网络中的lstm变体GRU从而来进行训练关于这边的介绍,博主在这篇博客中介绍过(RNN学习:利用LSTM,GRU层解决航空公司评论数据预测问题_theworld666的博客-CSDN博客

model=keras.Sequential()
model.add(layers.GRU(64))
model.add(layers.Dense(64,activation='relu'))
model.add(layers.BatchNormalization())
model.add(layers.Dense(32,activation='relu'))
model.add(layers.BatchNormalization())
model.add(layers.Dense(16,activation='relu'))
model.add(layers.BatchNormalization())
model.add(layers.Dense(10,activation= 'softmax'))
model.compile(optimizer=keras.optimizers.Adam(0.001),
                loss='sparse_categorical_crossentropy',
                    metrics=['acc']
                    )
model.fit(data_train,batch_size=32,epochs=10)

5.结果分析

然而我们的结果却并不尽人意

NLP实战01:从简单做起手把手教你一步步Python实现中文文本(新闻文本)分类

准确率却一直卡在60左右,这实在是有点差。。。后面在咨询大佬中,偶然得知,是博主学识浅薄了,LSTM可能对于这种非常大的数据适应性不是很好,无法记忆这么长的数据,所以博主在网络的选择上面出了问题,于是第一种方案从十几天前一直到现在,算是失败了。。但如果选取的是短篇的新闻效果还是非常可观的。对于本篇博客有任何疑问或者见解欢迎评论区指出。

Original: https://blog.csdn.net/theworld666/article/details/117606542
Author: theworld666
Title: NLP实战01:从简单做起手把手教你一步步Python实现中文文本(新闻文本)分类

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/547861/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球