代码
1 | # -*- coding: utf8 -*- |
测试
1 | from unittest import TestCase |
1 | # -*- coding: utf8 -*- |
1 | from unittest import TestCase |
书接上文,上文在计算loss时一共分为两个。
例如:
训练数据集 | 样本 |
---|---|
original_text | 我和你在一其 |
correct_text | 我和你在一起 |
det_labels | 0 0 0 0 0 1 |
我和你在一器
。此为mlm loss。那这篇文章改动了什么?
det_labels的获取方式更改了,怎么更改的?以mlm_result和correct_text进行对比进行获取。
如上例:即mlm_result输出我和你在一器
,和correct_text我和你在一起
进行对比。
即用GAN的思想来进行corrector!
此处我将mlm预测称为generator
(G
),二分类判别称为discriminator
(D
)。
分配G
和D
两者loss不同的weight。
1
和50
![]() |
![]() |
---|
可以看到一个现象,不管dev_metric还是train_metric,在epoch2和epoch3的时候,它的准确度很突然下降,对应的loss也会比刚开始的大的许多。随后效果才会慢慢的提升。
0.9
和0.1
![]() |
![]() |
---|
如果我把上图dev_metric展开下再和train_metric放到一起对比:
![]() |
![]() |
---|
可以看到效果:
0.1
和0.9
![]() |
![]() |
---|
0.1
和0.9
,并且判别器添加GELU![]() |
![]() |
---|
上面这些实验例子都有一个共同的现象:
1
和50
首先解释为什么选择1和50,这个地方来自electra地方的思想,可看上文。
0.9
和0.1
整体很平滑,仿佛判别器没有起到作用似的或者作用很小。
0.1
和0.9
没什么大的意外。
但是让我意外的是下面4情况。
0.1
和0.9
,并且判别器添加GELU我在看《机器学习实战:基于Scikit-Learn和TensorFlow》第二版 时里面讲到训练GAN有些小trick,比如可以给判别器添加一个激活函数。
但是当添加后,发现其抖动的更为严重。。。
这个是个实验值,没有具体理论依据哈,本身就是超参。看下图:
![]() |
![]() |
---|
d_loss和g_loss分别是判别器和生成器各自的loss。
从上图可以看出,d_loss比g_loss小大概9~10倍,所以依据来源在此。
当然还有一些其他的小技巧,就不做实验了,gan本来就难搞。。。
比如:
啥是模式崩溃?
就是当生成器学会苹果后,那判别器就会判别苹果。当生成器转头学会橘子后,那判别器会对橘子判别更准。
而对苹果和橘子共同存在的情况下效果不好。而达到一个纳什均衡。
此篇文章是对macbert4csc模型的一次尝试与思考,废话不多说,看内容。
[x180/macbert4csc-scalarmix-base-chinese]https://huggingface.co/x180/macbert4csc-scalarmix-base-chinese)。
这个模型分成两部分:
举例:
比如错句为我和你在一其
,正确的句子为我和你在一起
,错句输入MLM,得到的结果假设为我和你在一器
。然后输入linear判别器,判断和正确的句子做二分类。最后两个loss进行相加。
首先看看什么是macbert,全称是(MLM as corrector),它是哈工大和讯飞一起训练的模型。主要做的内容有两点:
第一条的做法好处是下游任务一般不会有[mask],那么就不会带来预训练模型和下游任务不匹配的问题。
第二条的做法好处是简单来讲就是更能理解句子的语义性(合理以及通顺)。
这个问题就是为什么选择macbert做微调,因为macbert对mlm中做mask替代的地方用了同义词替换。
这个问题是我自己强行加进来的,哈哈。。
先来看下electra的结构图。
electra模型分成两部分:
the
和painting
做[MASK]
,然后使用生成器进行训练获取结果, 其中the
对了,painting
对应了car
。painting
生成错了。其loss计算方式如下所示:
有木有发现,两者其实还蛮像的,哈哈。
下面是正经思考:
回答1:我觉得阔以,甚者我觉得结果要比macbert4csc更好,为什么?
回答2:我觉得阔以,因为对于多loss,一般没有好的解决方法,明明超参数,只能实验呗。作者在这里选择了50,因为他认为
二分类相比mlm的交叉熵更容易一些,所以给予了更大的权重。
但是我觉得还可以有另外一种思路来参考,即灾难性遗忘
,它是说下游任务对预训练模型进行fine-tune,会对预训练模型造成干扰,那么loss计算时可以分成两部分,pretrained loss和fine-tune loss,一般按经验fine-tune loss权重为0.5。
作者这里使用0.7/0.3的权重分配给MLM和sigmoid二分类,这里我对其做了如下调整:
ID | MLM weight | sigmoid二分类 weight | dev metric |
---|---|---|---|
1 | 1 | 0.5 | epoch26:0.9168 |
2 | 1 | 5 | epoch35:0.914 |
3 | 1 | 50 |
以macbert eval.py为准进行测试,记得把macbert_model_dir改成自己的。
以epoch 26的模型为准:
1 | Sentence Level: acc:0.7040, precision:0.8545, recall:0.6087, f1:0.7109, cost time:5.35 s |
和”shibing624/macbert4csc-base-chinese”进行对比,发现recall要高了不少,结果效果更好了些~。
dev metric 在epoch 35的时候为0.914,相比ID(1)在epoch 26 0.9168的结果,发现收敛速度变的慢了。
故这个忽略。
dev metric 在epoch 35的时候为0.9112,虽说还有小量上涨可能,但是train metric已经过拟合了,这个结果让我觉得…,emmmm,这些超参没有达到想象中的区别哇。
作者在进行二分类的时候使用了最后一层的hidden_states,那么是否可以对所有的hiddeen_states分配不同的权重。为什么?前面的layer更偏向浅层语义信息,比如词法,句法等,越往后代表的含义可能更深层次,本来就是预测词对不对,搞那么深不一定适合。
所以下面对其进行尝试。
添加scalarmix层,代码如下:
1 | class ScalarMix(nn.Module): |
结果如下:
ID | MLM weight | sigmoid二分类 weight | dev metric |
---|---|---|---|
1 | 1 | 0.5 | epoch12:0.9118 |
为啥epoch 12就停了,因为train metric基本已经达到1了。。。
由此可见,整个准确率的提升,更多是在mlm这个任务上,加了二分类判断其对不对,整体影响并没那个大。。。
后来我发现了一个地方,mlm weight和二分类weight我给的是1和0.5,压缩到1之内就分别是0.6666和0.3333,我嘞个去,这不基本和作者的0.7和0.3很相近了么。。下次需要提前注意下。
当我对mlm loss weight分配了更高的权重,结果发现效果有提升。
备忘一下~
之前在看腾讯开源的词向量时,Tencent AI Lab Embedding Corpus for Chinese Words and Phrases,在看到Simple Cases那里,瞬间感到震撼!!果然大公司就是大公司,有钱有地位。。。
跟着公司做了一些技术研究和项目后,发现目前nlp之所以发展没到位,最主要原因就是:算法和数据分家
。算法层面,目前整个学术界没有大的进步,另外像GPT3这种,一般玩不起。数据层面,没人开源数据,即使开源了,标注质量参差不齐,标注标准也是如此。那大家比什么,比的只有算法喽,结果最后就是华而不实(工业上应用)~。
那回到开始,觉得震撼之余,就在想那腾讯肯定也有相应的分词,结果找了半天,没找到。今天突然发现了,窃喜之余,记录一下。
关于它的介绍,TexSmart: 文本理解工具与服务,以及它的Demo,整体效果看下来,要好于目前很多开源的(当然,你懂我意思),大家算法可能都差不多。
但是分为离线版和http api版,差距有多大,这个木有尝试,反正官方说有差距。
以后尝试尝试。
参考地址:
这篇文章主要对pycorrector默认使用规则的代码进行debug和理解,不论怎样,应先读下作者的readme,有个充分的理解先。
初始化主要做了三件事:
1 | check_corrector_initialized() |
1 | # 编码统一,utf-8 to unicode |
额外插句:单从re_han
这里就可以看出,作者至少对jieba很熟悉。
1 | def split_2_short_text(text, include_symbol=False): |
关于kenlm,网上搜了下,除了纠错基本很少有人用到(而且还是针对pycorrector~),只有这篇文章说的还有点意思,而且看Github kenlm介绍,作者也是十分任性,只强调速度,没有强调用处。。。
简单来讲,kenlm是基于n-gram训练出来的一个预训练模型,它的更多用法可看Example。
加载词频
(这个我看了下,和jieba自带的那个dict.txt基本没关系,相当于作者自己训练了一个词频词典)
~~ * 自定义混淆集(空的,所以忽略这步)~~
自定义切词词典
(默认是空,个人感觉可以把jieba那个dict.txt加进去,哈哈哈)
一些特定词典
人名词典词频、place词典词频、停用词词典词频、将这些词典词频合并到一起
对于人名和place这种词典,不如使用现成了命名实体模型,这种词典的方式总之是无法完全枚举的。
1 | # 词、频数dict, TODO: 这里虽然有,但是貌似没有用到 |
这部分使用jieba的search模式进行分词。
它的实现原理是:先使用hmm进行分词,比如少先队员因该为老人让坐
,它的分词结果是["少先队员", "因该", "为", "老人", "让", "坐"]
,然后对每个词再用2阶gram和3阶gram进行切分,在self.FREQ
中进行查找是否存在,得到的结果如下:
1 | ('队员', 2, 4) |
分完词后,按词粒度判断是否在词典里,符号,英文则跳过,否则则认为是可能错的。
到这里识别出因该
是可能错误的。
取bigram和trigram,通过kenlm获取对应的score,然后求平均获取和句子长度一致的score。
比如:
1 | sent_scores = [-5.629326581954956, -6.566553155581156, -6.908517241477966, -7.255491574605306, -7.401519060134888, -7.489806890487671, -7.1438290278116865, -6.559153278668722, -6.858733296394348, -7.7903218269348145, -8.28114366531372] |
然后通过这个sent_scores
取判断哪些index是错的。
那作者是怎么判断的呢?
1 | def _get_maybe_error_index(scores, ratio=0.6745, threshold=2): |
平均绝对离差定义为各数据与平均值的离差的绝对值的平均数
,那作者这里的计算方式貌似就不一样了。至此获取到的可能错误列表是:
1 | [['因该', 4, 6, 'word'], ['坐', 10, 11, 'char']] |
假设当前输入word是因该
:
_confusion_word_set
_confusion_custom_set
他这个获取相同拼音的写法就让我觉得emo,直接在self.known(自定义词典)里找长度相同,然后判断拼音一样不就得了~
自定义混淆集就是自定义一些经验进行。比如{“因该”: “应该”}这种,增大候选集。
这地方分成三部分:
same pinyin 加载同音的列表
,以及加载形似字same stroke 加载形似字
。因
,然后获取相同拼音的same pinyin 加载同音的列表
,以及加载形似字same stroke 加载形似字
,然后和该
进行拼接,获取新的候选集。第二个字该
执行相同操作。这个地方就有意思了,如何获取最正确的那个呢?看下面代码。
1 | def get_lm_correct_item(self, cur_item, candidates, before_sent, after_sent, threshold=57, cut_type='char'): |
核心的地方在self.ppl_score
那里,代码如下:
1 |
|
看作者注释,说的很明白了,如果这个句子越是流畅的,那么他的score就会更高。
1 | pprint(sorted_ppl_scores) |
最后一步,作者以score最高的那个加了一个threshold,如果得分在这个阈值内的,添加到候选的top_items里面。
如果当前的cur_item,即因该
不在这个候选集里,那么取第一个top_items
,如果在,那么就返回当前的cur_item。
这步的目的在于防止误判。
因该
也是有可能作为一个单独的词,只是出现的可能性较小。本文尝试从几个方面来介绍提取关键词所知的技术,以及关键词提取所遇到的问题,接着介绍SIFRank-zh算法,最后穿插下个人的理解与总结。
刚开始接触这个概念的时候,网上一大堆介绍TF-IDF和TextRank算法,这俩简直已经称为了关键词提取的baseline。
关于TF-IDF,的确在许多文档中已经作为了baseline来和其他技术相对比,是一种简单易行并且效果不差的无监督技术。
TextRank具体我没看,此处略过。
那么,此处引入一个问题,什么叫关键词?换句话说,什么样的词我们认为是关键词?
比如一句话:从2021年11月1日起,南京各个社区将尝试采取网格化管理,增强人民群众安全。
,不同分词器的结果如下:
lac的分词结果:
1 | [('从', 'p'), |
ltpV3版本的分词结果:
1 | ['从', '2021年', '11月', '1日', '起', ',', |
这里我想突出一个问题,目前市面所见的所有分词器都是采用细粒度分词
,那这就导致一个最直接的问题,就是关键信息词被拆开了。
这句话本质想突出网格化管理
这个词,但是在两个分词器中都将其分成了两个词。
你可以说NER可以解决这个问题哇,从技术角度本身来讲,这的确是可行的。比如时间短语,机构短语,地址短语。
你也可以说数据标注标准不同,比如msra或者ptb数据集。
你也可以说粗粒度分词会更容易产生歧义。比如白天鹅在湖中游
等等。这条不太认同。
你也可以说粗粒度分词下如果想获取更细粒度分词则无法获得。这条我认为可有可无。
但是我想说的是,那能不能有一个分词器,从使用效果上来讲更贴切人直观感受,不需要关注底层分词和NER这两种技术的。
可惜没有!
之前我看腾讯开源了一个训练好的word2vec模型,在Simple Cases那里,简直看到了希望!!
当时就在想,怎么根据word2vec反推出一个分词?
过程就是分词和word2vec训练放到一个任务中,但是只保存分词的模型。
然后在脑里想分词实现技术有哪些,首先肯定排除掉最长距离或者最短距离分词,那么能想到的只有HMM和CRF。
不管HMM还是CRF,本质都是计算状态概率转移矩阵和发射概率矩阵,HMM多了个初始概率矩阵,这个还好。
但是想了半天,貌似都不太可行,为什么?
商品和服务
,有['商品', '和', '服务']
以及['商品', '和服', '务']
,仅仅这个例子,就有两种可能性,如果一个句子过长的话甚者有很多中语料的话,就无法估算那个语料才是真正正确的那个。那么在无法估计正确语料这条路来讲,crf就不可行。emmmmm,但是我觉得可以换条思路来实现,那就是用于辅助标注人员的方式来重标数据集,或者对标注人员说,我更倾向于使用粗粒度分词的。
额,说了这么些,感觉貌似又回到了起点。
但是是一劳永逸的一种方式。
上面介绍了这么多,本质来讲是想提取更粗粒度的,那么我们基于现有的条件下,可以借鉴的实现方式:
排序的本质是正确代表语句或文本的真实意图或者需要涵盖的方面点。从无监督方式出发的话,我们能够利用的特征:
SIFRank的实现主要分为以下步骤:
接下来会对其实现做更具体说明。
ELMoForManyLangs,SIFRank_zh作者指出的关于:
1 | 哈工大的elmoformanylangs 0.0.3中有个较为明显的问题,当返回所有层Embeddings的时候代码写错了,当output_layer=-2时并不是返回所有层的向量,只是返回了倒数第二层的。问题讨论在这里#31 |
已经解决,故可以忽略。
测试代码以官方test.py为准。
1 | #download from https://github.com/HIT-SCIR/ELMoForManyLangs |
1 | class SentEmbeddings(): |
1 | def get_word_weight(weightfile="", weightpara=2.7e-4): |
这地方主要干了初始化elmo和以jieba分词统计的词频为主进行获取词的权重。
- 分词使用thunlp,但是以jieba同级的词频为主,这地方不合适。
- 这样获取词的权重,也不太合适。是否可以使用tf-idf呢。
1 | zh_model = thulac.thulac(model_path=r'../auxiliary_data/thulac.models/',user_dict=r'../auxiliary_data/user_dict.txt') |
1 | class InputTextObj: |
1 | GRAMMAR_zh = """ NP: |
到这里位置作者完成了对候选词的处理,还是回到最上面讲候选词获取那里的问题,如果有一个更合适的分词器。
- 那么这里我们就可以重新获取dict.txt。
- 不需要这么复杂的正则表达式来获取候选词。
- 接下来的获取候选词词向量那里也会更适合。
另外一个方面,关于正则匹配那:
- 我们可以不局限于词性,也可以根据词的信息来合并,比如’和’,‘的’等字。
- 针对特定词进行对分词器做调整。
1 | def get_sent_segmented(tokens): |
但是想不明白的是,干嘛不直接用一个更成熟的分句工具呢,比如ltp和hanlp中都有现成的。
这一步和获取elmo每层输出作者将其称为文档分割(document segmentation,DS)
,其作用如下:
1 | DS:通过将文档分为较短且完整的句子(如16个词左右),并行计算来加速ELMo; |
注意,下面将不区分elmo和ELMoForManyLangs,如果不做说明,则统一为ELMoForManyLangs。
1 | def get_tokenized_words_embeddings(self, sents_tokened): |
elmo输出为三层结构,这个可以在ELMoForManyLangs中看到,
1 | output_layer: the target layer to output. |
比如sents_tokened长度为[44, 110],输出结果elmo_embedding为torch.Size([2, 3, 110, 1024])
。
1 | def context_embeddings_alignment(elmo_embeddings, tokens_segmented): |
这地方做了三件事情:
- 获取每个词对应的词向量,将相同词的向量append到一起。
- 求每个词的平均词向量
- 替换掉elmo最后一层的词对应的词向量
这一步作者叫做词向量对齐(embeddings alignment,EA)
,其作用如下:
1 | EA:同时利用锚点词向量对不同句子中的相同词的词向量进行对齐,来稳定同一词在相同语境下的词向量表示。 |
1 | def splice_embeddings(elmo_embeddings,tokens_segmented): |
比如tokens_segmented
长度为[44, 110]
,elmo_embeddings
shape为:torch.Size([2, 3, 110, 1024])
。
那么new_elmo_embeddings
的shape为:torch.Size([1, 3, 154, 1024])
。
1 | def get_weight_list(word2weight_pretrain, word2weight_finetune, tokenized_sents, lamda, database=""): |
1 | def get_oov_weight(tokenized_sents,word2weight,word,method="max_weight"): |
就是根据dict.txt计算出每个词的权重,所获取到的.
1 | def get_weighted_average(tokenized_sents, sents_tokened_tagged,weight_list, embeddings_list, embeddings_type="elmo"): |
只计算考虑的词性
。比如(n,np,ns)等。注意这里哦,这里有两点需要注意的:
- elmo第三层不是原来第三层的结果了,是作者称为
词向量对齐
的给替代了。- 他计算的是只考虑的词性,而不是所有词的平均向量。
1 | def get_candidate_weighted_average(tokenized_sents, weight_list, embeddings_list, start,end,embeddings_type="elmo"): |
整个计算过程和上一步基本一致。
到这一步作者完成了对文档向量的计算,以及候选词向量的计算。
不难看出,第一还是词权重的问题。第二是文档向量只考虑了目标词性。第三是候选词一般是复合词,那么在计算复合词权重的时候是词权重 * 词向量求平均的方式。
那如果我们有一个更合适的分词器,训练一个自己的词权重文件,以及训练一个更适合自己的elmo模型,那是否可以讲整套技术上是更为完整的。
1 |
|
计算每个候选词与整段话的余弦距离,但是这里默认每层的权重是[0.0,1.0,0.0]
,那这就导致作者声称的词向量对齐(embeddings alignment,EA)
技术并没有用到~
1 |
|
产生的结果比如:{“技术”: [0.8432613915568461, 0.8243992563094531, 0.8120348604031394]},那么又做了一次平均。
词向量对齐(embeddings alignment,EA)
技术默认没有用到。到这里作者完成了SIFRank_zh算法,的确是受限于目前的成果,整体流程也是具备参考价值的。
突出的问题,到这里为止,并没有利用到位置信息特征,比如行首或者行尾可能更具备代表含义。那么作者在此基础上,提供了SIFRank+算法。
1 |
|
我原本以为作者会用到词在原文中的索引位置,结果是候选词之间的索引位置。emmmm,但反过来想这其实也不正是原文中的相对索引位置嘛。
作者这里用到了两个技术点让我觉得很nice,一个是wnl.lemmatize
,其作用是词性还原的,对于英文来说有用。还有一个是softmax
,是用于归一化的。都能看出作者的扎实底子。
从作者这地方可以看出,整套流程是提取复合词的候选词,然后使用elmo计算候选词和以只考虑的目标词性所组成的句向量进行余弦计算其排序。
在不改变整体流程和技术的方式上
什么是表达式,用一组规则来进行信息表示与提取。
这个名字起的有点绕,本质来讲他是做下面这个事情的。
假设分词结果如下所示:
1 | [ |
如果从这句话中进行关键词提取,分词粒度太低,那么我们首先会想着聚合。
1 | [('社区', 'n'), ('网格化', 'n'), ('管理', 'n')] |
网格化管理
更能体现出比管理更具体的含义,那么你会接着使用2阶的n-gram
,那么网格化管理
会提取出来。
现在社区
也是2阶n-gram,他们应该聚合吗?显然是不应该的,那么我们认识到:
n-gram是必须的,但是配置出来的规则不止n-gram。
那么我们尝试添加进去词性
特征。
伪代码如下:
1 | if before_token.pos == 'n' and cur_token.pos == 'n': |
假设到此我们都可以用一堆hardcode来解决了,如果我们允许自定义配置,那么上面的hardcode就要换一种方式来表达。
此方法自行实现。我们可以定义每个token的判断逻辑。
1 | def token_match(token, element): |
到这里为止,我们认为实现了一个可自定义配置的表达式,但是问题来了,上面这个准确来讲是实现了硬匹配的,只能一个token一个token的来写表达式规则,比如我想实现[‘!n’, ‘!n’, ‘!n’, ‘!n’]这种,那就要写4遍这个。而不是!n+这种。
那么自行实现正则表达式会是更优的方式。
那先转换下思路,有没有现成的实现方式或者相关术语,可以拿来参考。
根据Nature Language Processing with Python第七章Extracting Information from Text中介绍到分块
概念。
我们将用于实体检测的基本技术是分块,它分割和标记多令牌序列,如下图所示。
那么由此可见,我们可以看到用于分块的正则表达式和n-gram方法。
1 | >>> sentence = [('the', 'DT'), ('little', 'JJ'), ('yellow', 'JJ'), ('dog', 'NN'), ('barked', 'VBD'), ('at', 'IN'), ('the', 'DT'), ('cat', 'NN')] |
由这个例子可见,grammer中:
NP
为自定义的名字,nonterminal,表示为这个grammer应该对应的label是什么。这个可自行参考constituency tree parser。{}
表示一套表达式的范围,rule。<>
对应token的表示。?
, *
, +
就对应正常的正则。搜了些资料,貌似没有根据词特征来进行patten匹配的。
通过源码可看出的确是不支持词匹配的。
基于这个的应用,可看SIFRank_zh
算法的应用。
如果需要其他特征,可以先词性匹配,后续加规则来实现。
自己实现一个更高级的😂😂😂。
tensorboard是让torch可以使用tensorflow的web可视化工具,之前叫tensorboardX。
至于其他的介绍以及为什么需要,可自行百度。
1 | # -*- coding: utf8 -*- |
终端跑下面这条命令:
1 | tensorboard --logdir=./runs |
其中数据集加载没有添加进来,引用代码可参考lstm_sent_polarity。
1 | # Defined in Section 4.6.7 |
本篇文章主要讲基于bert预训练模型的一些例子,希望可以从不同角度理解与应用基于bert的一些应用。
nlp发展了这么多年,经历了规则,统计,模型等阶段,目前预训练模型基本算是一统天下了。
大公司有更多资源,可以联合一些科研机构与组织搞一些事情,比如微软和nvidia利用更多的资源来探测模型的边界。
这个就很有意思,思考一个问题,什么叫意识?什么情况下产生了意识?
什么是意识,这个可以尝试用两个词来理解,计算
和算计
。计算很好理解,比如计算机,计算器,本质来讲是人输入指令,获得一个预期结果,不会产生任何歧义。而算计呢,它是一个综合体,它的输出是多样的,有可能不可预知的。它具有自己的思考。
那什么情况下产生了意识?这个问题就是这些大佬们所想要尝试认知的东西。比如人类有30亿碱基对,蚊子才几千万,单细胞生物可能更少可能就被认为不具备意识?如此看来的话,那我可以尝试扩充网络容量,更多的训练数据集,等到了某个程度下,突然机器就具备了某种智能。
这是个有意思的研究!
不过扯了这么多,小公司的话,更多是基于预训练模型的微调。
为什么要基于预训练模型微调呢,严格意义来讲就是预训练模型已经学习到了语义,一个认知大脑。基于此,给定一个具体任务,来对其进行微调,使其具备更快的收敛能力和更好的泛化能力。
所以掌握下还是很重要滴😂😂😂。
下面介绍四个应用示例,每一种大致介绍下,更具体的实现可以自行实现。
不过作者在这里使用了Trainer,这是transformers出的一套工具,可以让你更快的训练,但是封装太高,懒得折腾了,不如自己从头写😂😂😂。
代码.
这个是个ner任务,不知道ner的自行百度,模型后面接了一个linear,如果想要更深入,可以看看crf。
不过这个任务如果用于分词,词性标注还是很nice的。
代码.
这个任务还是蛮有意思的,之前也有类似的比赛。比如天池 疫情相似句对判定大赛 线上第一名方案。
整体实现思路基本一致,不过作者加入了对抗训练这些东西,感兴趣可以看看。
代码.
这个就是多分类任务,也是比较常见的场景。
代码.
这个我没看😂😂😂。
好吧,这本书快让我水了一波,感兴趣的需要基础的老铁们可以多翻翻。
缺失模块。
1、请确保node版本大于6.2
2、在博客根目录(注意不是yilia根目录)执行以下命令:
npm i hexo-generator-json-content --save
3、在根目录_config.yml里添加配置:
jsonContent: meta: false pages: false posts: title: true date: true path: true text: false raw: false content: false slug: false updated: false comments: false link: false permalink: false excerpt: false categories: false tags: true