史密斯電動獲得中聚電池4200萬美元承諾投資

美國純電動中型商用車生產商史密斯電動車公司(Smith Electric Vehicles)昨(12)日宣佈,該公司已經獲得了中聚電池有限公司的4200萬美元承諾投資。首輪200萬美元投資已經到位,剩餘資金將分兩輪進行投資,投資的前提條件是兩家公司需在未來幾個月取得具有里程碑意義的進展。

中聚電池是鋰離子電池及相關電動汽車產品製造商,此次進行4200萬美元投資讓中聚電池成為了史密斯電動的戰略性股東。

根據合作協定,中聚電池將成為史密斯電動的獨家電池供應商,而相關汽車應用領域的電池將會與史密斯電動的平臺和客戶要求實現相容。中聚電池還將成為某些電動汽車零部件的優先供應商,不過這些零部件要能在其下屬杭州工廠進行生產。

中聚電池公司主席兼執行董事曹忠先生說:「史密斯是一家國際知名的電動汽車供應商。中聚電池不久將改名為五龍電動車(集團),而史密斯和我們的專長會進行結合,再配以對替代能源汽車的宏觀補貼政策,這會讓我們獲得獨一無二的有利地位,能夠利用快速發展的中美電動汽車市場的機遇。」

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

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

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

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

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

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

※回頭車貨運收費標準

三星松下等忙插脚新能源汽車電池業務

隨著新能源汽車概念火速席卷全球,其配置電池亦迅速走熱,獲得不少大企業關注。據了解,近日消費電子行業巨頭三星、松下也陸續宣布進軍汽車電池市場。   據悉,三星集團旗下的三星SDI公司於本月初正式宣布將與福特公司合作開發高效輕便的電池技術,該電池僅重約10磅,相較普通混合型電池輕40%。   此外,值得注意的是,除福特外,三星亦與寶馬、克萊斯勒和馬恆達等知名企業間存在合作。2013年9月推出的純電動汽車「寶馬i3」搭載的就是三星SDI生產的世界最大容量60Ah級電池。   無獨有偶,同樣知名的消費電子行業松下亦對汽車電池表現出難得興趣。據松下公司透露,公司與電動汽車巨頭特斯拉共建超級電池廠的意向即將變為現實,雙方已成立研發團隊,並計劃在6月開工建設。   公開資料顯示,今年2月,松下與特斯拉宣布將共同投資建立鋰離子電池工廠,以滿足後者年產50萬輛電動汽車的產能需求,並將電池組每千瓦時成本降低超過30%。此前,雙方於2011年簽署協議,松下計劃在4年內為特斯拉提供6.4億塊汽車用鋰電池,這一供貨量後來增加至18億塊,約可為20萬~30萬輛電動汽車提供電池。

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

【其他文章推薦】

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

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

※回頭車貨運收費標準

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

※超省錢租車方案

LG Chem看中大陸電動車市場 將設第三座海外電池廠

中國大陸對抗空汙,大力推動環保車,LG Chem看好當地前景,15日宣佈將在中國設立合資電池工廠,目前已進入挑選規則合作對象的最後階段。

LG Chem表示,今年下半會公佈合資電池廠的設廠地點和其他細節。發言人Song Choong-sup強調,這將是LG Chem第三座海外電池工廠,該公司在美國密西根州和中國南京設有工廠。IHS預估,2020年中國電動車的電池市場將成長20倍。

中國第一汽車集團和長安汽車之前就已和LG Chem敲定協議,而最近,LG Chem和中國最大車廠上海汽車集團以及觀致汽車簽訂電池供應合約。Song證實,上汽的插電式油電混合車和觀致的次世代電動車將使用LG電池。

據稱,LG高層一致認為全球科技的未來主軸在聯網汽車和無人駕駛車,LG Display計畫明年成為全球車用面板的頂級供應商,內部主管表示,正與Mercedez、Audi等車廠攜手研發高階顯示面板,他們打算用LG Chem電池廠的客戶,將LG打造為汽車解決方案的供應商,並強調若不隨著時勢改變,將無法生存。

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

【其他文章推薦】

※超省錢租車方案

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

※回頭車貨運收費標準

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

Mysql和Redis數據同步策略

目錄

  • 為什麼對緩存只刪除不更新
  • 先更新數據庫還是先刪除緩存?
  • Cache Aside Pattern
  • Double-Delete
  • Read/Write Through Pattern
  • Write Behind
  • 設置緩存過期時間
  • 總結

為什麼對緩存只刪除不更新

不更新緩存是防止併發更新導致的數據不一致。
所以為了降低數據不一致的概率,不應該更新緩存,而是直接將其刪除,
然後等待下次發生cache miss時再把數據庫中的數據同步到緩存。

先更新數據庫還是先刪除緩存?

有兩個選擇:
1. 先刪除緩存,再更新數據庫
2. 先更新數據庫,再刪除緩存

如果先刪除緩存,有一個明顯的邏輯錯誤:考慮兩個併發操作,線程A刪除緩存后,線程B讀該數據時會發生Cache Miss,然後從數據庫中讀出該數據並同步到緩存中,此時線程A更新了數據庫。
結果導致,緩存中是老數據,數據庫中是新數據,並且之後的讀操作都會直接讀取緩存中的臟數據。(直到key過期被刪除或者被LRU策略踢出)
如果數據庫更新成功后,再刪除緩存,就不會有上面這個問題。
可能是由於數據庫優先,第二種方式也被稱為Cache Aside Pattern。

Cache Aside Pattern

cache aside在絕大多數情況下能做到數據一致性,但是在極端情況仍然存在問題。

  • 首先更新數據庫(A)和刪除緩存(B)不是原子操作,任何在A之後B之前的讀操作,都會讀到redis中的舊數據。
    正常情況下操作緩存的速度會很快,通常是毫秒級,臟數據存在的時間極端。
    但是,對超高併發的應用可能會在意這幾毫秒。
  • 更新完數據庫后,線程意外被kill掉(真的很不幸),由於沒有刪除緩存,緩存中的臟數據會一直存在。
  • 線程A讀數據時cache miss,從Mysql中查詢到數據,還沒來得及同步到redis中,
    此時線程B更新了數據庫並把Redis中的舊值刪除。隨後,線程A把之前查到的數據同步到了Redis。
    顯然,此時redis中的是臟數據。
    通常數據庫讀操作比寫操作快很多,所以除非線程A在同步redis前意外卡住了,否則發生上述情況的概率極低。

雖然以上情況都有可能發生,但是發生的概率相比“先刪除緩存再更新數據庫”會低很多。

Double-Delete

前面我們講到先刪除緩存(A)、后更新數據庫(B)的方案有明顯的錯誤,任何發生在A操作和B操作之間的併發讀都會造成數據的最終不一致。
Double-Delete是一種比較笨拙的修補方案,執行過程如下:

1.delete redis cache
2.update database
3.sleep(500ms)
3.delete redis cache

也很好理解,在睡眠500ms后嘗試再次刪除緩存中的臟數據,它通過兩次刪除來盡可能做到數據的最終一致。
其實,Double-Delete在數據一致性上比Cache Aside更靠譜,但是它的代價是昂貴的,
即使,把睡眠時間縮短到100ms,對耗時敏感的應用也不會考慮這種方案。

Read/Write Through Pattern

cache aside是我們自己的應用程序維護兩個數據存儲系統,而Read/Write Through Pattern是把同步數據的問題交給緩存系統了,應用程序不需要關心。
Read Through是指發生cache miss時,緩存系統自動去數據庫加載數據。
Write Through是指如果cache miss,直接更新數據庫,然後返回,如果cache hit,則更新緩存后,由緩存系統自動同步到數據庫。
以Redis為例,通常我們不會把數據庫的數據全部緩存到redis,而是採用一定的數據精簡或壓縮策略,以節省緩存空間。
就是說,讓緩存系統設計出通用的緩存方案不太現實,不過根據自己的業務定製一個在項目內部通用的中間件是可行的。

Write Behind

Write Behind方案在更新數據時,只更新緩存,不更新數據庫。而是由另外一個服務異步的把數據更新到數據庫。
邏輯上,和Linux中的write back很類似。這個設計的好處是,I/O操作很快,因為是純內存操作。
但是由於異步寫庫,可能要犧牲一些數據一致性,譬如突然宕機會丟失所有未寫入數據庫的內存數據。

阿里巴巴的Canal中間件是一種相反的設計,它先更新mysql,然後通過binlog把數據自動同步到redis。
這種方案會全量同步數據到redis,不適合只緩存熱點數據的應用。

設置緩存過期時間

無論採用哪種策略都應該設置緩存的過期時間。
過期時間設置太長,臟數據存在的時間就越長;
過期時間設置太短,大量的cache miss會讓查詢直接進入數據庫。
所以,需要根據業務場景考慮過期時間。

總結

以上沒有哪種方案是完美的,都無法做到強一致性。
我們總要在性能和數據準確性之間做出妥協。
Cache Aside Pattern適用於絕大多數的場景。

https://www.pixelstech.net/article/1562504974-Consistency-between-Redis-Cache-and-SQL-Database
https://coolshell.cn/articles/17416.html
為什麼不更新緩存,而是直接刪除

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

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

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

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

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

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

※回頭車貨運收費標準

正則匹配中的非貪婪匹配不是最短匹配

最近在工作中遇到一個需求,就是找出html中所有錨文字包含 聯繫方式 的超鏈接。剛開始我寫了一個很簡單的正則來解決這個問題<a.*?聯繫方式.*?</a。但是在測試的時候卻發現這個正則表達式並不像我想象的那樣工作。

圖中給出了一個正則表達式匹配的例子,可以看出在這段文字中有兩個匹配,但是第一個匹配所包含的結果已經超出了實際需要的範圍,包含了太多的超鏈接標籤,而我需要的是最短的匹配也就是圖中橫線畫出的範圍,這是怎麼回事?

正則匹配的原理

這要從正則匹配的原理說起,簡單的來說正則匹配是一種貪心的算法。它總是先找到第一個匹配的位置,然後向後繼續匹配其他的表達式符號。對於本文給出的正則表達式,會現在html中找到一個<a標籤,然後之後是.*?,直到找到一個聯繫方式,在這個過程中如果找到了另一個<a,會被當作.*?匹配的部分,而忘記了要匹配表達式的開頭就是<a。也就是說,除非發生失配,正則表達式不會主動地回溯。儘管使用了?來表達非貪婪匹配,也只能限制向後匹配時盡可能地短,而不能縮短已匹配部分的長度。也就是說,非貪婪匹配向後是最短匹配,但是向前不是最短匹配。

對於這個任務,我後來使用了其他效率更高的方法實現了,但是有沒有可能使用正則表達式來完成這個任務呢?

零寬斷言

零寬斷言是一種零寬度的匹配,它匹配到的內容不會保存到匹配結果中去,最終匹配結果只是一個位置而已。
作用是給指定位置添加一個限定條件,用來規定此位置之前或者之後的字符必須滿足限定條件才能使正則中的字表達式匹配成功。

零寬斷言總共有四種

對於這個需求,實際上應該找到離聯繫方式最近的一個<a,也就是說,在<a到聯繫方式之前不能再有其他的<a了。而最開始的正則匹配表達式<a.*?聯繫方式.*?</a中的.*?可以通過.來匹配任意一個字符,在這裏可以使用零寬度負先行斷言來限制.匹配的任何一個字符的右側不能夠再有<a。也就是.(?!<a),再將這個整體重複多次(.(?!<a))*?。這裏引入了一個額外的括號,為了不產生多餘的匹配,可以使用非捕獲組來去除不需要的匹配,最終可以將整個表達式寫成<a(:?.(?!<a))*?聯繫方式.*?</a。

可以看到匹配的範圍已經縮小到最後一個出現的超鏈接。

總結

因為正則表達式實現原理的限制,儘管選擇非貪婪匹配,匹配到的結果也不一定是最短的匹配。
通常正則表達式總是表明了“要匹配什麼”,而通過零寬度負斷言,則可以表明“不匹配什麼”,這比字符集中使用^來取反更加強大。

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

【其他文章推薦】

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

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

※回頭車貨運收費標準

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

※超省錢租車方案

用Python進行實時計算——PyFlink快速入門

Flink 1.9.0及更高版本支持Python,也就是PyFlink。

在最新版本的Flink 1.10中,PyFlink支持Python用戶定義的函數,使您能夠在Table API和SQL中註冊和使用這些函數。但是,聽完所有這些后,您可能仍然想知道PyFlink的架構到底是什麼?作為PyFlink的快速指南,本文將回答這些問題。

為什麼需要PyFlink?

Python上的Flink和Flink上的Python

那麼,PyFlink到底是什麼?顧名思義,PyFlink就是Apache Flink與Python的組合,或者說是Python上的Flink。但是Flink on Python是什麼意思?首先,兩者的結合意味着您可以在Python中使用Flink的所有功能。而且,更重要的是,PyFlink還允許您在Flink上使用Python廣泛的生態系統的計算功能,從而可以進一步促進其生態系統的開發。換句話說,這對雙方都是雙贏。如果您更深入地研究這個主題,您會發現Flink框架和Python語言的集成絕不是巧合。

Python和大數據生態系統

python語言與大數據緊密相連。為了理解這一點,我們可以看一下人們正在使用Python解決的一些實際問題。一項用戶調查显示,大多數人都在使用Python進行數據分析和機器學習應用程序。對於此類情況,大數據空間中還解決了一些理想的解決方案。除了擴大大數據產品的受眾範圍之外,Python和大數據的集成還通過將其獨立體繫結構擴展到分佈式體繫結構,極大地增強了Python生態系統的功能。這也解釋了在分析大量數據時對Python的強烈需求。

為什麼選擇Flink和Python?

Python和大數據的集成與其他最近的趨勢一致。但是,再次說明一下,為什麼Flink現在支持Python,而不是Go或R或另一種語言?而且,為什麼大多數用戶選擇PyFlink而不是PySpark和PyHive?

為了理解原因,讓我們首先考慮使用Flink框架的一些優勢:

  • 有利的體繫結構: Flink是具有統一流和批處理功能的純流計算引擎。
  • 新的活力:根據ASF的客觀統計,Flink是2019年最活躍的開源項目。
  • 高可靠性:作為一個開源項目,Flink經過長期測試,並廣泛應用於大數據公司的生產環境中。

接下來,讓我們看看為什麼Flink支持Python而不是其他語言。統計數據显示,Python是繼Java和C之後最受歡迎的語言,並且自2018年以來一直在快速發展。Java和Scala是Flink的默認語言,但是Flink支持Python似乎是合理的。

PyFlink是相關技術發展的必然產物。但是,僅僅了解PyFlink的重要性是不夠的,因為我們的最終目標是使Flink和Python用戶受益並解決實際問題。因此,我們需要進一步探索如何實現PyFlink。

PyFlink架構

要實現PyFlink,我們需要知道要實現的關鍵目標和要解決的核心問題。PyFlink的主要目標是什麼?簡而言之,PyFlink的主要目標如下:

  1. 使所有Flink功能對Python用戶可用。
  2. 在Flink上運行Python的分析和計算功能,以提高Python解決大數據問題的能力。

在此基礎上,讓我們分析實現這些目標需要解決的關鍵問題。

使Flink功能可供Python用戶使用

要實現PyFlink,是否需要像現有Java引擎一樣在Flink上開發Python引擎?答案是NO。嘗試在Flink 1.8版或更早版本中進行,但效果不佳。基本設計原則是以最小的成本實現給定的目標。最簡單但最好的方法是提供一層Python API,並重用現有的計算引擎。

那麼,我們應該為Flink提供哪些Python API?他們對我們很熟悉:高級表API和SQL,以及有狀態的DataStream API。現在,我們越來越接近Flink的內部邏輯,下一步是提供適用於Python的Table API和DataStream API。但是,剩下要解決的關鍵問題到底是什麼呢?

關鍵問題

顯然,關鍵問題在於在Python虛擬機(PyVM)和Java虛擬機(JVM)之間建立握手,這對於Flink支持多種語言至關重要。要解決此問題,我們必須選擇適當的通信技術。

選擇虛擬機通信技術

當前,有兩種解決方案可用於實現PyVM和JVM之間的通信,它們是Beam和Py4J。前者是一個著名的項目,具有多語言和多引擎支持,而後者是用於PyVM和JVM之間通信的專用解決方案。我們可以從幾個不同的角度比較和對比Apache Beam和Py4J,以了解它們之間的區別。首先,考慮一個比喻:要越過一堵牆,Py4J會像痣一樣在其中挖一個洞,而Apache Beam會像大熊一樣把整堵牆推倒。從這個角度來看,使用Apache Beam來實現VM通信有點複雜。簡而言之,這是因為Apache Beam專註於通用性,在極端情況下缺乏靈活性。

除此之外,Flink還需要交互式編程。此外,為了使Flink正常工作,我們還需要確保其API設計中的語義一致性,尤其是在其多語言支持方面。Apache Beam的現有體繫結構無法滿足這些要求,因此答案很明顯,Py4J是支持PyVM和JVM之間通信的最佳選擇。

技術架構

在PyVM和JVM之間建立通信之後,我們已經實現了向Python用戶提供Flink功能的第一個目標。我們已經在Flink 1.9版中實現了這一點。現在,讓我們看一下Flink 1.9版中PyFlink API的體繫結構:

Flink 1.9版使用Py4J來實現虛擬機通信。我們為PyVM啟用了網關,為JVM啟用了網關服務器以接收Python請求。此外,我們還提供了Python API中的TableENV和Table之類的對象,這些對象與Java API中提供的對象相同。因此,編寫Python API的本質是關於如何調用Java API。Flink 1.9版還解決了作業部署問題。它使您可以通過各種方式提交作業,例如運行Python命令以及使用Python Shell和CLI。

但是,此體繫結構提供了哪些優勢?首先,該體繫結構很簡單,並且可以確保Python API和Java API之間的語義一致性。其次,它還提供了與Java作業相當的出色Python作業處理性能。

在Flink上運行Python的分析和計算功能

上一節介紹了如何使Flink功能可供Python用戶使用。本節說明如何在Flink上運行Python函數。通常,我們可以通過以下兩種方式之一在Flink上運行Python函數:

  1. 選擇一個典型的Python類庫,並將其API添加到PyFlink。該方法花費很長時間,因為Python包含太多的類庫。在合併任何API之前,我們需要簡化Python執行。
  2. 基於現有的Flink Table API和Python類庫的特徵,我們可以將所有現有的Python類庫函數視為用戶定義的函數,並將其集成到Flink中。Flink 1.10及更高版本中支持此功能。功能集成的關鍵問題是什麼?同樣,它取決於Python用戶定義函數的執行。

接下來,讓我們為這個關鍵問題選擇一種技術。

選擇執行用戶定義功能的技術

實際上,執行Python用戶定義的函數非常複雜。它不僅涉及虛擬機之間的通信,還涉及以下所有方面:管理Python執行環境,解析Java和Python之間交換的業務數據,將Flink中的狀態後端傳遞給Python以及監視執行狀態。鑒於所有這些複雜性,現在是Apache Beam發揮作用的時候了。作為支持多種引擎和多種語言的大熊,Apache Beam可以在解決這種情況方面做很多工作,所以讓我們看看Apache Beam如何處理執行Python用戶定義的函數。

下面显示了可移植性框架,該框架是Apache Beam的高度抽象的體繫結構,旨在支持多種語言和引擎。當前,Apache Beam支持幾種不同的語言,包括Java,Go和Python。

用戶定義的功能架構

UDF體繫結構不僅需要實現PyVM與JVM之間的通信,還需要在編譯和運行階段滿足不同的要求。在下面的PyLink用戶定義功能架構圖中,JVM中的行為以綠色表示,而PyVM中的行為以藍色表示。讓我們看看編譯期間的局部設計。本地設計依賴於純API映射調用。Py4J用於VM通信。

現在,讓我們看看Python API和Java API在此架構中的工作方式。在Java方面,JobMaster將作業分配給TaskManager,就像處理普通Java作業一樣,並且TaskManager執行任務,這涉及到操作員在JVM和PyVM中的執行。在Python用戶定義的函數運算符中,我們將設計各種gRPC服務,用於JVM和PyVM之間的通信。例如,用於業務數據通信的DataService和用於Python UDF的StateService來調用Java State後端。還將提供許多其他服務,例如日誌記錄和指標。

我們如何使用PyFlink?

了解了PyFlink的體繫結構及其背後的思想之後,我們來看一下PyFlink的特定應用場景,以更好地了解其背後的方式和原因。

PyFlink的應用場景

PyFlink支持哪些業務方案?我們可以從兩個角度分析其應用場景:Python和Java。請記住,PyFlink也適用於Java可以應用的所有情況。

  1. 事件驅動的方案,例如實時數據監控。
  2. 數據分析,例如庫存管理和數據可視化。
  3. 數據管道,也稱為ETL方案,例如日誌解析。
  4. 機器學習,例如有針對性的建議。

您可以在所有這些情況下使用PyFlink。PyFlink也適用於特定於Python的方案,例如科學計算。在如此眾多的應用場景中,您可能想知道現在可以使用哪些特定的PyFlink API。因此,現在我們也來研究這個問題。

PyFlink安裝

在使用任何API之前,您需要安裝PyFlink。當前,要安裝PyFlink,請運行命令:pip install apache-Flink

PyFlink API

PyFlink API與Java Table API完全一致,以支持各種關係和窗口操作。某些易於使用的PyFlink API比SQL API更為強大,例如特定於列操作的API。除了API,PyFlink還提供了多種定義Python UDF的方法。

PyFlink中用戶定義的函數定義

可以擴展ScalarFunction(例如,通過添加指標)以提供更多輔助功能。另外,PyFlink用戶功能函數支持Python支持的所有方法定義,例如lambda,命名函數和可調用函數。

定義完這些方法后,我們可以使用PyFlink Decorators進行標記,並描述輸入和輸出數據類型。我們還可以基於Python的類型提示功能進一步簡化更高版本,以進行類型派生。以下示例將幫助您更好地了解如何定義用戶定義的函數。

定義Python用戶定義函數的一種情況

在本例中,我們將兩個数字相加。首先,為此,導入必要的類,然後定義前面提到的函數。這非常簡單,因此讓我們進行一個實際案例。

PyFlink的未來前景如何?

通常,使用PyFlink進行業務開發很簡單。您可以通過SQL或Table API輕鬆描述業務邏輯,而無需了解基礎實現。讓我們看一下PyFlink的整體前景。

目標驅動路線圖

PyFlink的開發始終受到目標的推動,這些目標是使Flink功能可供Python用戶使用並將Python函數集成到Flink中。根據下面显示的PyFlink路線圖,我們首先在PyVM和JVM之間建立了通信。然後,在Flink 1.9中,我們提供了Python Table API,向Python用戶開放了現有的Flink Table API功能。在Flink 1.10中,我們準備通過以下操作將Python函數集成到Flink:集成Apache Beam,設置Python用戶定義的函數執行環境,管理Python對其他類庫的依賴關係以及為用戶定義用戶定義的函數API,以便支持Python用戶定義函數。

為了擴展分佈式Python的功能,PyFlink提供了對Pandas Series和DataFrame支持,以便用戶可以在PyFlink中直接使用Pandas用戶定義的函數。此外,將來會在SQL客戶端上啟用Python用戶定義函數,以使PyFlink易於使用。PyFlink還將提供Python ML管道API,以使Python用戶能夠在機器學習中使用PyFlink。監視Python用戶定義的函數執行對實際生產和業務至關重要。因此,PyFlink將進一步為Python用戶定義函數提供度量管理。這些功能將包含在Flink 1.11中。

但是,這些只是PyFlink未來發展計劃的一部分。還有更多工作要做,例如優化PyFlink的性能,提供圖形計算API以及為Flink上的Pandas支持Pandas的本機API。我們將繼續向Python用戶提供Flink的現有功能,並將Python的強大功能集成到Flink中,以實現擴展Python生態系統的最初目標。

PyFlink的前景如何?您可能知道,PyFlink是Apache Flink的一部分,它涉及運行時和API層。

PyFlink在這兩層將如何發展?在運行時方面,PyFlink將構建用於JVM和PyVM之間通信的gRPC常規服務(例如控件,數據和狀態)。在此框架中,將抽象化Java Python用戶定義函數運算符,並構建Python執行容器以支持Python的多種執行方式。例如,PyFlink可以在Docker容器中甚至在外部服務集群中作為進程運行。特別是在外部服務群集中運行時,將以套接字的形式啟用無限擴展功能。這一切在後續的Python集成中都起着至關重要的作用。

在API方面,我們將在Flink中啟用基於Python的API,以實現我們的使命。這也依賴於Py4J VM通信框架。PyFlink將逐漸支持更多的API,包括Flink中的Java API(例如Python Table API,UDX,ML Pipeline,DataStream,CEP,Gelly和State API)以及在Python用戶中最受歡迎的Pandas API。基於這些API,PyFlink將繼續與其他生態系統集成以便於開發;例如Notebook,Zeppelin,Jupyter和Alink,這是阿里巴巴的Flink開源版本。到目前為止,PyAlink已完全整合了PyFlink的功能。PyFlink也將與現有的AI系統平台集成,例如著名的TensorFlow。

為此,PyFlink將一直保持活力。同樣,PyFlink的任務是使Flink功能可供Python用戶使用,並在Flink上運行Python分析和計算功能。

更多實時數據分析相關博文與科技資訊,歡迎關注 “實時流式計算”
關注 “實時流式計算” 回復 “电子書” 獲取Flink 300頁實戰电子書

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

【其他文章推薦】

※超省錢租車方案

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

※回頭車貨運收費標準

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

第五屆新能源汽車峰會暨展覽會2014

主辦單位:中國汽車工業協會、決策者會議策劃集團
支持機構:上海交通大學汽車工程研究院
時間:2014年11月12-14日 
地點:中國北京

【大會概況】

國家主席習近平5月24日指出,發展新能源汽車是邁向汽車強國的必由之路。從中央到地方,新能源汽車的推廣進入提速階段,新能源汽車補貼城市大幅擴容。

6月中旬,特斯拉CEO馬斯克表示,為了電動汽車技術的發展,特斯拉將開放其所有的專利。特斯拉專利技術的公開,能夠避免後來者在一些共性領域研發或測試的資源浪費,從而加速技術和商業模式的創新;加上不少汽車巨頭已經開始意識到新能源汽車市場的迅速興起而紛紛斥資研發與生產,新能源汽車市場的蓬勃拓展進程有望大大加快。

7月默克爾訪華,此行的一項重要議程就是啟動中德在電動車領域的合作的一個重要專案——中德電動汽車充電項目。在活動現場,工信部部長苗圩表示這一專案啟動是中德兩國在電動車產業領域合作得到推進的重要成果。

本屆大會結合行業趨勢發展,將研討新能源汽車發展,動力電池與動力能源供應模式,各類型商業運營模式創新,以及相關政策投資思想,引導消費者加深認知新能源汽車和推進新能源汽車產業發展方面,屆時300 多位全球新能源汽車有識之士歡聚一堂共同探討新能源汽車發展的各有關共性事項具有重要意義!

【上屆回顧】

第四屆綠色汽車大會於2013年10月9日至11日在中國北京海航萬豪酒店隆重召開。本次大會由亞洲最大的行業峰會主辦方——決策者會議策劃集團主辦, 得到中國汽車工業協會、中國高科技產業化研究會和韓國汽車工程研究院等國內外權威機構的指導與支持。

從中國和世界各地來的商界領袖、政府官員和產業密切相關部門的高層管理人員英相聚一堂,如電裝中國投資有限公司、德國大陸集團、上汽集團、艾爾維汽車工程技術、斯凱孚汽車技術有限公司和長安新能源汽車有限公司等等,共同探討行業熱門話題。

大會共吸引了來自30多個國家的200個參會代表、30位發言人、20家展商和55家媒體的參與。在全球與會代表的積極參與和回應下,它已經成長為亞洲第一的節能與新能源汽車行業盛會。

【本屆參數統計】

600+業內權威專家業內專業人士,400+專業參展觀眾,來自于320+行業知名企業單位,23+個國家
120+位參會代表來自語全球領先整車商,以及110+核心零部件提供商企業代表
40+ 知名權威發言人,為您敘說新能源汽車行業熱點資訊
16+ 小時商務交流機會,貫穿於雞尾酒會,小組討論,交流午宴及提問互動環節
6 場專題討論,為您深度解析關注行業熱點
5 年歷史,鑄就行業年度盛會

【展會特色】

實效性:展會期間將進行一對一會談、頒獎典禮,突出實效和品牌,做大做深供求雙方專業化配對洽談工作,為廣大業內人士及下游應用企業提供集中領略行業最新趨勢的機會。
品牌化:作為中國電動汽車行業最早商業化運作的峰會,歷經四年發展,無論是參會數量,還是贊助商數量,在國內同行業峰會中,都是雄踞前列,深受業界同仁的認可和讚揚,其知名度和美譽度在業內廣為流傳。成為中國電動汽車行業名副其實的第一會。 
國際化:往屆嘉賓有來自美國、日本、韓國、德國、丹麥、義大利、臺灣等國家和地區的國際企業參會,已經成為電動汽車行業的資訊分享、技術交流、貿易採購平臺。
專業化:是國內目前唯一的電動汽車行業的專業峰會之一,一年一屆。內容包含電動汽車(含混合動力)的整車、零部件、管理系統、充電站及相關配套設施等. 將吸引來自中國電動汽車企業超320家企業巨頭高層參觀,雲集政府機關行業協會,整車商,大學院校及研究院,零部件百強企業,核心技術設備提供商。
全媒體曝光:主辦方將基於網站、雜誌、微信、微博等多媒體平臺,在展前、展中、展後分別做全方位即時報導,預計將會實現超過10萬人次覆蓋。

【2014年新能源汽車頒獎典禮獎項設置】

年度優秀電動汽車電池生廠商獎
年度優秀綠色汽車諮詢公司獎
年度優秀綠色汽車解決方案提供商獎
終身成就獎
企業社會責任商獎
優秀核心零部件提供商獎
優秀綠色汽車服務商獎
優秀綠色汽車技術提供商獎

【展商評價】

“是一個尋找合作夥伴的理想場所,本次參展讓我們受益頗多,明年會一如既往支援綠色汽車大會!”
—— Shinry Technologies Co., Ltd

“通過很好的管道將我們的產品展現在客戶面前,非常滿意。”
—— AGC Automtive

“綠色汽車大會提供一個行業人士交流的平臺,參會參展企業眾多,達到了我們的參展期望值。”
—— Thermal Hazard Technology

“我們同時參加了峰會和展覽,非常值得推薦的活動!”
—— 捷特科

“非常滿意,無論是活動內容,參會嘉賓,還是規模層次都很出色,會推薦個同事。”
—— W.E.T. Automotive Systems (China) Ltd

會議官網:

聯絡人

邱玉芳
電話:021 63931899轉2041
傳真:021 6840 7632;郵編:200122
e-mail:
地址:上海長逸路15號復旦軟體園9樓

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

【其他文章推薦】

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

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

※回頭車貨運收費標準

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

※超省錢租車方案

取代老舊公務車 英國政府大手筆採購 150 輛 Tesla Model S

    根據國外媒體報導,英國中央政府正在規劃一筆約 850 萬美元的預算,用來採購約 150 輛的 Tesla Model S 電動車,用來取代中央政府部門使用的老舊車輛。這 150 輛 Tesla S 服役後,將占英國中央政府機關用車約 30 %。   英國政府將會以每輛約 3 萬 3000 英鎊(約合台幣 171 萬 7600 元)的價格取得這批 Tesla S,雖然說已經比 Tesla Model S 在英國的正式售價 5 萬英鎊要便宜,但是仍然超出預算許多。   英國政府會採用 Tesla S 的主要原因是:跟 3 萬英鎊價格帶的其他電動車款相比(主要是 BMW i3,即便是 i3 Rex 增程版也只有 300 公里),Tesla Model S 的 250 英哩續航力(約 402 公里),相較之下的確是實用太多了。   (圖片來源:)

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

【其他文章推薦】

※超省錢租車方案

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

※回頭車貨運收費標準

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

重學 Java 設計模式:實戰迭代器模式「模擬公司組織架構樹結構關係,深度迭代遍歷人員信息輸出場景」

作者:小傅哥
博客:https://bugstack.cn – 原創系列專題文章

沉澱、分享、成長,讓自己和他人都能有所收穫!

一、前言

相信相信的力量!

從懵懂的少年,到拿起鍵盤,可以寫一個HelloWorld。多數人在這並不會感覺有多難,也不會認為做不出來。因為這樣的例子,有老師的指導、有書本的例子、有前人的經驗。但隨着你的開發時間越來越長,要解決更複雜的問題或者技術創新,因此在網上搜了幾天幾夜都沒有答案,這個時候是否想過放棄,還是一直堅持不斷的嘗試一點點完成自己心裏要的結果。往往這種沒有前車之鑒需要自己解決問題的時候,可能真的會折磨到要崩潰,但你要願意執着、願意倔強,願意選擇相信相信的力量,就一定能解決。哪怕解決不了,也可以在這條路上摸索出其他更多的收穫,為後續前進的道路填充好墊腳石。

時間緊是寫垃圾代碼的理由?

擰螺絲?Ctrl+C、Ctrl+V?貼膏藥一樣寫代碼?沒有辦法,沒有時間,往往真的是借口,胸中沒用筆墨,才只能湊合。難道一定是好好寫代碼就浪費時間,拼湊CRUD就快嗎,根本不可能的。因為不會,沒用實操過,很少架構出全場景的設計,才很難寫出優良的代碼。多增強自身的編碼(武術)修為,在各種編碼場景中讓自己變得老練,才好應對緊急情況下的需求開發和人員安排。就像韓信一樣有謀有略,才能執掌百萬雄兵。

不要只是做個工具人!

因為日常的編寫簡單業務需求,導致自己像個工具人一樣,日久天長的也就很少去深入學習更多技術棧。看見有工具、有組件、有框架,拿來就用用,反正沒什麼體量也不會出什麼問題。但如果你想要更多的收入,哪怕是重複的造輪子,你也要去嘗試造一個,就算不用到生產,自己玩玩總可以吧。有些事情只有自己經歷過,才能有最深的感觸,參与過實踐過,才好總結點評學習。

二、開發環境

  1. JDK 1.8
  2. Idea + Maven
  3. 涉及工程一個,可以通過關注公眾號:bugstack蟲洞棧,回復源碼下載獲取(打開獲取的鏈接,找到序號18)
工程 描述
itstack-demo-design-15-00 開發樹形組織架構關係迭代器

三、迭代器模式介紹

迭代器模式,常見的就是我們日常使用的iterator遍歷。雖然這個設計模式在我們的實際業務開發中的場景並不多,但卻幾乎每天都要使用jdk為我們提供的list集合遍歷。另外增強的for循環雖然是循環輸出數據,但是他不是迭代器模式。迭代器模式的特點是實現Iterable接口,通過next的方式獲取集合元素,同時具備對元素的刪除等操作。而增強的for循環是不可以的。

這種設計模式的優點是可以讓我們以相同的方式,遍歷不同的數據結構元素,這些數據結構包括;數組、鏈表、樹等,而用戶在使用遍歷的時候並不需要去關心每一種數據結構的遍歷處理邏輯,從讓使用變得統一易用。

四、案例場景模擬

在本案例中我們模擬迭代遍歷輸出公司中樹形結構的組織架構關係中僱員列表

大部分公司的組織架構都是金字塔結構,也就這種樹形結構,分為一級、二級、三級等部門,每個組織部門由僱員填充,最終體現出一個整體的樹形組織架構關係。

一般我們常用的遍歷就是jdk默認提供的方法,對list集合遍歷。但是對於這樣的偏業務特性較大的樹形結構,如果需要使用到遍歷,那麼就可以自己來實現。接下來我們會把這個組織層次關係通過樹形數據結構來實現,並完成迭代器功能。

五、迭代器模式遍歷組織結構

在實現迭代器模式之前可以先閱讀下java中list方法關於iterator的實現部分,幾乎所有的迭代器開發都會按照這個模式來實現,這個模式主要分為以下幾塊;

  1. Collection,集合方法部分用於對自定義的數據結構添加通用方法;add、remove、iterator等核心方法。
  2. Iterable,提供獲取迭代器,這個接口類會被Collection繼承。
  3. Iterator,提供了兩個方法的定義;hasNext、next,會在具體的數據結構中寫實現方式。

除了這樣通用的迭代器實現方式外,我們的組織關係結構樹,是由節點和節點間的關係鏈構成,所以會比上述的內容多一些入參。

1. 工程結構

itstack-demo-design-15-02
└── src
    ├── main
    │   └── java
    │       └── org.itstack.demo.design
    │           ├── group
    │           │	├── Employee.java
    │           │	├── GroupStructure.java
    │           │	└── Link.java
    │           └──  lang
    │            	├── Collection.java
    │            	├── Iterable.java
    │            	└── Iterator.java
    └── test
        └── java
            └── org.itstack.demo.design.test
                └── ApiTest.java

迭代器模式模型結構

  • 以上是我們工程類圖的模型結構,左側是對迭代器的定義,右側是在數據結構中實現迭代器功能。
  • 關於左側部分的實現與jdk中的方式是一樣的,所以在學習的過程中可以互相參考,也可以自己擴展學習。
  • 另外這個遍歷方式一個樹形結構的深度遍歷,為了可以更加讓學習的小夥伴容易理解,這裏我實現了一種比較簡單的樹形結構深度遍歷方式。後續讀者也可以把遍歷擴展為橫向遍歷也就是寬度遍歷。

2. 代碼實現

2.1 僱員實體類

/**
 * 僱員
 */
public class Employee {

    private String uId;   // ID
    private String name;  // 姓名
    private String desc;  // 備註
    
    // ...get/set
}
  • 這是一個簡單的僱員類,也就是公司員工的信息類,包括必要的信息;id、姓名、備註。

2.2 樹節點鏈路

/**
 * 樹節點鏈路
 */
public class Link {

    private String fromId; // 僱員ID
    private String toId;   // 僱員ID    
    
    // ...get/set
}
  • 這個類用於描述結構樹中的各個節點之間的關係鏈,也就是A to B、B to C、B to D,以此描述出一套完整的樹組織結構。

2.3 迭代器定義

public interface Iterator<E> {

    boolean hasNext();

    E next();
    
}
  • 這裏的這個類和java的jdk中提供的是一樣的,這樣也方面後續讀者可以對照list的Iterator進行源碼學習。
  • 方法描述;hasNext,判斷是否有下一個元素、next,獲取下一個元素。這個在list的遍歷中是經常用到的。

2.4 可迭代接口定義

public interface Iterable<E> {

    Iterator<E> iterator();

}
  • 這個接口中提供了上面迭代器的實現Iterator的獲取,也就是後續在自己的數據結構中需要實現迭代器的功能並交給Iterable,由此讓外部調用方進行獲取使用。

2.5 集合功能接口定義

public interface Collection<E, L> extends Iterable<E> {

    boolean add(E e);

    boolean remove(E e);

    boolean addLink(String key, L l);

    boolean removeLink(String key);

    Iterator<E> iterator();

}
  • 這裏我們定義集合操作接口;Collection,同時繼承了另外一個接口Iterable的方法iterator()。這樣後續誰來實現這個接口,就需要實現上述定義的一些基本功能;添加元素、刪除元素、遍歷。
  • 同時你可能注意到這裏定義了兩個泛型<E, L>,因為我們的數據結構一個是用於添加元素,另外一個是用於添加樹節點的鏈路關係。

2.6 (核心)迭代器功能實現

public class GroupStructure implements Collection<Employee, Link> {

    private String groupId;                                                 // 組織ID,也是一個組織鏈的頭部ID
    private String groupName;                                               // 組織名稱
    private Map<String, Employee> employeeMap = new ConcurrentHashMap<String, Employee>();  // 僱員列表
    private Map<String, List<Link>> linkMap = new ConcurrentHashMap<String, List<Link>>();  // 組織架構關係;id->list
    private Map<String, String> invertedMap = new ConcurrentHashMap<String, String>();       // 反向關係鏈

    public GroupStructure(String groupId, String groupName) {
        this.groupId = groupId;
        this.groupName = groupName;
    }

    public boolean add(Employee employee) {
        return null != employeeMap.put(employee.getuId(), employee);
    }

    public boolean remove(Employee o) {
        return null != employeeMap.remove(o.getuId());
    }

    public boolean addLink(String key, Link link) {
        invertedMap.put(link.getToId(), link.getFromId());
        if (linkMap.containsKey(key)) {
            return linkMap.get(key).add(link);
        } else {
            List<Link> links = new LinkedList<Link>();
            links.add(link);
            linkMap.put(key, links);
            return true;
        }
    }

    public boolean removeLink(String key) {
        return null != linkMap.remove(key);
    }

    public Iterator<Employee> iterator() {

        return new Iterator<Employee>() {

            HashMap<String, Integer> keyMap = new HashMap<String, Integer>();

            int totalIdx = 0;
            private String fromId = groupId;  // 僱員ID,From
            private String toId = groupId;   // 僱員ID,To

            public boolean hasNext() {
                return totalIdx < employeeMap.size();
            }

            public Employee next() {
                List<Link> links = linkMap.get(toId);
                int cursorIdx = getCursorIdx(toId);

                // 同級節點掃描
                if (null == links) {
                    cursorIdx = getCursorIdx(fromId);
                    links = linkMap.get(fromId);
                }

                // 上級節點掃描
                while (cursorIdx > links.size() - 1) {
                    fromId = invertedMap.get(fromId);
                    cursorIdx = getCursorIdx(fromId);
                    links = linkMap.get(fromId);
                }

                // 獲取節點
                Link link = links.get(cursorIdx);
                toId = link.getToId();
                fromId = link.getFromId();
                totalIdx++;

                // 返回結果
                return employeeMap.get(link.getToId());
            }
             
            // 給每個層級定義寬度遍歷進度
            public int getCursorIdx(String key) {
                int idx = 0;
                if (keyMap.containsKey(key)) {
                    idx = keyMap.get(key);
                    keyMap.put(key, ++idx);
                } else {
                    keyMap.put(key, idx);
                }
                return idx;
            }
        };
    }

}
  • 以上的這部分代碼稍微有點長,主要包括了對元素的添加和刪除。另外最重要的是對遍歷的實現 new Iterator<Employee>。
  • 添加和刪除元素相對來說比較簡單,使用了兩個map數組結構進行定義;僱員列表、組織架構關係;id->list。當元素添加元素的時候,會分別在不同的方法中向map結構中進行填充指向關係(A->B),也就構建出了我們的樹形組織關係。

迭代器實現思路

  1. 這裏的樹形結構我們需要做的是深度遍歷,也就是左側的一直遍歷到最深節點。
  2. 當遍歷到最深節點后,開始遍歷最深節點的橫向節點。
  3. 當橫向節點遍歷完成后則向上尋找橫向節點,直至樹結構全部遍歷完成。

3. 測試驗證

3.1 編寫測試類

@Test
public void test_iterator() { 
    // 數據填充
    GroupStructure groupStructure = new GroupStructure("1", "小傅哥");  
    
    // 僱員信息
    groupStructure.add(new Employee("2", "花花", "二級部門"));
    groupStructure.add(new Employee("3", "豆包", "二級部門"));
    groupStructure.add(new Employee("4", "蹦蹦", "三級部門"));
    groupStructure.add(new Employee("5", "大燒", "三級部門"));
    groupStructure.add(new Employee("6", "虎哥", "四級部門"));
    groupStructure.add(new Employee("7", "玲姐", "四級部門"));
    groupStructure.add(new Employee("8", "秋雅", "四級部門"));   
    
    // 節點關係 1->(1,2) 2->(4,5)
    groupStructure.addLink("1", new Link("1", "2"));
    groupStructure.addLink("1", new Link("1", "3"));
    groupStructure.addLink("2", new Link("2", "4"));
    groupStructure.addLink("2", new Link("2", "5"));
    groupStructure.addLink("5", new Link("5", "6"));
    groupStructure.addLink("5", new Link("5", "7"));
    groupStructure.addLink("5", new Link("5", "8"));       

    Iterator<Employee> iterator = groupStructure.iterator();
    while (iterator.hasNext()) {
        Employee employee = iterator.next();
        logger.info("{},僱員 Id:{} Name:{}", employee.getDesc(), employee.getuId(), employee.getName());
    }
}

3.2 測試結果

22:23:37.166 [main] INFO  org.itstack.demo.design.test.ApiTest - 二級部門,僱員 Id:2 Name:花花
22:23:37.168 [main] INFO  org.itstack.demo.design.test.ApiTest - 三級部門,僱員 Id:4 Name:蹦蹦
22:23:37.169 [main] INFO  org.itstack.demo.design.test.ApiTest - 三級部門,僱員 Id:5 Name:大燒
22:23:37.169 [main] INFO  org.itstack.demo.design.test.ApiTest - 四級部門,僱員 Id:6 Name:虎哥
22:23:37.169 [main] INFO  org.itstack.demo.design.test.ApiTest - 四級部門,僱員 Id:7 Name:玲姐
22:23:37.169 [main] INFO  org.itstack.demo.design.test.ApiTest - 四級部門,僱員 Id:8 Name:秋雅
22:23:37.169 [main] INFO  org.itstack.demo.design.test.ApiTest - 二級部門,僱員 Id:3 Name:豆包

Process finished with exit code 0
  • 從遍歷的結果可以看到,我們是順着樹形結構的深度開始遍歷,一直到右側的節點3;僱員 Id:2、僱員 Id:4...僱員 Id:3

六、總結

  • 迭代器的設計模式從以上的功能實現可以看到,滿足了單一職責和開閉原則,外界的調用方也不需要知道任何一個不同的數據結構在使用上的遍歷差異。可以非常方便的擴展,也讓整個遍歷變得更加乾淨整潔。
  • 但從結構的實現上可以看到,迭代器模式的實現過程相對來說是比較負責的,類的實現上也擴增了需要外部定義的類,使得遍歷與原數據結構分開。雖然這是比較麻煩的,但可以看到在使用java的jdk時候,迭代器的模式還是很好用的,可以非常方便擴展和升級。
  • 以上的設計模式場景實現過程可能對新人有一些不好理解點,包括;迭代器三個和接口的定義、樹形結構的數據關係、樹結構深度遍歷思路。這些都需要反覆實現練習才能深入的理解,事必躬親,親歷親為,才能讓自己掌握這些知識。

七、推薦閱讀

  • 1. 重學 Java 設計模式:實戰工廠方法模式「多種類型商品不同接口,統一發獎服務搭建場景」
  • 2. 重學 Java 設計模式:實戰原型模式「上機考試多套試,每人題目和答案亂序排列場景」
  • 3. 重學 Java 設計模式:實戰橋接模式「多支付渠道(微信、支付寶)與多支付模式(刷臉、指紋)場景」
  • 4. 重學 Java 設計模式:實戰組合模式「營銷差異化人群發券,決策樹引擎搭建場景」
  • 5. 重學 Java 設計模式:實戰外觀模式「基於SpringBoot開發門面模式中間件,統一控制接口白名單場景」
  • 6. 重學 Java 設計模式:實戰享元模式「基於Redis秒殺,提供活動與庫存信息查詢場景」

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

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

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

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

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

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

※回頭車貨運收費標準

《T-GCN: A Temporal Graph Convolutional Network for Traffic Prediction》 論文解讀

論文鏈接:https://arxiv.org/abs/1811.05320

最近發現博客好像會被CSDN和一些奇怪的野雞網站爬下來?看見有人跟爬蟲機器人單方面討論問題我也蠻無奈的。總之原作者Missouter,博客鏈接https://www.cnblogs.com/missouter/,歡迎交流。

整理、精鍊了一下這篇論文的思路。

Abstract:

交通預測的難點在於交通拓撲網絡複雜的結構與隨時間動態發生的交通變化;為了提取交通網的空間與時間特徵,文章提出了一種時間性的圖卷積網絡模型,結合了門級循環單元(GRU)與圖卷積網絡(GCN)。其中圖卷積網絡被用於提取複雜拓撲結構中的空間性信息,而門級循環單元則為了提取時間關係,被用於學習交通數據中的動態數據。

Introduction:

交通預測過程:分析交通道路狀況,包含流量、速度、密度;挖掘交通模式,同時對道路上的交通狀況進行預測。

預測結果:交通管理者預測擁堵狀況、限制交通工具的科學基礎、出行者效率選擇出行工具、路線的保障。

難點:

1、 空間關係:交通流的變化被拓撲結構的城市交通網主導,上游的交通狀態通過傳輸作用影響下游的交通狀態,而下游交通狀態通過反饋作用再影響上游交通。

2、 時間關係:交通流隨時間動態變化,主要表現在周期性和趨勢上;現有的交通狀況被前一刻的交通狀況影響。

現存交通預測方法缺陷:一些交通預測方法(ARIMA、Kalman filtering model,etc)只關注了交通狀況的動態變化而忽視了空間關係,導致交通狀態的變化不被道路網約束,同時一些模型嘗試使用卷積神經網絡進行空間性建模,但這些模型一般只使用於歐幾里得類型的數據(規則矩陣、圖像等),無法在拓撲結構的城市交通網絡中運作。

T-GCN貢獻:

1、 結合了GCN與GRU,內容與abstract重複,不做多提。

2、 T-GCN的預測結果展示了一個不同視角下的穩定狀態,表示T-GCN除了預測短周期的變化,還能預測長周期的變化。

3、 我們使用兩個現實的數據集評估模型,相較其他預測模型,減少了1.5%~57.8%的預測錯誤率。

Related work:

交通預測方法分類:模型驅動的方法、數據驅動的方法;

模型驅動的方法:解釋即時、穩定的交通關係如交通流量、速度與密度,需要複雜細緻的系統建模與巨大的算力,且由於諸多因素的影響,現實環境中交通數據的多樣性無法被精確描繪。

數據驅動的方法:基於數據統計所得規律推斷交通狀況的變化。不分析物理屬性與交通系統的動態變化有着較高的複雜度。其中的historical average model不需要假設、計算過程簡單,但精確度不佳。

擁有更高精確度的模型被提出,分為兩種:含參數的與非參數的。

含參模型假定回歸函數,參數在對原始數據的處理過程中確定。傳統含參的模型是在系統模型為靜態的假設基礎上建立的,反映不了交通系統的非線性與不確定性,也克服不了交通事故等突發隨機事件的困難。不含參數的模型只需要足夠的歷史數據就能自動學習靜態規律特徵,但先前形如LSTM、GRU的模型僅僅考慮了時間關係而忽略了空間關係,不能精確預測道路上的交通信息,如何充分利用空間信息成了交通預測的關鍵,而利用CNN進行空間關係提取的模型雖然在交通預測上取得了顯著進步,但無法應用於複雜拓撲結構的城市交通網,隨着GCN研究的深入,拓撲結構空間特徵的提取問題也得到解決。

(這段論文寫的有點長…堆了一堆文字讀的我有點難受)

Methodology:

問題定義:根據歷史數據預測某一特定時間段的交通信息,交通數據通常被定義為速度、密集程度、交通流。使實驗不失普遍性,在實驗章節使用交通速度作為交通數據的代表。(Without loss of generality, we use traffic speed as an example of traffic information in experiment section.這句語感有點僵了)

定義:設定無權圖G=(V, E),V、E分別代表道路點與邊,N為道路的數量,設定鄰接N*N矩陣A表達道路與道路之間的聯繫;設定N*P特徵矩陣X,P代表點屬性特徵的數量,即歷史時間序列的長度,使用N*i矩陣 表示在時刻i,每條道路上的速度,屬性特徵也可以是交通速度、交通流等屬性。

問題轉化:交通空間-時間性預測被轉化為學習以拓撲圖G為前置與特徵矩陣X的映射函數,計算得到在下T時刻的交通信息:

過程概覽:首先以長度為n的歷史時間序列數據作為輸入,使用GCN接收拓撲結構的空間信息,其次將接收到的空間、時間信息輸入GRU當中,獲取各個單元間的動態信息變化,以提取時間性的特徵,最後在全連接層獲得結果。

空間關係建模:利用GCN提取圖結構的數據,通過給定的鄰接矩陣A、特徵矩陣X,GCN在圖上通過提取相鄰結點特徵構建傅里恭弘=叶 恭弘域,使用堆疊的卷積網絡,表示為:

Â為A與單位矩陣I相加所得, D為度矩陣, Hl為第l層的輸出, θl包含該層的參數, σ代表非線性回歸的激活函數。(我懷疑論文這裏的上標打錯了)

兩層GCN模型可被表示為:

其中 ,P*H的 矩陣代表從輸入到隱藏層的權重,P為特徵矩陣的長度,H為隱藏單元的數量;H*T的W1代表從隱藏層到輸出層的權重, f(X,A)∈RN*T代表長度為T的預測輸出,ReLU()作為修正線性單元,作激活層用。

時間關係建模:被廣泛應用的循環神經網絡因梯度消失/爆炸的原因,不適用於長周期的預測;LSTM與GRU作為循環神經網絡的變種,克服了上述問題。其共同原理都是利用門級機制儲存盡可能長的周期信息;LSTM因其複雜的結構,GRU結構更加簡單,故計算時間更短。

 

圖中ht-1表示t-1時刻的隱藏狀態, xt表示t時刻的交通信息, rt代表重置門,用於控制先前時刻狀態信息的度量; ut為上傳門,用於控制上傳到下一狀態的信息度量; ct為t時刻時儲存的信息, ht為t時刻的輸出狀態;總的來說,GRU通過獲取t-1時刻的隱藏狀態與當時的交通狀態信息得到t時刻的交通信息。

T-GCN:

 

T-GCN的結構如圖,右側為T-GCN的處理單元: 為t-1時刻的輸出,GC為圖卷積過程,ut 、 rt分別為上傳門與重置門, 為t時刻的輸出。具體計算過程為:

f(A,X)代表前文定義的GCN計算過程,w與b代表訓練過程中的權重與偏移量。(很大部分照搬了GNU的公式)

損失函數:

目標:最小化真實交通速度與預測交通速度的誤差。Y分別代表真實速度與預測速度,損失函數如下:

其中 λLreg用於防止過擬合。

Experiments:

選取數據集:

1、SZ-taxi:數據分為兩部分,156*156的鄰接矩陣表示路與路之間的空間關係,描述每條路上隨時間變化的特徵矩陣。

2、Losloop:由鄰接矩陣與特徵矩陣組成,鄰接矩陣由交通網絡中的傳感器計算;同時作者對數據集中的殘缺部分使用線性填充的方法進行了補全。

輸入的數據全部進行了歸一化處理,80%的數據用於訓練,而20%的數據被用於測試。實驗對接下來15、30、45、60分鐘的交通速度進行預測。

評價指標:

文章列出了五個用於評價T-GCN預測表現的指標:

1、均方根誤差:

2、平均絕對誤差:

3、準確率:

4、 確定係數:

5、可釋方差值:

其中yj’i分別代表第j次時間、第i條路的真實交通信息與預測信息,M為時間樣本的數量,N為路的數量,Y分別代表 與 的集合, 帶上劃線的Y為Y的平均數。

R2與var用於計算相關係數,衡量預測結果表示實際數據的能力,數值越大則預測能力越優越。

選取模型參數:

超參數:包括學習率(0.001)、抓取數量(32)、訓練輪數(5000)、隱藏單元數量(通過多次實驗取最優預測效果)

針對SZ-taxi文章選取[8,16,32,64,100,128],分析預測準確率的變化,得到不同隱藏單元數量下RASE與MAE、Accuracy、R2 、var的值如圖:

 

顯然數量為100時效果是最好的(真有這麼巧的事情嘛…)。隱藏單元超過一定數量性能下降的原因在於數據單元超過一定值後計算複雜度增加,且訓練數據會出現過擬合現象。

實驗結果:

將T-GCN預測效果與baseline對比,包括HA、ARIMA、SVR、GCN、GRU,所得實驗數據如下:

 

高預測精準度:門級循環網絡的預測精度顯著高於其他baseline算法,HA、ARIMA、SVR等算法因難以處理複雜、非固定的時間數據而預測效果不佳,GCN預測效果不佳的原因僅僅在於僅考慮了空間特徵而忽略了交通數據是一個典型的時間序列數據這一事實。

ARIMA比HA檢測效果弱的原因在於ARIMA不適用於長周期的檢測,且計算每個節點誤差的方式導致一些數據中的波動會導致最終的計算錯誤。

時空預測能力:為了檢驗模型是否能夠從交通數據中提取時空特徵,文章將模型與GCN、GNU模型進行了比較:

長周期預測能力:在不同的時間範圍(文章只寫了“horizon”,根據前後文認定為是時間範圍)下,T-GCN都能獲得最好的預測效果且預測結果擁有較小的變化趨勢,證明了T-GCN擁有更好的長周期預測能力;文章以T-GCN在不同時間點的結果作為論證:

 

干擾分析與魯棒性:通過向數據中添加兩種不同的噪聲檢驗T-GCN的魯棒性,高斯分佈、泊松分佈的 值作為自變量被改變,分別添加到兩種數據集上,得到結果:

 

由評估指標的隨噪聲的變化細微可以得出T-GCN具強魯棒性的結論。

模型解釋:

文章將T-GCN所得的預測結果與真實數據可視化得到結論:

 

模型對於峰谷值的預測效果不佳,原因在於T-GCN在傅里恭弘=叶 恭弘域中定義了平滑過濾器,通過不斷移動過濾器提取空間特徵,造成了全局預測中的細微變化,使得曲線中的峰變得平滑。

文章還指出預測與實際之間存在固定誤差,由數據集的特殊性造成,即SZ-taxi數據集表示某時刻出租車的數量可能為0,但實際道路上車輛的數量不一定為0;

對這篇論文的解讀就到這裏結束了,Methodology部分使用GCN與GNU的理論,設計了新的計算單元;Experiment部分很讓我受教,對實驗的條件、前提設定的非常詳盡,在介紹數據集與衡量指標后,對選取實驗參數作了嚴格的實驗論證;對實驗結果進行了詳盡的分析,通過與其他幾個模型的預測結果進行對比,從空間、時間、時間跨度預測、精度、魯棒性等角度對模型的優越性進行對比論證,數據的選取與展示都精確地契合了論證的論點;最後關於傅里恭弘=叶 恭弘與峰谷偏差的模型解釋很精妙。

關於GNU、LSTM的學習解讀會繼續跟進。同時也會對這篇論文git上的開源代碼進行解讀與實驗復現。

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

【其他文章推薦】

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

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

※回頭車貨運收費標準

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

※超省錢租車方案