点击蓝字 关注我们
前段时间,我在查阅新闻时,翻到了一篇有关《2022 年软件工程师报告》的内容,发现年薪最高的居然是网安,机器学习比不过 NLP,NLP 年薪比机器学习高出 2000 美元。
薪酬排名前十的软件工程师分别是:安全工程师、研发工程师、自然语言处理(NLP)、移动工程师、机器学习工程师、增强现实/虚拟现实工程师、数据库工程师、区块链工程师、数据工程师。
那什么是自然语言处理呢?今天,我来带你一探究竟~
自然语言处理的简介
NLP(Natural Language Processing,自然语言处理)当中所谓的「自然」是为了与人造的语言(比如 C 语言, JAVA 等)区分开来,指自然形成的语言,即平时人们日常使用的交流的语言。
(图片来源网络,如侵删)
「语言」则是人类区别其他动物的本质特性。在所有生物中,只有人类才具有语言能力。人类的多种智能都与语言有着密切的关系。
人类的逻辑思维以语言为形式,人类的绝大部分知识也是以语言文字的形式记载和流传下来的。
「处理」则指的是对自然语言的各种处理方法与运用。
NLP 不仅是计算语言学的应用领域,还是计算机科学和人工智能(AI)领域的一个重要研究方向。
NLP 主要研究人与计算机之间,用自然语言进行有效通信的各种理论和方法。因此,又可以说 NLP 是一门集语言学、计算机科学、数学于一体的学科。
不过,NLP 虽然是与语言学有关, NLP 又与语言学那种纯粹的研究自然语言有所区别。
语言学是以自然语言为研究对象,研究语言的性质、功能、结构、运用和历史发展以及其他与语言有关的问题。NLP 则是在于研究能有效实现人机间自然语言通信的计算机系统。
总的来说,自然语言处理可以概括为:就是利用计算机的强大的运算能力,采用统计手段来对语言进行处理,然后获得需要的信息,以达到最终想要的目的,而使用各种方法的一门技术。
NLP 分类
NLP 经过多年的发展与进步,从自然语言的角度出发,基本可以划分为两个部分:
自然语言的理解
自然语言的生成
自然语言理解是个综合的系统工程,涉及了很多细分的学科:
代表声音的音系学:语言中发音的系统化组织。
代表构词法的词态学:研究单词构成以及相互之间的关系。
代表语句结构的句法学:给定文本的那部分是语法正确的。
代表理解的语义句法学和语用学 :给定文本的含义和目的是什么。
语言理解涉及语言、语境和各种语言形式的学科。但总的来说,自然语言理解又可以分为三个方面:
词义分析
句法分析
语义分析
自然语言的生成则是从结构化的数据(可以通俗理解为自然语言理解分析后的数据)以读取的方式自动生成文本。
主要有三个阶段:
文本规划:完成结构化数据中的基础内容规划。
语句规划:从结构化数据中组合语句来表达信息流。
实现:产生语法通顺的语句来表达文本。
研究与应用
NLP 在目前大火的 AI 领域有着十分丰富的应用。总体来说,自然语言处理的研究问题(主要)有下面几种:
信息检索:对大规模文档进行索引;
语音识别:识别包含口语在内的自然语言的声学信号转换成符合预期的信号;
机器翻译:将一种语言翻译成另外一种语言;
智能问答:自动回答问题;
对话系统:通过多回合对话,跟用户进行聊天、回答、完成某项任务;
文本分类:将文本自动归类。
情感分析:判断某段文本的情感倾向
文本生成:根据需求自动生成文本
自动文摘:归纳,总结文本的摘要。
字符串操作
字符作为文本类数据的基本单元,其在自然语言处理中的地位可以说是非常的重要。
而且,大部分的自然语言处理任务都是从字符上着手,因此本次的实验将从下面这一些非常基础的 Python 字符串操作知识开始。
统计子串出现的次数
去除字符串
拼接字符串
比较
字符串大小写转换
翻转字符串
查找字符串
判断子串是否存在
字符串代替
检查字符串
.count()
方法返回特定的子串在字符串中出现的次数。
seq = '12345,1234,123,12,1'seq1 = '1'a = seq.count(seq1)
a
.strip()
方法可以去除字符串首尾的指定符号。无指定时,默认去除空格符 ' ' 和换行符 '\n'
。
seq = ' 我们正在使用蓝桥云课,蓝桥云课学会很多!'seq.strip()
seq.strip('!')
seq.strip(' 我们')
有时候只想要去除字符串开头的某个字符串,但是字符串的末尾有一个同样的字符串并不需要去掉。
这时候可以使用 .lstrip()
方法。
seq = '12321'seq.lstrip('1')
同样,可以使用 .rstrip()
方法来单独去除末尾的字符。
seq.rstrip('1')
经常会遇到需要将字符串拼接起来的情况,这时可以用运算符 + 来简单暴力的拼接。
seq1 = '实'seq2 = '验'seq3 = '楼'seq = seq1 + seq2 + seq3
seq
seq1 = ''seq = ['实', '验', '楼']# 将 seq 里面的每个字符拼接起来for n in seq:
seq1 += n
seq1
需要将字符串用特定的符号拼接起来的字符的时候,可以用 .join() 方法来进行拼接。
seq = ['2018', '10', '31']
seq = '-'.join(seq) # 用 '-' 拼接seq
seq = ['实', '验', '楼']
seq = ''.join(seq) # 用''空字符拼接seq
当想要比较两个字符串的大小时,这里需要加载 operator 工具,它是 Python 的标准库。不需要额外下载,直接通过 import
调用即可。operator 从左到右第一个字符开始,根据设定的规则比较,返回布尔值( True,False )。
判断 a < b 型:
import operator
seq1 = '字符串 1 号'seq2 = '字符串 2 号'operator.lt(seq1, seq2)
除了使用 operator 之外,还有一种方法更简便: 直接使用运算符比较。
直接使用运算符比较 a < b:
seq1 < seq2
可以看到两个结果是一致的。
判断 a <= b:
operator.le(seq1, seq2)
seq1 <= seq2
判断 a == b:
operator.eq(seq1, seq2)
seq1 == seq2
判断 a != b:
operator.ne(seq1, seq2)
seq1 != seq2
判断 a > b:
operator.gt(seq1, seq2)
seq1 > seq2
判断 a >=b:
operator.ge(seq1, seq2)
seq1 >= seq2
因此,使用 Python 的 operator 标准库和运算符比较结果是一致的,可以直接用来比较字符串,这种方法更加直观和简便。
在处理英文类文本的时候会遇到需要将文本全部转化为大写或者小写的时候。使用 .upper()
和 .lower()
可以很方便的完成这个任务。
使用 .upper()
将文本转化为大写。
seq = 'appLE'seq = seq.upper()
seq
使用 .lower()
将文本转化为小写。
seq = 'APPle'seq = seq.lower()
seq
为了查找到某段字符串当中某个子串的位置信息,有两种方法。一种是 .index
,一种是 .find
。
两种方法都可实现这个功能,不同的是 index
如果未找到的话,会报错,而 find
未找到的则会返回 -1
值。
.find()
方法,在序列当中找到子串的起始位置。(PS:第一个位置是 0
)
seq = '这个是一段字符串'seq1 = '字符串'seq.find(seq1)
.find()
方法,字符串中不存在子串返回 -1
seq2 = '无'seq.find(seq2)
接下来我们用 .index()
方法来试一试。
seq3 = '字符串'seq.index(seq3)
下面这段代码会报错,因为 .index()
方法如果没有找到子串,会报错提醒:substring not found。
seq4 = '无'seq.index(seq4)
当想要切分字符串时,有两种常用的方法。第一种是直用序列截取的方法。这种方法十分的简单,就是根据顺序来截取序列上你想要的某些片段。
想要截取 【这是字符串】, 中的‘这是字符’的时候。[0:4]
中 :
左边的 0
的意思是从序列位置 0(从 0 开始数),: 右边的 4 意思是截取到第 4 个字符(但并不包括从零开始数的第 4 个字符)。
这里字面理解起来有点绕,下面是几个例子试着自己感受一下。
seq = '这是字符串'seq1 = seq[0:4]
seq1
截取某个字符的时候可以通过这样。
seq2 = seq[0]
seq2
seq3 = seq[1:4]
seq3
这里如果结合字符串拼接的操作,还能把截出来的字符串拼接起来。
seq = '小了白了兔'a = seq[0]
b = seq[2]
c = seq[4]
seq1 = a+b+c
seq1
有的时候,需要把一个字符串按照某个字符切分开处理。比如【今天天气很好,我们出去玩】,要把两句话以 ','
切开成两句话。
split()
函数可以完成这个操作,函数返回一个由切分好的字符串组成的列表。
seq = '今天天气很好,我们出去玩'seq = seq.split(',')
seq
seq = '2018-11-11'seq = seq.split('-')
seq
seq = 'I have an apple'seq = seq.split(' ')
seq
seq = '号外!号外!特大新闻'seq = seq.split('!')
seq
需要翻转字符串的时候,那么我们直接用序列操作,直接以上面截取序列的方法,但是按照逆向的来截取实现翻转。
seq = '12345'seq = seq[::-1]
seq
遇到需要判断某子串在字符串中是否出现,并根据判断做出后续操作的情况。可以用 in
来作出判断,若存在则返回 True
,不存在则返回 False
,然后配合 if
,作出后续操作。
seq = 'abcdef''a' in seq
seq = '你的名字真好听!''的' in seq
in
关键字可以用在任何容器对象上,判断一个子对象是否存在于容器当中,并不局限于判断字符串是否存在某子串,还可以用在其他容器对象,例如 list
,tuple
,set
等类型。
举个例子,判断一个数是否在 list
中:
nums = [1, 2, 3, 4]2 in nums
下面试着配合 if
来完成一个后续操作。
seq = 'abcd'n = 0if 'a' in seq:
n += 1n
有时需要把字符串中的某段字符串用另一段字符串代替,比如 2018-01-01 中的 -
用 '/'
代替。
我们可以用到 .replace(a,b)
,他可以将某字符串中的 a
字符串替换成 b
字符串。
下面来实现一下:
seq = '2018-11-11'seq = seq.replace('-', '/')
seq
seq = '等会你还要来做实验吗?'seq = seq.replace('吗?', '哦!')
seq
seq = '小了白了兔'seq = seq.replace('了', '')
seq
当遇到需要判断字符串是否以某段字符开头的时候。比如想要判断 ‘abcdefg’ 是否以 'a' 开头。可以用 .startswish()
方法。
seq = 'abcdefg'seq.startswith('a')
seq = '我在蓝桥云课'seq.startswith('me')
同样的方法,我们可以用 .endswith()
来确定字符串是否以某段字符串结尾。
seq = 'abcd'seq.endswith('d')
seq = '我在蓝桥云课'seq.endswith('喽')
有时候,当想要检查字符串的构成,像是检查字符串是否由纯数字构成。
seq = 's123'seq.isdigit()
seq = '123'seq.isdigit()
以上内容均来源于蓝桥云课《自然语言处理基础入门》,本课程将以文本分类为目标,介绍自然语言处理相关的基础操作和应用。
扫码入群可领 3 日标准会员,即可免费学习《自然语言处理基础入门》哦~
▼扫码入群领取标准会员▼
如想进阶学习 NLP,蓝桥云课还会提供中高阶课程,供你学习哦~
戳戳“阅读原文”直达课程页面!