標籤: 新北清潔

  • MapReduce 論文閱讀筆記

    MapReduce 論文閱讀筆記

    目錄

    • Abstract
    • Introduction
    • 2 Programming Model
      • 2.1 Example
      • 2.2 Types
      • 2.3 More Examples
    • 3 Implementation
      • 3.1 Execution Overview
      • 3.2 Master Data Structures
      • 3.3 Fault Tolerance
        • Worker Failure (工作節點故障)
        • Master Failure(主節點故障)
        • Semantics in the Presence of Failures(語義可能存在的故障)
      • 3.4 Locality
      • 3.5 Task Granularity
      • 3.6 Backup Tasks
    • 4 Refinements
      • 4.1 Partitioning Function
      • 4.2 Ordering Guarantees
      • 4.3 Combiner Function
      • 4.4 Input and Output Types
      • 4.5 Side-effects
      • 4.6 Skipping Bad Records
      • 4.7 Local Execution
      • 4.8 Status Information
      • 4.9 Counters
    • Others

    Abstract

    MapReduce :

    • programming model 編程模型
    • an associated implementation for processing and generating large data sets.

    用戶只需要指定 Map(Map函數將 key/value 類型的 pair 生成中間結果的 pair) 和 Reduce 函數(Reduce 函數將所有具有相同中間結果的值組合起來)即可。

    MapReduce 封裝隱藏了分佈式系統并行計算的細節:

    • 輸入數據的分割
    • 計劃將程序分配到一組計算機中
    • 處理機器故障
    • 管理集群內部的通信

    程序(in functional style)分佈式的運行在大型分佈式的集群上,而且具有很好的可伸縮性 scalable。

    Introduction

    過去這些年,Google一直在尋找方法來實現處理大量數據(抓取到的文件,web日誌等)的方法,通常數據量很大而且必須分散在數以千計的電腦上來進行運算。為了處理如何使計算相互關聯,分配數據以及處理故障的問題,往往編寫大量的複雜代碼掩蓋了他們,最初的簡單計算的初衷卻被忽略掉。

    為了解決這種複雜性,抽象出了一個簡單的計算模型放到一個庫中,這個庫隱藏了可能出現的問題:

    • 并行計算
    • 容錯
    • 數據分發
    • 負載均衡

    這個抽象受到了 Lisp 以及很多函數式編程語言中存在的原語 mapreduce 的啟發。

    大多數并行計算都包含兩個步驟:

    • map:將每個邏輯記錄變成 key/value 的中間形式方便計算
    • reduce:將所有具有相同 key 的值組合到一起來進行合適的處理

    我們使用一個函數式的編程模型(functional programming model)可以讓處理大型的并行計算和使用重新執行作為容錯的主要機制變得很簡單。

    這項工作的主要貢獻是:提供了一個簡單但是很強大的接口(interface)讓自動化的并行計算和大規模計算的分發成為可能,結合該接口的實現,可以在商用機的大型集群上實現高性能。

    Section2 :描述了基本的編程模型給出幾個例子

    Section3 :描述MapReduce 接口針對集群運算環境的實現

    Section4 :一些針對該模型的細微的改良

    Section5 :針對實現設計出一系列性能衡量方法

    Section6 :MapReduce 在 Google 中的使用,以及使用 MapReduce 來重寫生產環境的索引系統

    Section7 :相關以及未來的工作

    2 Programming Model

    input: a set of key/value pairs

    output: a set of key/value pairs

    MapReduce 的用戶將只會使用兩個函數 MapReduce

    Map:用戶編寫,將輸入的 pair 變成 k/v 的中間 pairs,然後 MapReduce 會把具有相同 key 的 pair 送給 Reduce 函數

    Reduce: 用戶編寫,接受中間結果 key 和 key 的一系列值。將這些值組合起來成為更少的 k/v;通常每個 Reduce 函數只輸出一個 或者 0 個值。中間結果太多無法全部放到內存中,可以通過迭代的方法來處理大量的 value

    2.1 Example

    設想一個需要統計文件中每個單詞數量的一個問題,我們很可能編寫這樣的代碼:

    map(String key, String value):
    	// key: document name
    	// value: document contents
    	for each word w in value:
    		EmitIntermediate(w, "1")
          
    reduce(String key, String values):
    	// key: a word
    	// values: a list of counts
    	int result = 0
      for each v in values
        result += ParseInt(v)
      Emit(AsString(result))
    

    map:給每個單詞添加一個屬性(出現的次數,這裏就是1)

    reduce:給每個特定的單詞加起來計算總數並且提交

    此外,用戶編寫代碼以使用輸入和輸出文件的名稱以及可選的調整參數來填充mapreduce規範對象。然後,用戶調用MapReduce函數,並將其傳遞給指定對象。用戶代碼與MapReduce庫(在C ++中實現)鏈接在一起。

    2.2 Types

    儘管前面偽代碼使用 string 來寫的輸入輸出,但是從概念上說,是由用戶來指定 map 和 reduce 的類型

    map (k1, v1)  ->  list(k2, v2)
    map (k2, list(v2)) -> list(v2)
    

    輸入值和中間值來自不同的域,中間值和輸出值來自相同的域

    C ++實現在用戶定義的函數之間來回傳遞字符串,並將其留給用戶代碼以在字符串和適當的類型之間進行轉換

    2.3 More Examples

    這有一些可以使用 MapReduce 簡化的計算:

    Distributed Grep: 分佈式的匹配,map 函數提交一個符合匹配的 line, reduce 的作用只是複製中間結果到輸出

    Count of URL Access Frequency: 網頁訪問計數,map 處理網頁請求並且輸出中間結果為 <URL, 1>, reduce 功能是將所有的相同的 URL 計算到一起提交為 <URL, total count>

    Reverse Web-Link Graph: 翻轉網絡鏈接圖, map 輸出 <target, source> pairs ,將 target 命名為 source。reduce函數連接與給定目標URL關聯的所有源URL的列表,並提交該對 <target, list(source)>

    Term-Vector per Host: 術語向量是出現在一篇文章中最重要的術語集合列表<word, frequency> pairs。map 函數給每個輸入文件輸出一個 <hostname, term vector> pairs,reduce 函數傳遞給特定主機的術語向量,然後去掉不常出現的向量最後提交一個 <hostname, term vector> pair

    Invert Index:map函數解析每個文檔,併發出一系列<單詞,文檔ID>對。 reduce函數接受給定單詞的所有對,對相應的文檔ID進行排序,併發出一個“單詞,列表(文檔ID)”對。setofall輸出對形成一個簡單的倒排索引。易於擴展此計算以跟蹤單詞位置。

    Distributed Sort: 分佈式排序,map函數功能從每個記錄中提取鍵,併發出一個<key, record>對。 reduce函數將所有對保持不變。這種計算取決於第4.1節中描述的分區功能和第4.2節中描述的排序屬性。

    3 Implementation

    MapReduce 可以有很多不同的實現,正確實現是根據你自己所在的環境來進行實現,例如某個實現可能很適合一個共享內存的小機器,某個實現可能是在NUMA多處理器的環境下,也可能是在一個大的網絡連接的集群的機器中。

    NUMA Non-uniform memory access

    非統一內存訪問架構是一種為多處理器的電腦設計的內存架構,內存訪問時間取決於內存相對於處理器的位置。在NUMA下,處理器訪問它自己的本地內存的速度比非本地內存快一些。 非統一內存訪問架構的特點是:被共享的內存物理上是分佈式的,所有這些內存的集合就是全局地址空間

    這節描述的是 Google 雲計算環境下廣泛使用的,下面是 Google 的配置:

    1. 機器,都是典型的Linux系統,運行在基於x86的雙處理器上,每台機器 2-4GB 內存
    2. 網絡,使用商品網絡硬件,在機器級別通常為100Mb/s或1Gb/s,但平均平均對分帶寬要小得多
    3. 集群中有上百或者上千個機器,所以機器故障出現很正常
    4. 存儲,使用廉價的 IDE 硬盤直接保存每個機器自己的數據,開發出的分佈式文件系統來管理這些磁盤上的文件。文件系統使用複製來在不可靠的硬件上提供可用性和可靠性。
    5. 用戶通過一個任務調度系統提交任務。每個工作包含一系列的任務,使用任務調度器來分配到集群中可用的機器上

    3.1 Execution Overview

    Map 調用分佈在多個機器上,自動將輸入數據分配成 M 組,輸入的分割可以并行的發生在不同的機器上。 Reduce 調用也是分佈式的,通過將中間值的key使用一個分割函數(例如:hash(key) mod R)來將任務分配到不同的機器上。分區數量 R 的取值和分區數量也是通過用戶來指定的。

    下面這個圖說明了 MapReduce 執行的完整流程:

    1. 用戶程序中的 MapReduce 庫首先將輸入文件分成 M 份(每份 16MB – 64 MB),然後開始在集群中複製很多拷貝
    2. 程序中有一份拷貝是特殊的(master)。剩下的 worker 來被分配工作,有 M 個map任務和 R 個 reduce 任務來分配給不同的 worker。master 來挑選空閑的 worker 分配給他們每個一個 map task 或者 reduce task
    3. 一個被分配到 map 工作的 worker 將會從對應的分割的內容中讀取。它會解析 k/v pair 到輸入數據並且傳給到用戶定義的 map 函數。Map 函數產生的中間 key/value 數據將會被保存在內存的緩存中
    4. 緩存中的 pair 會被周期性的寫入到本地磁盤上,通並且過分割函數將該文件分成的 R 個區域。這些緩衝對的位置在本地磁盤上被傳遞迴主服務器,該主服務器負責將這些位置轉發給reduce worker。
    5. 當一個 reduce worker 被 master 告知這些存儲的區域,reduce worker 將使用遠程過程調用來從 map workers 的本地磁盤以及緩存中讀取 pair 對。當一個 reduce worker 讀取了所有的中間數據,它將會跟配相同的 key 來進行排序。排序是必需的因為通常會有很多不同的 key 映射到同一個 reduce 任務。如果中間數據太大來放到內存中排序,外排序就會被使用
    6. reduce worker 迭代排過序的中間數據,對於每個獨特的中間值 key,它會傳遞這個 key 和對應中間值到用戶定義的 reduce 函數中來處理。Reduce函數的輸出將附加到此reduce分區的最終輸出文件中
    7. 當所有的 map task 和 reduce task 都被完成之後,master 喚醒用戶程序。這個時候,MapReduce 的調用返回到用戶的代碼邏輯中

    在成功的完成之後,mapreduce執行的輸出將會在 R 個輸出文件中(每個reduce task 都會被用戶指定文件的名稱)。通常來說,用戶不會將 R 個輸出文件合併成一個,而是將這個文件作為另一個 MapReduce 的輸入。或者把他們當成另外的分佈式程序的輸入

    3.2 Master Data Structures

    master 保存一些數據結構。對於每個 map 和 reduce 任務,它會保存狀態(idle,in-progress,completed),以及識別每個 worker machine(非空閑任務)。

    master 是處於 map 任務發送到 reduce 任務中間的導管,master 會保存中間文件區域的位置。因此,對於每個完成的 map 任務, master 保存 R 個由map任務產生的中間文件的大小和位置。當 map 任務完成之後,會更新這些文件的位置和大小。這些信息將逐漸被推送到已經在工作的 reduce 任務。

    3.3 Fault Tolerance

    由於 MapReduce 是用來在大量機器上處理大量數據的一個庫,所以這個庫必需能夠有很好的容錯能力。

    Worker Failure (工作節點故障)

    master 節點周期性的 ping 每個 worker 節點。如果在一個特定的時間內沒有收到回復,那麼 master 節點就會將這個 worker 標記為失敗。完成 map 任務的 worker 節點將會被重置為 idle 空閑狀態,然後就可以被其他 worker 節點安排。相似的,如果一個節點上的 map 或者 reduce 任務在執行過程中失敗了,那麼這個任務將會被重置然後分配然後重新分配。

    如果一個 map 任務的節點在完成任務之後出現故障,那麼就需要重新執行這個任務,因為這個節點變得不可訪問。但是如果是 reduce 任務完成之後節點出現故障,不需要重新執行,這是因為 reduce 任務的輸出被保存到一個全局文件系統中。

    當一個 map 任務首先在節點 A 上執行之後在節點 B 上執行時,所有正在執行的 reduce 節點將會被告知這次重新執行過程。所有還沒有從 worker A 讀取數據的 reduce 任務將會 worker B 讀取。

    MapReduce 可以處理大規模的 worker 節點故障。例如在一次 MapReduce 任務中,一個由80台計算機組成的集群由於網絡問題無法訪問,MapReduce 的 master 節點只是簡單的讓那些不能正常執行任務的工作節點再次執行任務,然後繼續向前執行任務直到完成 MapReduce 操作。

    Master Failure(主節點故障)

    讓 master 節點周期性的上述master節點的數據結構的檢查點。如果 master task 失敗了,可以從上一個檢查點的拷貝恢復。但是如果只有一個主節點,那麼出現故障的可能性非常小,因此如果主節點出現故障,我們的當前的實現就中止了此次 MapReduce 任務。客戶端可以檢查到這種情況,然後可以選擇是否重試 MapReduce 操作。

    Semantics in the Presence of Failures(語義可能存在的故障)

    當用戶指定的 map 和 reduce 操作對於他們的輸入輸出都確定好了之後,分佈式的實現將會產生一個類似於線性執行過程任務執行的結果。

    我們依賴於 map 和 reduce 任務的 原子性 commit 作為這個特性的保證。每個執行過程中的任務都會將把他的輸出保存到一個私有的臨時文件中。一個 reduce 任務產生一個這樣的文件,但是一個 map 任務將會產生 R 個這樣的文件。當一個 map 任務完成之後, worker 節點發送包含這 R 個文件名的消息到 master 節點。如果這個節點已經接收到完成的消息,那麼將會忽略這個消息,否則將會把這些文件名保存到 master 節點的數據結構中。

    當一個 reduce 任務完成的時候,reduce worker 將會原子性的將它的臨時文件重命名成一個輸出文件。如果有以個 reduce 任務在多個機器上同時完成,那麼這個重命名的操作將會對於一個輸出文件多次執行。我們依賴於基礎文件系統提供的原子重命名操作,以確保最終文件系統狀態僅包含一次執行reduce任務所產生的數據。

    map 和 reduce 操作絕大部分都是確定性的,事實上我們的語義將會和線性順序執行的程序的結果一致,這樣很容易分析程序的行為。當 map/reduce 操作是不確定的時候,我們提供弱化但是可信的語義。例如在一個不確定的語義中,一個特定 reduce 任務的輸出和這個任務順序執行的結果一致。然而,用於不同reduce任務R2的輸出可以對應於由不確定性程序的不同順序執行所產生的用於R2的輸出。(這裏保留疑問,沒有太懂什麼意思,指的是有可能是線性結果一致的意思嗎?)

    考慮有一個 map 任務 M,和兩個 reduce 任務 R1,R2,e(Ri)是 Ri提交的結果,弱一點的語義指的是,e(R1) 可能讀取的 M 的一個執行的結果而 e(R2) 可能讀取的是 R 執行輸出的另外一個結果。

    3.4 Locality

    網絡帶寬是在雲計算環境中比較稀缺的資源(盡量少用)。通過將輸入文件(由GFS保管)保存到本地磁盤上來減少網絡帶寬的使用。GFS 將每個文件分成 64 MB的塊,然後將每塊保存幾個副本(通常為3份)在不同的機器上。MapReduce 盡量將這些位置信息保存下來然後盡量將含有某個文件主機的任務分配給它,這樣就可以減少網絡的傳遞使用。如果失敗,那麼將會嘗試從靠近輸入數據的一個副本主機去啟動這個任務。當在一個集群上執行大型的 MapReduce 操作的時候,輸入數據一般都是本地讀取,減少網絡帶寬的使用。

    3.5 Task Granularity

    我們將一個 map 任務分成 M 塊,然後 reduce 會處理最後輸出成 R 塊。

    理想情況下,M 和 R 應該遠遠大於集群中的 worker 節點數量。讓每個節點執行不同的任務將會有利於動態的負載均衡,同時會加速當一個 worker 節點故障之後的恢復,map 任務完成之後可以分配到所有的其他節點上。

    R 和 M 在實現過程中會有邊界,因為 schedule 決策需要 O(M + R)的時間,保存這個信息到內存中需要 O(M*R)的複雜度(常數內存很小)。

    R 通常是由用戶指定的,這是由於每個 reduce 任務的輸出將會輸出到單獨的文件中。在實際中,通常 M 被選擇到每個單獨的任務輸入數據將會是 16MB ~ 64MB,讓 R 要比我們使用的機器的數目的小几倍。

    例如,M =20,000,R = 5,000,worker machines = 2000

    3.6 Backup Tasks

    讓整個 MapReduce 任務時間延長的原因主要有 “拖延者”:某一個機器在 map/reduce 任務上花費了太多的時間。導致這個 “拖延者” 的原因可能有很多,比如一塊讀寫速度超級慢的硬盤 1MB/s(其他的是 30MB/s)比如集群在這個機器上也分配了其他任務,這些任務競爭使用 CPU、硬盤網絡等等。我們最近遇到的一個問題是機器初始化代碼中的一個錯誤,該錯誤導致禁用了處理器緩存:受影響機器的計算速度降低了一百倍。

    4 Refinements

    儘管上面說的夠用了,但是我們還是找到一些可以優化的點。

    4.1 Partitioning Function

    用戶將會指定輸出文件的數量 R。輸入數據將會根據中間值來把這些數據分區。一個默認的分區函數就是 hash函數(hash(key) mod R) 。通常情況下這樣很好,但是在某些情況下不是很好。例如,輸出數據是 URL key,我們希望具有相同主機 hostname 的 URL 在一起,這樣,MapReduce 提供了用戶自己制定 分區函數的方式,例如可以寫為(hash(Hostname(urlkey))),這樣具有相同的 hostname 的URL將會在一個相同的輸出文件中。

    4.2 Ordering Guarantees

    我們保證了在某個給定的分區中,中間值的 k/v pair 將會按照增序排列,這樣在某些需要有序的場景下是很有用的。

    4.3 Combiner Function

    在某些情況下,最終的輸出文件reduce是需要根據中間值來合併的。例如在2.1的 word count 中,需要統計每個單詞的數目,我們輸出的是 <word, 1> 這樣的形式。這些pair都需要通過網絡來進行發送到 reduce 工作節點,我們提供了一個 combiner 函數,讓用戶可以在發送數據之前執行的函數,也就是說在本地先合併,然後再發送到網絡中去。

    在每個執行 map task 的機器都會執行 conbine 函數。

    combine 和 reduce 的唯一區別:

    • combine 輸出是到中間值文件中
    • reduce 輸出到一個最終的輸出文件中

    4.4 Input and Output Types

    MapReduce 庫提供了幾種輸入的類型。

    例如,在 “text” 模式下輸入將每一個行當作 k/v pair,這行的偏移量當作 key,這行的內容當作 value。

    用戶可以通過實現 reader 接口在實現自己的輸入類型,儘管大多數用戶都只使用預定義的類型。

    reader 不一定要從文件中讀取數據,也可以從數據庫中讀取數據,或者從內存中的某個的某個數據結構中獲取數據。

    同樣的,輸出也可以自定義。

    4.5 Side-effects

    在某些情況下,用戶需要產生一些額外的輸出文件在reduce 的輸出結果中。我們依靠這個應用程序自己的編寫者來使此類副作用成為原子和冪等的。通常應用程序將會寫入一個臨時文件中,然後當它完成的時候將會原子性的重命名這個文件。

    我們不提供原子性的兩節點提交由一個任務產生的多個輸出文件。因此,產生多個輸出的結果的任務應該是確定性的。

    4.6 Skipping Bad Records

    在處理大量數據的時候,由於用戶的 map/reduce 函數的錯誤在處理某些數據的時候產生bug,這個時候可以選擇跳過這些 bug。有的時候我們可以查找到bug所在的地方,但是有的時候我們找不到bug,因為可能是第三方的庫導致的錯誤,我們提供了一種可選的執行模式來跳過這些可能出現錯誤的記錄。

    每個 worker 進程都會有一個監聽段錯誤和總線錯誤的處理器。在執行用戶的 map/reduce 函數之前,mapreduce 將會在一個全局變量中保存順序編號。如果用戶代碼產生了一個 signal,那麼就會發送一個 UDP包到 MapReduce 的 master 節點上。當 master 節點發現在某個幾點上出現了很多次故障的時候,之後就會跳過這個記錄。

    4.7 Local Execution

    在 Map/Reduce 中debug需要一些 trick,因為在分佈式系統中執行可能是在幾千台機器中,工作分配也是動態的。MapReduce 提供了一個另外的本地MapReduce 的本地實現(順序執行),這樣就可以在本地來進行 debug了。

    4.8 Status Information

    master 節點通過 HTTP 服務器提供一個显示當前狀態的網頁。這個界面显示了多少任務完成了,多少任務還在執行,中間數據有多少字節等,還包含了錯誤的標準輸出文件的鏈接等,用戶可以通過這個界面預估還有多久可以完成任務。當執行很慢的時候,可以通過這個界面來查找原因。

    另外,top-level 的狀態信息還會显示哪些 worker 節點有故障,哪些任務失敗了。

    4.9 Counters

    提供一個全局的計數器來統計某些數據,例如統計大寫單詞的出現次數。

     Counter* uppercase;
      uppercase = GetCounter("uppercase");
      map(String name, String contents):
        for each word w in contents:
    			if (IsCapitalized(w)): 
    				uppercase->Increment(); 
    			EmitIntermediate(w, "1");
    

    計數器的值會從每個節點周期性的發送到master節點,主節點統計計數器的值並且在 狀態頁面显示。

    有些值MapReduce 會自己去統計。

    計數器功能對於完整性檢查MapReduce操作的行為很有用。例如,在某些MapReduce操作中,用戶代碼可能想要確保所生成的輸出對的數量完全等於所處理的輸入對的數量,或者所處理的德語文檔的比例在該比例之內。

    Others

    shuffle:將所有具有相同 key 的value 發送個單個的 reduce 進程,在網絡上傳輸數據,是MapReduce代價最大的部分

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

    【其他文章推薦】

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

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

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

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

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

  • 使用json-server與Mockjs搭建模擬服務

    使用json-server與Mockjs搭建模擬服務

    為什麼使用

    在項目開發中,常常需要邊寫前端頁面邊寫後端接口,但是後端接口服務往往是滯後於前端開發的,或者是不能及時提供的。出於前端開發的迅速和便捷去考慮,我們可以根據後端接口數據結構去模擬(mock)數據從而實現前端的獨立開發。
    JsonServer 主要的作用就是搭建本地的數據接口,創建json文件,便於調試調用
    Mockjs 主要的作用就是生成隨機數據,支持生成隨機的文本、数字、布爾值、日期、郵箱、鏈接、圖片、顏色等

    如何使用

    以下操作需要node.js環境

    1.創建文件夾

    選擇自己喜歡的位置創建一個文件夾,比如E:/mock

    2.安裝json-server

    進入E:/mock

    npm install json-server -g 

    安裝完執行 json-server -h,若安裝成功則會显示選項

    Options:
    –config, -c Path to config file [default: “json-server.json”]
    –port, -p Set port [default: 3000]
    –host, -H Set host [default: “localhost”]
    –watch, -w Watch file(s) [boolean]
    –routes, -r Path to routes file
    –middlewares, -m Paths to middleware files [array]
    –static, -s Set static files directory
    –read-only, –ro Allow only GET requests [boolean]
    –no-cors, –nc Disable Cross-Origin Resource Sharing [boolean]
    –no-gzip, –ng Disable GZIP Content-Encoding [boolean]
    –snapshots, -S Set snapshots directory [default: “.”]
    –delay, -d Add delay to responses (ms)
    –id, -i Set database id property (e.g. _id) [default: “id”]
    –foreignKeySuffix, –fks Set foreign key suffix (e.g. _id as in post_id)
    [default: “Id”]
    –quiet, -q Suppress log messages from output [boolean]
    –help, -h Show help [boolean]
    –version, -v Show version number [boolean]

    3.使用json-server
    • 創建json文件,如db.json,文件內容如下
    { "posts": [ { "id": 1, "title": "json-server", "author": "typicode" } ], "comments": [ { "id": 1, "body": "some comment", "postId": 1 } ], "profile": { "name": "typicode" } } 
    • 啟動json-server,cmd執行
    json-server --watch db.json 

    看到如下內容

     

    1574216715(1).jpg


    則運行成功,直接訪問圖中显示的三個地址可得結果,如


     

    1574216903(1).jpg


    至此,簡單的json-server服務已經搭建成功了,後續如果有更多需求,如跨域、參數查詢、路由這些,請參考json-server的github

     

    4.安裝Mockjs

    進入E:/mock

    npm install mockjs --save 
    5.使用Mockjs
    • 創建js文件,如news.js,文件內容如下
    let Mock=require('mockjs'); let Random=Mock.Random; module.exports=()=>{ let data={ news:[] }; let images=[1,2,3].map(x=>Random.image('120x60',Random.color(),Random.word(2,6))); for(let i=1;i<=100;i++){ let content=Random.cparagraph(0,10); data.news.push({ id:i, title:Random.cword(8,20), desc:content.substr(0,40), tag:Random.cword(2,6), views:Random.integer(100,5000), images:images.slice(0,Random.integer(1,3)) }) } return data } 
    • 啟動json-server,cmd執行
    json-server --watch news.js 

    訪問結果(部分)


     
     

    完成了以上的搭建與驗證過程后,你就可以開始使用json-server與Mockjs來繼續構建模擬服務器了,來滿足自己的各種需要

    Tips:

    1、也可以使用json-server db.json ,使用“json-server –watch db.json”命令可以實時監測db.json的變化;如果沒有 — watch 命令,即使db.json已經發生了改變,重新發請求,仍然會返回原先的mock data,返回狀態碼304,認為沒有變化。

    2、同時,我們可以發送 POST、PUT、PATCH和DELETE請求,相應的結果會通過lowdb自動保存到db.json。關於POST、PUT等相關請求的發送。

    3、我們的request body應該是一個json對象,比如{“name”:”Lynn”};

    4、POST、PUT、PATCH請求頭中要包含Content-Type: application/json;

    5、id的值是自動生成且不易變的。PUT請求和PATCH請求中自帶的id會被忽略。

     

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

    【其他文章推薦】

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

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

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

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

    ※超省錢租車方案

  • springboot_自動配置原理

    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/,如有侵權,請聯繫我們,我們將及時處理

    【其他文章推薦】

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

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

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

    ※超省錢租車方案

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

  • BERT的前世今生

    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維修中心