整合營(yíng)銷服務(wù)商

          電腦端+手機(jī)端+微信端=數(shù)據(jù)同步管理

          免費(fèi)咨詢熱線:

          為什么要學(xué)習(xí)HTML?HTML會(huì)過(guò)時(shí)嗎?

          編程有沒(méi)有必要學(xué) HTML 呢?這是編程初學(xué)者中非常普遍的問(wèn)題,而且在網(wǎng)上意見(jiàn)分歧很大。關(guān)于初學(xué)者在學(xué)習(xí) HTML 前的一些常見(jiàn)問(wèn)題,編程獅W3Cschool整理了以下資料希望對(duì)你有所幫助:

          學(xué)編程不需要學(xué)習(xí)HTML?

          那些說(shuō)不需要 HTML 知識(shí)的人要么不了解 Web 設(shè)計(jì),要么別有用心。雖然現(xiàn)在哪怕不會(huì) HTML 也有其他方法可以解決 web 設(shè)計(jì)相關(guān)問(wèn)題,但絕大多數(shù)資深前端開(kāi)發(fā)者還是會(huì)建議你最好還是要學(xué)習(xí)它的。

          沒(méi)有時(shí)間學(xué)習(xí)HTML?

          通常了解基本知識(shí)只需要20到40分鐘。花幾個(gè)小時(shí)學(xué)習(xí) w3cschool官網(wǎng) 的《HTML 教程 》和《HTML 微課 》,你就可以制作一個(gè)簡(jiǎn)單而完整的網(wǎng)頁(yè)。如果你愿意每周花幾個(gè)小時(shí),學(xué)習(xí)幾個(gè)月的 《前端開(kāi)發(fā)體系課程 _ 》,那么您將對(duì)網(wǎng)站的工作方式有一個(gè)很好的了解。這種時(shí)間上的投資將獲得很大的回報(bào)比。試想下,如果你本周花在學(xué)習(xí)上一小時(shí),未來(lái)的工作上每個(gè)月都將永遠(yuǎn)節(jié)省一個(gè)小時(shí)。盡管投資回收期在開(kāi)始時(shí)比較緩慢,但你最終可以只需要花費(fèi)一小部分時(shí)間用來(lái)完成工作,你覺(jué)得值得嗎?

          編寫(xiě)HTML太慢?

          這是勸退很多人的一個(gè)原因,但實(shí)際上這個(gè)問(wèn)題是不存在的。因?yàn)榇蠖鄶?shù)情況下我們不需要編寫(xiě) HTML 代碼,只需了解它即可。

          我有一個(gè)很好的所見(jiàn)即所得編輯器,所以我不需要HTML

          市面上有很多可視化的工具如 WYSIWYG 、Dreamweaver及現(xiàn)在越來(lái)越多的”低代碼“云開(kāi)發(fā)工具等,它可以幫助你更高效地工作。如前所述,你并不是要手動(dòng)輸入 HTML 代碼,而是要了解 HTML 的工作原理。

          例如:射釘槍能比錘子更快地幫助您建造房屋,但是如果你不知道如何搭建框架以及將釘子釘在何處,造出來(lái)的房屋很可能會(huì)倒塌。我們需要了解如何手動(dòng)構(gòu)造 HTML,然后使用所見(jiàn)即所得工具更快地工作。

          PS:所見(jiàn)即所得的編輯器永遠(yuǎn)不會(huì)是完美的,總有時(shí)候是需要我們手動(dòng)來(lái)調(diào)整 HTML。。

          我不擅長(zhǎng)學(xué)習(xí)計(jì)算機(jī)語(yǔ)言

          放心,雖然我們時(shí)常把它稱為語(yǔ)言,但其實(shí) HTML 并不是一種編程語(yǔ)言(從技術(shù)上講,HTML 被稱為“mark up”語(yǔ)言,也就是標(biāo)記語(yǔ)言,英文全稱是“HyperText Markup Language”。)。從難度上講,它就像是小孩子們的“密碼”游戲。真正難點(diǎn)在于要學(xué)習(xí)的東西太多了,但是請(qǐng)記住,你不必全部都學(xué)會(huì)!只要按照自己的步調(diào)學(xué)習(xí)盡可能多的知識(shí)即可。

          不要將費(fèi)時(shí)困難混淆。HTML 很耗時(shí),但是并不難。另外,你不需要學(xué)會(huì)全部知識(shí)點(diǎn),即使只花費(fèi)幾個(gè)小時(shí)來(lái)學(xué)習(xí)基本結(jié)構(gòu)也將極大地幫助你。

          HTML會(huì)過(guò)時(shí)嗎?

          不會(huì)。其他編程語(yǔ)言一直在發(fā)展中,并且很可能最終會(huì)取代 HTML,但是 HTML 將在很長(zhǎng)一段時(shí)間內(nèi)繼續(xù)作為幾乎所有網(wǎng)站的基礎(chǔ)。在任何情況下,HTML 都會(huì)為您提供堅(jiān)實(shí)的基礎(chǔ),然后再采用 XML 等新語(yǔ)言。

          HTML對(duì)我而言太過(guò)局限了

          如果您的目的是創(chuàng)建網(wǎng)頁(yè),那么很抱歉告訴你,無(wú)論你喜不喜歡,你只能選擇 HTML,因?yàn)樗菢?gòu)成網(wǎng)絡(luò)構(gòu)成的基礎(chǔ)。如果你真的想以其他格式(例如PDF)來(lái)傳送,請(qǐng)注意,它并不是一個(gè)網(wǎng)頁(yè),所以它不能實(shí)現(xiàn)我們?cè)诰W(wǎng)頁(yè)中的一些常見(jiàn)功能。

          以上就是編程獅W3Cschool為你整理的關(guān)于《為什么要學(xué)習(xí)HTML?HTML會(huì)過(guò)時(shí)嗎?》的全部?jī)?nèi)容,現(xiàn)在你要開(kāi)始學(xué)習(xí) HTML 了嗎?

          能每一個(gè)前端工程師都想要理解瀏覽器的工作原理。

          我們希望知道從在瀏覽器地址欄中輸入 url 到頁(yè)面展現(xiàn)的短短幾秒內(nèi)瀏覽器究竟做了什么;

          我們希望了解平時(shí)常常聽(tīng)說(shuō)的各種代碼優(yōu)化方案是究竟為什么能起到優(yōu)化的作用;

          我們希望更細(xì)化的了解瀏覽器的渲染流程。

          瀏覽器的多進(jìn)程架構(gòu)

          一個(gè)好的程序常常被劃分為幾個(gè)相互獨(dú)立又彼此配合的模塊,瀏覽器也是如此,以 Chrome 為例,它由多個(gè)進(jìn)程組成,每個(gè)進(jìn)程都有自己核心的職責(zé),它們相互配合完成瀏覽器的整體功能,每個(gè)進(jìn)程中又包含多個(gè)線程,一個(gè)進(jìn)程內(nèi)的多個(gè)線程也會(huì)協(xié)同工作,配合完成所在進(jìn)程的職責(zé)。

          對(duì)一些前端開(kāi)發(fā)同學(xué)來(lái)說(shuō),進(jìn)程和線程的概念可能會(huì)有些模糊,為了更好的理解瀏覽器的多進(jìn)程架構(gòu),這里我們簡(jiǎn)單討論一下進(jìn)程和線程。

          進(jìn)程(process)和線程(thread)


          進(jìn)程就像是一個(gè)有邊界的生產(chǎn)廠間,而線程就像是廠間內(nèi)的一個(gè)個(gè)員工,可以自己做自己的事情,也可以相互配合做同一件事情。

          當(dāng)我們啟動(dòng)一個(gè)應(yīng)用,計(jì)算機(jī)會(huì)創(chuàng)建一個(gè)進(jìn)程,操作系統(tǒng)會(huì)為進(jìn)程分配一部分內(nèi)存,應(yīng)用的所有狀態(tài)都會(huì)保存在這塊內(nèi)存中,應(yīng)用也許還會(huì)創(chuàng)建多個(gè)線程來(lái)輔助工作,這些線程可以共享這部分內(nèi)存中的數(shù)據(jù)。如果應(yīng)用關(guān)閉,進(jìn)程會(huì)被終結(jié),操作系統(tǒng)會(huì)釋放相關(guān)內(nèi)存。更生動(dòng)的示意圖如下:

          一個(gè)進(jìn)程還可以要求操作系統(tǒng)生成另一個(gè)進(jìn)程來(lái)執(zhí)行不同的任務(wù),系統(tǒng)會(huì)為新的進(jìn)程分配獨(dú)立的內(nèi)存,兩個(gè)進(jìn)程之間可以使用 IPC (Inter Process Communication)進(jìn)行通信。很多應(yīng)用都會(huì)采用這樣的設(shè)計(jì),如果一個(gè)工作進(jìn)程反應(yīng)遲鈍,重啟這個(gè)進(jìn)程不會(huì)影響應(yīng)用其它進(jìn)程的工作。

          如果對(duì)進(jìn)程及線程的理解還存在疑惑,可以參考下述文章:

          http://www.ruanyifeng.com/blog/2013/04/processes_and_threads.html

          瀏覽器的架構(gòu)

          有了上面的知識(shí)做鋪墊,我們可以更合理的討論瀏覽器的架構(gòu)了,其實(shí)如果要開(kāi)發(fā)一個(gè)瀏覽器,它可以是單進(jìn)程多線程的應(yīng)用,也可以是使用 IPC 通信的多進(jìn)程應(yīng)用。


          不同瀏覽器的架構(gòu)模型

          不同瀏覽器采用了不同的架構(gòu)模式,這里并不存在標(biāo)準(zhǔn),本文以 Chrome 為例進(jìn)行說(shuō)明 :

          Chrome 采用多進(jìn)程架構(gòu),其頂層存在一個(gè) Browser process 用以協(xié)調(diào)瀏覽器的其它進(jìn)程。


          Chrome 的不同進(jìn)程

          具體說(shuō)來(lái),Chrome 的主要進(jìn)程及其職責(zé)如下:

          Browser Process:

          • 負(fù)責(zé)包括地址欄,書(shū)簽欄,前進(jìn)后退按鈕等部分的工作;
          • 負(fù)責(zé)處理瀏覽器的一些不可見(jiàn)的底層操作,比如網(wǎng)絡(luò)請(qǐng)求和文件訪問(wèn);

          Renderer Process:

          • 負(fù)責(zé)一個(gè) tab 內(nèi)關(guān)于網(wǎng)頁(yè)呈現(xiàn)的所有事情

          Plugin Process:

          • 負(fù)責(zé)控制一個(gè)網(wǎng)頁(yè)用到的所有插件,如 flash
          • GPU Process
          • 負(fù)責(zé)處理 GPU 相關(guān)的任務(wù)



          不同進(jìn)程負(fù)責(zé)的瀏覽器區(qū)域示意圖

          Chrome 還為我們提供了「任務(wù)管理器」,供我們方便的查看當(dāng)前瀏覽器中運(yùn)行的所有進(jìn)程及每個(gè)進(jìn)程占用的系統(tǒng)資源,右鍵單擊還可以查看更多類別信息。

          通過(guò)「頁(yè)面右上角的三個(gè)點(diǎn)點(diǎn)點(diǎn) — 更多工具 — 任務(wù)管理器」即可打開(kāi)相關(guān)面板。

          Chrome 多進(jìn)程架構(gòu)的優(yōu)缺點(diǎn)

          優(yōu)點(diǎn)

          某一渲染進(jìn)程出問(wèn)題不會(huì)影響其他進(jìn)程

          更為安全,在系統(tǒng)層面上限定了不同進(jìn)程的權(quán)限

          缺點(diǎn)

          由于不同進(jìn)程間的內(nèi)存不共享,不同進(jìn)程的內(nèi)存常常需要包含相同的內(nèi)容。

          為了節(jié)省內(nèi)存,Chrome 限制了最多的進(jìn)程數(shù),最大進(jìn)程數(shù)量由設(shè)備的內(nèi)存和 CPU 能力決定,當(dāng)達(dá)到這一限制時(shí),新打開(kāi)的 Tab 會(huì)共用之前同一個(gè)站點(diǎn)的渲染進(jìn)程。

          測(cè)試了一下在 Chrome 中打開(kāi)不斷打開(kāi)知乎首頁(yè),在 Mac i5 8g 上可以啟動(dòng)四十多個(gè)渲染進(jìn)程,之后新打開(kāi) tab 會(huì)合并到已有的渲染進(jìn)程中。

          Chrome 把瀏覽器不同程序的功能看做服務(wù),這些服務(wù)可以方便的分割為不同的進(jìn)程或者合并為一個(gè)進(jìn)程。以 Broswer Process 為例,如果 Chrome 運(yùn)行在強(qiáng)大的硬件上,它會(huì)分割不同的服務(wù)到不同的進(jìn)程,這樣 Chrome 整體的運(yùn)行會(huì)更加穩(wěn)定,但是如果 Chrome 運(yùn)行在資源貧瘠的設(shè)備上,這些服務(wù)又會(huì)合并到同一個(gè)進(jìn)程中運(yùn)行,這樣可以節(jié)省內(nèi)存,示意圖如下。

          iframe 的渲染 – Site Isolation

          在上面的進(jìn)程圖中我們還可以看到一些進(jìn)程下還存在著 Subframe,這就是 Site Isolation 機(jī)制作用的結(jié)果。

          Site Isolation 機(jī)制從 Chrome 67 開(kāi)始默認(rèn)啟用。這種機(jī)制允許在同一個(gè) Tab 下的跨站 iframe 使用單獨(dú)的進(jìn)程來(lái)渲染,這樣會(huì)更為安全。


          iframe 會(huì)采用不同的渲染進(jìn)程

          Site Isolation 被大家看做里程碑式的功能, 其成功實(shí)現(xiàn)是多年工程努力的結(jié)果。Site Isolation 不是簡(jiǎn)單的疊加多個(gè)進(jìn)程。這種機(jī)制在底層改變了 iframe 之間通信的方法,Chrome 的其它功能都需要做對(duì)應(yīng)的調(diào)整,比如說(shuō) devtools 需要相應(yīng)的支持,甚至 Ctrl + F 也需要支持。關(guān)于 Site Isolation 的更多內(nèi)容可參考下述鏈接:

          https://developers.google.com/web/updates/2018/07/site-isolation

          介紹完了瀏覽器的基本架構(gòu)模式,接下來(lái)我們看看一個(gè)常見(jiàn)的導(dǎo)航過(guò)程對(duì)瀏覽器來(lái)說(shuō)究竟發(fā)生了什么。

          導(dǎo)航過(guò)程發(fā)生了什么

          也許大多數(shù)人使用 Chrome 最多的場(chǎng)景就是在地址欄輸入關(guān)鍵字進(jìn)行搜索或者輸入地址導(dǎo)航到某個(gè)網(wǎng)站,我們來(lái)看看瀏覽器是怎么看待這個(gè)過(guò)程的。

          我們知道瀏覽器 Tab 外的工作主要由 Browser Process 掌控,Browser Process 又對(duì)這些工作進(jìn)一步劃分,使用不同線程進(jìn)行處理:

          • UI thread : 控制瀏覽器上的按鈕及輸入框;
          • network thread: 處理網(wǎng)絡(luò)請(qǐng)求,從網(wǎng)上獲取數(shù)據(jù);
          • storage thread: 控制文件等的訪問(wèn);



          瀏覽器主進(jìn)程中的不同線程

          回到我們的問(wèn)題,當(dāng)我們?cè)跒g覽器地址欄中輸入文字,并點(diǎn)擊回車獲得頁(yè)面內(nèi)容的過(guò)程在瀏覽器看來(lái)可以分為以下幾步:

          1. 處理輸入

          UI thread 需要判斷用戶輸入的是 URL 還是 query;

          2. 開(kāi)始導(dǎo)航

          當(dāng)用戶點(diǎn)擊回車鍵,UI thread 通知 network thread 獲取網(wǎng)頁(yè)內(nèi)容,并控制 tab 上的 spinner 展現(xiàn),表示正在加載中。

          network thread 會(huì)執(zhí)行 DNS 查詢,隨后為請(qǐng)求建立 TLS 連接。


          UI thread 通知 Network thread 加載相關(guān)信息

          如果 network thread 接收到了重定向請(qǐng)求頭如 301,network thread 會(huì)通知 UI thread 服務(wù)器要求重定向,之后,另外一個(gè) URL 請(qǐng)求會(huì)被觸發(fā)。

          3. 讀取響應(yīng)

          當(dāng)請(qǐng)求響應(yīng)返回的時(shí)候,network thread 會(huì)依據(jù) Content-Type 及 MIME Type sniffing 判斷響應(yīng)內(nèi)容的格式。


          判斷響應(yīng)內(nèi)容的格式

          如果響應(yīng)內(nèi)容的格式是 HTML ,下一步將會(huì)把這些數(shù)據(jù)傳遞給 renderer process,如果是 zip 文件或者其它文件,會(huì)把相關(guān)數(shù)據(jù)傳輸給下載管理器。

          Safe Browsing 檢查也會(huì)在此時(shí)觸發(fā),如果域名或者請(qǐng)求內(nèi)容匹配到已知的惡意站點(diǎn),network thread 會(huì)展示一個(gè)警告頁(yè)。此外 CORB 檢測(cè)也會(huì)觸發(fā)確保敏感數(shù)據(jù)不會(huì)被傳遞給渲染進(jìn)程。


          4. 查找渲染進(jìn)程

          當(dāng)上述所有檢查完成,network thread 確信瀏覽器可以導(dǎo)航到請(qǐng)求網(wǎng)頁(yè),network thread 會(huì)通知 UI thread 數(shù)據(jù)已經(jīng)準(zhǔn)備好,UI thread 會(huì)查找到一個(gè) renderer process 進(jìn)行網(wǎng)頁(yè)的渲染。


          收到 Network thread 返回的數(shù)據(jù)后,UI thread 查找相關(guān)的渲染進(jìn)程

          由于網(wǎng)絡(luò)請(qǐng)求獲取響應(yīng)需要時(shí)間,這里其實(shí)還存在著一個(gè)加速方案。當(dāng) UI thread 發(fā)送 URL 請(qǐng)求給 network thread 時(shí),瀏覽器其實(shí)已經(jīng)知道了將要導(dǎo)航到那個(gè)站點(diǎn)。UI thread 會(huì)并行的預(yù)先查找和啟動(dòng)一個(gè)渲染進(jìn)程,如果一切正常,當(dāng) network thread 接收到數(shù)據(jù)時(shí),渲染進(jìn)程已經(jīng)準(zhǔn)備就緒了,但是如果遇到重定向,準(zhǔn)備好的渲染進(jìn)程也許就不可用了,這時(shí)候就需要重啟一個(gè)新的渲染進(jìn)程。

          5. 確認(rèn)導(dǎo)航

          進(jìn)過(guò)了上述過(guò)程,數(shù)據(jù)以及渲染進(jìn)程都可用了, Browser Process 會(huì)給 renderer process 發(fā)送 IPC 消息來(lái)確認(rèn)導(dǎo)航,一旦 Browser Process 收到 renderer process 的渲染確認(rèn)消息,導(dǎo)航過(guò)程結(jié)束,頁(yè)面加載過(guò)程開(kāi)始。

          此時(shí),地址欄會(huì)更新,展示出新頁(yè)面的網(wǎng)頁(yè)信息。history tab 會(huì)更新,可通過(guò)返回鍵返回導(dǎo)航來(lái)的頁(yè)面,為了讓關(guān)閉 tab 或者窗口后便于恢復(fù),這些信息會(huì)存放在硬盤(pán)中。


          6. 額外的步驟

          一旦導(dǎo)航被確認(rèn),renderer process 會(huì)使用相關(guān)的資源渲染頁(yè)面,下文中我們將重點(diǎn)介紹渲染流程。當(dāng) renderer process 渲染結(jié)束(渲染結(jié)束意味著該頁(yè)面內(nèi)的所有的頁(yè)面,包括所有 iframe 都觸發(fā)了 onload 時(shí)),會(huì)發(fā)送 IPC 信號(hào)到 Browser process, UI thread 會(huì)停止展示 tab 中的 spinner。


          Renderer Process 發(fā)送 IPC 消息通知 browser process 頁(yè)面已經(jīng)加載完成。

          當(dāng)然上面的流程只是網(wǎng)頁(yè)首幀渲染完成,在此之后,客戶端依舊可下載額外的資源渲染出新的視圖。

          在這里我們可以明確一點(diǎn),所有的 JS 代碼其實(shí)都由 renderer Process 控制的,所以在你瀏覽網(wǎng)頁(yè)內(nèi)容的過(guò)程大部分時(shí)候不會(huì)涉及到其它的進(jìn)程。不過(guò)也許你也曾經(jīng)監(jiān)聽(tīng)過(guò) beforeunload 事件,這個(gè)事件再次涉及到 Browser Process 和 renderer Process 的交互,當(dāng)當(dāng)前頁(yè)面關(guān)閉時(shí)(關(guān)閉 Tab ,刷新等等),Browser Process 需要通知 renderer Process 進(jìn)行相關(guān)的檢查,對(duì)相關(guān)事件進(jìn)行處理。


          瀏覽器進(jìn)程發(fā)送 IPC 消息給渲染進(jìn)程,通知要離開(kāi)當(dāng)前網(wǎng)站了

          如果導(dǎo)航由 renderer process 觸發(fā)(比如在用戶點(diǎn)擊某鏈接,或者 JS 執(zhí)行 window.location = "http://newsite.com" ) renderer process 會(huì)首先檢查是否有 beforeunload 事件處理器,導(dǎo)航請(qǐng)求由 renderer process 傳遞給 Browser process。

          如果導(dǎo)航到新的網(wǎng)站,會(huì)啟用一個(gè)新的 render process 來(lái)處理新頁(yè)面的渲染,老的進(jìn)程會(huì)留下來(lái)處理類似 unload 等事件。

          關(guān)于頁(yè)面的生命周期,更多內(nèi)容可參考 Page Lifecycle API 。


          瀏覽器進(jìn)程發(fā)送 IPC 消息到新的渲染進(jìn)程通知渲染新的頁(yè)面,同時(shí)通知舊的渲染進(jìn)程卸載。

          除了上述流程,有些頁(yè)面還擁有 Service Worker (服務(wù)工作線程),Service Worker 讓開(kāi)發(fā)者對(duì)本地緩存及判斷何時(shí)從網(wǎng)絡(luò)上獲取信息有了更多的控制權(quán),如果 Service Worker 被設(shè)置為從本地 cache 中加載數(shù)據(jù),那么就沒(méi)有必要從網(wǎng)上獲取更多數(shù)據(jù)了。

          值得注意的是 service worker 也是運(yùn)行在渲染進(jìn)程中的 JS 代碼,因此對(duì)于擁有 Service Worker 的頁(yè)面,上述流程有些許的不同。

          當(dāng)有 Service Worker 被注冊(cè)時(shí),其作用域會(huì)被保存,當(dāng)有導(dǎo)航時(shí),network thread 會(huì)在注冊(cè)過(guò)的 Service Worker 的作用域中檢查相關(guān)域名,如果存在對(duì)應(yīng)的 Service worker,UI thread 會(huì)找到一個(gè) renderer process 來(lái)處理相關(guān)代碼,Service Worker 可能會(huì)從 cache 中加載數(shù)據(jù),從而終止對(duì)網(wǎng)絡(luò)的請(qǐng)求,也可能從網(wǎng)上請(qǐng)求新的數(shù)據(jù)。


          Service Worker 依據(jù)具體情形做處理。

          關(guān)于 Service Worker 的更多內(nèi)容可參考:

          https://developers.google.com/web/fundamentals/primers/service-workers/lifecycle

          如果 Service Worker 最終決定通過(guò)網(wǎng)上獲取數(shù)據(jù),Browser 進(jìn)程 和 renderer 進(jìn)程的交互其實(shí)會(huì)延后數(shù)據(jù)的請(qǐng)求時(shí)間 。Navigation Preload 是一種與 Service Worker 并行的加速加載資源的機(jī)制,服務(wù)端通過(guò)請(qǐng)求頭可以識(shí)別這類請(qǐng)求,而做出相應(yīng)的處理。

          更多內(nèi)容可參考:

          https://developers.google.com/web/updates/2017/02/navigation-preload

          渲染進(jìn)程是如何工作的?

          渲染進(jìn)程幾乎負(fù)責(zé) Tab 內(nèi)的所有事情,渲染進(jìn)程的核心目的在于轉(zhuǎn)換 HTML CSS JS 為用戶可交互的 web 頁(yè)面。渲染進(jìn)程中主要包含以下線程:


          渲染進(jìn)程包含的線程

          1. 主線程 Main thread

          2. 工作線程 Worker thread

          3. 排版線程 Compositor thread

          4. 光柵線程 Raster thread

          后文我們將逐步介紹不同線程的職責(zé),在此之前我們先看看渲染的流程。

          1. 構(gòu)建 DOM

          當(dāng)渲染進(jìn)程接收到導(dǎo)航的確認(rèn)信息,開(kāi)始接受 HTML 數(shù)據(jù)時(shí),主線程會(huì)解析文本字符串為 DOM。

          渲染 html 為 DOM 的方法由 HTML Standard 定義。

          2. 加載次級(jí)的資源

          網(wǎng)頁(yè)中常常包含諸如圖片,CSS,JS 等額外的資源,這些資源需要從網(wǎng)絡(luò)上或者 cache 中獲取。主進(jìn)程可以在構(gòu)建 DOM 的過(guò)程中會(huì)逐一請(qǐng)求它們,為了加速 preload scanner 會(huì)同時(shí)運(yùn)行,如果在 html 中存在 <img><link> 等標(biāo)簽,preload scanner 會(huì)把這些請(qǐng)求傳遞給 Browser process 中的 network thread 進(jìn)行相關(guān)資源的下載。

          3.JS 的下載與執(zhí)行

          當(dāng)遇到 <script> 標(biāo)簽時(shí),渲染進(jìn)程會(huì)停止解析 HTML,而去加載,解析和執(zhí)行 JS 代碼,停止解析 html 的原因在于 JS 可能會(huì)改變 DOM 的結(jié)構(gòu)(使用諸如 documwnt.write()等 API)。

          不過(guò)開(kāi)發(fā)者其實(shí)也有多種方式來(lái)告知瀏覽器應(yīng)對(duì)如何應(yīng)對(duì)某個(gè)資源,比如說(shuō)如果在<script> 標(biāo)簽上添加了 async 或 defer 等屬性,瀏覽器會(huì)異步的加載和執(zhí)行 JS 代碼,而不會(huì)阻塞渲染。更多的方法可參考 Resource Prioritization – Getting the Browser to Help You。

          4. 樣式計(jì)算

          僅僅渲染 DOM 還不足以獲知頁(yè)面的具體樣式,主進(jìn)程還會(huì)基于 CSS 選擇器解析 CSS 獲取每一個(gè)節(jié)點(diǎn)的最終的計(jì)算樣式值。即使不提供任何 CSS,瀏覽器對(duì)每個(gè)元素也會(huì)有一個(gè)默認(rèn)的樣式。


          渲染進(jìn)程主線程計(jì)算每一個(gè)元素節(jié)點(diǎn)的最終樣式值

          5. 獲取布局

          想要渲染一個(gè)完整的頁(yè)面,除了獲知每個(gè)節(jié)點(diǎn)的具體樣式,還需要獲知每一個(gè)節(jié)點(diǎn)在頁(yè)面上的位置,布局其實(shí)是找到所有元素的幾何關(guān)系的過(guò)程。其具體過(guò)程如下:

          通過(guò)遍歷 DOM 及相關(guān)元素的計(jì)算樣式,主線程會(huì)構(gòu)建出包含每個(gè)元素的坐標(biāo)信息及盒子大小的布局樹(shù)。布局樹(shù)和 DOM 樹(shù)類似,但是其中只包含頁(yè)面可見(jiàn)的元素,如果一個(gè)元素設(shè)置了 display:none ,這個(gè)元素不會(huì)出現(xiàn)在布局樹(shù)上,偽元素雖然在 DOM 樹(shù)上不可見(jiàn),但是在布局樹(shù)上是可見(jiàn)的。


          6. 繪制各元素

          即使知道了不同元素的位置及樣式信息,我們還需要知道不同元素的繪制先后順序才能正確繪制出整個(gè)頁(yè)面。在繪制階段,主線程會(huì)遍歷布局樹(shù)以創(chuàng)建繪制記錄。繪制記錄可以看做是記錄各元素繪制先后順序的筆記。


          主線程依據(jù)布局樹(shù)構(gòu)建繪制記錄

          7. 合成幀

          熟悉 PS 等繪圖軟件的童鞋肯定對(duì)圖層這一概念不陌生,現(xiàn)代 Chrome 其實(shí)利用了這一概念來(lái)組合不同的層。

          復(fù)合是一種分割頁(yè)面為不同的層,并單獨(dú)柵格化,隨后組合為幀的技術(shù)。不同層的組合由 compositor 線程(合成器線程)完成。

          主線程會(huì)遍歷布局樹(shù)來(lái)創(chuàng)建層樹(shù)(layer tree),添加了 will-change CSS 屬性的元素,會(huì)被看做單獨(dú)的一層。


          主線程遍歷布局樹(shù)生成層樹(shù)

          你可能會(huì)想給每一個(gè)元素都添加上 will-change,不過(guò)組合過(guò)多的層也許會(huì)比在每一幀都柵格化頁(yè)面中的某些小部分更慢。為了更合理的使用層,可參考 堅(jiān)持僅合成器的屬性和管理層計(jì)數(shù) 。

          一旦層樹(shù)被創(chuàng)建,渲染順序被確定,主線程會(huì)把這些信息通知給合成器線程,合成器線程會(huì)柵格化每一層。有的層的可以達(dá)到整個(gè)頁(yè)面的大小,因此,合成器線程將它們分成多個(gè)磁貼,并將每個(gè)磁貼發(fā)送到柵格線程,柵格線程會(huì)柵格化每一個(gè)磁貼并存儲(chǔ)在 GPU 顯存中。


          柵格線程會(huì)柵格化每一個(gè)磁貼并存儲(chǔ)在 GPU 顯存中

          一旦磁貼被光柵化,合成器線程會(huì)收集稱為繪制四邊形的磁貼信息以創(chuàng)建合成幀。

          合成幀隨后會(huì)通過(guò) IPC 消息傳遞給瀏覽器進(jìn)程,由于瀏覽器的 UI 改變或者其它拓展的渲染進(jìn)程也可以添加合成幀,這些合成幀會(huì)被傳遞給 GPU 用以展示在屏幕上,如果滾動(dòng)發(fā)生,合成器線程會(huì)創(chuàng)建另一個(gè)合成幀發(fā)送給 GPU。


          合成器線程會(huì)發(fā)送合成幀給 GPU 渲染

          合成器的優(yōu)點(diǎn)在于,其工作無(wú)關(guān)主線程,合成器線程不需要等待樣式計(jì)算或者 JS 執(zhí)行,這就是為什么合成器相關(guān)的動(dòng)畫(huà) 最流暢,如果某個(gè)動(dòng)畫(huà)涉及到布局或者繪制的調(diào)整,就會(huì)涉及到主線程的重新計(jì)算,自然會(huì)慢很多。

          瀏覽器對(duì)事件的處理

          瀏覽器通過(guò)對(duì)不同事件的處理來(lái)滿足各種交互需求,這一部分我們一起看看從瀏覽器的視角,事件是什么,在此我們先主要考慮鼠標(biāo)事件。

          在瀏覽器的看來(lái),用戶的所有手勢(shì)都是輸入,鼠標(biāo)滾動(dòng),懸置,點(diǎn)擊等等都是。

          當(dāng)用戶在屏幕上觸發(fā)諸如 touch 等手勢(shì)時(shí),首先收到手勢(shì)信息的是 Browser process, 不過(guò) Browser process 只會(huì)感知到在哪里發(fā)生了手勢(shì),對(duì) tab 內(nèi)內(nèi)容的處理是還是由渲染進(jìn)程控制的。

          事件發(fā)生時(shí),瀏覽器進(jìn)程會(huì)發(fā)送事件類型及相應(yīng)的坐標(biāo)給渲染進(jìn)程,渲染進(jìn)程隨后找到事件對(duì)象并執(zhí)行所有綁定在其上的相關(guān)事件處理函數(shù)。


          事件從瀏覽器進(jìn)程傳送給渲染進(jìn)程

          前文中,我們提到過(guò)合成器可以獨(dú)立于主線程之外通過(guò)合成柵格化層平滑的處理滾動(dòng)。如果頁(yè)面中沒(méi)有綁定相關(guān)事件,組合器線程可以獨(dú)立于主線程創(chuàng)建組合幀。如果頁(yè)面綁定了相關(guān)事件處理器,主線程就不得不出來(lái)工作了。這時(shí)候合成器線程會(huì)怎么處理呢?

          這里涉及到一個(gè)專業(yè)名詞「理解非快速滾動(dòng)區(qū)域(non-fast scrollable region)」由于執(zhí)行 JS 是主線程的工作,當(dāng)頁(yè)面合成時(shí),合成器線程會(huì)標(biāo)記頁(yè)面中綁定有事件處理器的區(qū)域?yàn)?non-fast scrollable region ,如果存在這個(gè)標(biāo)注,合成器線程會(huì)把發(fā)生在此處的事件發(fā)送給主線程,如果事件不是發(fā)生在這些區(qū)域,合成器線程則會(huì)直接合成新的幀而不用等到主線程的響應(yīng)。


          涉及 non-fast scrollable region 的事件,合成器線程會(huì)通知主線程進(jìn)行相關(guān)處理。

          web 開(kāi)發(fā)中常用的事件處理模式是事件委托,基于事件冒泡,我們常常在最頂層綁定事件:

          復(fù)制代碼

          document.body.addEventListener('touchstart', 
          event => {
           if (event.target === area) {
           event.preventDefault();
           }
          }
          );
           
          

          上述做法很常見(jiàn),但是如果從瀏覽器的角度看,整個(gè)頁(yè)面都成了 non-fast scrollable region 了。

          這意味著即使操作的是頁(yè)面無(wú)綁定事件處理器的區(qū)域,每次輸入時(shí),合成器線程也需要和主線程通信并等待反饋,流暢的合成器獨(dú)立處理合成幀的模式就失效了。


          由于事件綁定在最頂部,整個(gè)頁(yè)面都成為了 non-fast scrollable region。

          為了防止這種情況,我們可以為事件處理器傳遞 passive: true 做為參數(shù),這樣寫(xiě)就能讓瀏覽器即監(jiān)聽(tīng)相關(guān)事件,又讓組合器線程在等等主線程響應(yīng)前構(gòu)建新的組合幀。

          復(fù)制代碼

          document.body.addEventListener('touchstart', 
          event => {
           if (event.target === area) {
           event.preventDefault()
           }
           }, {passive: true}
          );
           
          

          不過(guò)上述寫(xiě)法可能又會(huì)帶來(lái)另外一個(gè)問(wèn)題,假設(shè)某個(gè)區(qū)域你只想要水平滾動(dòng),使用 passive: true 可以實(shí)現(xiàn)平滑滾動(dòng),但是垂直方向的滾動(dòng)可能會(huì)先于event.preventDefault()發(fā)生,此時(shí)可以通過(guò) event.cancelable 來(lái)防止這種情況。

          復(fù)制代碼

          document.body.addEventListener('pointermove', event => {
           if (event.cancelable) {
           event.preventDefault(); // block the native scroll
           /*
           * do what you want the application to do here
           */
           } 
          }, {passive: true});
           
          

          也可以使用 css 屬性 touch-action 來(lái)完全消除事件處理器的影響,如:

          復(fù)制代碼

          #area { 
           touch-action: pan-x; 
          }
           
          

          查找到事件對(duì)象

          當(dāng)組合器線程發(fā)送輸入事件給主線程時(shí),主線程首先會(huì)進(jìn)行命中測(cè)試(hit test)來(lái)查找對(duì)應(yīng)的事件目標(biāo),命中測(cè)試會(huì)基于渲染過(guò)程中生成的繪制記錄( paint records )查找事件發(fā)生坐標(biāo)下存在的元素。


          主線程依據(jù)繪制記錄查找事件相關(guān)元素。

          事件的優(yōu)化

          一般我們屏幕的刷新速率為 60fps,但是某些事件的觸發(fā)量會(huì)不止這個(gè)值,出于優(yōu)化的目的,Chrome 會(huì)合并連續(xù)的事件 (如 wheel, mousewheel, mousemove, pointermove, touchmove ),并延遲到下一幀渲染時(shí)候執(zhí)行 。

          而如 keydown, keyup, mouseup, mousedown, touchstart, 和 touchend 等非連續(xù)性事件則會(huì)立即被觸發(fā)。


          Chrome 會(huì)合并連續(xù)事件到下一幀觸發(fā)。

          合并事件雖然能提示性能,但是如果你的應(yīng)用是繪畫(huà)等,則很難繪制一條平滑的曲線了,此時(shí)可以使用 getCoalescedEvents API 來(lái)獲取組合的事件。示例代碼如下:

          復(fù)制代碼

          window.addEventListener('pointermove', event => {
           const events = event.getCoalescedEvents();
           for (let event of events) {
           const x = event.pageX;
           const y = event.pageY;
           // draw a line using x and y coordinates.
           }
          });
           
          



          花了好久來(lái)整理上面的內(nèi)容,整理的過(guò)程收獲還挺大的,也希望這篇筆記能對(duì)你有所啟發(fā),如果有任何疑問(wèn),歡迎一起來(lái)討論。

          本文經(jīng)作者授權(quán)轉(zhuǎn)載,原文鏈接為:

          https://zhuanlan.zhihu.com/p/47407398

          參考鏈接

          • https://developers.google.com/web/updates/2018/09/inside-browser-part1
          • https://developers.google.com/web/updates/2018/09/inside-browser-part2
          • https://developers.google.com/web/updates/2018/09/inside-browser-part3
          • https://developers.google.com/web/updates/2018/09/inside-browser-part4
          • https://www.html5rocks.com/zh/tutorials/internals/howbrowserswork/#Layered_representation

          解一定的技術(shù)原理,對(duì)產(chǎn)品經(jīng)理而言是有益處的。本文講述的圖像處理的基本思路,希望大家能夠?qū)Ξ?dāng)前圖像處理技術(shù)有一定了解。

          現(xiàn)在有個(gè)概念叫泛產(chǎn)品經(jīng)理,這個(gè)概念本身是好的,核心說(shuō)的是產(chǎn)品思維,但是在工作上我認(rèn)為還是有一定誤導(dǎo)性。產(chǎn)品經(jīng)理在工作中要突出自己的核心價(jià)值與職業(yè)壁壘,如果無(wú)法構(gòu)建良好的職業(yè)壁壘,就會(huì)面臨中年危機(jī)帶來(lái)的挑戰(zhàn)。

          人工智能相對(duì)的技術(shù)內(nèi)容是塑造職業(yè)壁壘的有力武器,并非要求產(chǎn)品經(jīng)理能夠自己寫(xiě)代碼開(kāi)發(fā)產(chǎn)品,而且在了解技術(shù)原理后,能夠?qū)I(yè)務(wù)快速高效的轉(zhuǎn)化為可實(shí)施的產(chǎn)品問(wèn)題,對(duì)于人工智能相關(guān)的產(chǎn)品更加重要。所有了解一定的技術(shù)原理,對(duì)產(chǎn)品經(jīng)理而言是有益處的。本文講述的圖像處理的基本思路,希望大家能夠?qū)Ξ?dāng)前圖像處理技術(shù)有一定了解。

          卷積神經(jīng)網(wǎng)絡(luò)(Convolutional Neural Network, CNN)是一種前饋神經(jīng)網(wǎng)絡(luò),是當(dāng)今圖像處理的主流技術(shù)。說(shuō)起CNN卷積網(wǎng)絡(luò),不得不說(shuō)2012 年Alex Krizhevsky 憑借它們贏得了那一年的 ImageNet 大賽(由斯坦福大學(xué)李飛飛發(fā)起的世界級(jí)人工智能大賽),AlexNet將圖像分類誤差記錄從 26% 降低到 15%,之后很多公司開(kāi)始將深度學(xué)習(xí)作為的核心技術(shù)發(fā)展。Facebook、谷歌、亞馬遜等知名公司都利用卷積網(wǎng)絡(luò)進(jìn)行圖像識(shí)別,商品推送等工作。

          CNN卷積神經(jīng)網(wǎng)絡(luò)是一個(gè)大家族,對(duì)圖像而言主要有以下4個(gè)關(guān)鍵技術(shù)應(yīng)用。

          1. 物體定位:預(yù)測(cè)包含主要物體的圖像區(qū)域,以便識(shí)別區(qū)域中的物體。
          2. 物體識(shí)別:針對(duì)分割好的目標(biāo)進(jìn)行分類。
          3. 目標(biāo)分割:將圖像目標(biāo)分割出來(lái),針對(duì)圖像上的像素進(jìn)行歸屬,例中如人類、建筑物等。
          4. 關(guān)鍵點(diǎn)檢測(cè):從圖像中檢測(cè)目標(biāo)物體上某關(guān)鍵點(diǎn)的位置,例如人類面部關(guān)鍵點(diǎn)信息。

          CNN網(wǎng)絡(luò)訓(xùn)練數(shù)據(jù)集是公開(kāi)的,支持全球的開(kāi)發(fā)者進(jìn)行下載訓(xùn)練模型數(shù)據(jù)集:

          (1)MNIST:最受歡迎的深度學(xué)習(xí)數(shù)據(jù)集之一。手寫(xiě)數(shù)字?jǐn)?shù)據(jù)集,包含一組60,000個(gè)示例的訓(xùn)練集和一個(gè)包含10,000個(gè)示例的測(cè)試集。http://deeplearning.net/tutorial/gettingstarted.html

          (2)ImageNet:李飛飛創(chuàng)立的全球視覺(jué)識(shí)別挑戰(zhàn)賽數(shù)據(jù)集(ILSVRC)。http://image-net.org/index

          (3)PASCAL:標(biāo)準(zhǔn)化的優(yōu)秀的數(shù)據(jù)集,數(shù)據(jù)集可以用于圖像分類、目標(biāo)檢測(cè)、圖像分割。http://host.robots.ox.ac.uk/pascal/VOC/

          (4)MS-COCO:COCO是一個(gè)大型的、豐富的物體檢測(cè),分割和字幕數(shù)據(jù)集。http://cocodataset.org/

          為什么要用CNN來(lái)處理圖像呢?

          原因很簡(jiǎn)單,因?yàn)槟茉诙虝r(shí)間內(nèi)提取圖像特征。

          一般來(lái)講,普通神經(jīng)網(wǎng)絡(luò)將輸入層和隱含層進(jìn)行全連接(Full Connected),從而保證系統(tǒng)能夠提取張圖像的特征。從算力的角度來(lái)分析,較小的圖像從整幅圖像中計(jì)算特征是可行的。比如提取一張28×28的小照片的特征,當(dāng)前CPU還夠用。

          但是,如果提取大的圖像(如 96×96 的圖像),要使用這種普通神經(jīng)網(wǎng)絡(luò)全全連接方法來(lái)學(xué)習(xí)整幅圖像上的特征,將變得非常耗時(shí)。需要設(shè)計(jì)個(gè)輸入單元,如果要學(xué)習(xí) 100 個(gè)特征,那么就有個(gè)參數(shù)需要進(jìn)行運(yùn)算。

          相比之下,96×96 的圖像計(jì)算過(guò)程比28×28圖像的處理過(guò)程慢100倍。大家都明白當(dāng)前的相片動(dòng)不動(dòng)就是高清大圖,普通神經(jīng)網(wǎng)絡(luò)按照全連接的方式無(wú)法預(yù)計(jì)何時(shí)才能處理完。

          下面的內(nèi)容是本節(jié)的重點(diǎn)部分,我們具體來(lái)講述一下CNN網(wǎng)絡(luò)的實(shí)現(xiàn)過(guò)程。

          1. 圖像的輸入

          我們首先要搞清楚一張照片是如何輸入到神經(jīng)網(wǎng)絡(luò)中的。眾所周知,計(jì)算機(jī)適合處理的是矩陣運(yùn)算,所以必須要把圖片轉(zhuǎn)換成矩陣后計(jì)算機(jī)才能認(rèn)識(shí)。所有的彩色圖像都由紅綠藍(lán)(RGB)疊加而成,成為圖像的三個(gè)通道,一張圖片在計(jì)算機(jī)中存儲(chǔ)也是通過(guò)這三個(gè)矩陣完成的。

          圖4-23圖的色彩通道

          如圖4-23所示,一張64*64個(gè)像素大小的圖片(例如白色可以表示成RGB(255,255,255),可以用3個(gè)64*64大小的矩陣來(lái)代表這個(gè)圖。上面指畫(huà)三個(gè)5 * 4的矩陣來(lái)代表64*64的全尺寸矩陣。RGB這三個(gè)矩陣稱為為圖像的3個(gè)通道,也作為神經(jīng)網(wǎng)絡(luò)的輸入數(shù)據(jù)。

          2. 卷積神經(jīng)網(wǎng)絡(luò)的組成

          與其他神經(jīng)網(wǎng)絡(luò)相同,CNN網(wǎng)絡(luò)同樣也包含輸入層、隱藏層、輸出層幾大部分,卷積神經(jīng)網(wǎng)絡(luò)的主要運(yùn)算過(guò)程如圖4-24所示。

          圖4-24卷積神經(jīng)網(wǎng)絡(luò)處理過(guò)程

          卷積層(Convolutional layer):卷積層由多個(gè)卷積單元組成,每個(gè)卷積單元的參數(shù)都是通過(guò)反向傳播算法優(yōu)化得到的。卷積運(yùn)算主要為了提取圖像的特征,隨著卷積層的增加,多層網(wǎng)絡(luò)可以提取更為復(fù)雜的圖像特征。

          線性整流(Rectified Linear Units layer, ReLU layer):主要指的是激活函數(shù)運(yùn)算(Activation function)使用線性整流的ReLu函數(shù)(Rectified Linear Units, ReLU)。

          池化層(Pooling layer):在卷積之后圖像的維度特征依然很多,將特征矩陣分割成幾個(gè)單個(gè)區(qū)塊,取其最大值或平均值,起到了降維的作用。

          全連接層(Fully-Connected layer):把所有局部特征以及各通道的特征矩陣結(jié)合變?yōu)橄蛄看恚?jì)算最后每一類的得分。

          3. 計(jì)算過(guò)程

          CNN網(wǎng)絡(luò)的計(jì)算過(guò)程如圖XXX,每個(gè)組成模塊代表了不同的計(jì)算內(nèi)容。

          (1)數(shù)據(jù)規(guī)則化

          彩色圖像的輸入通常先要分解為R(紅)G(綠)B(藍(lán))三個(gè)通道,其中每個(gè)值介于0~255之間。

          (2)卷積運(yùn)算(Convolution)

          前面講到,由于普通的神經(jīng)網(wǎng)絡(luò)對(duì)于輸入與隱層采用全連接的方式進(jìn)行特征提取,在處理圖像時(shí),稍微大一些的圖將會(huì)導(dǎo)致計(jì)算量巨大而變得十分緩慢。卷積運(yùn)算正是為了解決這一問(wèn)題,每個(gè)隱含單元只能連接輸入單元的一部分,我們可以理解為是一種特征的提取方法。

          首先我們來(lái)明確幾個(gè)基礎(chǔ)概念:深度(depth)、步長(zhǎng)(stride)、補(bǔ)零(zero-padding)、卷積核(convolution kernel)。

          深度(depth):深度指的是圖的深度與它控制輸出單元的深度,也表示為連接同一塊區(qū)域的神經(jīng)元個(gè)數(shù)。

          步幅(stride):用來(lái)描述卷積核移動(dòng)的步長(zhǎng)。

          補(bǔ)零(zero-padding):通過(guò)對(duì)圖片邊緣補(bǔ)零來(lái)填充圖片邊緣,從而控制輸出單元的空間大小。

          卷積核(convolution kernel):在輸出圖像中每一個(gè)像素是輸入圖像中一個(gè)小區(qū)域中像素的加權(quán)平均的權(quán)值函數(shù)。卷積核可以有多個(gè),卷積核參數(shù)可以通過(guò)誤差反向傳播來(lái)進(jìn)行訓(xùn)練。

          如圖4-25為步長(zhǎng)=1的卷積計(jì)算過(guò)程,卷積核依次向右移動(dòng)進(jìn)行卷積運(yùn)算得到相應(yīng)結(jié)果。

          圖4-25 卷積運(yùn)算過(guò)程

          為圖像計(jì)算可以對(duì)邊緣進(jìn)行補(bǔ)零,可見(jiàn)這個(gè)過(guò)程改變了圖像的運(yùn)算大小,如圖4-26所示。

          卷積運(yùn)算的過(guò)程其實(shí)非常簡(jiǎn)單,過(guò)程如圖4-27描述,可以概括為公式(4.3.6)。其中B代表卷積后的結(jié)果,K是卷積核,A為圖像的輸入矩陣。

          圖4-27 卷積運(yùn)算過(guò)程

          如圖4-27所示,可見(jiàn)卷積核K為2*2的卷積核,詳細(xì)運(yùn)算過(guò)程如下。

          全部圖像卷積運(yùn)算可以通過(guò)公式(4.3.6)進(jìn)行。

          (3)激活

          CNN卷積神經(jīng)網(wǎng)絡(luò)在卷積后需要經(jīng)過(guò)激活過(guò)程,當(dāng)前通常使用的激活函數(shù)是Relu函數(shù)。Relu函數(shù)的主要特點(diǎn)在之前的章節(jié)已經(jīng)講過(guò)。從函數(shù)的圖像上來(lái)看,單側(cè)抑制,相對(duì)寬闊的興奮邊界,具有稀疏激活性的特點(diǎn)。

          (4)池化(Pooling)

          池化的目的是提取特征,減少向下一個(gè)階段傳遞的數(shù)據(jù)量。池化操作相對(duì)于對(duì)每個(gè)深度切片是獨(dú)立,池化規(guī)模一般為像素的 2*2,與卷積運(yùn)算相比,池化層運(yùn)算一般有以下幾種:

          1. 最大池化(Max Pooling):取4個(gè)點(diǎn)數(shù)值的最大值。這是最常用的池化算法。
          2. 均值池化(Mean Pooling):取4個(gè)點(diǎn)數(shù)值的均值。
          3. 高斯池化(Gauss Pooling):按照高斯模糊的方法。

          如圖4-28,描述了最大池化的計(jì)算方法。

          圖4-28 池化運(yùn)算過(guò)程

          (5)全連接(Fully-connected layer)

          全連接層一般出現(xiàn)最后幾步,在卷積神經(jīng)網(wǎng)絡(luò)中起到“分類器”的作用。如果說(shuō)卷積層、池化層和激活函數(shù)層等操作是將原始數(shù)據(jù)映射到隱層特征空間的話,全連接層則起到將學(xué)到的“分布式特征表示”映射到樣本標(biāo)記空間的作用。全連接過(guò)程是對(duì)矩陣的展開(kāi)過(guò)程,也可以理解為輸出矩陣與一個(gè)1*1的卷積核進(jìn)行卷積運(yùn)算,最后展開(kāi)為一個(gè)1*n的向量。

          在卷積神經(jīng)網(wǎng)絡(luò)中,全連接層一般使用Softmax函數(shù)來(lái)進(jìn)行分類。Softmax函數(shù)適用于數(shù)據(jù)分類,用于保證每個(gè)分類概率總和為1。

          卷積神經(jīng)網(wǎng)絡(luò)(CNN)的計(jì)算過(guò)程雖然講解繁瑣,但對(duì)于了解深刻理解神經(jīng)網(wǎng)絡(luò)算法非常有益。卷積神經(jīng)網(wǎng)絡(luò)經(jīng)過(guò)近30年的發(fā)展擁有多條網(wǎng)絡(luò)發(fā)展分支,并且持續(xù)高速發(fā)展之中。其中有網(wǎng)絡(luò)層數(shù)加深的VGG16與VGG19等,有卷積模塊增強(qiáng)的NIN網(wǎng)絡(luò)等,從分類任務(wù)向目標(biāo)檢測(cè)任務(wù)過(guò)度的新型網(wǎng)絡(luò)R-CNN等,圖4-29展示了卷積神經(jīng)網(wǎng)絡(luò)的不同發(fā)展分支。

          #專欄作家#

          白白,人人都是產(chǎn)品經(jīng)理專欄作家。公眾號(hào):白白說(shuō)話(xiaob-talk)。醫(yī)藥行業(yè)資深產(chǎn)品專家,負(fù)責(zé)人工智能行業(yè)類產(chǎn)品綜合架構(gòu)與技術(shù)開(kāi)發(fā)。在行業(yè)云產(chǎn)品架構(gòu),藥物設(shè)計(jì)AI輔助、醫(yī)療知識(shí)圖譜等領(lǐng)域有深入研究。

          本文原創(chuàng)發(fā)布于人人都是產(chǎn)品經(jīng)理。未經(jīng)許可,禁止轉(zhuǎn)載。

          題圖來(lái)自Unsplash,基于 CC0 協(xié)議


          主站蜘蛛池模板: 久久久精品一区二区三区 | 色婷婷综合久久久久中文一区二区| 亚洲综合在线成人一区| 精品无码一区二区三区爱欲| 无码一区二区三区视频| 蜜桃臀无码内射一区二区三区| 日本一区二区三区免费高清在线| 欧美日韩国产免费一区二区三区| 风间由美性色一区二区三区| 国产一区二区四区在线观看| 国产精品 一区 在线| 国产成人高清亚洲一区91| 国产主播在线一区| 亚洲熟女乱色一区二区三区| 91在线一区二区三区| 精品无码人妻一区二区三区| 精品无码人妻一区二区三区| 人妻无码一区二区三区免费| 精品三级AV无码一区| 日韩免费视频一区二区| 无码精品人妻一区二区三区中| 精品国产一区二区三区久久| 欧洲精品码一区二区三区| 中文字幕一区二区三区在线播放| 亚洲国产国产综合一区首页| 色综合视频一区中文字幕| 一区二区视频传媒有限公司| AV天堂午夜精品一区二区三区| 无码人妻AⅤ一区二区三区水密桃 无码欧精品亚洲日韩一区夜夜嗨 无码毛片一区二区三区中文字幕 无码毛片一区二区三区视频免费播放 | 亚洲美女一区二区三区| 精品无人区一区二区三区在线 | 国产一区二区三区在线免费观看 | 国产福利酱国产一区二区| 国产一区三区三区| 风间由美性色一区二区三区| 国产伦精品一区二区三区| 男女久久久国产一区二区三区| 国产精品高清一区二区三区不卡 | 精品乱码一区内射人妻无码| 高清国产精品人妻一区二区| 亚洲Av高清一区二区三区|