Skip to content

Commit

Permalink
add db
Browse files Browse the repository at this point in the history
  • Loading branch information
liqiankun1111 committed Oct 12, 2024
1 parent 3b27049 commit 0838318
Show file tree
Hide file tree
Showing 23 changed files with 230 additions and 46 deletions.
29 changes: 25 additions & 4 deletions _posts/MachineLearning/Model/2024-10-11-bert.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ keywords: gcn

---

## 简介(未完成)
## 简介

* TOC
{:toc}
Expand All @@ -19,7 +19,6 @@ BERT 是一个用 Transformers 作为特征抽取器的深度双向预训练语

bert 名称来自 Bidirectional Encoder Representations from Transformers. Unlike recent language representation models, BERT is designed to pre-train deep bidirectional(相对gpt的单向来说,是双向的) representations by jointly conditioning on both left and right context in all layers. As a result, the pre-trained BERT representations can be fine-tuned with just one additional output layer to create state-of-the-art models for a wide range of tasks, such as question answering and language inference, without substantial task-specific architecture modifications. PS:ELMo 是基于rnn,在应用到下游任务时,还需要做一些模型结构的变动。有了一个训练好的bert之后,只需要再加一个额外的层,就可以适配各种任务。


## 模型结构

BERT的基础集成单元是Transformer的Encoder,BERT与Transformer 的编码方式一样。将固定长度的字符串作为输入,数据由下而上传递计算,每一层都用到了self attention,并通过前馈神经网络传递其结果,将其交给下一个编码器。
Expand All @@ -42,11 +41,33 @@ BERT的基础集成单元是Transformer的Encoder,BERT与Transformer 的编码

## 训练方式

[一文读懂深度学习:从神经元到BERT](https://mp.weixin.qq.com/s/wrqxuMidw7HvgTVUvTBGng)相比语言模型任务只做预测下一个位置的单词,想要训练包含更多信息的语言模型,就需要让语言模型完成更复杂的任务,BERT 主要完成完形填空和句对预测的任务,即两个 loss:一个是 Masked Language Model,另一个是 Next Sentence Prediction。

### Masked Language Model

MLM是为了训练深度双向语言表示向量,BERT 用了一个非常直接的方式,遮住句子里某些单词,让编码器预测这个单词是什么。
![](/public/upload/machine/bert_masked.jpg)

BERT 具体训练方法为:随机遮住 15%的单词作为训练样本。
1. 其中 80%用 masked token 来代替。
2. 10%用随机的一个词来替换。
3. 10%保持这个词不变。

直观上来说,只有 15%的词被遮盖的原因是性能开销,双向编码器比单向编码器训练要慢;选 80% mask,20%具体单词的原因是在 pretrain 的时候做了 mask,在特定任务微调如分类任务的时候,并不对输入序列做 mask,会产生 gap,任务不一致;10%用随机的一个词来替换,10%保持这个词不变的原因是让编码器不知道哪些词需要预测的,哪些词是错误的,因此被迫需要学习每一个 token 的表示向量,做了一个折中。

![](/public/upload/machine/bert_masked_token_prediction.jpg)

PS:训练时,自己知道自己mask 了哪个词,所以也是无监督了。

## 应用
### Next Sentence Prediction

预训练一个二分类的模型,来学习句子之间的关系。预测下一个句子的方法对学习句子之间关系很有帮助。

训练方法:正样本和负样本比例是 1:1,50%的句子是正样本,即给定句子 A 和 B,B 是 A 的实际语境下一句;负样本:在语料库中随机选择的句子作为 B。通过两个特定的 token[CLS][SEP]来串接两个句子,该任务在[CLS]位置输出预测。

![](/public/upload/machine/bert_next_sentence_prediction.jpg)

## Fine-tune

BERT的论文为我们介绍了几种BERT可以处理的NLP任务:
1. 短文本相似
Expand All @@ -56,7 +77,7 @@ BERT的论文为我们介绍了几种BERT可以处理的NLP任务:
4. 语义标注
5. 特征提取 ==> rag 里的emebedding

PS:最后一层的输出 选用[cls] 对应的embedding 或多个emebedding 套个FFNN + softmax,二分类或多分类任务就都可以解决了。
针对不同任务,BERT 采用不同部分的输出做预测,分类任务利用[CLS]位置的 embedding,NER 任务利用每个 token 的输出 embedding。PS:最后一层的输出 选用[cls] 对应的embedding 或多个emebedding 套个FFNN + softmax,二分类或多分类任务就都可以解决了。

## 其它

Expand Down
15 changes: 12 additions & 3 deletions _posts/Technology/Architecture/2018-10-01-object_oriented.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,18 +98,27 @@ UML的创始人Grady booch在 Object Oriented Analysis and Design with Applicati

什么东西稳定?问题域越明确,越容易形成稳定的抽象。从这个角度而言,越偏向纯技术的领域越稳定,比如,对于文件的操作,无外乎就是打开、关闭,读写,这套玩意几十年如一日,稳定,持久,有用。再比如,服务治理中间件,解决的就是微服务互相通信的问题,包括服务注册、发现、负载均衡、熔断等。所以不管是Spring Cloud还是Dubbo,也可以很稳定的被抽象,被复用。消息中间件也是一样,就是要解决消息的生产、传递、消费问题,也很稳定。其它的技术领域也是一样,比如云计算,整个IT基础实施也是相对稳定的问题域,就是要提供可隔离的网络、高可靠的存储、可弹性的计算。所以也能在更大层面被抽象,被复用。**底层技术的难度在于技术深度**。就问题域而言,它要解决的问题是相对稳定的、清晰的。这就给合理的抽象,持续的打磨迭代带来了机会。PS:稳定不稳定就看你是否持续投入人去改。

什么东西不稳定?上层业务应用看起来没有什么“技术含量”,但其难度在于合理的业务抽象和设计权衡。越上层的业务越不稳定,稳定抽象的难度越大。这也是为什么当年阿里的业务中台失败的原因。因为他尝试在一个极其不稳定的电商业务领域,构建一套相对稳定,可复用的中台抽象。这种基于不稳定问题域的抽象复用,会带来极大的耦合成本,主要体现在三个方面:
什么东西不稳定?**上层业务应用看起来没有什么“技术含量”,但其难度在于合理的业务抽象和设计权衡**。越上层的业务越不稳定,稳定抽象的难度越大。这也是为什么当年阿里的业务中台失败的原因。因为他尝试在一个极其不稳定的电商业务领域,构建一套相对稳定,可复用的中台抽象。这种基于不稳定问题域的抽象复用,会带来极大的耦合成本,主要体现在三个方面:
1. 人员协作耦合:如果需要中台提供新的扩展点,也就是新的抽象,你就要协调一堆的人,还要排期,这叫协作耦合。
2. 代码耦合:因为业务逻辑是直接以代码的方式嵌入在中台系统,导致多个团队要在一起搞代码,其测试、联调、集成、发布成本都很高。另外,因为新框架的认知成本造成的认知复杂度,也使得coding的难度加大。
3. 部署耦合:因为是中台统一部署,从而导致不同的业务之间可能会相互影响。比如某个业务突发事件,可能导致其它业务的稳定性都受到影响。

![](/public/upload/architecture/abstract_value.jpg)

对于高价值区,这个没有任何异议,我们要不遗余力的去构建公共的技术底座,复用公共的技术能力,从而提升整体的研发效率。这里请Don't Repeat Yourself!这里要特别留意的是极度危险区。比如上文提到的不同电商业务的履约服务,但实际上问题域的共性很小,稳定性很差就属于极度危险区。这里虽然也可以抽象,但抽象层次往往过高,不会有多大的复用价值,再加上深度耦合带来的问题。烟囱式的解耦将是更加合适的选择!危险区是那些复用程度很高,但稳定性不足的领域。比如商品领域,还是以电商业务为例。虽然饿了么、淘宝、飞猪的业务差异很大,但是商品的类目管理、属性管理,商品上架,浏览,搜索,推荐还是有很大的共性所在。这里肯定是有复用的空间的,但是也要注意程度的把控。可以考虑把中台做薄,复用可以复用的部分,比如商品数据的存储,类目管理可以由平台统一做。对于商品审核、上架这些差异性比较大的部分,交给业务自己去处理。还是解耦比较好,一股脑的做厚中台,又会陷入耦合的噩梦。
**对于高价值区,这个没有任何异议,我们要不遗余力的去构建公共的技术底座,复用公共的技术能力,从而提升整体的研发效率**。这里请Don't Repeat Yourself!这里要特别留意的是极度危险区。比如上文提到的不同电商业务的履约服务,但实际上问题域的共性很小,稳定性很差就属于极度危险区。这里虽然也可以抽象,但抽象层次往往过高,不会有多大的复用价值,再加上深度耦合带来的问题。烟囱式的解耦将是更加合适的选择!**危险区是那些复用程度很高,但稳定性不足的领域**。比如商品领域,还是以电商业务为例。虽然饿了么、淘宝、飞猪的业务差异很大,但是商品的类目管理、属性管理,商品上架,浏览,搜索,推荐还是有很大的共性所在。这里肯定是有复用的空间的,但是也要注意程度的把控。可以考虑把中台做薄,复用可以复用的部分,比如商品数据的存储,类目管理可以由平台统一做。对于商品审核、上架这些差异性比较大的部分,交给业务自己去处理。还是解耦比较好,一股脑的做厚中台,又会陷入耦合的噩梦。

Don't Repeat Yourself在大部分时候是正确的,但是复用的代价就是会引入耦合。正如Neal Ford在《Fundamentals of Software Architecture》一书中所说:“When an architect designs a system that favors reuse, they also favor coupling”。特别是在人员众多的大型系统中,**耦合的代价往往要比duplication的代价大的多**,天下没有免费的午餐,因此,如果共性不够大,问题域变化多,抽象不稳定。我宁愿用少量的duplication解耦,也不愿意陷入耦合的噩梦。
Don't Repeat Yourself在大部分时候是正确的,但是复用的代价就是会引入耦合,DRY 的函数会被大量的地方引用,导致其内部逻辑需要考虑各种情况,逻辑及其复杂,修改风险也极高。正如Neal Ford在《Fundamentals of Software Architecture》一书中所说:“When an architect designs a system that favors reuse, they also favor coupling”。特别是在人员众多的大型系统中,**耦合的代价往往要比duplication的代价大的多**,天下没有免费的午餐,因此,如果共性不够大,问题域变化多,抽象不稳定。我宁愿用少量的duplication解耦,也不愿意陷入耦合的噩梦。

[代码复用:DDD视角下的平衡艺术](https://mp.weixin.qq.com/s/5gIBJByRZfNPbh6yjAvj9w)在 《架构整洁之道》中提到,**“拖延决策” 也是优秀架构设计的特点之一**。因为随着软件的开发和业务的迭代,我们掌握的信息越来越多,后期做出的决策肯定比项目早期的草率决定要靠谱。《复杂软件设计之道》中吐槽道:架构师们总是在只掌握 20% 信息的情况下,就已经做出了 80% 的决策。通过纯粹设计原则的角度是看不出来软件设计决策是否正确的,必须从更高的视角出发才行。
1. 成本角度谈复用,文件系统对上层提供了非常简单的文件模型,数据库对应用也提供了非常好理解的表模型。而他们的实现非常复杂,需要考虑并发,数据完整性,事务等一系列问题。相比理解他们的实现,学习模型和接口成本几乎可以忽略不计。上面的案例有共同的特点,**即模块的接口很简单,但是提供的功能却是深刻的。这个时候复用就非常的合算**
这刚好就是 John Ousterhout 教授(Raft 的发明者)在其著作 《软件设计哲学》中提到 深模块 的概念。深模块在简单的接口后隐藏了许多功能。深模块代表很好的抽象,其内部复杂性只有很小一部分对其用户可见。浅模块的接口复杂度和实现复杂度接近,与其去了解模块的接口,开发人员还不如自己重新实现一遍。
2. 效益角度谈复用。Supercell 游戏公司将之前的爆款中备受玩家欢迎的风格,素材和程序逻辑沉淀下来,通过复用之前积累,可以快速产出新的爆款。上面的两个例子刚好就代表了两种提升产品核心竞争力的逻辑:复用之前具有竞争力的技术模块,让过去的成功经验助力未来的产品成功;给用户提供一致的体验,考虑用户的使用习惯,降低学习成本。复用不同模块能取得效果的程度也是不同的,复用什么样模块更有可能获得上述两点效果呢?DDD 中对子域的划分或许能够给我们答案,
1. 核心子域,能够给公司带来核心竞争力的领域模块,拥有很高的复杂度和差异化价值,比如滴滴的司机调度算法,支付宝的交易系统,钉钉的 IM 系统等等,属于该子域的模块应该尽可能地复用, 将其竞争力也注入到其他产品,甚至投入精兵强将,提升其可扩展性,进一步拉开和竞争对手差距。
2. 支持子域,用来支撑核心子域,但是不能带来竞争力。因为不能带来核心竞争力,不如各个业务根据自己需求,使用脚手架快速搭建,定制起来还更加方便
3. 通用子域,通用的业务或者技术问题领域, 比较复杂, 却不能给企业带来核心竞争力。好在一般有现成的解决方案,可以直接采购。比如财务系统,可以直接采购用友,金蝶;分库分表,消息队列可以直接使用开源软件,或者购买云上解决方案,尽可能复用,但是复用的目的与核心子域不同,主要是为了降低研发成本。

### 抽象的产出

数据模型通常分为三个层次:概念模型、逻辑模型和物理模型。
![](/public/upload/architecture/abstract_data.jpg)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ keywords: system design principle

## 复用

软件工程设计,上至远古大神阿兰·图灵、冯·诺依曼,下至20世纪互联网高度发达的今天,诞生的各种框架与工具,本质上只在朝着2个方向在发展:可复用、可扩展,一对天然矛盾而又长期共存的2个方向。纯技术团队解决的问题是确定性的,如何减少RT、如何提高吞吐,这一整年甚至好几年都只有这一个命题。但业务团队不一样,今天要打渗透,明天要做拉新,后天又有新打法出来。并且也没人能保证这样做了业务就一定会成功,业务是极具不确定性的。业务团队想用一个简单的if解决这个业务场景的变化,中台团队则倾向于再抽象一层。而抽象性与其本身的表达能力是向左的,抽象层次越高,表达能力越低,越难以理解。中台的抽象往往不是针对某一单一的业务场景,而是适配所有已接入的业务系统以及面向未来可能的扩展性。这会导致任何一处的改动,产生的影响范围都具有极高的认知成本。随着人员的不断更迭,现有系统的维护者,可能不认识系统里90%的代码。
[架构设计的悖论,复用是美好的还是邪恶的](https://mp.weixin.qq.com/s/0jNNTZZfw24Vv85XdwK-tQ)软件工程设计,上至远古大神阿兰·图灵、冯·诺依曼,下至20世纪互联网高度发达的今天,诞生的各种框架与工具,本质上只在朝着2个方向在发展:可复用、可扩展,一对天然矛盾而又长期共存的2个方向。纯技术团队解决的问题是确定性的,如何减少RT、如何提高吞吐,这一整年甚至好几年都只有这一个命题。但业务团队不一样,今天要打渗透,明天要做拉新,后天又有新打法出来。并且也没人能保证这样做了业务就一定会成功,业务是极具不确定性的。业务团队想用一个简单的if解决这个业务场景的变化,中台团队则倾向于再抽象一层。而抽象性与其本身的表达能力是向左的,抽象层次越高,表达能力越低,越难以理解。中台的抽象往往不是针对某一单一的业务场景,而是适配所有已接入的业务系统以及面向未来可能的扩展性。这会导致任何一处的改动,产生的影响范围都具有极高的认知成本。随着人员的不断更迭,现有系统的维护者,可能不认识系统里90%的代码。

复用本身最直接的目的就是降低成本,同样的事只用干一次,那软件工程的成本到底在哪里?我们平常评估需求工时,到底是3人日还是还是3.5人日,其实很难有一个准确的测算。但我们依然给出了一个相对“确定”的工时人天,囊括从需求分析、方案设计、编码开发、协调测试、发布上线等各个流程。无论准确与否,我们也确实在按照这种模式运作。3人日或5人日,整体差异不会太大。**但软件的成本,真的就是等同于开发成本吗?**软件工程成本在于维护。一行代码当时写下去只花了1分钟,但只要它还在线上运行,我们就需要投入无形的维护成本。你很难把这篇雷区的雷都排光,甚至你都不知道到底还有哪些是雷区。我们总是嘲笑有些代码写得像面条代码 Spaghetti code ,缺乏设计缺乏美感,但当你被线上的问题搞得晕头转向时,面条代码看似不够优雅,但它对系统的损害远比那些错误的抽象,低得多得多。你可以很清楚的知道改动这行代码,带来的变化是什么。但复用的代码正好与之相反,它拥有高度的复用性与收敛性,一行代码的调整,就可以把你想改的那8个场景都改过来,当然,还有你没想到的另外20个场景,它也改了。

Expand Down
Loading

0 comments on commit 0838318

Please sign in to comment.