ViT(Vision Transformer)论文阅读
1. ViT简介
ViT是2020年的一篇paper,目前(2023年2月)在google引用超11000次,CV图像领域中被广泛使用。在ViT出来之前,Transformer架构已经在NLP领域大显身手,在CV领域还是用的CNN,通过ViT这篇paper在CV中正式引入Transormer,且效果不错。
ViT是2020年的一篇paper,目前(2023年2月)在google引用超11000次,CV图像领域中被广泛使用。在ViT出来之前,Transformer架构已经在NLP领域大显身手,在CV领域还是用的CNN,通过ViT这篇paper在CV中正式引入Transormer,且效果不错。
在pytorch DDP数据并行时会对数据集进行切分,每个rank节点只处理部分数据。使用DistributedSampler来会把dataset数据集采样为一个子数据集。定义如下:
1 | torch.utils.data.distributed.DistributedSampler(dataset, num_replicas=None, rank=None, shuffle=True, seed=0, drop_last=False) |
world_size
rank
DistributedSampler
时,torch.util.data.Dataloader创建时的shuffle参数,相当于把随机的功能交给了DistributedSampler
。默认为Truenum_replicas
整除;为False的话Sampler为增加额外的indices;默认为Falseposition embedding
,
embedding的方法采用了sinine和cosine来进行。I am a robot
进行编码:RMSNorm论文中对LayerNorm的公式做了改造。在原有LayerNorm中借助了每个layer统计的mean和variance对参数进行了调整,但RMSNorm认为re-centering invariance property
是不必要的,只用保留re-scaling invariance property
。
LayerNorm的计算如下:
改造后的RMSNorm如下:
RMS中去除了mean
的统计值的使用,只使用root mean square(RMS)
进行归一化。
LLaMA 训练了从7B到65B不同参数量的模型,从Hoffmann的论文【Training compute-optimal large languag】中证明了在有限计算代价的情况下(给定总的FLOPs大小),表现最好的不是参数量最大的模型,而是在更多数据上训练的稍小的模型。
LLaMA实现了两个目标: 1. LLaMA-13B跟GPT-3相比, 参数量小了10倍,但效果更好;LLaMA-65B比Chinchilla-70B和PaLM-540B更好。 2. 只依赖公开的开源数据集也可以达到最好的SOTA效果。
SentencePiece
是用于NLP训练中对句子进行token化的工具,跟语言无关,
SentencePiece中包含了byte-pairencoding(BPE)
和unigram language model
两种切分subword的算法。
SentencePiece
中包含有四个部分:
协程(coroutine) 的概念根据Donald
Knuth的说法早在1958年就由Melvin Conway提出了,对应wikipedia的定义如下:
> Coroutines are computer program components that generalize
subroutines for non-preemptive multitasking, by allowing execution to be
suspended and resumed. Coroutines are well-suited for implementing
familiar program components such as cooperative tasks, exceptions, event
loops, iterators, infinite lists and pipes.
这里_子例程(subroutine)是一个概括性的术语,子例程可以是整个程序中的一个代码区块,当它被主程序调用的时候就会进入运行。例如函数就是子例程中的一种。
1
c = max(a,b);
图中左边是子例程的执行过程,右边是协程的执行过程,可以很明显的看出来执行过程中的区别。
*
先说左边,子例程可以看成是某个函数,子例程的执行过程中通常是嵌套顺序执行的过程,子例程1和子例程2的关系(调用和被调用)不是完全平等的,子例程1能调用子例程2,但子例程2不能反过来调用子例程1。
*
再说右边,协程1和协程2的关系是完全对等的,协程1执行过程中可以中断挂起执行另外一个协程2,反之也是可以的,直到最终两个协程都执行完以后再返回回到主程序中,即协程1和协程2相互协作完成了整个任务。
接下来举一个协程实现生产者和消费者的例子: 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15var q := new queue
coroutine produce
loop
while q is not full
create some new items
add the items to q
yield to consume
coroutine consume
loop
while q is not empty
remove some items from q
use the items
yield to produce
通常会提到 进程是资源分配的最小单位,线程是CPU调度的最小单位, 一个进程里可以有多个线程 ,这里直接画了个图来说明三者关系。
Python最初的版本里是包含了yield/send关键字,通过yield/send可以方便的实现一个协程的例子,这里还是以为生产者和消费者为例,具体实现方式如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33#!/usr/bin/env python
# -*- coding:utf-8 -*-
def consumer():
"""consumer定义"""
ret = ''
while True:
# 挂起consumer,恢复producer, ret会传回给producer
item_id = yield ret
if not item_id:
return
print('consume item_id:{}'.format(item_id))
ret = 'success'
def producer(consumer):
"""producer定义"""
# send一个None可以看成是启动consumer
# consumer这里包含了yield关键字相当于是一个generator
consumer.send(None)
item_id = 0
# 生产的item的总数
item_total_count = 3
while item_id < item_total_count:
item_id = item_id + 1
print('produce item:{}'.format(item_id))
# 挂起producer,恢复consumer, item_id会传回给consumer
ret = c.send(item_id)
print('consumer return:{}'.format(ret))
consumer.close()
if __name__ == "__main__":
c = consumer()
producer(c)
结果:
1
2
3
4
5
6
7
8
9produce item:1
consume item_id:1
consumer return:success
produce item:2
consume item_id:2
consumer return:success
produce item:3
consume item_id:3
consumer return:success
python 3.5版本开始引入了async/await关键字给了我们另外一种实现的方法,还是以为生产者和消费者为例,具体实现方式如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38#!/usr/bin/env python
# -*- coding:utf-8 -*-
import asyncio
import random
async def producer(queue, item_total_count):
"""producer 定义"""
for item_id in range(0, item_total_count):
# 生产一个新的item
print('produce item_id:{}'.format(item_id))
# 模拟IO操作, 挂起producer,恢复consumer
#await asyncio.sleep(random.random())
# 把item放入队列, 挂起producer,恢复consumer
await queue.put(item_id)
# 放入一个None到队列表示生产全部结束
await queue.put(None)
async def consumer(queue):
"""consumer 定义"""
while True:
# 等待从队列中获得一个新的item, 等待过程中会挂起consumer,恢复producer
item_id = await queue.get()
if item_id is None:
# 表示生产者都生产完了,没有待消费的请求了
break
print('consume item_id:{}'.format(item_id))
# 模拟IO操作, 挂起consumer,恢复producer
#await asyncio.sleep(random.random())
if __name__ == "__main__":
loop = asyncio.get_event_loop()
queue = asyncio.Queue(loop=loop)
producer_coro = producer(queue, 3)
consumer_coro = consumer(queue)
loop.run_until_complete(asyncio.gather(producer_coro, consumer_coro))
loop.close()
结果:
1
2
3
4
5
6produce item_id:0
produce item_id:1
produce item_id:2
consume item_id:0
consume item_id:1
consume item_id:2
本文主要根据A Berkeley View of Systems Challenges for AI进行了汇总,以及一些材料上的收集,论文中对未来AI系统以及研究的方向做了非常广泛的讨论。
Mission-critical的含义就是在AI在生活中起到的任务越来越重要,例如自动驾驶、机器人辅助医疗、智能家居等,这些AI的应用非常关键以至于可以影响到人的生死。AI在不断变化的环境中进行部署,必须不断的适应周围环境并学习新的知识。比如自动驾驶需要在处理之前没有遇到过的危险场景中,观察学习其他车辆如何行动从而恰当的处理。另外,关键任务AI也要能处理各种噪音数据以及恶意的攻击。挑战: 不断地与周围动态环境进行互动学习,从而做出及时、鲁棒、安全的决策。
基于用户的个性化决策要考虑到用户自己的习惯与偏好,例如虚拟助理的语音可以模仿用户的口音,自动驾驶可以学习用户的驾驶习惯等。这样的个性化应用需要收集到大量敏感的用户信息,这些信息的滥用可能会造成用户的经济以及精神上的伤害。
挑战: 设计AI系统必须支持个性化的应用,但是这些个性化应用不能损害用户的利益,不能泄露用户的隐私。
许多公司在利用第三方的数据去提升他们自己的AI服务能力,例如医院之间的数据共享可以更好的组织传染病的爆发、金融机构之间的数据共享可以更好的进行反欺诈检测。这种应用的扩展使得从一家公司进行数据收集、处理,变成了一个公司使用多方的数据资源来进行决策。
挑战: 设计AI系统需要支持多源数据的训练,这些数据都来自不同的公司或者组织,并在训练过程中保证各家原始数据的机密性,在保证数据机密性的基础上甚至可以提供AI的能力给它的竞争对手。
海量数据的存储和处理是近些年AI系统成功的关键,由于下列两个原因使得后续的数据处理能力很难跟上数据扩张的速度。 * 数据增长是指数级的。IoE设备在2018年采集的数据大小是400ZB,是2015年的50倍,到2025年,需要有3到4个数量级的增长才能处理人类的基因组数据,需要要求接下来的每年计算能力都至少要翻倍。 * 硬件的发展到了瓶颈。需要10年DRAMs和磁盘大小才能翻倍,需要20年CPU的性能才能翻倍。
挑战: 发展领域(domain-specific)的架构和软件系统去满足后摩尔时代性能要求,例如定制的人工智能芯片、高效处理的数据的边缘云计算(edge-cloud)以及数据的采集与抽样方法的发展。
机器学习中一个通常的预估任务是为了预估一个函数$ y: ^n \(, 预估过程中使用一组具有实数值的特征向量\) ^n $ 去预测目标 $ \((在回归预估中\) = $, 在分类预估中 $ = +, - \(). 高维稀疏场景下向量\) \(中大部分元素\) x_i \(的值都是0, 我们定义\) m(x) $为向量 $ $ 中非零元素的个数,$ _{D} \(为所有向量\) \(的\) m(x) \(值的平均值。实际中(例如推荐系统)经常会碰到超大规模稀疏的情况(\) _{D} n \()。 下面举一个例子,假设我们有一个电影的推荐系统,系统中每一条记录表示一个用户(\) u U \()在某个时间点(\) t \(}对一个电影(item)(\) i I \()的评分(\) r , 2, 3, 4, 5 \(). 用户\) U $和电影item $ I $的示例如下: > $ U = Alice(A), Bob(B), Charlie(C), $ > $ I = Titanic (TI), Notting Hill (NH), Star Wars (SW), Star Trek (ST), $ 系统可观测到的用户数据为$ S $示例如下: > $ S = (A, TI, 2010-1, 5), (A, NH, 2010-2, 3), (A, SW, 2010-4, 1), $ > $ (B, SW, 2009-5, 4), (B, ST, 2009-8, 5), (C, TI, 2009-9, 1), (C, SW, 2009-12, 5) $
如下图所示:
图中展示了如何从观测到的用户数据$ S \(去创建训练所需要的特征向量的过程,图中蓝色框住的地方表示系统中的用户,每一条记录都表示一个用户的一个行为对\) (u, i, t, r) S \(,上面\) S \(中的第一条记录\) (A, TI, 2010-1, 5) \(,Alice简写为A,在蓝框中\) (x_{A}^{(1)} = 1) \(,红色框表示看的电影的item,这里\) x_{TI}^{(1)} = 1 $. 黄色框中表示用户对历史看过的所有的电影的历史评分,这里历史评分的取值经过了归一化操作,归一化以后的值的和为1。绿色表示从09年1月开始计算经历的月份数。深红色的框表示用户上次评价的电影名, 评价过的电影对应的位置设置成1,未评价的设置成0。