NLP Learning | 初识NLP

NLP的Demo工具和预处理技术

自然语言处理(英语:Natural Language Processing,缩写作 NLP)是人工智能和语言学领域的分支学科。此领域探讨如何处理及运用自然语言;自然语言处理包括多方面和步骤,基本有认知、理解、生成等部分。
从今天开始,我将和大家一起学习自然语言处理的一些基础知识及经典模型,探索深度学习的另一神奇领域。

1 体验自然语言乐趣的小工具:Pipeline

Pipeline是由 Hugging Face开发的一个用于多种NLP任务的深度学习包,其主要贡献在于对文本预处理、模型构建、结果表示等主要过程进行封装,实现端到端的输入输出,并且几乎支持所有主流的预训练模型。
本次实验主要选取Pipeline中的情感分析、文本翻译、摘要提取共三个功能,利用实际应用中的例子进行测试。

1.1 情感分析

情感分析是对带有情感色彩的主观性文本进行分析、处理、归纳和推理的过程,主要用于预测电影票房、股票趋势、舆情分析、改进服务及产品、及了解用户的体验等。本实验中情感分析输入输出如表1所示。
在这里插入图片描述

情感分析代码片段如下:

# 1.情感分析代码片段
# 介绍:分析文本情感
# 1.情感分析示例
classifier = pipeline("sentiment-analysis")
classifier_sentence=[
"I like apple",# Positive
"I hate this so much!", # Negative
    "I've been waiting for a HuggingFace course my whole life." ,# Positive
    "Aiming at the real-time detection of multiple objects and micro-objects in large-scene RS images,a cascaded convolutional neural network real-time object-detection framework for RS images is proposed,which integrates visual perception and convolutional memory network reasoning."# Positive]
print("="*27,"情感分析输出{}\n{}".format("="*27,classifier(classifier_sentence)))

输出结果:

======================== 情感分析输出========================
[{
    
    'label': 'POSITIVE', 'score': 0.9995661377906799},
{
    
    'label': 'NEGATIVE', 'score': 0.9994558691978455},
{
    
    'label': 'POSITIVE', 'score': 0.9598046541213989},
{
    
    'label': 'NEGATIVE', 'score': 0.6896899342536926}]

1.2 文本翻译

文本翻译是利用计算机将一种自然语言(源语言)转换为另一种自然语言(目标语言)的过程,它是计算语言学的一个分支,具有重要的科学研究价值。本实验采用Helsinki-NLP分支下的opus-mt-en-zh翻译模型进行英译汉操作,其代码片段如下:

# 2.文本翻译代码片段
# 介绍:利用Pipeline中translation功能实现英译汉
# 2.文本翻译
translator = pipeline("translation", model="Helsinki-NLP/opus-mt-en-zh")
trans_sentence=[
    'The object detection task and the classification task follow the same process in the image feature extraction part of the network',
    'Object detection is a fundamental problem in the field of Computer Vision, which can be widely used in many fields such as environment monitoring,intrusion detection human-machine interaction and so on.'
]
print("="*27,"文本翻译输出{}\n{}".format("="*27,translator(trans_sentence)))

输出结果:

========================= 文本翻译输出========================
[{
    
    'translation_text': '目标探测任务和分类任务在网络图像特征提取部分遵循同样的程序'}, 
{
    
    'translation_text': '物体探测是计算机视野领域的一个基本问题,可广泛用于环境监测、入侵探测人体机械相互作用等许多领域。'}]

1.3 摘要提取

摘要提取任务是在尽可能保留主要信息的情况下,将长文本压缩成短文本,对于从海量信息中快速、准确地获取有效信息至关重要。本实验采用sshleifer分支下的distilbart-cnn-12-6模型进行摘要提取,其代码片段如下:

# 3.摘要提取代码片段
# 介绍:利用Pipeline中summarization功能实现自动摘要
# 3.摘要提取
summarizer = pipeline("summarization")
sum_sentence='Automatic object detection technology based on RS image is an intelligent data analysis method to realize automatic classification and location of RS objects. It is one of the important research directions in the field of RS image interpretation, and has received extensive attention in the civil and military fields. Automatic detection of remote sensing objects has played an important role in many practical applications such as urban planning, traffic safety, environmental monitoring and so on.'
print("="*27,"摘要提取输出{}\n{}".format("="*27,summarizer(sum_sentence)),"="*27)

输出结果:

====================== 摘要提取输出======================
[{
    
    'summary_text': ' Automatic object detection technology based on RS image is an intelligent 
data analysis method . Automatic detection of RS objects has played an important role in many 
practical applications such as urban planning, traffic safety, environmental monitoring and so on.
It has received extensive attention in the civil and military fields .'}] 

2 英文语料预处理及分析

在数据分析和数据挖掘中,通常需要经历前期准备、数据爬取、数据预处理、数据分析、数据可视化、评估分析等步骤,其中的数据预处理会直接影响后续模型分析的好坏,对于分析结果有重要意义。语料预处理主要指保留语料中有价值的数据,删除噪音数据,本次实验主要采用文本词频分析及文本向量化实现语料预处理。

2.1 文本词频分析

2.1.1 自主实现英文文本分词

由于英文文本天然地具有分词特性,即英文文本可按照单词与单词之间空格直接划分词组,只需将非字母类型的字符进行剔除即可,所以按照这个逻辑,本实验自主编写了英文文本分词函数,其主体内容如下:

# 4.英文分词代码片段
# 介绍:首先使用空格对特殊字符进行替换,然后使用空格分词,最后将上一步结果中的空格剔除,得到最终的英文文本分词结果
def get_words(input_txt):

    for idx in range(len(input_txt)):
        for ch in '!"#$%&()*+,./:;<=>?@[\\]^_‘{|}~£':
            input_txt[idx] = input_txt[idx].replace(ch, ' ')
        input_txt[idx]=[item for item in filter(lambda x: x != '', input_txt[idx].split(' '))]
        return input_txt

对于原始输入:

tv future in the hands of viewers with home theatre systems plasma high-definition. tvs  and digital video recorders moving into the living room the way people watch tv will be radically different in five years time.

经过分词后的结果为:

'tv', 'future', 'in', 'the', 'hands', 'of', 'viewers', 'with', 'home', 'theatre', 'systems', 'plasma', 'high-definition', 'tvs', 'and', 'digital', 'video', 'recorders', 'moving', 'into', 'the', 'living', 'room', 'the', 'way', 'people', 'watch', 'tv', 'will', 'be', 'radically', 'different', 'in', 'five', 'years', 'time'

可以看到,对于我们预定义的标点符号和空格,函数能够较好分词。

2.1.2 词干提取及去停用词操作

在分析语料的过程中,通常会存在一些脏数据或噪声词组干扰我们的实验结果,这就需要对分词后的语料进行数据清洗。比如进行英文分词后,结果中可能存在一些脏数据或停用词,如“a”、“the”、“ours”等。为了得到更好的分析结果,需要使用nltk工具进行词干提取及停用词剔除,相关内容如下:

# 5.词干提取及停用词剔除代码片段
# 介绍:对英文文本分词结果进行清洗,主要包括get_stemWords操作和get_stopWords
def get_stemWords(sentences):

    porter_stem = PorterStemmer()
    res=[]
    for words in sentences:
        temp = []
        for word in words:
            temp.append(porter_stem.stem(word))
        res.append(temp)
       return res

def get_stopWords(stem_sentences):

    stop_words = stopwords.words("english")
    for idx in range(len(stem_sentences)):
        stem_sentences[idx]=[word for word in stem_sentences[idx] if not word in stop_words]
    return stem_sentences

对于分词后的结果:

'howard', 'hits', 'back', 'at', 'mongrel', 'jibe', 'michael', 'howard', 'has', 'said', 'a', 'claim', 'by', 'peter', 'hain', 'that', 'the', 'tory', 'leader', 'is', 'acting', 'like', 'an', 'attack'

词干提取输出为:

'howard', 'hit', 'back', 'at', 'mongrel', 'jibe', 'michael', 'howard', 'ha', 'said', 'a', 'claim', 'by', 'peter', 'hain', 'that', 'the', 'tori', 'leader', 'is', 'act', 'like', 'an', 'attack'

停用词剔除结果为:

'howard', 'hit', 'back', 'mongrel', 'jibe', 'michael', 'howard', 'ha', 'said', 'claim', 'peter', 'hain', 'tori', 'leader', 'act', 'like', 'attack'

可以看到,对于分词结果,词干提取能够对单词进行还原,得到其对应的词根;停用词剔除则可以将单词中的干扰数据进行去除,得到比较理想的文本数据。

2.1.3 生成语料词表

考虑到后续TF-IDF分析还会使用词表,所以先将词表写入csv文件,写入过程中直接将标签向量化:0- tech;1- business;2- sport;3- entertainment;4- politics

# 6.词表写入代码片段
# 介绍:将清洗后的英文文本分词结果写入csv文件
def write2csv(stopWords,labels):

    contents = []
    for item in stopWords:
        contents.append(" ".join(item))
    with open('fenci_data.csv', "w",newline='') as f:
        writer = csv.writer(f)
        writer.writerow(['contents', 'labels'])
        for idx in range(len(contents)):
            writer.writerow([contents[idx], labels[idx]])

而后本实验调用nltk中的FreqDist统计了预处理后的词频,主要统计分词结果中词频最高的50个单词,其函数主体如下:

# 7.词频统计代码片段
# 介绍:对清洗后的英文文本分词结果进行词频统计
def get_wordFrequency(stopWords):
    for words in stopWords:
        freq_dist = FreqDist(words)
        # for k, v in freq_dist.items():
        #     print(str(k) + ':' + str(v))
    standard_freq_vector = freq_dist.most_common(50)
    return standard_freq_vector

输出结果:

('howard', 14), ('mr', 13), ('said', 8), ('hi', 8), ('parti', 7), ('labour', 6), ('michael', 5), ('tori', 5), ('tell', 5), ('elect', 5)

2.2 文本向量化

权重计算是指通过特征权重来衡量特征项在文档表示中的重要程度,给特征词赋予一定的权重来衡量统计文本特征词,TF-IDF是用于数据分析和信息处理经典的权重计算技术。TF-IDF技术的核心思想是如果某个特征词在一篇文章中出现的频率TF高,并且在其他文章中很少出现,则认为此词或者短语具有很好的类别区分能力,适合用来做权重计算。
本实验主要使用Scikit-Learn中的CountVectorizer和TfidfTransformer两个类来计算词频和TF-IDF值。其中,CountVectorizer主要作用是将文本词转换为词频矩阵的形式,再调用fit_transform()函数计算各个词语出现的次数;而后使用TfidfTransformer实现统计vectorizer变量中每个词语的TF-IDF值,TF-IDF值采用矩阵数组的形式存储,每一行数据代表一个文本语料,每一行的每一列都代表其中一个特征对应的权重,得到TF-IDF后就可以运用各种数据分析算法进行分析。

# 8.文本向量化代码片段
# 介绍:将词表中的文本进行向量化
# 特征提取及文本向量化
corpus = TextCollection(stopWords)
name,tf,idf,tf_idf=[],[],[],[]
for item in corpus:
    name.append(item)
    tf.append(corpus.tf(item,corpus))
    idf.append(item)
    tf_idf.append(corpus.tf_idf(item,corpus))
df_dic={
    
    "word":name,"TF value":tf,"IDF value":idf,"TF_IDF":tf_idf}
data = pd.DataFrame(df_dic)

3 基于TF-IDF和SVM的英文文本分类

3.1 数据预处理

数据预处理部分主要参照本文第二部分,包括文本分词、词干提取、剔除停用词、文本向量化等操作,这里不再赘述。值得注意的是,最终需要得到文本向量及其对应的标签,这部分的主体代码如下:

# 9.数据预处理代码片段
# 介绍:文本数据及标签预处理
def category2label(data):
	# 文本标签转化为数值标签,方便后续分类计算
    status_dict = data['category'].unique().tolist()
    return data['category'].apply(lambda x: status_dict.index(x))


def textProcessing(data):
    # 文本数据转化为TD-IDF向量
    input_txt=data['text']
    words=get_words(input_txt)
    stemWords=get_stemWords(words)
    stopWords=get_stopWords(stemWords)
    data['contents']=stopWords

    contents=[]
    for item in data['contents']:
        contents.append(' '.join(item))

    vectorizer = CountVectorizer()
    transformer = TfidfTransformer()
    tfidf = transformer.fit_transform(vectorizer.fit_transform(contents))
    word = vectorizer.get_feature_names()
    print("单词数量:", len(word))
    X = coo_matrix(tfidf, dtype=np.float32).toarray()
    return X

3.2 数据划分及模型构建评估

将预处理后的数据使用sklearn中的model_selection库,按照7:3的比例划分为训练集和测试集,利用训练数据进行模型训练,训练结束后再利用测试数据进行模型评估。
调用sklearn中的SVC多分类模型进行模型训练随后使用混淆矩阵对模型的精度进行计算,粗略对模型进行评估,这部分的主体代码如下:

# 10.数据划分及模型构建评估
# 介绍:利用划分后的数据进行模型训练及评估
def train_test(X,Y):

    from sklearn.model_selection import train_test_split
    X_train, X_test, y_train, y_test = train_test_split(X,Y,test_size=0.3,random_state=1)
    clf = SVC(probability=True).fit(X_train,y_train)
    y_pred = clf.predict(X_test)
    y_pred_np = np.array(y_pred)
    correct_score = (y_pred_np == y_test).sum()
    print("模型的准确率为:{}".format(100 * correct_score / y_test.shape[0]))
    my_confusion_matrix(y_test,y_pred)

3.3 利用混淆矩阵分析实验结果

将混淆矩阵转化为热力矩阵,如图4所示。
可以发现:
(1)模型整体预测效果较好,各类的预测误差都较小。
(2)对于sport、entertainment、business而言,误差分别只有1、1、2,预测精度高于误差为5的tech和politics,其中以样本基数大的sport精度最高。
(3)除business这类以外,其余四个类别的FN数量都为2,其中以样本基数大的sport类召回率最高。
在这里插入图片描述

# 11.绘制混淆矩阵代码片段
# 介绍:利用混淆矩阵绘制热力图
def plot_confusion_matrix(cm, classes, normalize=False, title='confusion matrix', cmap=plt.cm.Blues):
    plt.figure()
    plt.imshow(cm, interpolation='nearest', cmap=cmap)
    plt.title(title)
    plt.colorbar()
    tick_marks = np.arange(len(classes))
    plt.xticks(tick_marks, classes, rotation=90)
    plt.yticks(tick_marks, classes)

    plt.axis("equal")

    ax = plt.gca()
    left, right = plt.xlim()
    ax.spines['left'].set_position(('data', left))
    ax.spines['right'].set_position(('data', right))
    for edge_i in ['top', 'bottom', 'right', 'left']:
        ax.spines[edge_i].set_edgecolor("white")

    thresh = cm.max() / 2.
    for i, j in itertools.product(range(cm.shape[0]), range(cm.shape[1])):
        num = '{:.2f}'.format(cm[i, j]) if normalize else int(cm[i, j])
        plt.text(j, i, num,
                 verticalalignment='center',
                 horizontalalignment="center",
                 color="white" if num > thresh else "black")


    plt.xlabel('True')
    plt.ylabel('Predict')
    plt.tight_layout()
    plt.savefig('confusion_matrix.png', transparent=True, dpi=800)

    plt.show()

附录:实验源码及数据

关注微信公众号:炼丹小天才
回复nlp1即可获得实验源码及数据

猜你喜欢

转载自blog.csdn.net/weixin_43427721/article/details/125750737
NLP