首页 AI Studio教育版 帖子详情
作业帖 | NLP+推荐-深度学习集训营
收藏
快速回复
AI Studio教育版 其他课程答疑 17674 149
作业帖 | NLP+推荐-深度学习集训营
收藏
快速回复
AI Studio教育版 其他课程答疑 17674 149

百度深度学习集训营第二阶段的NLP+推荐系统内容开讲啦,每个阶段的作业都将有各自的奖励,欢迎大家学习~

PS:如遇帖子过期、审核不通过的情况,请先复制内容保存在word文档,然后根据提示,完成个人实名验证,刷新后重新粘贴复制的内容,即可提交~

欢迎大家报名参加~

请大家按照作业格式将作业回帖在下面,并备注自己的AI Studio用户名~

 

2月27日第二次作业

作业奖励:3月2日中午12点之前完成,会从中挑选10位回答优秀的同学获得飞桨定制数据线+本

实践作业:(必做)

路径:AI Studio课程-作业-NLP作业2

•请尝试用飞桨实现一个CBOW模型,并使用text8语料进行训练(或尝试提高skip-gram的训练速度)

附加题:(选做,答案回复在作业帖下)

•打开你的脑洞,尝试embedding的各种花样玩法,比如计算同义词,进行推理,将embedding进行聚类,或者用t-sne进行可视化。

附加题回复格式:

AI Studio用户名:XXXX

作业2-1附加题:XXX

 

2月25日第一次作业

作业奖励: 3月2日中午12点之前完成,会从中挑选10位幸运的同学获得飞桨定制数据线+本

作业1-1

(1)下载飞桨本地并安装成功,将截图发给班主任
(2)学习使用PaddleNLP下面的LAC模型或Jieba分词
LAC模型地址:https://github.com/PaddlePaddle/models/tree/release/1.6/PaddleNLP/lexical_analysis
Jieba模型:https://github.com/fxsjy/jieba
(3)对人民日报语料完成切词,并通过统计每个词出现的概率,计算信息熵
语料地址:https://github.com/fangj/rmrb/tree/master/example/1946%E5%B9%B405%E6%9C%88

作业1-2

(1)思考一下,假设输入一个词表里面含有N个词,输入一个长度为M的句子,那么最大前向匹配的计算复杂度是多少?
(2)给定一个句子,如何计算里面有多少种分词候选,你能给出代码实现吗?
(3)除了最大前向匹配和N-gram算法,你还知道其他分词算法吗,请给出一段小描述。

回复作业格式:

AI Studio用户名:XXXX

作业1-1:XXX

作业1-2:

(1)XXX

(2)XXX

 

报名流程:

1.加入QQ群:677320960,班主任会在QQ群里进行学习资料、答疑、奖品等活动

2.点此链接,加入课程报名并实践:https://aistudio.baidu.com/aistudio/course/introduce/888

温馨提示:课程的录播会在3个工作日内上传到AI studio《百度架构师手把手教深度学习》课程上

8
收藏
回复
全部评论(149)
时间顺序
j
jianghaoyu123
#22 回复于2020-02

AI Studio用户名:jianghaoyu123

作业1-1

(1) 已经安装成功。

(2) 已利用jieba分词进行分词。

(3)解:
计算所得的信息熵为8.4748 (去掉了一些停顿助词)
具体思路为先读取各个原始文件,取其文章的文字部分,再进行停顿词和符号的去除,接着进行分词,再统计词频以字典的形式存储,最后将字典转换成DataFrame统计信息熵。

# -*- coding:utf-8 -*-
import jieba
import os 
import re
import pandas as pd
import numpy as np

#去掉符号的函数
def remove_tokens(tem): 
punct = ('!', '"', '#', '$', '%', '&', '(', ')', '*', '+', ',', '-', '.', '/', ':', ';', '<', '=', '>', '?', '@', '[', '\\', ']', '_', 
'{', '|', '}', '~', '°', '±', '×', '—', '‘', '’', '“', '”', '′', '″', '≤', '≥', '①', '②', '③', '④', '⑤', '⑥',
'⑦', '⑧', '⑨', '⑩', '、', '。', '《', '》', '【', '】', '〔', '〕', '!', '"', '(', ')', ',', ':', ';', '?', '~',
'¥','。','.','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','1','2',
'3','4','5','6','7','8','9','0','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U',
'V','W','X','Y','Z','\n','\t','\u3000')
for key in punct:
tem=tem.replace(key, ' ')
return tem

#去除常见的停顿助词的函数,可以从专门的库里面下载,这里手打了几个作为示例
def remove_zhuci(tem): 
zhuci = ('的','了', '和', '与','阿','啊','啦','唉','呢','吧','哇','呀','不仅','虽然','但是','而且','因为','所以',
'不但','但','不只','一些','甚至','接着','然后','之','已','于','在','我','你','他','她','是','着','也',
'说','要','对','不','都','这','那','又','并','就','去','它')
for key in zhuci:
tem=tem.replace(key, ' ')
return tem

#分词函数
def words_count(file):
char1='/svg>

作业1-2

(1) 解:
设句子的长度为M,词表里有N个单词。
为了计算最大前向匹配的计算复杂度,考虑最坏情况,假设每次取词的Max_len=M,词表中N个单词每个单词的长度都为1。
第一轮,取子串,子串长度为M,则第一轮需要比较M*N次;
第二轮,去掉第一个字,取剩余字符为子串,子串长度为M-1,则第二轮需比较(M-1)*N次;
...
第M轮,去掉前M-1个字,取剩余字符为子串,子串长度为M-(M-1)=1,则第M轮需比较1*N次;
所以,一共需要比较N*(1+M)*M/2次,即计算复杂度为N*(1+M)*M/2;

(2) 解:
思路:首先建立分词的有向无环图,接着利用有向图,得到所有的路径,即可得到所有候选分词组合的种类数量。

# -*- coding:utf-8 -*-
#首先,假设我们有一个词表,词表以集合变量word_dict表示,里面储存了所有的单词;再假设我们有一个句子,句子假设以字符串变量sentence表示。
word_dict={'XX','XX',...'XX'} #word_dict是我们的已知字典词表
word={}; #先建立一个空字典储存所有的字对应的可能分词,构成有向图;
for i in range(len(sentence)):
word[sentence[i]]=[]; #每个字建立一个列表储存所有的分词,构成有向图的顶点。
for j in range(i+1,len(sentence)):
if sentence[i:j] in word_dict:
word[i].append(j) #j表示每个分词中最后一个字的位置加一,构成了有向图中的边。

##利用递归法,构建函数寻找有向图所有的可能路径,并返回最终所有可能路径的数量。
def findAllPath(word,start=0,path=[]): 
path = path +[start]
if start >= len(word):
return [path]

paths = [] #存储所有路径 
for node in word[start]:
if node not in path:
newpaths = findAllPath(word,node,path) #此处用到递归,寻找所有路径
print(newpaths)
for newpath in newpaths:
paths.append(newpath) 
return len(paths)
Nums=findAllPath(word,0,[]) #所有的可能分词组合的种类数量。

(3) 答:
除了最大前向匹配和N-gram算法,还有以下的分词算法:
① 逆向最大匹配法:
与正向前向匹配法类似,区别在于从句子的末尾开始处理,如果匹配不成功则减去最前面的一个字。
② 双向最大匹配法
将正向最大匹配法得到的分词结果和逆向最大匹配法的到的结果进行比较,利用一些设定的规则,例如分词所得词条数最小的为最优的方法,从而决定正确的分词方法。
③ 最短路径分词算法
即第(2)题所采用的算法,首先将一句话中的所有词匹配出来,构成词图,之后寻找从起始点到终点的最短路径作为最佳组合方式。
④ HMM隐马尔可夫模型
利用四个隐含状态描述不同字在词中的位置,B表示词组的开头,M词组的中间,E词组的结尾,S表示单字成词。通过标注好的分词训练集,可以得到HMM的各个参数,然后使用维特比算法来解释测试集,得到分词结果。
此外,还有基于深度学习的BERT、ALBERT模型等等。

0
回复
G
Gasolxia
#23 回复于2020-02

AIStudio用户名:Gasolxia

作业1-1

(1)paddlepaddle安装截图

(2) 分词使用

(3)信息熵计算

信息熵为:11.761

 

作业1-2
(1)匹配次数:N*(m(m+1)/2),时间复杂度即为O(NM~2)

(2)

(3)分词算法: 
逆向最大匹配法:与正向相反从末端开始匹配,用被处理的末尾字串中的前n个字作为匹配字段,查找词典。
双向最大匹配:将正向最大匹配与逆向最大匹配结果比较,选取词数切分最少的作为结果。
还有基于统计的分词算法,隐马尔科夫模型(HMM),条件随机场(CRF)等

 

 

 

0
回复
Shirou
#24 回复于2020-02

AI Studio用户名:Shirou

作业1-1:

(1) Pass

(2)

import paddlehub as hub
lac = hub.Module(name = 'lac')
test_text = ["南京市长江大桥","今天的天气真好"]
inputs = {"text" : test_text}
results = lac.lexical_analysis(data = inputs)
for result in results: 
    print(result['word'])

[out]:

['南京市', '长江大桥']
['今天', '的', '天气', '真好']

(3)

import paddlehub as hub
import os
from collections import Counter
import math
from time import *

begin_time = time()
lac = hub.Module(name = 'lac')
path = "E:/baidu_first_lesson/article"
files_name = os.listdir(path)
word_list = []
for f in files_name:
    dirs = os.path.join(path,f)
    text = open(dirs, encoding = 'utf-8').read()
    text = text.strip().replace(' ', '').replace('\n', '')\
                .replace('“', '').replace('”', '').replace('、', '')\
                .replace(',', '').replace('。', '').replace(':', '')\
                .replace('(', '').replace(')', '').replace('-', '')\
                .replace('!', '').replace('?', '').replace('%', '')\
                .replace('《', '').replace('》', '').replace(';', '')
    inputs = {"text" : text}
    results = lac.lexical_analysis(data = inputs)
    for result in results:
        word_list += result['word']

cnt_dict = Counter(word_list)
entropy = 0
for i in cnt_dict:
    cnt_dict[i] /= len(word_list)
    p = cnt_dict[i]
    entropy += p * math.log(p, 2)
entropy = -entropy
print("信息熵: ", entropy)

end_time = time()
run_time = end_time - begin_time
print("运行时间为{:.2f}s".format(run_time))

[out]:

信息熵: 9.549771313996938
运行时间为1605.68s

 

 

作业1-2:

(1) 思考一下,假设输入一个词表里面含有N个词,输入一个长度为M的句子,那么最大前向匹配的计算复杂度是多少?
答:考虑最坏的情况:单字匹配
需要匹配的次数:N*M + N*(M-1) + N*(M-2)+....+N*1 = N*((M+1)*M/2)
复杂度:O(NM^2)

(2) 给定一个句子,如何计算里面有多少种分词候选,你能给出代码实现吗?
答:例句:南京市长江大桥

"""
程序参考了@phoinikas
测试用例参考了@纠缠state
"""
def break_text_count(seg_text, text, dictionary):
    if len(text) == 0:
        print('/'.join(seg_text))
        return 1
    
    cnt = 0
    for i in range(1, len(text)+1):
        if text[:i] not in dictionary:
            continue
        cnt += break_text_count(seg_text + [text[:i]], text[i:], dictionary)
    return cnt
    
d = ['南京','南京市','市长','长江','大桥','江','南','京','市','长','大','桥']
text = '南京市长江大桥'
print(break_text_count([], text, d))

[out]:

南/京/市/长/江/大/桥
南/京/市/长/江/大桥
南/京/市/长江/大/桥
南/京/市/长江/大桥
南/京/市长/江/大/桥
南/京/市长/江/大桥
南京/市/长/江/大/桥
南京/市/长/江/大桥
南京/市/长江/大/桥
南京/市/长江/大桥
南京/市长/江/大/桥
南京/市长/江/大桥
南京市/长/江/大/桥
南京市/长/江/大桥
南京市/长江/大/桥
南京市/长江/大桥
16

(3) 除了最大前向匹配和N-gram算法,你还知道其他分词算法吗,请给出一段小描述。

答:

当前主流模型:BiLSTM + CRF

BiLSTM: 双向长短期记忆网络,主要借助存储单元的结构来保存较长的依赖关系。可以通过输入门、输出门和遗忘门来调整之前状态对当前存储单元状态的影响。然而在整句层面,BiLSTM缺乏的特征分析,所以需要借助条件随机场(Conditional Random Fields, CRF)的帮助。

CRF: 可以在句子级别上根据特征模板进行序列标注,并通过Viterbi解码来获得最优解。但是CRF提取特征困难,可以结合LSTM改进。

BiLSTM + CRF: 即能保证提取足够多的整句特征,也能有效的进行序列标注。

 

 

 

0
回复
pipi
#25 回复于2020-02

AI Studio用户名:pipi

作业1-1:

1、本地安装paddlepaddle

2、Jieba分词

3、计算信息熵

作业1-2:

1、复杂度为O(N*M^2)

2、分词方案

3、基于词典的还有后向匹配和双向匹配,后向与前向类似,只是方向相反,即从后向前寻找词典中存在的词并输出。双向匹配为:比较正向匹配和反向匹配结果,可以在单字数量或词数量上设定规则进行选择。

基于统计的有隐马尔可夫、条件随机场等。

基于深度的分词w2v+RNN等。

0
回复
AI_Java
#26 回复于2020-02

AI Studio: 不忘初心

作业1-1

(2)学习使用PaddleNLP下面的LAC模型或Jieba分词

# encoding=utf-8
import jieba

strs=["百度AI Studio真的很不错","南京长江大桥","我不是结巴"]
for count, str in enumerate(strs,start=1):
seg_list = jieba.cut(str)
print(count)
print('/'.join(list(seg_list)))
1
百度/AI Studio/真/的/很不错
2
南京长江大桥
3
我/不是/一个个个/结巴巴​​

作业1-2:

(1)最坏情况只能单字,一共要尝试匹配的词有N*(M+M-1+...+2+1)个,复杂度为O(NM^2)。

(3)其他分词算法

1、逆向最长匹配
在使用正向最长匹配分词时,有时会产生意料之外的结果,比如“研究生命起源”,会被切分成[研究生, 命, 起源],因此有人提出逆向最长匹配,从后往前扫描,保留最长词汇。然而还是产生于前向最长匹配同样的问题,因此有人提出综合两种规则,期待取长补短,也就是双向最长匹配。

2、双向最长匹配
在分词时,有时正向效果好,有时逆向效果好,双向最长匹配的思想是从两种结果中挑选出更好的一个。流程如下:同时执行正向和逆向最长匹配,若两者的词数不同,则返回词数更少的那一个,否则返回两者中单字最少的那一个。当单字数也相同时,优先返回逆向最长匹配结果。

0
回复
j
jianghaoyu123
#27 回复于2020-02
AI Studio用户名:jianghaoyu123 作业1-1 (1) 已经安装成功。 [图片] (2) 已利用jieba分词进行分词。 [图片] (3)解: 计算所得的信息熵为8.4748 (去掉了一些停顿助词) 具体思路为先读取各个原始文件,取其文章的文字部分,再进行停顿词和符号的去除,接着进行分词,再统计词频以字典的形式存储,最后将字典转换成DataFrame统计信息熵。 [代码] [代码] (3) 答: 除了最大前向匹配和N-gram算法,还有以下的分词算法: ① 逆向最大匹配法: 与正向前向匹配法类似,区别在于从句子的末尾开始处理,如果匹配不成功则减去最前面的一个字。 ② 双向最大匹配法 将正向最大匹配法得到的分词结果和逆向最大匹配法的到的结果进行比较,利用一些设定的规则,例如分词所得词条数最小的为最优的方法,从而决定正确的分词方法。 ③ 最短路径分词算法 即第(2)题所采用的算法,首先将一句话中的所有词匹配出来,构成词图,之后寻找从起始点到终点的最短路径作为最佳组合方式。 ④ HMM隐马尔可夫模型 利用四个隐含状态描述不同字在词中的位置,B表示词组的开头,M词组的中间,E词组的结尾,S表示单字成词。通过标注好的分词训练集,可以得到HMM的各个参数,然后使用维特比算法来解释测试集,得到分词结果。 此外,还有基于深度学习的BERT、ALBERT模型等等。
展开

AI Studio用户名:jianghaoyu123

(第一次使用这个平台,之前提交的时候浏览器抽风,没有输入完就直接交出去了,所以跟帖重新提交一下,以后会注意,抱歉)

作业1-1

(1) 已经安装成功。

(2) 已利用jieba分词进行分词。

(3)解:
计算所得的信息熵为8.4748 (去掉了一些停顿助词,信息熵的log部分以e为底数)
具体思路为先读取各个原始文件,取其文章的文字部分,再进行停顿词和符号的去除,接着进行分词,再统计词频以字典的形式存储,最后将字典转换成DataFrame统计信息熵。

# -*- coding:utf-8 -*-
import jieba
import os 
import re
import pandas as pd
import numpy as np

#去掉符号的函数
def remove_tokens(tem):   
   punct = ('!', '"', '#', '$', '%', '&', '(', ')', '*', '+', ',', '-', '.', '/', ':', ';', '<', '=', '>', '?', '@', '[', '\\', ']', '_', 
              '{', '|', '}', '~', '°', '±', '×', '—', '‘', '’', '“', '”', '′', '″', '≤', '≥', '①', '②', '③', '④', '⑤', '⑥',
              '⑦', '⑧', '⑨', '⑩', '、', '。', '《', '》', '【', '】', '〔', '〕', '!', '"', '(', ')', ',', ':', ';', '?', '~',
              '¥','。','.','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','1','2',
               '3','4','5','6','7','8','9','0','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U',
               'V','W','X','Y','Z','\n','\t','\u3000')
   for key in punct:
       tem=tem.replace(key, ' ')
   return tem

#去除常见的停顿助词的函数,可以从专门的库里面下载,这里手打了几个作为示例
def remove_zhuci(tem):   
   zhuci = ('的','了', '和', '与','阿','啊','啦','唉','呢','吧','哇','呀','不仅','虽然','但是','而且','因为','所以',
                  '不但','但','不只','一些','甚至','接着','然后','之','已','于','在','我','你','他','她','是','着','也',
                '说','要','对','不','都','这','那','又','并','就','去','它')
   for key in zhuci:
       tem=tem.replace(key, ' ')
   return tem

#分词函数
def words_count(file):
   char1='' #原始文件中正文部分前面的一个字符串,这里网页上显示不出来。
   char2='

\n' #原始文件中正文部分后面的一个字符串,这里网页上显示不出来。 with open(file, 'r',encoding='UTF8') as f: raw = f.read() nPos1=raw.find(char1) nPos2=raw.find(char2) raw=raw[nPos1+len(char1):nPos2] raw=remove_tokens(raw) raw=remove_zhuci(raw) word_list = list(jieba.cut(raw, cut_all=False)) return word_list #构建字典,统计词频的函数 def word_dict(word_list,word_fre): for word in word_list: if word in word_fre.keys(): word_fre[word] += 1 else: word_fre[word] = 1 del word_fre[' '] return word_fre #读取所有的数据并进行分词以及创建词频字典 word_fre={} #储存词频的字典 path_tem="./rmrb" for file in os.listdir(path_tem): file_tem = os.path.join(path_tem,file) word_list = words_count(file_tem) word_fre= word_dict(word_list,word_fre) #词频字典转换成pandas格式,计算信息熵 data=pd.DataFrame(index=range(len(word_fre)),columns = ['单词','词频']) i=0 for key,value in word_fre.items(): data.iloc[i,0]=key data.iloc[i,1]=value i=i+1 data['词频']=data['词频'].astype('float') data.sort_values(by='词频',axis=0,ascending=False) data['词频']=data['词频']/(data['词频'].sum(axis=0)) informationentropy=-(np.log(data['词频'])*data['词频']).sum() #信息熵的计算


作业1-2

(1) 解:
设句子的长度为M,词表里有N个单词。
为了计算最大前向匹配的计算复杂度,考虑最坏情况,假设每次取词的Max_len=M,词表中N个单词每个单词的长度都为1。
第一轮,取子串,子串长度为M,则第一轮需要比较M*N次;
第二轮,去掉第一个字,取剩余字符为子串,子串长度为M-1,则第二轮需比较(M-1)*N次;
...
第M轮,去掉前M-1个字,取剩余字符为子串,子串长度为M-(M-1)=1,则第M轮需比较1*N次;
所以,一共需要比较N*(1+M)*M/2次,即计算复杂度为N*(1+M)*M/2;

(2) 解:
思路:首先建立分词的有向无环图,接着利用有向图,得到所有的路径,即可得到所有候选分词组合的种类数量。

# -*- coding:utf-8 -*-
#首先,假设我们有一个词表,词表以集合变量word_dict表示,里面储存了所有的单词;再假设我们有一个句子,句子假设以字符串变量sentence表示。
word_dict={'XX','XX',...'XX'} #word_dict是我们的已知字典词表
word={}; #先建立一个空字典储存所有的字对应的可能分词,构成有向图;
for i in range(len(sentence)):
   word[sentence[i]]=[];  #每个字建立一个列表储存所有的分词,构成有向图的顶点。
   for j in range(i+1,len(sentence)):
      if sentence[i:j] in word_dict:
          word[i].append(j)  #j表示每个分词中最后一个字的位置加一,构成了有向图中的边。

##利用递归法,构建函数寻找有向图所有的可能路径,并返回最终所有可能路径的数量。
def findAllPath(word,start=0,path=[]): 
    path = path +[start]
    if start >= len(word):
        return [path]
 
    paths = [] #存储所有路径    
    for node in word[start]:
        if node not in path:
            newpaths = findAllPath(word,node,path)   #此处用到递归,寻找所有路径
            print(newpaths)
            for newpath in newpaths:
                paths.append(newpath)    
    return len(paths)
Nums=findAllPath(word,0,[]) #所有的可能分词组合的种类数量。

(3) 答:
除了最大前向匹配和N-gram算法,还有以下的分词算法:
① 逆向最大匹配法:
与正向前向匹配法类似,区别在于从句子的末尾开始处理,如果匹配不成功则减去最前面的一个字。
② 双向最大匹配法
将正向最大匹配法得到的分词结果和逆向最大匹配法的到的结果进行比较,利用一些设定的规则,例如分词所得词条数最小的为最优的方法,从而决定正确的分词方法。
③ 最短路径分词算法
即第(2)题所采用的算法,首先将一句话中的所有词匹配出来,构成词图,之后寻找从起始点到终点的最短路径作为最佳组合方式。
④ HMM隐马尔可夫模型
利用四个隐含状态描述不同字在词中的位置,B表示词组的开头,M词组的中间,E词组的结尾,S表示单字成词。通过标注好的分词训练集,可以得到HMM的各个参数,然后使用维特比算法来解释测试集,得到分词结果。
此外,还有基于深度学习的BERT、ALBERT模型等等。

1
回复
Wuhiu
#28 回复于2020-02

AI Studio用户名:Jesus丶cia

作业1-1

(1)下载飞桨本地并安装成功,将截图发给班主任

(2)学习使用PaddleNLP下面的LAC模型或Jieba分词

  • LAC的学习

LAC inference依赖 PaddlePaddle 和PaddleHub,前者已在(1)中安装,接下来下载安装PaddleHub,使用pip安装:

pip install paddlehub

克隆LAC代码到本地:

git clone https://github.com/PaddlePaddle/models.git
cd models/PaddleNLP/lexical_analysis

下载数据集和LAC模型:

python downloads.py dataset
# download baseline model
python downloads.py lac

模型评估,由于我是在win10运行,所以将shell脚本的python命令拿出来运行:

python eval.py \
        --batch_size 200 \
        --word_emb_dim 128 \
        --grnn_hidden_dim 128 \
        --bigru_num 2 \
        --use_cuda False \
        --init_checkpoint ./model_baseline \
        --test_data ./data/test.tsv \
        --word_dict_path ./conf/word.dic \
        --label_dict_path ./conf/tag.dic \
        --word_rep_dict_path ./conf/q2b.dic

评估结果:

训练和预测过程类似,就不赘述。

  • jieba的学习

主要根据github的示例学习,示例代码如下:

# encoding=utf-8
import jieba

jieba.enable_paddle()
strs=["我来到北京清华大学","乒乓球拍卖完了","中国科学技术大学"]
for str in strs:
    seg_list = jieba.cut(str,use_paddle=True) # 使用paddle模式
    print("Paddle Mode: " + '/'.join(list(seg_list)))

结果如下:

(3)对人民日报语料完成切词,并通过统计每个词出现的概率,计算信息熵

使用了LAC和jieba两种模型进行分词,值得注意的是,在python中使用LAC进行分词时需要使用PaddleHub,并根据demo编写代码。

代码的思路:1)得到语料库所有文件的路径,进而得到所有文件文本内容,保存在一个list中,接着分别使用LAC和jiaba进行分词,得到所有文本分词后的list,再去除停用词(这里主要是标点符号),接着统计每个词的频率用作概率,最后计算信息熵,代码如下:

import os
import re

import paddlehub as hub
import jieba

import pandas as pd
import math

import time

content_list = [] #列表每个元素是一个字符串,字符串的内容是一篇文章
stop_words = [] #维护一个停用词表,这里主要拿来去除标点符号

def getFilePathList(rootDirPath):
    filePath_list = []
    for walk in os.walk(rootDirPath):
        part_filePath_list = [os.path.join(walk[0], file) for file in walk[2]]
        filePath_list.extend(part_filePath_list)
    return filePath_list

def getFileContent(filePath_list):
    for filePath in filePath_list:
        with open(filePath, encoding='utf8') as file:
            fileStr = '-'.join(file.readlines())
            content = re.sub('\s+', '-', fileStr)
            content_list.append(content)

def tokenizer_by_lac():
    lac = hub.Module(name='lac')
    words_by_lac = []
    inputs = {"text": content_list}
    results = lac.lexical_analysis(data=inputs)
    for result in results:
        words_by_lac += result['word']
    return words_by_lac

def tokenizer_by_jiaba():
    jieba.enable_paddle()
    words_by_jieba = []
    for content in content_list:
        result = jieba.cut(content_list[0], use_paddle=True, cut_all=False)# 使用paddle模式和精确模式
        words_by_jieba += list(result)
    return words_by_jieba

def get_stop_words():
    with open('stopwords.txt', encoding="utf-8") as f:
        for line in f.readlines():
            line = line[:-1]
            line = line.strip()
            stop_words.append(line)    

def remove_stop_words(words):
    words_temp = []
    for word in words:
        if word not in stop_words: #可以通过用dict保存停用词降低查询复杂度
            words_temp.append(word)
    return words_temp

def get_entropy(words):
    probability = dict(pd.value_counts(words, normalize=True)) #统计频率计算词x概率
    entropy = 0
    for v in probability.values():
        entropy += v*math.log(v,2)
    return -entropy

def homework1_1_run():
    filePath_list = getFilePathList('rmrb\\example\\1946年05月')#数据集相对本脚本的路径
    getFileContent(filePath_list)
    
    words_by_lac = tokenizer_by_lac()
    words_by_jieba = tokenizer_by_jiaba()
    
    get_stop_words()
    words_by_lac = remove_stop_words(words_by_lac)
    words_by_jieba = remove_stop_words(words_by_jieba)
    
    entropy_by_lac = get_entropy(words_by_lac)
    entropy_by_jieba = get_entropy(words_by_jieba)
    print('entropy_by_lac: %f'%(entropy_by_lac))
    print('entropy_by_jieba: %f'%(entropy_by_jieba))
    return entropy_by_lac , entropy_by_jieba    
if __name__ == "__main__":
    start_time = time.time()
    homework1_1_run()
    end_time = time.time()
    print("elapsed time: %.5f"%(end_time-start_time))
    

运行结果如下:

一些中间结果如下:

作业1-2

(1)思考一下,假设输入一个词表里面含有N个词,输入一个长度为M的句子,那么最大前向匹配的计算复杂度是多少?

假设词典中最长单词的字数为M,则长度为M的句子最多的分词数为M,最小为1,总数为1+2+...+M=M(1+M)/2,复杂度为O(M^2);若词典用数组存储,查询复杂度O(N),总计算复杂度O(NM^2),若词典用字典存储,查询复杂度O(1),总计算复杂度O(M^2)。

(2)给定一个句子,如何计算里面有多少种分词候选,你能给出代码实现吗?

思路:遍历句子的每种分词组合,与词典匹配,匹配成功则用剩余部分继续匹配,否则忽略这种分词,代码如下:

word_list=[]
count = 0
def match(text, dictionary):
    if len(text)==0:
        print('/'.join(word_list))
        global count
        count+=1
    for i in range(len(text)):
        for j in range(len(dictionary)):
            if text[0:i+1] == dictionary[j]:
                word_list.append(text[0:i+1])
                match(text[i+1:len(text)+1], dictionary)
                word_list.pop()

text="为七百万人民请命"
dictionary=["为","七","百","万","人","民","请","命","七百","七百万","人民","请命"]
match(text,dictionary)
print("分词候选总数:%d"%(count))

结果如下:

(3)除了最大前向匹配和N-gram算法,你还知道其他分词算法吗,请给出一段小描述。

  • 最少分词法 (最短路径法 )

设待分词句子S=c_1c_2 ... c_n,建立一个节点数为n+1的有向无环图,节点依次编号v_0...v_n,节点相连的边对应句子中的词,如果w=c_i...c_j是词典中的一个词,则c_i和c_j间建立有向边,重复建立边的过程直到没有新的边产生,从产生的路径中选边最少的作为分词结果

优点:切分原则符合汉语自身规律; 需要的语言资源(词表)也不多。

缺点:对许多歧义字段难以区分,最短路径有多条时,缺乏相应标准,在句子长度越大时体现的越明显。

  • 由字构词 (基于字标注)的分词方法

该方法与N-gram方法不同,它是一种判别式方法,将分词过程看作是字的分类问题。该方法认为,每个字在构造一个特定的词语时都占据着一个确定的构词位置(即词位)。假定每个字只有4个词位:词首(B)、词中(M)、词尾(E)和单独成词(S),那么,每个字归属一特定的词位。当字的词位确定了,分词也就完成了。

优点:更容易学习,能更好的处理未登录词。

缺点:可解释性变差

1
回复
消极兔子
#29 回复于2020-02

AI Studio用户名:消极兔子

作业1-2:

(1)O(NM^2)

(2)

test_file = 'train/train.txt'#训练语料
test_file2 = 'test/test.txt'#测试语料
test_file3 = 'test_sc/test_sc_zhengxiang.txt'#生成结果

def get_dic(test_file): #读取文本返回列表
with open(test_file,'r',encoding='utf-8',) as f:
try:
file_content = f.read().split()
finally:
f.close()
chars = list(set(file_content))
return chars

dic = get_dic(test_file)
def readfile(test_file2):
max_length = 5

h = open(test_file3,'w',encoding='utf-8',)
with open(test_file2,'r',encoding='utf-8',) as f:
lines = f.readlines()

for line in lines:#分别对每行进行正向最大匹配处理
max_length = 5
my_list = []
len_hang = len(line)
while len_hang>0 :
tryWord = line[0:max_length]
while tryWord not in dic:
if len(tryWord)==1:
break
tryWord=tryWord[0:len(tryWord)-1]
my_list.append(tryWord)
line = line[len(tryWord):]
len_hang = len(line)

for t in my_list:#将分词结果写入生成文件
if t == '\n' :
h.write('\n')
else:
h.write(t + " ")

h.close()

readfile(test_file2)

(3)神经网络分词算法,以神经网络理论(BP模型)为基础进行汉语分词。

          联想—回溯法,建立三个知识库——特征词词库、实词词库和规则库。首先将待切分的汉字字符串序列按特征词词库分割为若干子串,子串可以是词,也可以是 由几个词组合而成的词群;然后,再利用实词词库和规则库将词群再细分为词。切词时,要利用一定的语法知识,建立联想机制和回溯机制。联想机制由联想网络和 联想推理构成,联想网络描述每个虚词的构词能力,联想推理利用相应的联想网络来判定所描述的虚词究竟是单独成词还是作为其他词中的构词成分。回溯机制则主要用于处理歧义句子的切分。

1
回复
bnpzsx
#30 回复于2020-02

AI Studio用户名:bnpzsx

作业1-1:

(2) 学习使用LAC模型

在模型源码中inference_model.py的基础上,将LAC模型打包成类供直接使用

(3) 对人民日报语料完成切词,并通过统计每个词出现的概率,计算信息熵

导入使用的库

import os
from collections import Counter

import numpy as np
from tqdm import tqdm

from PaddleNLP.lexical_analysis.lac import LAC

 原始数据预处理函数

def process(path):
    with open(path, encoding='utf8') as f:
        text = f.read()
        start = text.find('专栏:')
        start = text.find('\n', start)
        if start == -1:
            print(f'-->file {path} fail')
            return ''
        else:
            text = text[start + 2:]
            text = text.replace('    ', '')
            text = text.replace(' ', '')
            return text

信息熵计算函数

def calcentropy(counter: Counter) -> float:
    s = sum(list(counter.values()))
    r = 0
    for k, v in counter.items():
        p = v / s
        r += - p * np.log2(p)
    return r

主程序

model = LAC()
counter1 = Counter()
counter2 = Counter()
def update(text_list):
    result = model.predict(text_list)
    for sent, tags in result:
        counter1.update([ch for ch, tag in zip(sent, tags)])
        counter2.update([ch for ch, tag in zip(sent, tags) if tag != 'w'])

batch = []
for file in tqdm(os.listdir(path), ascii=True):
    p = os.path.join(path, file)
    batch.extend(process(p).split('\n'))
    if len(batch) > 255:
        update(batch)
        batch = []
update(batch)

print(f'包含标点符号, 信息熵为 {calcentropy(counter1)}')
print(f'不含标点符号, 信息熵为 {calcentropy(counter2)}')

结果

作业1-2

(1) 先考虑查表次数, 设最大词长度为m, 每种长度分词匹配几率相等, 每段平均匹配m/2次,平均有M/(m/2)段, 查表复杂度为O(M)

假如词表用哈希表储存, 则匹配复杂度为O(1), 总复杂度为O(M)

假如词表用线性表存储, 则匹配复杂度为为O(N/2), 总复杂度为O(MN/2)

1
回复
Daniel wang
#31 回复于2020-02

AI Studio用户名:创图科技web

作业1-1:

(1)安装成功的结果

(2)过程略,在(3)里有体现

  (3) 仅使用1946年5月的数据做处理,过滤方面只做了一些常规的停用词处理,具体代码如下:

# -*- coding: utf-8 -*-
'''
飞浆NLP第一课作业
'''
import os,re
import jieba
from math import log

def load_data(r_path):
    for f in os.listdir(r_path):
        f_path=os.path.join(r_path,f)
        if os.path.isfile(f_path):
            #读取数据
            this_file=open(f_path,'rb')
            content=this_file.read().decode('utf8')
            yield f,content
            this_file.close()
            
# 利用jieba对文本进行分词,返回切词后的list
def seg_doc(str_doc):
    str_doc=re.sub('#', '', str_doc)
    sent_list = str_doc.split('\n')
    # 1 获取停用词
    stwlist = get_stop_words()
    # 2 分词并去除停用词
    word_2dlist = [rm_tokens(jieba.cut(part),stwlist) for part in sent_list]
    # 3 合并列表 多层LIST转一层
    word_list = sum(word_2dlist, [])
    return word_list 

# 创建停用词列表
def get_stop_words(path=r'./data/stopwords.txt'):
    file = open(path, 'r',encoding='utf-8').read().split('\n')
    return set(file)


# 去掉一些停用词和数字
def rm_tokens(words,stwlist):
    words_list = list(words)
    stop_words = stwlist
    for i in range(words_list.__len__())[::-1]:
        if words_list[i] in stop_words: # 去除停用词
            words_list.pop(i)
        elif words_list[i].isdigit(): # 去除数字
            words_list.pop(i)
        elif len(words_list[i]) == 1:  # 去除单个字符
            words_list.pop(i)
        elif words_list[i] == " ":  # 去除空字符
            words_list.pop(i)
    return words_list


if __name__=='__main__':
    datas=load_data(r'./data/1946年05月/')
    word_freq={}
    for i,data in enumerate(datas):
        word_list=seg_doc(data[1])
        for word in word_list:
            word_freq.setdefault(word,0)
            word_freq[word]+=1
    
    print('----------词频统计完毕---------------------')   
    #显示TOP10的词
    sort_words=sorted(word_freq.items(), key=lambda k:k[1], reverse=True)
    print('TOP 10的词及词频为:\n{}'.format(sort_words[:10]))
    print('----------开始计算概率及信息熵-------------------')
    shannonEnt = 0.0
    numEntries=sum(word_freq.values())
    word_prob={}
    for word in word_freq:
        prob = float(word_freq[word])/numEntries
        word_prob[word]=prob
        shannonEnt -= prob * log(prob,2)  
    sort_prob=sorted(word_prob.items(),key=lambda k:k[1],reverse=True)
    print('TOP 10的词及概率为:\n{}'.format(sort_prob[:10]))
    print('信息熵为:{:.4f}'.format(shannonEnt))


运行结果如下:信息熵为 12.5552

 

作业1-2:

(1)思考一下,假设输入一个词表里面含有N个词,输入一个长度为M的句子,那么最大前向匹配的计算复杂度是多少?

答:计算复杂度为O((N*M)^2)

具体过程如下:

输入句子(长度为5):S1=“商品和服务”
定义:最大词长:3
假设存在词表(长度为N):...,商品,服务,....
最大前向匹配的过程如下:
(1)S2="",S1不为空,从S1左边取出长度为3的侯选子串W=“商品和”
(2)查词表,W不在词表中,将W最右边的一个字去掉,得到W=“商品”
(3)查词表,“商品”在词表中,将W加入S2,S2="商品/",同时将W从S1中去除,此时S1=“和服务”
(4)S1不为空,于是从S1中取出侯选子串 W=“和服务”
(5)查词表,W不在词表中,将W最右边的一个字去掉,得到W=“和服”
(6)查词表,W不在词表中,将W最右边的一个字去掉,得到W=“和”,这时W是一个单字,将W加入到S2中,同时从S1中去除,此时S2=“商品/和/”
(7)S1不为空,于是从S1中取出侯选子串W=”服务“
(8)查词表,”服务“在词表中,将W加入S2,S2=”商品/和/服务“,同时将W从S1中去除
(9)S1为空,输出S2作为分词结果,分词结束

代码如下:

#最大前向匹配
def forward_segment(text,dic):
    s2=[]
    max_len=3
    i=0
    while len(text)>0:
        w=text[0:max_len]
        while w not in dic:
            if len(w)==1:
                break
            w=w[0:len(w)-1]
        s2.append(w)
        text=text[len(w):]
    print('分词结果:{}'.format(s2))

if __name__=='__main__':
    dic=['商品','百度','服务']
    s1='商品和服务'
    forward_segment(s1,dic)


运行结果为:

(2)给定一个句子,如何计算里面有多少种分词候选,你能给出代码实现吗?

seg_words=jieba.lcut('南京市长江大桥',cut_all=True)
print('/'.join(seg_words))
print('共有{}种分词侯选'.format(len(seg_words)))


(3)除了最大前向匹配和N-gram算法,你还知道其他分词算法吗,请给出一段小描述。

答:还有最大后向匹配和最大双向匹配,后向与前向有点类似,只是方向不同,后向匹配即从后向前寻找词典中存在的词并输出。双向最大匹配算法的原理就是将前向最大匹配算法和后向最大匹配算法进行比较,从而确定正确的分词方法。

0
回复
bnpzsx
#32 回复于2020-02
bnpzsx #30
AI Studio用户名:bnpzsx 作业1-1: (2) 学习使用LAC模型 在模型源码中inference_model.py的基础上,将LAC模型打包成类供直接使用 [图片] (3) 对人民日报语料完成切词,并通过统计每个词出现的概率,计算信息熵 导入使用的库 [代码]  原始数据预处理函数 [代码] 信息熵计算函数 [代码] 主程序 [代码] 结果 [图片] 作业1-2: (1) 先考虑查表次数, 设最大词长度为m, 每种长度分词匹配几率相等, 每段平均匹配m/2次,平均有M/(m/2)段, 查表复杂度为O(M) 假如词表用哈希表储存, 则匹配复杂度为O(1), 总复杂度为O(M) 假如词表用线性表存储, 则匹配复杂度为为O(N/2), 总复杂度为O(MN/2)
展开

补充(按tab缩进无效然后空格直接就提交了)

AI Studio用户名:bnpzsx

作业1-2:

(2) 给定一个句子,如何计算里面有多少种分词候选?

这题可以看做把一串字按顺序分到n个容器中, 容器数量可以为1至m(句子长度), 代码如下

import math

def num_combination(n, m):
    'C(n,m) n 元集合的 m 元集合数'
    f = math.factorial
    return f(n) // f(n - m) // f(m)

def analysis(text: str) -> int:
    '''给定一个句子,计算里面有多少种分词候选'''
    #问题转化: m个球有几种分法?    
    #分别用 0 - (m-1) 个板去分隔 m 个球
    m = len(text)
    r = 0
    for i in range(m):
        r += num_combination(m - 1, i)
    return r

#简版算法
def analysis1(text: str) -> int:
    '''给定一个句子,计算里面有多少种分词候选'''
    return 2 ** (len(text) - 1)

(3) 中文分词算法主要分为基于词典分词算法基于统计的机器学习算法, 基于词典的分词算法包含正向最大匹配法逆向最大匹配法双向匹配分词法等, 它们的区别在于匹配策略不同. 基于统计的机器学习算法中有一类叫基于字标注的分词法, 常见的有2-tag,4-tag6-tag这几种方法, 最简单的2-tag将词首标记为B,其他位置标记为I. 将机器学习算法词典相结合一方面能够提高分词准确率,另一方面能够改善领域适应性.

0
回复
须佐能泘丶
#33 回复于2020-02

AI Studio用户名:须佐能泘丶

作业1-1: 

(1)

(2)可以看出在某些方面LAC的分词的效果是不错的。

(3)仅选了一篇文章作为计算,读入文本已忽略。

import os
import codecs
import jieba
import re
import math

entropy = 0
words = []
words_frequency = dict()

# 数据清洗
def clean_data(value):
result = re.sub('\W+', '', value).replace("_", '')
return result

#
fileContent = ''

fileContent = clean_data(fileContent)
seg_list = jieba.cut(fileContent)
seg_list = list(seg_list)
words += seg_list
words_count = len(words)

for word in words:
if word not in words_frequency.keys():
words_frequency[word] = 1
else:
words_frequency[word] += 1

for index, value in words_frequency.items():
p = value / words_count
entropy -= p * math.log(p)

#按照词频排序
words_sorted = list(words_frequency.items())
words_sorted.sort(key=lambda e: e[1], reverse=True)

# 输出结果
print('entropy: ', entropy)
print('top 3 words: ', words_sorted[1],words_sorted[2],words_sorted[3])

结果为:entropy: 6.155414934660004   top 3 words: ('了', 34) ('黄河', 26) ('国民党', 21)

 

作业1-2:

(1)假定输入最大长度为M,而每次都是到最后一次才匹配上,那么时间复杂度为O(NM)

(2)思路:从第一个字开始,长度+1为词,去字典里寻找,找到加入数组,开始找长度为3的词,不断循环直至失去匹配或到句末。然后开始第二字的寻找,直到最后。

(3)后向最大匹配算法:与前向最大匹配算法类似,只是方向相反,即从后向前寻找词典中存在的词并输出。

         双向最大匹配算法:就是将正向最大匹配算法和逆向最大匹配算法进行比较,从而确定正确的分词方法。

0
回复
L
LXYTSOS
#34 回复于2020-02
LXYTSOS #5
AI Studio用户名:LXYTSOS 作业1-1 (1)安装paddle [图片] (2)(3)jieba分词的使用以及对人民日报语料库的分词,计算信息熵。 [代码] [图片] 作业1-2 (1)需要匹配的次数为n * (m*(m+1)/2),所以计算复杂度是O(NM^2) (2)使用栈,入栈当前的候选分词,栈顶元素弹出时,在这个词语基础上对后续句子进行切分,把候选词入栈,重复上述过程。 [代码] (3)其他分词算法 1、逆向最长匹配 在使用正向最长匹配分词时,有时会产生意料之外的结果,比如“研究生命起源”,会被切分成[研究生, 命, 起源],因此有人提出逆向最长匹配,从后往前扫描,保留最长词汇。然而还是产生于前向最长匹配同样的问题,因此有人提出综合两种规则,期待取长补短,也就是双向最长匹配。 2、双向最长匹配 在分词时,有时正向效果好,有时逆向效果好,双向最长匹配的思想是从两种结果中挑选出更好的一个。流程如下:同时执行正向和逆向最长匹配,若两者的词数不同,则返回词数更少的那一个,否则返回两者中单字最少的那一个。当单字数也相同时,优先返回逆向最长匹配结果。
展开
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
__title__ =
__author__ = liuxiangyu
__mtime__ = 2020/2/26 10:50
"""
import os
import math
import jieba

data_path = 'data'
word_frequency = dict()
word_counts = 0
entropy = 0

for file_name in os.listdir(data_path):
    with open(os.path.join(data_path, file_name), encoding='utf-8') as f:
        content = []
        lines = f.readlines()
        for line in lines:
            line = line.strip().replace(' ', '').replace('\n', '')\
                .replace('“', '').replace('”', '').replace('、', '')\
                .replace(',', '').replace('。', '').replace('。', '')\
                .replace('(', '').replace(')', '').replace('-', '')
            content.append(line)
        content = ''.join(content)
        seg_list = jieba.cut(content)
        seg_list = list(seg_list)
        word_counts += len(seg_list)
        for seg in seg_list:
            if seg not in word_frequency.keys():
                word_frequency[seg] = 1
            else:
                word_frequency[seg] += 1

for k, v in word_frequency.items():
    p = v / word_counts
    entropy -= p * math.log(p) / math.log(2)

print('entropy: ', entropy)

0
回复
为人名服务11i
#35 回复于2020-02

AI stdio 账号:为人名服务11i

作业1-2

1. 思考一下,假设输入一个词表里面含有N个词,输入一个长度为M的句子,那么最大前向匹配的计算复杂度是多少?

解:前向最大匹配就是从前向后寻找在词典中存在的词

假设输入一个词表里面含有N个词,输入一个长度为M的句子,考虑最坏的情况,即词表中每个单词的长度为1,取词的最大长度为M,于是采用归纳总结法:

需要匹配的次数为:N*M+N*(M-1)+...+N*1=1/2N*M*(M+1)

复杂度: O(NM^2)

2. 给定一个句子,如何计算里面有多少种分词候选,你能给出代码实现吗?

# encoding=utf-8

def text_count(text, word, dict):

    if len(word) == 0:

        print('/'.join(text))

        return 1

    count = 0

    for i in range(1, len(word)+1):

        if word[:i] not in dict:

            continue

        count += text_count(text + [word[:i]], word[i:], dict)

    return count

    

dictionary = ['南京','南京市','市长','长江','大桥','江','南','京','市','长','大','桥']

data = '南京市长江大桥'

candidate = text_count([], data, dictionary)

print("Count is:", candidate)

3.除了最大前向匹配和N-gram算法,你还知道其他分词算法吗,请给出一段小描述。

双向最大匹配算法的原理就是将正向最大匹配算法和逆向最大匹配算法进行比较,从而确定正确的分词方法。

步骤如下:

Step1: 比较正向最大匹配和逆向最大匹配结果。

Step2: 如果分词数量结果不同,那么取分词数量较少的那个。

如果分词数量结果相同:

A. 分词结果相同,可以返回任何一个。

B. 分词结果不同,返回单字数比较少的那个,

如果单字数个数也相同,则任意返回一个。

1
回复
yuzaihuan
#36 回复于2020-02

AI Studio用户名:yuzaihuan

作业1-(1)

作业1-(2)

作业1-(3)

作业·1-2

(1)最坏情况只能单字,一共要尝试匹配的词有N*(M+M-1+...+2+1)个,复杂度为O(NM^2)。

(3)其他分词算法:最大前向匹配算法是基于词表的分词方法,N-gram算法是基于统计的分词方法,还有一类为基于序列标注的分词方法,

0
回复
2
2728ppt
#37 回复于2020-02

AI Studio用户名:  2728ppt

1-1

(1)

(2) 

 

(3)

 

1-2

(1)答:对于长度为N的词典,长度为M的句子,最大匹配长度为不会超过句子的长度M,最坏情况下每个字是一个词都需要切分,且存储方式查找词的时间复杂度是O(N)时,总的时间复杂度O(NM^2)。

 

(2)答:用递归的方法做

 

(3)答:

1.后向最长匹配:和前向最大匹配原理相同,只是匹配文本的方式从文本结尾向前匹配。正向匹配和后向匹配的结果90%情况下是相同的
2.双向最长匹配:同时执行正向和逆向最长匹配,从两种结果中挑选出更好的返回。
3.基于语义理解的分析,基于语言模型来分词的:在所有分词中通过语言模型计算概率,选择概率最大的作为最终的分词结果,该方法的改进方法用维特比算法实现。
4.基于统计方法的分词
5.基于深度学习模型的分词

0
回复
freecarving
#38 回复于2020-02

AI Studio用户名:XM436gr

作业1-1:

(1)

(2)

(3)

作业1-2:

(1)复杂度为O(N*M^2)

(2)

(3)
        逆向最大匹配法(和正向最大匹配法类似,区别是从右到左的方向进行扫描);
        最少切分(使每一句中切出的词数最小);
        双向最大匹配法(和正向最大匹配法类似,区别是从左到右、从右到左进行两次扫描)

        此外还有HMM隐马尔可夫模型和RNN循环神经网络模型切词方法。

 

0
回复
d
ddocan56
#39 回复于2020-02

AI Studio用户名:ddocan56
**作业1-1:**
(1)截图已发班主任
(2)学习使用PaddleNLP下面的LAC模型或Jieba分词 LAC模型
```python
# encoding=utf-8
import jieba
jieba.enable_paddle()# 启动paddle模式。 0.40版之后开始支持,早期版本不支持
strs=["一行行行行行,一行不行行行不行","乒乓球拍卖完了","中国科学技术大学"]
for str in strs:
seg_list = jieba.cut(str,use_paddle=True) # 使用paddle模式
print("Paddle Mode: " + '/'.join(list(seg_list)))
seg_list = jieba.cut("我来到北京清华大学", cut_all=False)
print("Default Mode: " + "/ ".join(seg_list)) # 精确模式
seg_list = jieba.cut("一行行行行行,一行不行行行不行") # 默认是精确模式
print(", ".join(seg_list))

```

[out]:

```powershell
Paddle enabled successfully......
2020-02-27 12:51:59,250-DEBUG: Paddle enabled successfully......

Paddle Mode: 一行行行行行,一行不行行行/不行
Paddle Mode: 乒乓球/拍卖/完/了
Paddle Mode: 中国科学技术大学
Default Mode: 我/ 来到/ 北京/ 清华大学
一行行, 行行行, ,, 一行, 不行, 行, 行不行

```
(3)对人民日报语料完成切词,并通过统计每个词出现的概率,计算信息熵
![在这里插入图片描述](https://img-blog.csdnimg.cn/20200227144628572.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTE4MTg3NjY=,size_16,color_FFFFFF,t_70)**作业1-2**

(1)思考一下,假设输入一个词表里面含有N个词,输入一个长度为M的句子,那么最大前向匹配的计算复杂度是多少?
答:最坏的情况下假设每次取词的Max_len=M,词表中N个单词每个单词的长度都为1;则需要比较的次数为
M*N+(M-1)*N+(M-2)*N+(M-3)*N+……+2*N+1*N=${\frac{M*(M-1)} {2} }$*N
复杂度为$O(NM^2)$。
(2)给定一个句子,如何计算里面有多少种分词候选,你能给出代码实现吗?
答:先通过jieba.cut_for_search分词得到词典,而后采用count_seg_candidates递归查找能够分词成功的句子并返回数量。
```python
import jieba
s="南京市长江大桥"
dict=list(jieba.cut(s,cut_all=True))
print("使用jieba获得词典为")
print(dict)
##count_seg_candidates递归查找能够分词成功的句子
def count_seg_candidates(candidate, remained, dictionary):
if len(remained) == 0:
print('/'.join(candidate))
return 1
count = 0
for i in range(1, len(remained)+1):
if (remained[:i]) not in dictionary:
continue
count += count_seg_candidates(candidate + [remained[:i]], remained[i:], dictionary)
return count
print('分词候选数',count_seg_candidates([],s,dict))
```
输出为

```powershell
使用jieba获得词典为
['南京', '南京市', '京市', '市长', '长江', '长江大桥', '大桥']
南京市/长江/大桥
南京市/长江大桥
分词候选数 2
```

(3)除了最大前向匹配和N-gram算法,你还知道其他分词算法吗,请给出一段小描述。
答:还有逆向最大匹配法(BMM)、双向最大匹配法。双向最大匹配算法结合了FMM、BMM:1. 如果正反向分析结果词数不同,则取分析数较少的那个;2. 如果分词结果词数相同: 分词结果相同,就说明没有歧义,可返回任意一个; 分词结果不同,返回其中单字较少的那个。
除N-gram算法,还有HMM隐马尔可夫模型、CRF条件随机场 基于深度学习BiLSTM-CRF网络模型。

0
回复
aven9008
#40 回复于2020-02

AI Studio 用户名:aven9008

作业1-1

(1)下载飞桨本地并安装成功,将截图发给班主任

安装gpu版坑点:需要提前安装CUDA,cuDNN。

1.1安装CUDA

1.2 拷贝cudnn里面的文件拷贝到NVIDIA GPU Computing Toolkit对应的版本号的相对应的文件夹下,如下图:

1.3 .验证安装可能会遇到CUDA缺少文件cublas64_100.dll,解决方案可以是这样子,将CUDA原安装路径下的bin文件下cublas64_10.dll拷贝,并且重命名cublas64_100.dll。
(2)学习使用PaddleNLP下面的LAC模型或Jieba分词
LAC模型地址:https://github.com/PaddlePaddle/models/tree/release/1.6/PaddleNLP/lexical_analysis

1.1. 安装PadleHub python -m pip install paddlehub

1.2. LAC模型的使用:


Jieba模型:https://github.com/fxsjy/jieba

1.1. 使用结巴分词对比,安装jiebaf分词,python –m pip install jieba

1.2. 结巴分词结果

发现Jieba分词更精确一些
(3)对人民日报语料完成切词,并通过统计每个词出现的概率,计算信息熵
语料地址:https://github.com/fangj/rmrb/tree/master/example/1946%E5%B9%B405%E6%9C%88

这里使用Jieba分词进行分词处理,使用语料是1946年5月的信息,代码及结果如下:

结果:10.884328343900028

作业1-2

(1)思考一下,假设输入一个词表里面含有N个词,输入一个长度为M的句子,那么最大前向匹配的计算复杂度是多少?

算法简述:从子串S开始判断在词表中是否存在S,不存在则去掉字符串S最后一个字符得到子串S,再判断词表中是否存在S,直到找到词表中存在S或S长度为1,返回该词。句子从句首去掉返回的词语后的字符串继续执行以上步骤,直到句子剩下的长度小于或等于1

最坏的情况是,句中的每个字都被切出来,则需要执行1+2+3+4……+M次,则时间复杂度为O(M*(M+1)/2)=>O(n^2)


(2)给定一个句子,如何计算里面有多少种分词候选,你能给出代码实现吗?

思路:在词典中找到与句子子串匹配的词的列表,循环列表,去掉item后的子串再循环该步骤。

代码实现如下:

运行结果:

(3)除了最大前向匹配和N-gram算法,你还知道其他分词算法吗,请给出一段小描述。

机械分词方法,又叫基于字符串匹配的分词方法,它是按照一定的策略将待分析的字符串与一个“充分大的”机器词典中的词条进行匹配,若在词典中找到某个字符串,则识别出一个词。

0
回复
d
ddocan56
#41 回复于2020-02

因为不支持MarkDown,显示错乱,我重发一次。

AI Studio用户名:ddocan56
作业1-1:
(1)截图已发班主任
(2)学习使用PaddleNLP下面的LAC模型或Jieba分词 LAC模型

(3)对人民日报语料完成切词,并通过统计每个词出现的概率,计算信息熵

作业1-2
(1)思考一下,假设输入一个词表里面含有N个词,输入一个长度为M的句子,那么最大前向匹配的计算复杂度是多少?
答:最坏的情况下假设每次取词的Max_len=M,词表中N个单词每个单词的长度都为1;则需要比较的次数为
M*N+(M-1)*N+(M-2)N+(M-3)N+……+2N+1N=(M∗(M−1)/2)​*N
复杂度为O(NM^2),由于句子字数相对于词表N来说太小,所以复杂度为O(N)。
(2)给定一个句子,如何计算里面有多少种分词候选,你能给出代码实现吗?
答:先通过jieba.cut_for_search分词得到词典,而后采用count_seg_candidates递归查找能够分词成功的句子并返回数量。

(3)除了最大前向匹配和N-gram算法,你还知道其他分词算法吗,请给出一段小描述。
答:还有逆向最大匹配法(BMM)、双向最大匹配法。双向最大匹配算法结合了FMM、BMM:1. 如果正反向分析结果词数不同,则取分析数较少的那个;2. 如果分词结果词数相同: 分词结果相同,就说明没有歧义,可返回任意一个; 分词结果不同,返回其中单字较少的那个。
除N-gram算法,还有HMM隐马尔可夫模型、CRF条件随机场 基于深度学习BiLSTM-CRF网络模型。

0
回复
在@后输入用户全名并按空格结束,可艾特全站任一用户