最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

首個基于Transformer的分割檢測+視覺大模型視頻課程(23年新課+源碼+課件)

2023-11-27 11:00 作者:bili_48219728313  | 我要投稿

學(xué)習(xí)資料地址1:https://pan.baidu.com/s/1mpYHRFi68lzNuA8neYI15w 提取碼:pwjd?

學(xué)習(xí)資料地址2:https://share.weiyun.com/tnVNHGMD 密碼:3fj7iy


自動駕駛是高安全型應(yīng)用,需要高性能和高可靠的深度學(xué)習(xí)模型,Vision Transformer是理想的選摔。現(xiàn)在主流的自動駕駛感知算法基本都使用了Vision Transformer相關(guān)技術(shù),比如分割、2D/3D檢測,以及最近大火的大模型 (如SAM),Vision Transformer在自動駕駛領(lǐng)域的落地方面遍地開花。5一方面,在自動駕駛或圖像處理相關(guān)算法崗位的面試題中,Vision Transformer是必考題,需要對其理論知識有深入理解,并且在項目中真實的使用過相關(guān)技術(shù)。


Transformer出自于Google于2017年發(fā)表的論文《Attention is all you need》,最開始是用于機器翻譯,并且取得了非常好的效果。但是自提出以來,Transformer不僅僅在NLP領(lǐng)域大放異彩,并且在CV、RS等領(lǐng)域也取得了非常不錯的表現(xiàn)。尤其是2020年,絕對稱得上是Transformer的元年,比如在CV領(lǐng)域,基于Transformer的模型橫掃各大榜單,完爆基于CNN的模型。為什么Transformer模型表現(xiàn)如此優(yōu)異?它的原理是什么?它成功的關(guān)鍵又包含哪些?本文將簡要地回答一下這些問題。


我們知道Transformer模型最初是用于機器翻譯的,機器翻譯應(yīng)用的輸入是某種語言的一個句子,輸出是另外一種語言的句子。

var i *int = nil

fmt.Println("i.size:", unsafe.Sizeof(i)) //8


var i8 *int8 = nil

fmt.Println("i8.size:", unsafe.Sizeof(i8)) //8


var s *string = nil

fmt.Println("s.size:", unsafe.Sizeof(s)) //8


var ps *struct{} = nil

fmt.Println("ps.size:", unsafe.Sizeof(ps)) //8


var si []int = nil

var si1 []int = nil

fmt.Println("si.size:", unsafe.Sizeof(si)) //24


var ii interface{} = nil

fmt.Println("ii.size:", unsafe.Sizeof(ii)) //16

我們以生成我,愛,機器,學(xué)習(xí),翻譯成<bos>,i,love,machine,learning,<eos>這個例子做生成過程來解釋。

訓(xùn)練:


把“我/愛/機器/學(xué)習(xí)”embedding后輸入到encoder里去,最后一層的encoder最終輸出的outputs [10, 512](假設(shè)我們采用的embedding長度為512,而且batch size = 1),此outputs 乘以新的參數(shù)矩陣,可以作為decoder里每一層用到的K和V;

將<bos>作為decoder的初始輸入,將decoder的最大概率輸出詞向量A1和‘i’做cross entropy(交叉熵)計算error。

將<bos>,“i” 作為decoder的輸入,將decoder的最大概率輸出詞 A2 和‘love’做cross entropy計算error。

將<bos>,“i”,“l(fā)ove” 作為decoder的輸入,將decoder的最大概率輸出詞A3和’machine’ 做cross entropy計算error。

將<bos>,“i”,"love ",“machine” 作為decoder的輸入,將decoder最大概率輸出詞A4和‘learning’做cross entropy計算error。

將<bos>,“i”,"love ",“machine”,“l(fā)earning” 作為decoder的輸入,將decoder最大概率輸出詞A5和終止符做cross entropy計算error。

那么并行的時候是怎么做的呢,我們會有一個mask矩陣在這叫seq mask,因為他起到的作用是在decoder編碼我們的target seq的時候?qū)γ恳粋€詞的生成遮蓋它之后的詞的信息。

func main() {

s := []string{"a", "b", "c"}

fmt.Println("s:origin", s)

changes1(s)

fmt.Println("s:f1", s)


changes2(s)

fmt.Println("s:f2", s)


changes3(s)

fmt.Println("s:f3", s)

}


func changes1(s []string) {

var tmp = []string{"x", "y", "z"}

s = tmp

}


func changes2(s []string) {

// item只是一個副本,不能改變s中元素的值

for i, item := range s {

item = "d"

fmt.Printf("item=%s;s[%d]=%s", item, i, s[i])

}

}


func changes3(s []string) {

for i := range s {

s[i] = "d"

}

}


首先我們需要為每個輸入向量(也就是詞向量)創(chuàng)建3個向量,分別叫做Query、Key、Value。那么如何創(chuàng)建呢?我們可以對輸入詞向量分別乘上3個矩陣來得到Q、K、V向量,這3個矩陣的參數(shù)在訓(xùn)練的過程是可以訓(xùn)練的。注意Q、K、V向量的維度是一樣的,但是它們的維度可以比輸入詞向量小一點,比如設(shè)置成64,其實這步也不是必要的,這樣設(shè)置主要是為了與后面的Mulit-head注意力機制保持一致(當(dāng)使用8頭注意力時,單頭所處理的詞向量維度為512/8=64,此時Q、K、V向量與輸入詞向量就一致了)。我們假設(shè)輸入序列為英文的"Thinking Machines"

想要深度理解Attention機制,就需要了解一下它產(chǎn)生的背景、在哪類問題下產(chǎn)生,以及最初是為了解決什么問題而產(chǎn)生。


首先回顧一下機器翻譯領(lǐng)域的模型演進歷史:


機器翻譯是從RNN開始跨入神經(jīng)網(wǎng)絡(luò)機器翻譯時代的,幾個比較重要的階段分別是: Simple RNN, Contextualize RNN,Contextualized RNN with attention, Transformer(2017),下面來一一介紹。


「Simple RNN」 :這個encoder-decoder模型結(jié)構(gòu)中,encoder將整個源端序列(不論長度)壓縮成一個向量(encoder output),源端信息和decoder之間唯一的聯(lián)系只是: encoder output會作為decoder的initial states的輸入。這樣帶來一個顯而易見的問題就是,隨著decoder長度的增加,encoder output的信息會衰減。

func main(){

var c = make(chan int)

fmt.Printf("c.pointer=%p\n", c) //c.pointer=0xc000022180

go func() {

c <- 1

addChannel(c)

close(c)

}()


for item := range c {

//item: 1

//item: 2

fmt.Println("item:", item)

}

}


func addChannel(done chan int) {

done <- 2

fmt.Printf("done.pointer=%p\n", done) //done.pointer=0xc000022180

}

在測試模型的時候,Test:decoder沒有l(wèi)abel,采用自回歸一個詞一個詞的輸出,要翻譯的中文正常從encoder并行輸入(和訓(xùn)練的時候一樣)得到每個單詞的embedding,然后decoder第一次先輸入bos再此表中的id,得到翻譯的第一個單詞,然后自回歸,如此循環(huán)直到預(yù)測達到eos停止標記

type visit struct {

a1? unsafe.Pointer

a2? unsafe.Pointer

typ Type

}


func deepValueEqual(v1, v2 Value, visited map[visit]bool) bool {

if !v1.IsValid() || !v2.IsValid() {

return v1.IsValid() == v2.IsValid()

}

if v1.Type() != v2.Type() {

return false

}


// We want to avoid putting more in the visited map than we need to.

// For any possible reference cycle that might be encountered,

// hard(v1, v2) needs to return true for at least one of the types in the cycle,

// and it's safe and valid to get Value's internal pointer.

hard := func(v1, v2 Value) bool {

switch v1.Kind() {

case Pointer:

if v1.typ.ptrdata == 0 {

// not-in-heap pointers can't be cyclic.

// At least, all of our current uses of runtime/internal/sys.NotInHeap

// have that property. The runtime ones aren't cyclic (and we don't use

// DeepEqual on them anyway), and the cgo-generated ones are

// all empty structs.

return false

}

fallthrough

case Map, Slice, Interface:

// Nil pointers cannot be cyclic. Avoid putting them in the visited map.

return !v1.IsNil() && !v2.IsNil()

}

return false

}


if hard(v1, v2) {

// For a Pointer or Map value, we need to check flagIndir,

// which we do by calling the pointer method.

// For Slice or Interface, flagIndir is always set,

// and using v.ptr suffices.

ptrval := func(v Value) unsafe.Pointer {

switch v.Kind() {

case Pointer, Map:

return v.pointer()

default:

return v.ptr

}

}

addr1 := ptrval(v1)

addr2 := ptrval(v2)

if uintptr(addr1) > uintptr(addr2) {

// Canonicalize order to reduce number of entries in visited.

// Assumes non-moving garbage collector.

addr1, addr2 = addr2, addr1

}


// Short circuit if references are already seen.

typ := v1.Type()

v := visit{addr1, addr2, typ}

if visited[v] {

return true

}


// Remember for later.

visited[v] = true

}


switch v1.Kind() {

case Array:

for i := 0; i < v1.Len(); i++ {

if !deepValueEqual(v1.Index(i), v2.Index(i), visited) {

return false

}

}

return true

case Slice:

if v1.IsNil() != v2.IsNil() {

return false

}

if v1.Len() != v2.Len() {

return false

}

if v1.UnsafePointer() == v2.UnsafePointer() {

return true

}

// Special case for []byte, which is common.

if v1.Type().Elem().Kind() == Uint8 {

return bytealg.Equal(v1.Bytes(), v2.Bytes())

}

for i := 0; i < v1.Len(); i++ {

if !deepValueEqual(v1.Index(i), v2.Index(i), visited) {

return false

}

}

return true

case Interface:

if v1.IsNil() || v2.IsNil() {

return v1.IsNil() == v2.IsNil()

}

return deepValueEqual(v1.Elem(), v2.Elem(), visited)

case Pointer:

if v1.UnsafePointer() == v2.UnsafePointer() {

return true

}

return deepValueEqual(v1.Elem(), v2.Elem(), visited)

case Struct:

for i, n := 0, v1.NumField(); i < n; i++ {

if !deepValueEqual(v1.Field(i), v2.Field(i), visited) {

return false

}

}

return true

case Map:

if v1.IsNil() != v2.IsNil() {

return false

}

if v1.Len() != v2.Len() {

return false

}

if v1.UnsafePointer() == v2.UnsafePointer() {

return true

}

for _, k := range v1.MapKeys() {

val1 := v1.MapIndex(k)

val2 := v2.MapIndex(k)

if !val1.IsValid() || !val2.IsValid() || !deepValueEqual(val1, val2, visited) {

return false

}

}

return true

case Func:

if v1.IsNil() && v2.IsNil() {

return true

}

// Can't do better than this:

return false

case Int, Int8, Int16, Int32, Int64:

return v1.Int() == v2.Int()

case Uint, Uint8, Uint16, Uint32, Uint64, Uintptr:

return v1.Uint() == v2.Uint()

case String:

return v1.String() == v2.String()

case Bool:

return v1.Bool() == v2.Bool()

case Float32, Float64:

return v1.Float() == v2.Float()

case Complex64, Complex128:

return v1.Complex() == v2.Complex()

default:

// Normal equality suffices

return valueInterface(v1, false) == valueInterface(v2, false)

}

}

這便是encoder的整體計算流程圖了,Transformer模型中堆疊了多個這樣的encoder,無非就是輸出連接輸入罷了,常規(guī)操作。

最后再附上一個Transformer的代碼實現(xiàn),讀者有興趣可以跟著自己復(fù)現(xiàn)一下Transformer模型的代碼。

? ?package main


? ?import (

? ? ? ?"log"

? ? ? ?"sync"

? ?)


? ?func init() {

? ? ? ?log.SetFlags(log.Lshortfile)

? ?}

? ?func main() {

? ? ? ?lock := sync.Mutex{}


? ? ? ?//Go 1.18 新增,是一種非阻塞模式的取鎖操作。當(dāng)調(diào)用 TryLock() 時,

? ? ? ?//該函數(shù)僅簡單地返回 true 或者 false,代表是否加鎖成功

? ? ? ?//在某些情況下,如果我們希望在獲取鎖失敗時,并不想停止執(zhí)行,

? ? ? ?//而是可以進入其他的邏輯就可以使用TryLock()

? ? ? ?log.Println("TryLock:", lock.TryLock())

? ? ? ?//已經(jīng)通過TryLock()加鎖,不能再次加鎖

? ? ? ?lock.Lock()


? ?}


首個基于Transformer的分割檢測+視覺大模型視頻課程(23年新課+源碼+課件)的評論 (共 條)

分享到微博請遵守國家法律
十堰市| 泰来县| 樟树市| 达尔| 沁源县| 建水县| 恩施市| 揭西县| 宜章县| 象州县| 夹江县| 罗平县| 射洪县| 三门峡市| 鄄城县| 沭阳县| 石台县| 婺源县| 东明县| 桓仁| 太仓市| 延边| 鄂伦春自治旗| 太康县| 克东县| 桂平市| 凤台县| 花莲市| 毕节市| 上杭县| 彩票| 鹿邑县| 南雄市| 临漳县| 邵阳县| 朝阳区| 招远市| 沙雅县| 来安县| 沾益县| 甘洛县|