springboot_自動配置原理

目錄

  • 1.1 @SpringBootApplication
  • 2.1 @EnableAutoConfiguration
    • 2.1.1 @AutoConfigurationPackage
    • 2.1.2 @Import({Registrar.class})
  • 3.1 以HttpEncodingAutoConfiguration為例

springboot啥都不難,總所周知spring全家桶系列難就難在理解源碼。。。。。。。

今天結合網上資料,自己總結了一下springboot的自動配置原理。

我現在使用的springboot版本為2.3.1.不同版本的springboot在源碼上有差別!但大體一致。

管他三七二十一先打個斷點再說:

1.1 @SpringBootApplication

這個註解點進去我們可以看到:

這裏面主要關注兩個東西:

  • @SpringBootConfiguration
  • @EnableAutoConfiguration
    第一個註解點進去:

    可以看到這個@SpringBootConfiguration本質就是一個@Configuration,標註在某個類上,表示這是一個Spring Boot的配置類。
    第二個註解@EnableAutoConfiguration: 開啟自動配置類,SpringBoot的精華所在。(最重要的就是這個註解)

2.1 @EnableAutoConfiguration

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import({AutoConfigurationImportSelector.class})
public @interface EnableAutoConfiguration {
    String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";

    Class<?>[] exclude() default {};

    String[] excludeName() default {};
}

兩個比較重要的註解:

  • @AutoConfigurationPackage:自動配置包。
  • @Import({AutoConfigurationImportSelector.class}):導入自動配置的組件。

2.1.1 @AutoConfigurationPackage

點進去瞅瞅:

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import({Registrar.class})
public @interface AutoConfigurationPackage {
    String[] basePackages() default {};

    Class<?>[] basePackageClasses() default {};
}

發現這裡有導入Regitstrar類:

static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {
        Registrar() {
        }

        public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
            AutoConfigurationPackages.register(registry, (String[])(new AutoConfigurationPackages.PackageImports(metadata)).getPackageNames().toArray(new String[0]));
        }

        public Set<Object> determineImports(AnnotationMetadata metadata) {
            return Collections.singleton(new AutoConfigurationPackages.PackageImports(metadata));
        }
    }

new PackageImport(metadata).getPackageName(),它其實返回了當前主程序類的 **同級以及子級 ** 的包組件。

什麼意思呢?

我們來看這樣一個目錄:

bean1和我們的springboot啟動類位於同一個包下,二bean2不是位於我們啟動類的同級目錄或者子級目錄,那麼我們啟動的時候bean2是不會被加載到的!所以你項目的一切需要加入容器的類必須放在啟動類的同級包下或者它的子級目錄中。

2.1.2 @Import({Registrar.class})

AutoConfigurationImportSelector有一個方法為:selectImports。

public String[] selectImports(AnnotationMetadata annotationMetadata) {
        if (!this.isEnabled(annotationMetadata)) {
            return NO_IMPORTS;
        } else {
            AutoConfigurationImportSelector.AutoConfigurationEntry autoConfigurationEntry = this.getAutoConfigurationEntry(annotationMetadata);
            return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
        }
    }

它首先回去檢查是否開啟了自動配置類,然後才回去加載註解數據 this.getAutoConfigurationEntry(annotationMetadata);
那麼這個annotationMetadata在哪兒?
來看下面一行代碼:

  protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
        List<String> configurations = SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.getBeanClassLoader());
        Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you are using a custom packaging, make sure that file is correct.");
        return configurations;
    }

SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.getBeanClassLoader());
再點進去我們會發現這一行代碼:
Enumeration urls = classLoader != null ? classLoader.getResources(“META-INF/spring.factories”) : ClassLoader.getSystemResources(“META-INF/spring.factories”);

它其實是去加載 public static final String FACTORIES_RESOURCE_LOCATION = “META-INF/spring.factories”;外部文件。這個外部文件,有很多自動配置的類。如下:

spring.factories文件由一組一組的key=value的形式,其中一個key是EnableAutoConfiguration類的全類名,而它的value是一個xxxxAutoConfiguration的類名的列表,這些類名以逗號分隔。
springboot項目啟動時,@SpringBootApplication用在啟動類在SpringApplication.run(…)的內部就會執行selectImports()方法,找到所有JavaConfig自動配置類的全限定名對應的class,然後將所有自動配置類加載到Spring容器中。

3.1 以HttpEncodingAutoConfiguration為例

@Configuration(
    proxyBeanMethods = false
)    //表示是一個配置類,可以給容器中添加組件
@EnableConfigurationProperties({ServerProperties.class})// 啟用ConfigurationProperties功能
@ConditionalOnWebApplication(
    type = Type.SERVLET
)
@ConditionalOnClass({CharacterEncodingFilter.class})
@ConditionalOnProperty(
    prefix = "server.servlet.encoding",
    value = {"enabled"},
    matchIfMissing = true
)

@EnableConfigurationProperties({ServerProperties.class})// 啟用ConfigurationProperties功能
ServerProperties.class:

@ConfigurationProperties(
    prefix = "server",
    ignoreUnknownFields = true
)

@ConditionalOnWebApplication :spring底層@Conditional註解,根據不同的條件進行判斷,如果滿足條件整個配置類才會生效。

總結:
1.springboot會自動加載大量的自動配置類。
2.只要我們要用的組件有,我們就不需要再去配置
3.給容器添加組件的時候。會從properties類中獲取某些屬性。我們就可以在配置文件中指定這些屬性。
xxxxxAutoConfiguration:自動配置類

給容器中添加屬性:
xxxxProperties:封裝配置文件中的相關屬性。

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

新北清潔公司,居家、辦公、裝潢細清專業服務

※別再煩惱如何寫文案,掌握八大原則!

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※超省錢租車方案

※教你寫出一流的銷售文案?

BMW 高階電動車 i3 與 i8 正式登陸

BMW Corp  21 日首度針對中國大陸消費者行銷純電動車「i3 」,讓當地剛剛萌芽的高階電動車市場競爭開始升級。   華爾街日報 22 日報導,i3 21 日在大陸正式開賣、定價約 73,000 美元。i3 是 BMW 在大陸第一款純電動車,電動車製造商特斯拉 (Tesla) 才剛在 4 月份將大陸第一台「Model S」電動車交給當地顧客。Model S 在大陸的定價約 121,000 美元。   BMW 雖然並未透露正式的銷售目標,但該公司中國分部執行長 Karsten Engel 曾在 4 月表示,BMW 希望 2014 年能在當地賣出 1,000 台左右的 i3 與 i8。BMW 目前已經在北京、上海、深圳以及瀋陽指定了 7 家經銷商。   特斯拉成長動能逐漸趨緩,得在亞洲(尤其是大陸)加把勁,才能達成 2014 年預設的銷售目標。現在 BMW 又來搶食大餅,特斯拉可得趕緊擬定對策了。  

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※為什麼 USB CONNECTOR 是電子產業重要的元件?

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※台北網頁設計公司全省服務真心推薦

※想知道最厲害的網頁設計公司"嚨底家"!

新北清潔公司,居家、辦公、裝潢細清專業服務

※推薦評價好的iphone維修中心

大陸代工給鴻海?特斯拉駁斥傳言

美國電動車廠特斯拉交貨能力大幅提升,出現逾 7 成的成長,面對會否將代工業務拉回大陸時,特斯拉卻傾向冷處理,甚至還主動發出官方回應,強調「目前沒有在大陸代工生產的計畫」,看來先前外界傳出鴻海要在中國替 Tesla 代工電動車的合作計畫,恐怕還要再等一等。   特斯拉 2013 年共交付 2 萬輛 Model S,2014 年有機會上看 3.5 萬輛,市場將特斯拉交貨能力大增原因指向生產線的擴展,特斯拉美國生產基地最近又新增了一條生產線,周產能達 1,000 輛。   除了在美擴充生產線,會否將代工產線拉回大陸,也成了市場關注焦點,但對此,特斯拉卻傾向冷處理,還特別發出官方回應,強調「特斯拉現所有在華銷售的車輛都是在美國生產,再進口到中國,目前沒有在大陸代工生產的計畫。」  

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理
【其他文章推薦】

USB CONNECTOR掌控什麼技術要點? 帶您認識其相關發展及效能

台北網頁設計公司這麼多該如何選擇?

※智慧手機時代的來臨,RWD網頁設計為架站首選

※評比南投搬家公司費用收費行情懶人包大公開

※幫你省時又省力,新北清潔一流服務好口碑

※回頭車貨運收費標準

重歐美輕亞洲 特斯拉第200個充電站投入使用

近日,特斯拉宣佈其第200個超級充電站已開放使用。這個超級充電站位於美國加州南部的奧克斯納德河流公園公務中心附近。特斯拉目前有57%的充電站位於美國。這些超級充電站可讓特斯拉電動汽車30分鐘充滿電。   特斯拉正不斷完善其充電網路,其向南有霍索恩(Hawthorne)和特甬牧場(Tejon Ranch)超級充電站,向北有索爾萬(Solvang)超級充電站,東部則有巴斯托(Barstow)超級充電站。他們表示明年其充電站網路將覆蓋美國98%的區域。   目前特斯拉已分別在北美、歐洲和亞洲建造了114座、66座、20座超級充電站。為了完善充電網路,特斯拉未來將在北美進一步縮小超級充電站間的間隙,並且將其將延伸至加拿大,而在歐洲,特斯拉將增大超級充電站密度和覆蓋國家。但是在亞洲,特斯拉的超級充電站建造計畫則顯得相對保守,如今在中國僅有7座。

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

南投搬家公司費用需注意的眉眉角角,別等搬了再說!

新北清潔公司,居家、辦公、裝潢細清專業服務

※教你寫出一流的銷售文案?

Tesla 第二產線將完工 預估產能跳增 3 倍

近 3 個月前,特斯拉一度為了建置第 2 條產線而短暫停工,現在有分析師指出,擴廠工程已接近完成,且推估新產線產能還將跳增逾 3 倍。   Global Equities Research 分析師 Trip Chowdhry 最近參訪完特斯拉廠房後指出,新產線運轉已沒有問題,預估每週可產出 3,000 輛電動車。   特斯拉曾在第二季財報上揭露,原有產線每週產能約 800 輛,Chowdhry 預測約莫再 4 至 6 週的時間,舊產線產出即可提升至 1,000 輛。另外,Chowdhry 還注意到工廠內仍有許多閒置空間,似乎是預留給特斯拉正在開發的新一代平價電動車 Model 3。   廠房設施重整約花了特斯拉 1 億美元,若不算超級電池工廠,這是該公司史上最大單筆投資計畫。第 2 條產線開始投產後,特斯拉將可以 2 條產線同時生產 Model S 轎車與 Model X 運動休旅車。

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※想知道最厲害的網頁設計公司"嚨底家"!

※幫你省時又省力,新北清潔一流服務好口碑

※別再煩惱如何寫文案,掌握八大原則!

中鋼參一腳 入股特斯拉馬達供應商富田

中鋼集團於上周正式入股美國電動車大廠特斯拉(Tesla)馬達獨家供應商富田電機,成為其最大股東後,中鋼董事長鄒若齊 10 月 1 日首度透露,中鋼已向特斯拉釋出善意,將全力協助富田提升生產能力,希望能夠達到即時供料的能力,確保三方的穩定供應鏈關係。   中鋼轉投資、位於中部的富田公司,現在是特斯拉唯一的馬達材料供應商。中鋼日前投資富田,就是考量這一層供料關係,進而希望能夠強化與特斯拉的合作。   鄒若齊說,富田是中鋼重要的電磁鋼片客戶,但以它目前的產能,一年配合特斯拉的需求,是有能力供應幾千輛電動車所需的馬達給特斯拉。但若要富田供應上萬輛所需的馬達,恐就有困難。因此中鋼投資富田,最大目的就是要協助提升它的生產能力,希望未來能夠做到即時供料給特斯拉的目標,以穩定特斯拉的信心。

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

新北清潔公司,居家、辦公、裝潢細清專業服務

※別再煩惱如何寫文案,掌握八大原則!

※教你寫出一流的銷售文案?

※超省錢租車方案

看好電動車!三星 LG 等韓企搶入功率半導體市場

看好物聯網、電動車及智慧裝置未來的發展潛力,南韓大型企業正在全力衝刺功率半導體 (power semiconductor)。南韓媒體 ETNews 2 日報導,LG 電子 (LG Electronics) 正在積極研發功率半導體科技,該公司副董事長 Ku Bon-jun  2014 年稍早就曾親自訪問日本某家半導體公司,並取得技術顧問服務。分析顯示,Ku 這趟行程應該是為了開發 LG 集團瞄準的下一個成長動能──電動車。   功率半導體不但對耗電量有直接影響,也關係到電動車的品質好壞。LG 電子最近收購了 IC 設計商 Silicon Works,也是為了同樣的目的。   三星電子 (Samsung Electronics) 也在持續關注功率半導體的研發部門。三星除了自行開發行動裝置與面板的電源管理 IC 外,還打算發展應用於電動車、可再生能源的相關裝置。三星已經成功在自家的通訊晶片「Exynos Modem 303」導入電源管理解決方案「封包追蹤 (envelope tracking)」技術。這種技術可即時依據頻率、耗電量分配電力,並x連結至基頻 IC、電源管理 IC 以及無線功率放大器 (PA)。

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

新北清潔公司,居家、辦公、裝潢細清專業服務

※別再煩惱如何寫文案,掌握八大原則!

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※超省錢租車方案

※教你寫出一流的銷售文案?

平整化底盤式樣GC8 強大的540ps馬力

這輛前期型的Impreza GC8鯊魚,是在英國的速霸陸改裝車群組中,獲得相當高評價的ZEN‏ Performerzen自家工廠賽車,沒有誇張的寬車體,也沒有將懸吊形式變更,在UK單圈計時賽事中依舊取得冠軍寶座,是一輛單純破紀錄所打造的賽車。

這輛車是由ZEN‏ Performerzen所打造,專門為了在UK單圈計時賽中破紀錄使用的純賽車,當初打造時的考量,就是僅有純粹的快而已。

心臟部分使用上EJ25的中缸作為基礎,使用上EJ25後期的鎢鋼曲軸,搭配上WISECO鍛造活塞與H斷面連桿,將排氣量設定在少見的2.3升化。黑豆(上半座)部分更換上了ZEN自家製的高角度凸輪軸與汽門套件,徹底強化高轉速區域的動力輸出。

中缸的部分採用EJ25的規格,ZEN打造時選擇了EJ25的鎢鋼曲軸,搭配WISECO鍛造活塞與H斷面連桿,將排氣量設定在相當少見的2300cc規格,並且搭配自家製的高角度凸輪軸與強化汽門系列產品,徹底強化高轉速時的性能出力。

透過自製的芭蕉將蓋瑞特的GT40R渦輪本體移動至水箱架後方,這具渦輪機的大小約是在HKS GT3540與HKS T04Z之間的大小,AUTRONIC SM4全取代賽車用可程式電腦的貫穿下,現狀已經可以輸出540ps的最大馬力。

在自製的排氣芭蕉最上的渦輪機部分,安裝上了蓋瑞特的GT40R渦輪機,出風量約是在HKS GT3540與HKS T04Z之間的大小,AUTRONIC SM4全取代賽車用可程式電腦的貫穿下,現狀已經可以輸出540ps的最大馬力。

避震器為ZEN自家在賽道磨練出的EXE-TC RS04 外掛氣瓶多way版本,由於GC8的車體重量並不重的關係,制動系統選擇上對向四活塞的STOPTECH卡鉗,搭配並不大的330mm浮動碟盤,輪胎則是大家相當熟悉的Toyo R888。

斯巴達式密密麻麻的防滾季充斥的車室。儀錶已經被多功能的AMI液晶儀錶取代,將所有車輛資訊整合其中,讓駕駛可以更容易了解目前車況,並且為了降低反光的影響,ZEN也順勢將中控台施以麂皮包覆,變速箱則是並未選擇重量較高的六速系列,而是少了許多機構的PPG五速序列式變速箱,在齒輪強度、換檔速度與重量三元素中取得完美平衡,由於是單圈式樣,EXEDY碳纖維離合器需要預熱的特性自然也不影響。

進氣岐管用上EJ20早期的產品,因為與引擎本體的口徑與位置上的差異,因此訂做這個專用的轉接墊片,透過加工再讓岐管內管徑更大,這也是很多歐洲跑拉力賽事鯊魚常見的改法。

冷卻系統是水與酒精採50比50的混合比例,透過岐管上向燃燒室內噴射,降低燃燒室的溫度,大幅防止爆震的產生,也就是常見的水噴射系統。

雖然外觀上的空力套件並沒有太多著墨,但底盤的部分則是做了相當完整的設定,從車頭下方開始一路到車尾全部都施以包覆,完成了平整化底盤的設定,當然其中要將零件塞到裡面是下了不少苦功。

很多愛GC的車主來說對於這種98前的中控台設計是情有獨鍾。為了預防反光的問題,ZEN包上了麂皮材質解決這情況,方向盤前方的AMI儀錶則是取代了原廠設定,並且將大量的車輛資訊整合在裡面。

密密麻麻的防滾架與車體施以焊接強化,並且與車身施以同色的塗裝烤漆。

看起來就像一台原廠的GC8鯊魚,但動力與底盤的提昇都已經是滿配了,雖然細節上沒有相當的精緻,但確實是擁有相當的水準。

新聞來源:https://www.carnews.com/article/info/628b596e-dbac-11ea-ad31-42010af00004/

【其他文章推薦】

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

新北清潔公司,居家、辦公、裝潢細清專業服務

※別再煩惱如何寫文案,掌握八大原則!

※教你寫出一流的銷售文案?

※超省錢租車方案

BERT的前世今生

Transformer

Transformer來自論文: All Attention Is You Need

別人的總結資源:

  1. 谷歌官方AI博客: Transformer: A Novel Neural Network Architecture for Language Understanding
  2. Attention機制詳解(二)——Self-Attention與Transformer谷歌軟件工程師
  3. 放棄幻想,全面擁抱Transformer:自然語言處理三大特徵抽取器(CNN/RNN/TF)比較中科院軟件所 · 自然語言處理 /搜索 10年工作經驗的博士(阿里,微博);
  4. Calvo的博客:Dissecting BERT Part 1: The Encoder,儘管說是解析Bert,但是因為Bert的Encoder就是Transformer,所以其實它是在解析Transformer,裏面舉的例子很好;
  5. 再然後可以進階一下,參考哈佛大學NLP研究組寫的“The Annotated Transformer. ”,代碼原理雙管齊下,講得也很清楚。
  6. 《Attention is All You Need》淺讀(簡介+代碼)這個總結的角度也很棒。

A High-Level Look

可以將輸入的語言序列轉換成另外一種序列,比如下圖的神經機器翻譯:

Transformer模型由編碼器-解碼器組合組成,解碼器負責對序列進行編碼,提取時間和空間信息,解碼器負責利用時間和空間特徵信息進行上下文預測,下圖是單個結構:

編碼器和解碼器堆棧的組合結構,在谷歌的實驗結構中採用了6個編碼器和6解碼器相對應,使模型的編碼能力和解碼能力達到一個平衡狀態(堆棧式結構):

編碼器-解碼器的內部結構,類似seq2seq模型:

seq2seq模型:

Encoder: 由6個相同的層組成, 每層包含兩個sub-layers.第一個sub-layer就是multi-head attention layer,然後是一個簡單的全連接層。其中每個sub-layer都加了residual connection(殘差連接)和normalisation(歸一化)。

Decoder: 由6個相同的層組成,這裏的layer包含三個sub-layers, 第一個sub-layer 是masked multi-head attention layer。這裡有個特別點就是masked, 作用就是防止在訓練的時候,使用未來的輸出的單詞。比如訓練時,第一個單詞是不能參考第二個單詞的生成結果的。Masked是在點乘attention操作中加了一個mask的操作,這個操作是保證softmax操作之後不會將非法的values連到attention中,提高泛化性。

Self-Attention at a High Level

假設下面的句子就是我們需要翻譯的輸入句:

”The animal didn’t cross the street because it was too tired”

當模型處理單詞的時候,self attention層可以通過當前單詞去查看其輸入序列中的其他單詞,以此來尋找編碼這個單詞更好的線索。

Self-Attention in Detail

第一步是將輸入的嵌入詞向量通過三個不同的參數矩陣得到三個向量,分別是一個Query向量,一個Key向量和一個Value向量,參數矩陣分別為Wq,Wk,Wv,,如下圖所示:

第二步是通過當前詞的q向量與其他詞的k向量計算當前詞相對於其他詞的得分,分數採用點積進行計算,如下圖所示:

第三步和第四步是講得到的分數除以k值維數的平方根(k值維數為64,可以使訓練過程有更加穩定的梯度,這個歸一化的值是經驗所得),再通過softmax得到每個得分的標準化得分:

第五步是對當前詞所得到的標準化值對所有value向量進行加權求和得到當前詞的attention向量,這樣就使不同單詞的嵌入向量有了attention的參与,從而預測上下文句子的時候體現不同的重要的重要程度。

Matrix Calculation of Self-Attention

  • Attendtion向量計算的矩陣形式,通過全職矩陣進行詞向量的計算大大加快了神經網絡的速度

  • X矩陣中的每一行對應於輸入句子中的一個單詞。(圖中的4個方框論文中為512個)和q / k / v向量(圖中的3個方框論文中為64個)

公式中濃縮前面步驟2到5來計算self attention層的輸出。

The Beast With Many Heads

使用“Multi-headed”的機制來進一步完善self-attention層。“Multi-headed”主要通過兩個方面改善了Attention層的性能,參數組成和子空間映射:

Many Heads的優缺點:

  • 它拓展了模型關注不同位置的能力。Multi head 的每個參數矩陣都會記錄單詞的位置信息,使原來的單個位置信息變得更加複雜。

  • 它為attention層提供了多個“representation subspaces”。由下圖可以看到,在self attention中,我們有多個個Query / Key / Value權重矩陣(Transformer使用8個attention heads),使特徵的提取變得更加複雜,而不是作為一個整體的特徵進行,每個單獨的子空間都會進行上下文的信息融合

在8個不同的子空間進行self-attention的操作,每個單詞生成獨立的8個向量

將8個子空間生成的向量壓縮成一個大向量,每個向量的子空間矩陣能夠學習到更多細節,壓縮過程採用一個更大的參數矩陣進行,對multi-head向量進行組合,生成最終的特徵向量。

整體的框圖來表示一下計算的過程:

Representing The Order of The Sequence Using Positional Encoding

其實上面介紹的網絡裏面並沒有考慮序列的位置信息,在RNN中不同時刻的信息是通過遞歸網絡的時間t來刻畫的,有明顯的時間刻度,所以引入了位置向量來解決時間刻度問題。

為了讓模型捕捉到單詞的順序信息,添加位置編碼向量信息(POSITIONAL ENCODING),位置編碼向量不需要訓練,它有一個規則的產生方式,生成與詞嵌入向量有着相同的向量就可以。

通過構造函數sin、cos來對位置進行嵌入,pos為單詞位置信息,而i用來表達dimension 這裏為了好說明,如果2i= dmodel, PE 的函數就是sin(pos/10000)。這樣的sin, cos的函數是可以通過線性關係互相表達的,通過兩個函數對奇偶維度進行編碼。位置編碼的公式如下圖所示:

個人認為選擇正餘弦函數主要是在-1和1之間是一個對稱關係,兩個相鄰的維度編碼相差比較大,在位置上有更好的區分性,1000是序列的長度,一般盡量將取值範圍控制在四分一個周期裏面,這樣會使每一個序列的每一個維度都取唯一的值。

The Residuals

編碼器和解碼器裏面的每一層都採用殘差的思想進行訓練,目的就是為了解決網絡過深情況下的難訓練問題,殘差連接可以將目標值問題轉化成零值問題,一定程度也可以減少網絡的過擬合問題。

使用殘差連接的編碼器內部結構:

使用殘差連接的編碼器-解碼器內部結構:

The Decoder Side

通過自回歸方式進行預測,解碼器每一個時間步輸入一個單詞,然後輸出一個單詞,將預測的單詞作為下一時刻的輸入進行單詞的預測,直到預測結束。

The Final Linear and Softmax Layer

  • 線性層是一個簡單的全連接神經網絡,模型一次生成一個輸出,我們可以假設模型從該概率分佈中選擇具有最高概率的單詞並丟棄其餘的單詞。

  • 對於最終句子的生成有2個方法:一個是貪婪算法(greedy decoding),一個是波束搜索(beam search)。

Bidirectional Encoder Representation from Transformers

Word Embedding

  • 線性模型,主要是對高維空間進行映射,其實是對one-hot向量的空間轉換。

  • 通過神經網絡對輸入的詞進行映射,獲取詞向量,一般有cbow和skip-gram兩種方法,此方法訓練的詞向量與上下文無關,並沒有參考位置信息,只是對詞的有無進行參考,採用的是負採樣,預測的時候進行的是一個二分類器,模型認為只要在下文中找出正確的詞就認為是完成了任務。

尚未解決一詞多義等問題。比如多義詞Bank,有兩個常用含義,但是Word Embedding在對bank這個單詞進行編碼的時候,是區分不開這兩個含義的,因為它們儘管上下文環境中出現的單詞不同,但是在用語言模型訓練的時候,不論什麼上下文的句子經過word2vec,都是預測相同的單詞bank,而同一個單詞占的是同一行的參數空間,這導致兩種不同的上下文信息都會編碼到相同的word embedding空間里去。所以word embedding無法區分多義詞的不同語義,這就是它的一個比較嚴重的問題。

Embedding from Language Models(ELMO)

  • ElMO採用雙向的LSTM做上下文相關的任務,從前到后和後到前分別做一遍LSTM的encoding操作,從而獲得兩個方向的token聯繫。

  • Word Embedding本質上是個靜態的方式,所謂靜態指的是訓練好之後每個單詞的表達就固定住了,以後使用的時候,不論新句子上下文單詞是什麼,這個單詞的Word Embedding不會跟着上下文場景的變化而改變,所以對於比如Bank這個詞,它事先學好的Word Embedding中混合了幾種語義 ,在應用中來了個新句子,即使從上下文中(比如句子包含money等詞)明顯可以看出它代表的是“銀行”的含義,但是對應的Word Embedding內容也不會變,它還是混合了多種語義。

ELMO的本質思想是:

事先用語言模型學好一個單詞的Word Embedding,此時多義詞無法區分,不過這沒關係。在我實際使用Word Embedding的時候,單詞已經具備了特定的上下文了,這個時候我可以根據上下文單詞的語義去調整單詞的Word Embedding表示,這樣經過調整后的Word Embedding更能表達在這個上下文中的具體含義,自然也就解決了多義詞的問題了。所以ELMO本身是個根據當前上下文對Word Embedding動態調整的思路。

一樣的,在具體進行下游任務的時候,採用神經網絡參數微調的方法根據不同的詞的上下文環境對詞向量進行調整,從而得到同一詞的不同向量表示。

缺點:

  • LSTM的抽取能力遠遠落後於Transformer,主要是并行計算能力

  • 拼接方式融合雙向特徵能力偏弱

Bidirectional Encoder Representation from Transformers

BRET採用兩階段模型,首先是語言模型預訓練;其次是使用Fine-Tuning模式解決下游任務。在預訓練階段採用了類似ELMO的雙向語言模型,雙向指的是對於預測單詞的上文和下文是否參与,如果都參与預測那麼就是雙向,雙向容易導致自己看自己的問題,後面提出mask來解決

經過預訓練的BRET模型,其已經具備了豐富的詞向量特徵信息,然後將此詞向量信息與下游任務進行組合進行NLP下游任務,例如文本生成,文本分類。

如何能夠更好將BRET模型與下游任務進行改造是一個比較複雜的問題,再好的預訓練語言模型都要與下游的任務模型相結合才有好的效果, BRET的優勢在於可以自由根據預訓練模型進行單詞級別的任務和句子級的任務。

BRET模型的創新

就是論文中指出的Masked 語言模型和Next Sentence Prediction。而Masked語言模型上面講了,本質思想其實是CBOW,但是細節方面有改進。

Masked 語言模型:

  • 而Masked語言模型上面講了,本質思想其實是CBOW,但是細節方面有改進,掩蓋的同時,要輸出掩蓋的詞的位置,然後用真實詞來預測。
  • Mask LM主要是為了增加模型的魯棒性和實際性能,但是在訓練時使用mask過多會影響實際任務的表現,所以做了一些處理:隨機選擇語料中15%的單詞,把它摳掉,也就是用[Mask]掩碼代替原始單詞,然後要求模型去正確預測被摳掉的單詞。但是這裡有個問題:訓練過程大量看到[mask]標記,但是真正後面用的時候是不會有這個標記的,這會引導模型認為輸出是針對[mask]這個標記的,但是實際使用又見不到這個標記,這自然會有問題。為了避免這個問題, BRET改造了一下,15%的被選中要執行[mask]替身這項光榮任務的單詞中,只有80%真正被替換成[mask]標記,10%被狸貓換太子隨機替換成另外一個單詞,10%情況這個單詞還待在原地不做改動。這就是Masked雙向語音模型的具體做法。

Next Sentence Prediction:

  • 指的是做語言模型預訓練的時候,分兩種情況選擇兩個句子,一種是選擇語料中真正順序相連的兩個句子;另外一種是第二個句子從語料庫中拋色子,隨機選擇一個拼到第一個句子後面。
  • 我們要求模型除了做上述的Masked語言模型任務外,附帶再做個句子關係預測,判斷第二個句子是不是真的是第一個句子的後續句子。之所以這麼做,是考慮到很多NLP任務是句子關係判斷任務,單詞預測粒度的訓練到不了句子關係這個層級,增加這個任務有助於下游句子關係判斷任務。所以可以看到,它的預訓練是個多任務過程。這也是BRET的一個創新,一般用於句級任務。

Transformer&BERT總結

  • 首先是兩階段模型,第一階段雙向語言模型預訓練,這裏注意要用雙向而不是單向,第二階段採用具體任務Fine-tuning或者做特徵集成;

  • 第二是特徵抽取要用Transformer作為特徵提取器而不是RNN或者CNN;

  • 第三,雙向語言模型可以採取CBOW的方法去做(當然我覺得這個是個細節問題,不算太關鍵,前兩個因素比較關鍵)。 BRET最大的亮點在於效果好及普適性強,幾乎所有NLP任務都可以套用BRET這種兩階段解決思路,而且效果應該會有明顯提升。可以預見的是,未來一段時間在NLP應用領域,Transformer將佔據主導地位,而且這種兩階段預訓練方法也會主導各種應用。

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※為什麼 USB CONNECTOR 是電子產業重要的元件?

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※台北網頁設計公司全省服務真心推薦

※想知道最厲害的網頁設計公司"嚨底家"!

新北清潔公司,居家、辦公、裝潢細清專業服務

※推薦評價好的iphone維修中心

談談 Promise 以及實現 Fetch 的思路

Promise 是異步編程的一種解決方案。

Promise


/**
 * 屬性
 */
Promise.length
Promise.prototype

/**
 * 方法
 */
Promise.all(iterable)   // 所有成功觸發成功  任何失敗觸發失敗
Promise.race(iterable)  // 任意一個成功或失敗后觸發
Promise.reject(reason)
Promise.resolve(value)

/**
 * 原型
 */
Promise.prototype.constructor
//方法
Promise.prototype.catch(onRejected)
Promise.prototype.then(onFulfilled, onRejected)
Promise.prototype.finally(onFinally)

Promise 有三種狀態

  • pending: 初始狀態,既不是成功,也不是失敗狀態。
  • resolve: 意味着操作成功完成。(resoloved)
  • reject: 意味着操作失敗。

pending

pending 是初始狀態,執行 resolve/reject 會進入對應狀態,如果不執行,責一直為 pending 狀態

例如下面代碼,promise 將一直在 pending 狀態,不會執行 then/catch.

new Promise(function (resolve, reject) { })
  .then(res => console.log(res))
  .catch(err => console.log(err))

resolve

resolve 意味着操作成功完成, 如果有 .then,值會傳入 .then 的第一個參數函數里。

new Promise(function (resolve, reject) {
  resolve(1)
})
  .then(res => console.log(res))

then 的第一個參數是成功的回調,第一個參數的返回值會影響接下來鏈的去向。第一個參數的返回值一般有三種情況

  • 無返回值:會去執行下一個 .then ,沒有參數
  • 返回值非promise:調用下一個then的函數,參數為返回值
  • 返回值為promise:根據promise的執行結果,執行 下一個then/catch,如果一直是pending,則不執行下一個then/catch

例如想要在當前 then 終止,可以這樣操作:

  .then((res) => new Promise(() => {}))

reject

reject 意味着操作失敗。

使用 .catch 會捕獲到錯誤信息。

與代碼報錯(如 undefined.a)不同的是, 代碼報錯如果不使用 catch 捕獲,會向外傳遞,最終傳遞到根結點;而 reject 屬於 promise 錯誤,即使不使用 catch 捕獲也不會對全局有影響。

用 promise 實現 fetch

先來看幾個問題:

  1. 如果請求 code 404, 會走 then 還是 catch? (答案:then)
  2. 控制台能看到一行 404 的錯誤, 為什麼還是走 then 不是 catch 呢
  3. 如果請求跨域失敗,走 then 還是 catch?(答案:catch)
  4. 同樣是控制台看到錯誤,兩者有什麼區別呢?
  5. 跨域失敗的報錯, 和 then 中 undefined.a 報錯,如果都不 catch,後者在 react 腳手架開發環境頁面會蹦,兩者有什麼區別?

帶着這幾個問題,來看看 fetch。

fetch 返回值是 promise,所以有三種狀態 pending、resolve、reject.

  • pending: 請求中
  • resolve: 請求成功(code 200/404/500 等, 非 200 控制台輸出錯誤)
  • reject: 請求失敗(跨域失敗、連接超時、無網絡等,控制台輸出錯誤)

我們還發現,請求失敗時,只能 catch 到最後一行錯誤, 如圖

捕獲后

為什麼 404 在控制台看到錯誤,還走 then, resolve 如何實現

實現有幾個難點,

  1. throw 後面代碼不會執行;
  2. 先報錯,后執行 then;
  3. catch 后錯誤不會打印在控制台;

試了下,Promise.reject(‘xxx’) 這樣的報錯方式雖然是微觀任務,但是總是在.then之後才在控制台輸出,更像是宏觀任務。所以也加個setTImeout宏觀任務調至後面。

var fetch = function () {
  return new Promise(function (resolve, reject) {
    setTimeout(function () {
      if ('請求成功 200') {
        resolve('Response數據結構');
      } else if ('請求成功 404,500等') {
        Promise.reject('GET xxxxxxxx 404');
        setTimeout(function () {
          resolve('Response數據結構');
        });
      }
    })
  })
}

請求失敗 例如跨域失敗 reject 如何實現呢

同樣加個 setTimeout

var fetch = function () {
  return new Promise(function (resolve, reject) {
    setTimeout(function () {
      if ('請求成功 200') {
        resolve('Response數據結構');
      } else if ('請求成功 404,500等') {
        Promise.reject('GET xxxxxxxx 404');
        setTimeout(function () {
          resolve('Response數據結構');
        });
      } else if ('請求失敗') {
        Promise.reject('Access to fetch xxxxx with CORS disabled.');
        Promise.reject('GET xxxxx net::ERR_FAILED');
        setTimeout(function () {
          reject('TypeError: Failed to fetch');
        });
      }
    })
  })
}

還是有些問題,我們實現的因為在promise 中,錯誤會有前綴 Uncaught (in promise)。瀏覽器客戶端應該有更好的實現方式。

最後總結一下 fetch 的三種情況

  • pending: 請求中
  • resolve: 請求成功(code 200: 調用 resolve 返回數據; code: 404/500 等, 先拋錯,再調用 resolve 返回數據。)
  • reject: 請求失敗(跨域失敗、連接超時、無網絡等,先控制台拋錯,再調用 reject)

拋錯均不影響代碼執行,與 undefined.a 不同。

whosmeya.com

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理
【其他文章推薦】

USB CONNECTOR掌控什麼技術要點? 帶您認識其相關發展及效能

台北網頁設計公司這麼多該如何選擇?

※智慧手機時代的來臨,RWD網頁設計為架站首選

※評比南投搬家公司費用收費行情懶人包大公開

※幫你省時又省力,新北清潔一流服務好口碑

※回頭車貨運收費標準