中國積極推動無補貼綠能專案,太陽能市場有望回穩

雖然中國政府在 2018 年中旬推出 531 新政,讓該國投資去年太陽能總投資下降 53%,重挫當地太陽能投資與建設發展,但該國政府目前已推出無補貼再生能源計畫,或許有望重振中國太陽能市場,彭博能源財經(BNEF)推測 2019 年中國太陽能新增裝置量仍可達到 34-44GW。

中國過去一直以來對當地太陽能產業發展相當優待,提供優渥的補貼金額與固定電價價格以鼓勵太陽能等再生能源發展,大量企業開始投資太陽能產業,形成一股靠補貼攀升的太陽能熱潮,造成產能過剩與補貼缺口過大,據統計,截至 2017 年底,再生能源補貼缺口已達 1,000 億人民幣(約新台幣 4,600 億元)。

因此中國政府在 2018 年中無預警推出新政策,大幅限制電廠建設與補助,為中國高速發展的太陽能產業踩下煞車踏板,未來也將採取嚴控指標方式,並積極鼓勵低價補貼或是無補貼專案。

無補貼專案優惠多

就好比中國在去年 8 月推出首項無補貼太陽能示範專案規劃,每省限定 300-500MW,並在 10 月開始申請、預計在 2019 年 3 月前後開工拚年底前併網發電。日前該政府也為了促進再生能源無補貼發展公布 12 項全新計畫,像是要做好風電、光電發電量檢測,不能在電力供過於求等預警紅色地區推行專案,廠商也要保證將來可以全額併網發電與不浪費。

中國此次將「無補貼專案」定義為無國家補貼、先導計畫不限規模、不佔用補貼指標的計畫,因此在政策方面也有釋出許多善意,要求地方政府對無補貼太陽能與風電在土地利用、成本上給予支持之餘,政府也會為綠色證書市場化交易指出明燈,未來無補貼或是低價補貼專案可以透過中國綠色電力證書交易獲益,與此同時也要求電力公司讓無補貼專案優先發電和全額收購電量,並鼓勵金融機構支持無補貼專案。

另外中國政府也將執行固定電價(FIT)政策,無補貼、低價補貼風電與太陽能專案可簽定 20 年以上的購電合約,提高電價的長期穩定性,也不要會求參與跨區電力市場化交易。

中國國家發改委表示,這些專案獲得核准後就能在 2020 年底前開始施工,但沒有在限定時間完工的專案將會被取消,為其他無補貼專案挪出空間。並明確指出,從現在到 2020 年底前獲準的專案都可採用這項政策,政府則會在 2020 年後依據技術與成本擬定新的政策。

只不過中國目前也有不少地方無法規劃無補貼專案,對此中國政府也表示,推動低價專案並非立即取消所有補貼,若無法達到無補貼或低價補貼仍可採競爭性配置專案政策,並希望這些專案可透過競爭降低電價以減少政府補貼。

BNEF 分析師 Jonathan Luan 表示,這些政策代表著未來中國將朝無補貼再生能源邁進,並有機會促成全新的太陽能專案,公司則對中國的太陽能市場樂觀看待,預測 2019 年新增裝置量可達 34-44GW。

(合作媒體:。首圖來源: CC BY 2.0)

延伸閱讀:

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

【其他文章推薦】

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

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

※想知道購買電動車哪裡補助最多?台中電動車補助資訊懶人包彙整

南投搬家公司費用,距離,噸數怎麼算?達人教你簡易估價知識!

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

※超省錢租車方案

消滅太平洋垃圾帶 巨型垃圾搜集器正式上路

摘錄自2018年9月9日蘋果日報美國報導

位於美國加州和夏威夷之間有個全球最大的垃圾帶,聚集人類多年來不斷丟棄到大海中的垃圾。為了解決此生態浩劫,由荷蘭24歲青年研發的巨型垃圾蒐集器昨(8)日正式上場,將沿路「撿回」垃圾,還給大海一個乾淨空間。

這個長約600公尺的巨大垃圾搜集器周六從舊金山港口出發,朝著相當於40個台灣面積的太平洋垃圾帶(Great Pacific Garbage Patch)前進。搜集器呈U型漂浮設計,在海上攔截垃圾。裝置以低於水流的速度行進,讓潮汐和海浪產生推力,將海洋垃圾往裝置中心帶去。裝置底下設有網狀裝置,能攔下較小、沉降在水面下的海洋廢棄物。而過濾網產生的推力,則能使魚類和其他生物,得以輕鬆繞過網子底下、通過裝置而不被攔截。被攔下的海洋垃圾,再由團隊派出船隻定期載運回陸地,進行資源回收再利用。

此計畫由荷蘭青年斯萊特(Boyan Slat)所創立的「海洋清理計劃」(Ocean Cleanup Project)推動。該組織已募得3500萬美元(約10億7870萬元台幣)資金,預計在2020年前在太平洋海域上放置60個搜集器檔板。斯萊特說:「我們的目標是在5年內清理5成太平洋垃圾帶中的垃圾。」斯萊特還說,這些漂浮檔板可抵抗惡劣氣候,使用期限長達20年,可望蒐集到9成海面漂浮垃圾。

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

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

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

※想知道購買電動車哪裡補助最多?台中電動車補助資訊懶人包彙整

南投搬家公司費用,距離,噸數怎麼算?達人教你簡易估價知識!

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

※超省錢租車方案

台達加入國際電動車倡議 EV100,推動全球低碳交通

電源管理及能源基礎解決方案廠商台達 26 日宣布響應國際電動車倡議 EV100,成為台灣第一家及全球第一家電動車能源基礎設施提供者的會員。台達承諾於 2030 年前,將在主要營運據點廣設電動車充電設施,提供員工及客戶電動車使用誘因,協助推動低碳交通轉型以對抗氣候變遷。

EV100 為氣候組織(The Climate Group)2017 年發起的全球倡議,目的為透過全球具有影響力的企業及政府組織,加速交通運輸之低碳轉型,以呼應全球升溫低於 2℃ 的聯合國目標。目前已有 HP、聯合利華、Ikea、百度等 20 家國際企業響應。

台達發言人暨企業永續發展周志宏資深協理表示,氣候變遷日益急劇,降低交通設施帶來的溫室氣體排放為另一項重要課題。電動車為低碳城市的解決方案之一,近年來受到外界許多關注,台達以「環保 節能 愛地球」為企業使命,致力為永續城市提供解決方案。運用核心能力持續研發高效能電源及整合式系統,為城市的智慧能源設施布局,並且成為全球領先的電動車製造商提供關鍵車用零組件。在企業內部,我們希望透過友善及便利的電動車充電樁與服務,提供員工及客戶使用電動車的誘因,減少環境負荷。台達至今已於全球總部、營運據點,以及全球生產據點,設置超過 40 支電動車充電樁,支援不同規格的充電需求,並已在廠區提供電動巴士作為交通車,預計將全面使用電動巴士,以降低員工交通的碳排。

因應全球電動車與充電網絡蓬勃發展的趨勢,台達整合內部 40 年以上的電源轉換與管理的技術能力,提供業界先進的電動車充電解決方案。日前更榮獲美國能源部研發專案經費,合作開發充電輸出功率可達 400kW 的高速電動車充電機(Extreme Fast Charger,XFC),預期不到 10 分鐘的快速充電即可為未來電動車款提供 180 英里的行駛里程(約 288 公里)。除了電動車充電技術的提升,此研究專案的數據和成果將能幫助汽車製造商、相關技術提供者、城市政府、與電力公司更加了解電動車高速充電如何影響電力需量反應規劃,以及充電站如何整合可再生能源,以避免大量的高速充電對電網基礎設施造成壓力。

(資訊、圖片來源:)

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

【其他文章推薦】

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

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

※想知道購買電動車哪裡補助最多?台中電動車補助資訊懶人包彙整

南投搬家公司費用,距離,噸數怎麼算?達人教你簡易估價知識!

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

※超省錢租車方案

JSR133提案-修復Java內存模型

目錄

  • 1. 什麼是內存模型?
  • 2. JSR 133是關於什麼的?
  • 3. 再談指令重排序
  • 4.同步都做了什麼?
  • 5. final字段在舊的內存模型中為什麼可以改變?
  • 6.“初始化安全”與final字段?
  • 7. 增強volatile語義
  • 8. 修復“double-checked locking”的問題
  • 9. 為什麼要關心這些問題?
  • 延伸閱讀

1. 什麼是內存模型?

在多處理器系統中,為了提高訪問數據的速度,通常會增加一層或多層高速緩存(越靠近處理器的緩存速度越快)。
但是緩存同時也帶來了許多新的挑戰。比如,當兩個處理器同時讀取同一個內存位置時,看到的結果可能會不一樣?
在處理器維度上,內存模型定義了一些規則來保證當前處理器可以立即看到其他處理器的寫入,以及當前處理器的寫入對其他處理器立即可見。這些規則被稱為緩存一致性協議
有些多處理器架構實現了強一致性,所有的處理器在同一時刻看到的同一內存位置的值是一樣的。
而其他處理器實現的則是較弱的一致性,需要使用被稱為內存屏障的特殊機器指令使來實現最終一致性(通過刷新緩存或使緩存失效)。
這些內存屏障通常在釋放鎖和獲取鎖時被執行;對於高級語言(如Java)的程序員來說,它們是不可見的。

在強一致性的處理器上,由於減少了對內存屏障的依賴,編寫併發程序會更容易一些。
但是,相反的,近年來處理器設計的趨勢是使用較弱的內存模型,因為放寬對緩存一致性的要求可以使得多處理器系統有更好的伸縮性和更大的內存。

此外,編譯器、緩存或運行時還被允許通過指令重排序改變內存的操作順序(相對於程序所表現的順序)。
例如,編譯器可能會往後移動一個寫入操作,只要移動操作不改變程序的原本語義(as-if-serial語義),就可以自由進行更改。
再比如,緩存可能會推遲把數據刷回到主內存中,直到它認為時機合適了。
這種靈活的設計,目的都是為了獲得得最佳的性能,
但是在多線程環境下,指令重排會使得跨線程可見性的問題變的更複雜。

為了方便理解,我們來看個代碼示例:

Class Reordering {
  int x = 0, y = 0;
  //thread A
   public void writer() {
        x = 1;
        y = 2;
    }

    //thread B
    public void reader() {
        int r1 = y;
        int r2 = x;
     }
}

假設這段代碼被兩個線程併發執行,線程A執行writer(),線程B執行reader()。
如果線程B在reader()中看到了y=2,那麼直覺上我們會認為它看到的x肯定是1,因為在writer()中x=1y=2之前 。
然而,發生重排序時y=2會早於x=1執行,此時,實際的執行順序會是這樣的:

y=2;
int r1=y;
int r2=x;
x=1;

結果就是,r1的值是2,r2的值是0。
從線程A的角度看,x=1與y=2哪個先執行結果是一樣的(或者說沒有違反as-if-serial語義),但是在多線程環境下,這種重排序會產生混亂的結果。

我們可以看到,高速緩存指令重排序提高了效率的同時也引出了新的問題,這顯然使得編寫併發程序變得更加困難。
Java內存模型就是為了解決這類問題,它對多線程之間如何通過內存進行交互做了明確的說明。
更具體點,Java內存模型描述了程序中的變量與實際計算機的存儲設備(包括內存、緩存、寄存器)之間交互的底層細節。
例如,Java提供了volatile、final和 synchronized等工具,用於幫助程序員向編譯器表明對併發程序的要求。
更重要的是,Java內存模型保證這些同步工具可以正確的運行在任何處理器架構上,使Java併發應用做到“Write Once, Run Anywhere”。

相比之下,大多數其他語言(例如C/C++)都沒有提供显示的內存模型。
C程序繼承了處理器的內存模型,這意味着,C語言的併發程序在一個處理器架構中可以正確運行,在另外一個架構中則不一定。

2. JSR 133是關於什麼的?

Java提供的跨平台內存模型是一個雄心勃勃的計劃,在當時是具有開創性的。
但不幸的是,定義一個即直觀又一致的內存模型比預期的要困難得多。
自1997年以來,在《Java語言規範》的第17章關於Java內存模型的定義中發現了一些嚴重的缺陷。
這些缺陷使一些同步工具產生混亂的結果,例如final字段可以被更改。
JSR 133為Java語言定義了一個新的內存模型,修復了舊版內存模型的缺陷(修改了final和volatile的語義)
JSR的主要目標包括不限於這些:

  1. 正確同步的語義應該更直觀更簡單。
  2. 應該定義不完整或不正確同步的語義,以最小化潛在的安全隱患
  3. 程序員應該有足夠的自信推斷出多線程程序如何與內存交互的。
  4. 提供一個新的初始化安全性保證(initialization safety)。
    如果一個對象被正確初始化了(初始化期間,對象的引用沒有逃逸,比如構造函數里把this賦值給變量),那麼所有可以看到該對象引用的線程,都可以看到在構造函數中被賦值的final變量。這不需要使用synchronized或volatile。

3. 再談指令重排序

在許多情況下,出於優化執行效率的目的,數據(實例變量、靜態字段、數組元素等)可以在寄存器、緩存和內存之間以不同於程序中聲明的順序被移動。
例如,線程先寫入字段a,再寫入字段b,並且b的值不依賴a,那麼編譯器就可以自由的對這些操作重新排序,在寫入a之前把b的寫入刷回到內存。
除了編譯器,重排序還可能發生在JIT、緩存、處理器上。
無論發生在哪裡,重排序都必須遵循as-if-serial語義,這意味着在單線程程序中,程序不會覺察到重排序的存在,或者說給單線程程序一種沒有發生過重排序的錯覺。
但是,重排序在沒有同步的多線程程序中會產生影響。在這種程序中,一個線程能夠觀察到其他線程的運行情況,並且可能檢測到變量訪問順序與代碼中指定的順序不一致。
大多數情況下,一個線程不會在乎另一個線程在做什麼,但是,如果有,就是同步的用武之地。

4.同步都做了什麼?

同步有很多面,最為程序員熟知的是它的互斥性,同一時刻只能有一個線程持有monitor。
但是,同步不僅僅是互斥性。同步還能保證一個線程在同步塊中的寫內存操作對其他持有相同monitor的線程立即可見。
當線程退出同步塊時(釋放monitor),會把緩存中的數據刷回到主內存,使主內存中保持最新的數據。
當線程進入同步塊時(獲取monitor),會使本地處理器緩存失效,使得變量必須從主內存中重新加載。
我們可以看到,之前的所有寫操作對後來的線程都是可見的。

5. final字段在舊的內存模型中為什麼可以改變?

證明final字段可以改變的最佳示例是String類的實現(JDK 1.4版本)。
String對象包含三個字段:一個字符串數組的引用value、一個記錄數組中開始位置的offset、字符串長度length。
通過這種方式,可以實現多個String/StringBuffer對象共享一個相同的字符串數組,從而避免為每個對象分配額外的空間。
例如,String.substring()通過與原String對象共享一個數組來產生一個新的對象,唯一的不同是length和offset字段。

String s1 = "/usr/tmp";
String s2 = s1.substring(4); 

s2和s1共享一個字符串數組”/usr/tmp”,不同的是s2的offset=4,length=4,s1的offset=0,length=8。
在String的構造函數運行之前,根類Object的構造函數會先初始化所有字段為默認值,包括final的length和offset字段。
當String的構造函數運行時,再把length和offset賦值為期望的值。
但是這一過程,在舊的內存模型中,如果沒有使用同步,另一個線程可能會看到offset的默認值0,然後在看到正確的值4.
結果導致一個迷幻的現象,開始看到字符串s2的內容是’/usr’,然後再看到’/tmp’。
這不符合我們對final語義的認識,但是在舊內存模型中確實存在這樣的問題。
(JDK7開始,改變了substring的實現方式,每次都會創建一個新的對象)

6.“初始化安全”與final字段?

新的內存模型提供一個新初始化安全( initialization safety)保障。
意味着,只要一個對象被正確的構造,那麼所有的線程都會看到這些在構造函數中被賦值的final字段。
“正確”的構造是指在構造函數執行期間,對象的引用沒有發生逃逸。或者說,在構造函數中沒有把該對象的引用賦值給任何變量。

class FinalFieldExample {
  final int x;
  int y;
  static FinalFieldExample f;
  public FinalFieldExample() {
    x = 3;
    y = 4;
  }

  static void writer() {
    f = new FinalFieldExample();
  }

  static void reader() {
    if (f != null) {
      int i = f.x;
      int j = f.y;
    }
  }
}

示例中,初始化安全保證執行reader()方法的線程看到的f.x=3,因為它是final字段,但是不保證能看到y=4,因為它不是final的。
但是如果構造函數像這樣:

public FinalFieldExample() { // bad!
  x = 3;
  y = 4;
  global.obj = this;  //  allowing this to escape
}

初始化安全不能保證讀取global.obj的線程看到的x的值是3,因為對象引用this發生了逃逸。

不僅如此,任何通過final字段(構造函數中被賦值的)可以觸達的變量都可以保證對其他線程可見。
這意味着如果一個final字段包含一個引用,例如ArrayList,除了該字段的引用對其他線程可見,ArrayList中的元素對其他線程也是可見的。

初始化安全增強了final的語義,使其更符合我們對final的直觀感受,任何情況下都不會改變。

7. 增強volatile語義

volatile變量是用於線程之間傳遞狀態的特殊變量,這要求任何線程看到的都是volatile變量的最新值。
為實現可見性,禁止在寄存器中分配它們,還必須確保修改volatile后,要把最新值從緩存刷到內存中。
類似的,在讀取volatile變量之前,必須使高速緩存失效,這樣其他線程會直接讀取主內存中的數據。
在舊的內存模型中,多個volatile變量之間不能互相重排序,但是它們被允許可以與非volatile變量一起重排序,這消弱了volatile作為線程間交流信號的作用。
我們來看個示例:

Map configs;
volatile boolean initialized = false;
. . .
 
// In thread A
configs  =  readConfigFile(fileName);
processConfigOptions( configs);
initialized = true;
. . .
 
// In thread B
while (initialized) {
    // use configs
}

示例中,線程A負責配置數據初始化工作,初始化完成后線程B開始執行。
實際上,volatile變量initialized扮演者守衛者的角色,它表示前置工作已經完成,依賴這些數據的其他線程可以執行了。
但是,當volatile變量與非volatile變量被編譯器放到一起重新排序時,“守衛者”就形同虛設了。
重排序發生時,可能會使readConfigFile()中某個動作在initialized = true之後執行,
那麼,線程B在看到initialized的值為true后,在使用configs對象時,會讀取到沒有被正確初始化的數據。
這是volatile很典型的應用場景,但是在舊的內存模型中卻不能正確的工作。

JSR 133專家組決定在新的內存模型中,不再允許volatile變量與其他任務內存操作一起重排序
這意味着,volatile變量之前的內存操作不會在其後執行,volatile變量之後的內存操作不會在其前執行。
volatile變量相當於一個屏障,重排序不能越過對volatile的內存操作。(實際上,jvm確實使用了內存屏障指令)
增強volatile語義的副作用也很明顯,禁止重排序會有一定的性能損失。

8. 修復“double-checked locking”的問題

double-checked locking是單例模式的其中一種實現,它支持懶加載且是線程安全的。
大概長這個樣子:

private static Something instance = null;

public Something getInstance() {
  if (instance == null) {
    synchronized (this) {
      if (instance == null)
        instance = new Something();//
    }
  }
  return instance;
}

它通過兩次檢查巧妙的避開了在公共代碼路徑上使用同步,從而避免了同步所帶來的性能開銷。
它唯一的問題就是——不起作用。為什麼呢?
instance的賦值操作會與SomeThing()構造函數中的變量初始化一起被編譯器或緩存重排序,這可能會導致把未完全初始化的對象引用賦值給instance。
現在很多人知道把instance聲明為volatile可以修復這個問題,但是在舊的內存模型(JDK 1.5之前)中並不可行,原因前面有提到,volatile可以與非volatile字段一起重排序。

儘管,新的內存模型修復了double-checked locking的問題,但仍不鼓勵這種實現方式,因為volatile並不是免費的。
相比之下,Initialization On Demand Holder Class更值得被推薦,
它不僅實現了懶加載和線程安全,還提供了更好的性能和更清晰的代碼邏輯。大概長這個樣子:

public class Something {
    private Something() {}
    //static innner class
    private static class LazyHolder {
        static final Something INSTANCE = new Something(); //static  field
    }

    public static Something getInstance() {
        return LazyHolder.INSTANCE;
    }
}

這種實現完全沒有使用同步工具,而是利用了Java語言規範的兩個基本原則,
其一,JVM保證靜態變量的初始化對所有使用該類的線程立即可見;
其二,內部類首次被使用時才會觸發類的初始化,這實現了懶加載。

9. 為什麼要關心這些問題?

併發問題一般不會在測試環境出現,生成環境的併發問題又不容易復現,這兩個特點使得併發問題通常比較棘手。
所以你最好提前花點時間學習併發知識,以確保寫出正確的併發程序。我知道這很困難,但是應該比排查生產環境的併發問題容易的多。

延伸閱讀

1.JSR 133 (Java Memory Model) FAQ,2004
2.volatile關鍵字
3.Double-checked問題
4.內存屏障和volatile語義
5.修復Java內存模型
6.String substring 在jdk7中會創建新的數組
7.Memory Ordering
8.有MESI協議為什麼還需要volatile?
9.Initialization On Demand Holder Class
10.The JSR-133 Cookbook for Compiler Writers

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

【其他文章推薦】

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

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

※想知道購買電動車哪裡補助最多?台中電動車補助資訊懶人包彙整

南投搬家公司費用,距離,噸數怎麼算?達人教你簡易估價知識!

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

※超省錢租車方案

德鐵挑戰氣候目標 2030年減碳50%、使用70%綠電

環境資訊中心記者 陳文姿報導

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

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

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

※想知道購買電動車哪裡補助最多?台中電動車補助資訊懶人包彙整

南投搬家公司費用,距離,噸數怎麼算?達人教你簡易估價知識!

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

※超省錢租車方案

【譯】Announcing Entity Framework Core 5.0 Preview 5

  今天我們宣布EF Core 5.0發布第五個預覽版。

1 先決條件

  EF Core 5.0 的預覽版要求  .NET Standard 2.1。這意味着:

      • EF Core 5.0 在 .NET Core 3.1 上運行,不需要 .NET 5。根據 .NET 5 計劃的改變,這可能會在未來發生變化。

      • EF Core 5.0 運行在其他支持 .NET Standard 2.1 的平台上。

      • EF Core 5.0 將不會在 .NET Standard 2.0 平台上運行,包括 .NET Framework。

2 如何獲取EF Core 5.0預覽版

  使用NuGet添加,例如添加SQL Server的提供程序:

dotnet add package Microsoft.EntityFrameworkCore.SqlServer --version 5.0.0-preview.5.20278.2

  目前發布的 EF Core包包括:

      • Microsoft.EntityFrameworkCore – 主程序

      • Microsoft.EntityFrameworkCore.SqlServer – SQL Server與SQL Azure提供者

      • Microsoft.EntityFrameworkCore.Sqlite – SQLite提供者

      • Microsoft.EntityFrameworkCore.Cosmos – Azure Cosmos DB提供者

      • Microsoft.EntityFrameworkCore.InMemory – 內存數據庫提供者

      • Microsoft.EntityFrameworkCore.Tools –Visual Studio Package Manager Console的 EF Core PowerShell命令

      • Microsoft.EntityFrameworkCore.Design – EF Core的設計時組件

      • Microsoft.EntityFrameworkCore.SqlServer.NetTopologySuite – SQL Server 空間類型支持

      • Microsoft.EntityFrameworkCore.Sqlite.NetTopologySuite – SQLite空間類型支持

      • Microsoft.EntityFrameworkCore.Proxies –延遲加載與變化跟蹤代理

      • Microsoft.EntityFrameworkCore.Abstractions – 分離的EF Core抽象

      • Microsoft.EntityFrameworkCore.Relational – 關係數據庫提供程序的共享EF Core組件

      • Microsoft.EntityFrameworkCore.Analyzers – EF Core的C#分析器

      • Microsoft.EntityFrameworkCore.Sqlite.Core – SQLite提供者(沒有打包的本機二進制文件)

  我們還發布了Microsoft.Data.Sqlite.Core ADO.NET provider的預覽版。

3 安裝dotnet ef

  與EF Core 3.0和3.1一樣,dotnet EF命令行工具不再包含在.NET Core SDK中。在執行EF Core的migration或scaffolding命令之前,必須將此包作為全局或本地工具安裝。

  若要全局安裝預覽版工具,需要先使用以下命令卸載現有的版本:

dotnet tool uninstall --global dotnet-ef

  然後,進行安裝:

dotnet tool install --global dotnet-ef --version 5.0.0-preview.5.20278.2

  可以將此新版本的dotnet ef與使用較舊版本的EF Core運行時的項目一起使用。

4 EF Core 5.0預覽版的一些新功能

4.1 數據庫排序規則

  現在可以在 EF Model中指定數據庫的默認排序規則。

modelBuilder.UseCollation("German_PhoneBook_CI_AS");

  然後,Migrations將生成以下內容以在 SQL Server 上創建數據庫:

CREATE DATABASE [Test]
COLLATE German_PhoneBook_CI_AS;

  也可以指定用於特定數據庫列的排序規則。

  例如:

modelBuilder
     .Entity<User>()
     .Property(e => e.Name)
     .UseCollation("German_PhoneBook_CI_AS");

  為了那些不使用migration的人,現在,在 DbContext scaffolding時,將從數據庫進行反向工程。最後,EF.Functions.Collate() 允許使用不同的排序規則進行臨時查詢。

  例如:

context.Users.Single(e => EF.Functions.Collate(e.Name, "French_CI_AS") == "Jean-Michel Jarre");

  這將生成 SQL Server 的以下查詢:

SELECT TOP(2) [u].[Id], [u].[Name]
FROM [Users] AS [u]
WHERE [u].[Name] COLLATE French_CI_AS = N'Jean-Michel Jarre'

  請注意,臨時排序規則應謹慎使用,因為它們會對數據庫性能產生負面影響。

4.2 傳遞參數給IDesignTimeDbContextFactory

  參數現在從命令行傳入IDesignTimeDbContextFactory 的 CreateDbContext 方法。

  例如,為了指示這是開發構建,可以在命令行上傳遞自定義參數(例如 dev):

dotnet ef migrations add two --verbose --dev

  然後,此參數將傳遞到工廠:

public class MyDbContextFactory : IDesignTimeDbContextFactory<SomeDbContext>
{
    public SomeDbContext CreateDbContext(string[] args)
        => new SomeDbContext(args.Contains("--dev"));
}

4.3 具有標識解析的無跟蹤查詢

  現在,可以將無跟蹤查詢配置為執行標識解析。

  例如,以下查詢將為每個Post創建新的Blog實例,即使每個Blog具有相同的主鍵也是如此。

context.Posts.AsNoTracking().Include(e => e.Blog).ToList();

  但是,可以更改此查詢以確保只創建單個 Blog 實例,但代價通常是稍微慢一點,並且使用更多內存:

context.Posts.AsNoTracking().PerformIdentityResolution().Include(e => e.Blog).ToList();

  請注意,這僅適用於無跟蹤查詢,因為所有跟蹤查詢都已表現出此行為。

4.4 持久化計算列

  大多數數據庫允許在計算后存儲計算列的值。

  雖然這佔用磁盤空間,但計算列在更新時只計算一次,而不是在每次檢索其值時計算。

  這還允許對某些數據庫的列設置索引。

  EF Core 5.0 允許將計算列配置為存儲列。

  例如:

modelBuilder
    .Entity<User>()
    .Property(e => e.SomethingComputed)
    .HasComputedColumnSql("my sql", stored: true);

4.5 SQLite計算列

  EF Core 現在支持 SQLite 數據庫的計算列。

5 有用的短鏈接

  提供了以下短鏈接,便於參考和訪問。

      • 主要文檔:https://aka.ms/efdocs
      • EF Core 的問題和功能請求:https://aka.ms/efcorefeedback
      • EF路線圖:https://aka.ms/efroadmap
      • EF Core 5.x 中的新增功能是什麼:https://aka.ms/efcore5

原文鏈接

  https://devblogs.microsoft.com/dotnet/announcing-entity-framework-core-5-0-preview-5/?utm_source=vs_developer_news&utm_medium=referral

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

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

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

※想知道購買電動車哪裡補助最多?台中電動車補助資訊懶人包彙整

南投搬家公司費用,距離,噸數怎麼算?達人教你簡易估價知識!

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

※超省錢租車方案

聚甘新

能源發展仍需時間,統振前3季營運近損平

 

 

    統振前三季數據服務、流通事業與數位娛樂獲利持穩成長,惟能源部門則仍處於投入階段,前3季營運維持在損平邊緣,與去年表現相當;看好電動車長期發展趨勢,統振持續耕耘電動自行車、電動機車等市場,目前在兩岸也有開發案進行中,惟因相關開發案都需要一段時間醞釀,對整體營運貢獻仍需持續觀察。   統振母公司目前從事行動電話預付卡銷售、網路遊戲儲值卡買賣,動能主要來自外勞預付卡市佔率成長,而統振旗下轉投資數位電通則主要經營電商通路,去年起新增美妝產品,至於數位點子多媒體則以數位內容業務為主,包括連續劇版權買賣及演唱會業務;另外,統振旗下還有兩家從事電池模組相關業務的子公司達振與統達,達振在中國擁有工廠,目前主要生產3C相關電池模組,未來將逐步轉型至電動車電池模組,而統達則負責開發相關電動自行車、電動機車電池模組與交換系統。   統振前3季數據服務部門(母公司部份)約占合併營收61%,能源部門(統達與達振)佔29%,流通事業(數位電通)佔7%,數位娛樂(數位點子多媒體)3%,而前3季除了能源部門持續虧損,其他部門獲利則都穩定增長,但因能源部門前3季虧損約9,000多萬元,而其他部分獲利合計則約7,000多萬元,前3季營運仍在損平邊緣,統振前3季EPS為 -0.06元,Q3底每股淨值為12.63元。   看好電動車長期發展趨勢,統振持續投入高功率電池模組開發,而有鑑於台廠較難直接切入電動汽車供應鏈,統振也先從電動腳踏車、電動機車切入,而目前中國電動兩輪車仍以鉛酸蓄電池為主流,惟考量環保、輕量化等趨勢,加以政策驅動,且近年鋰電池成本也持續改善,將有助於提升鋰電池轉換需求,統振目前也持續與相關廠商合作,等待市場規模逐步放大。   統振今年前3季合併營收為22.34億元,年減9.7%;前3季EPS為 -0.06元,與去年同期的 -0.02元差異不大。統振近幾年本業大多呈現小幅虧損,主要係因能源部份仍在支出階段,但其他部門獲利則相對穩定。   (本文內容由授權使用,首圖為統振旗下達陣能源鋰電池模組,來源:)  

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

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

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

※想知道購買電動車哪裡補助最多?台中電動車補助資訊懶人包彙整

南投搬家公司費用,距離,噸數怎麼算?達人教你簡易估價知識!

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

※超省錢租車方案

聚甘新

特斯拉帶動電池需求,住友化學擬擴產四倍

特斯拉(Tesla)雖然傳出供貨不及、營收下滑等問題,但仍明顯帶動全球市場對於電動車的關注與需求。看好電動車用鋰電池的需求量將繼續成長,日本住友化學(Sumitomo Chemical)計畫在2018年時將位於南韓的分隔膜(separator)產能擴增至2016年初水準的4倍。

根據《日經》報導,電動車市場的擴大,直接推動電動車用鋰電池的供應鏈強度,從材料到電池包都成為產業關注的焦點。特斯拉的車用電池由日本Panasonic所提供,而Panasonic供應給特斯拉的電池所使用的分隔膜,則由住友化學供應。因應特斯拉打算在2018年將年產能提高到50萬輛、2020年增至100萬輛,住友化學預期Panasonic的分隔膜需求會在接下來暴漲,因此決定擴產。

正極與負極材料、分隔膜、電解液是鋰電池的四大關鍵材料,且日廠佔有絕對的市佔率。除住友化學供應分隔膜給 Panasonic 之外,Toray也有供應分隔膜給Panasonic、LG Chem,且預計在2018年底時將產能提高70%。另一分隔膜廠商旭化成計畫在2020年底前倍增分隔膜產能,住友金屬礦山打算在近年將正極材料產能擴大兩倍、昭和電工則規畫在今年底前提高負極材料產能80%。

MoneyDJ引用日本市調機構富士經濟的說法,認為全球電動車市場會在2020年左右急速擴大,到2035年時成長到567萬輛,較2015年飆漲近16倍之多。其中,又以中國、歐洲市場的成長幅度最為明顯。

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

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

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

※想知道購買電動車哪裡補助最多?台中電動車補助資訊懶人包彙整

南投搬家公司費用,距離,噸數怎麼算?達人教你簡易估價知識!

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

※超省錢租車方案

聚甘新

ASP.NET Core 對Controller進行單元測試

單元測試對我們的代碼質量非常重要。很多同學都會對業務邏輯或者工具方法寫測試用例,但是往往忽略了對Controller層寫單元測試。我所在的公司沒見過一個對Controller寫過測試的。今天來演示下如果對Controller進行單元測試。以下內容默認您對單元測試有所了解,比如如何mock一個接口。在這裏多叨叨一句,面向接口的好處,除了能夠快速的替換實現類(其實大部分接口不會有多個實現),最大的好處就是可以進行mock,可以進行單元測試。

測試Action

下面的Action非常簡單,非常常見的一種代碼。根據用戶id去獲取用戶信息然後展示出來。下面看看如何對這個Action進行測試。

   public class UserController : Controller
    {
        private readonly IUserService _userService;
        public UserController(IUserService userService)
        {
            _userService = userService;
        }

        public IActionResult UserInfo(string userId)
        {
            if (string.IsNullOrEmpty(userId))
            {
                throw new ArgumentNullException(nameof(userId));
            }

            var user = _userService.Get(userId);
            return View(user);
        }
      
    }

測試代碼:

  [TestMethod()]
        public void UserInfoTest()
        {

            var userService = new Mock<IUserService>();
            userService.Setup(s => s.Get(It.IsAny<string>())).Returns(new User());

            var ctrl = new UserController(userService.Object);
            //對空參數進行assert
            Assert.ThrowsException<ArgumentNullException>(() => {
                var result = ctrl.UserInfo(null);
            });
            //對空參數進行assert
            Assert.ThrowsException<ArgumentNullException>(() => {
                var result = ctrl.UserInfo("");
            });

            var result = ctrl.UserInfo("1");
            Assert.IsNotNull(result);
            Assert.IsInstanceOfType(result, typeof(ViewResult));
        }

我們對一個Action進行測試主要的思路就是模擬各種入參,使測試代碼能夠到達所有的分支,並且Assert輸出是否為空,是否為指定的類型等。

對ViewModel進行測試

我們編寫Action的時候還會涉及ViewModel給視圖傳遞數據,這部分也需要進行測試。修改測試用例,加入對ViewModel的測試代碼:

  [TestMethod()]
        public void UserInfoTest()
        {
            var userService = new Mock<IUserService>();
            userService.Setup(s => s.Get(It.IsAny<string>())).Returns(new User()
            {
                Id = "x"
            }) ;

            var ctrl = new UserController(userService.Object);
            Assert.ThrowsException<ArgumentNullException>(() => {
                var result = ctrl.UserInfo(null);
            });
            Assert.ThrowsException<ArgumentNullException>(() => {
                var result = ctrl.UserInfo("");
            });

            var result = ctrl.UserInfo("1");
            Assert.IsNotNull(result);
            Assert.IsInstanceOfType(result, typeof(ViewResult));
            //對viewModel進行assert
            var vr = result as ViewResult;
            Assert.IsNotNull(vr.Model);
            Assert.IsInstanceOfType(vr.Model, typeof(User));
            var user = vr.Model as User;
            Assert.AreEqual("x", user.Id);
        }

對ViewData進行測試

我們編寫Action的時候還會涉及ViewData給視圖傳遞數據,這部分同樣需要測試。修改Action代碼,對ViewData進行賦值:

   public IActionResult UserInfo(string userId)
        {
            if (string.IsNullOrEmpty(userId))
            {
                throw new ArgumentNullException(nameof(userId));
            }

            var user = _userService.Get(userId);

            ViewData["title"] = "user_info";

            return View(user);
        }
      

修改測試用例,加入對ViewData的測試代碼:

   [TestMethod()]
        public void UserInfoTest()
        {
            var userService = new Mock<IUserService>();
            userService.Setup(s => s.Get(It.IsAny<string>())).Returns(new User()
            {
                Id = "x"
            }) ;

            var ctrl = new UserController(userService.Object);
            Assert.ThrowsException<ArgumentNullException>(() => {
                var result = ctrl.UserInfo(null);
            });
            Assert.ThrowsException<ArgumentNullException>(() => {
                var result = ctrl.UserInfo("");
            });

            var result = ctrl.UserInfo("1");
            Assert.IsNotNull(result);
            Assert.IsInstanceOfType(result, typeof(ViewResult));

            var vr = result as ViewResult;
            Assert.IsNotNull(vr.Model);
            Assert.IsInstanceOfType(vr.Model, typeof(User));
            var user = vr.Model as User;
            Assert.AreEqual("x", user.Id);
            //對viewData進行assert
            Assert.IsTrue(vr.ViewData.ContainsKey("title"));
            var title = vr.ViewData["title"];
            Assert.AreEqual("user_info", title);
        }

對ViewBag進行測試

因為ViewBag事實上是ViewData的dynamic類型的包裝,所以Action代碼不用改,可以直接對ViewBag進行測試:

     [TestMethod()]
        public void UserInfoTest()
        {
            var userService = new Mock<IUserService>();
            userService.Setup(s => s.Get(It.IsAny<string>())).Returns(new User()
            {
                Id = "x"
            }) ;

            var ctrl = new UserController(userService.Object);
            Assert.ThrowsException<ArgumentNullException>(() => {
                var result = ctrl.UserInfo(null);
            });
            Assert.ThrowsException<ArgumentNullException>(() => {
                var result = ctrl.UserInfo("");
            });

            var result = ctrl.UserInfo("1");
            Assert.IsNotNull(result);
            Assert.IsInstanceOfType(result, typeof(ViewResult));

            var vr = result as ViewResult;
            Assert.IsNotNull(vr.Model);
            Assert.IsInstanceOfType(vr.Model, typeof(User));
            var user = vr.Model as User;
            Assert.AreEqual("x", user.Id);

            Assert.IsTrue(vr.ViewData.ContainsKey("title"));
            var title = vr.ViewData["title"];
            Assert.AreEqual("user_info", title);
            //對viewBag進行assert
            string title1 = ctrl.ViewBag.title;
            Assert.AreEqual("user_info", title1);
        }

設置HttpContext

我們編寫Action的時候很多時候需要調用基類里的HttpContext,比如獲取Request對象,獲取Path,獲取Headers等等,所以有的時候需要自己實例化HttpContext以進行測試。

    var ctrl = new AccountController();
    ctrl.ControllerContext = new ControllerContext();
    ctrl.ControllerContext.HttpContext = new DefaultHttpContext();

對HttpContext.SignInAsync進行mock

我們使用ASP.NET Core框架進行登錄認證的時候,往往使用HttpContext.SignInAsync進行認證授權,所以單元測試的時候也需要進行mock。下面是一個典型的登錄Action,對密碼進行認證后調用SignInAsync在客戶端生成登錄憑證,否則跳到登錄失敗頁面。

   public async Task<IActionResult> Login(string password)
        {
            if (password == "123")
            {
                var claims = new List<Claim>
                {
                  new Claim("UserName","x")
                };
                var authProperties = new AuthenticationProperties
                {
                };
                var claimsIdentity = new ClaimsIdentity(
                  claims, CookieAuthenticationDefaults.AuthenticationScheme);
                await HttpContext.SignInAsync(
                    CookieAuthenticationDefaults.AuthenticationScheme,
                    new ClaimsPrincipal(claimsIdentity),
                    authProperties);
                return Redirect("login_success");
            }

            return Redirect("login_fail");
        }

HttpContext.SignInAsync其實個時擴展方法,SignInAsync其實最終是調用了IAuthenticationService里的SignInAsync方法。所以我們需要mock的就是IAuthenticationService接口,否者代碼走到HttpContext.SignInAsync會提示找不到IAuthenticationService的service。而IAuthenticationService本身是通過IServiceProvider注入到程序里的,所以同時需要mock接口IServiceProvider。

    [TestMethod()]
        public async Task LoginTest()
        {
            var ctrl = new AccountController();

            var authenticationService = new Mock<IAuthenticationService>();
            var sp = new Mock<IServiceProvider>();
            sp.Setup(s => s.GetService(typeof(IAuthenticationService)))
                .Returns(() => {
                    return authenticationService.Object;
                });
            ctrl.ControllerContext = new ControllerContext();
            ctrl.ControllerContext.HttpContext = new DefaultHttpContext();
            ctrl.ControllerContext.HttpContext.RequestServices = sp.Object;

           var result = await ctrl.Login("123");
            Assert.IsNotNull(result);
            Assert.IsInstanceOfType(result, typeof(RedirectResult));
            var rr = result as RedirectResult;
            Assert.AreEqual("login_success", rr.Url);

            result = await ctrl.Login("1");
            Assert.IsNotNull(result);
            Assert.IsInstanceOfType(result, typeof(RedirectResult));
            rr = result as RedirectResult;
            Assert.AreEqual("login_fail", rr.Url);
        }

對HttpContext.AuthenticateAsync進行mock

HttpContext.AuthenticateAsync同樣比較常用。這個擴展方法同樣是在IAuthenticationService里,所以測試代碼跟上面的SignInAsync類似,只是需要對AuthenticateAsync繼續mock返回值success or fail。

     public async Task<IActionResult> Login()
        {
            if ((await HttpContext.AuthenticateAsync()).Succeeded)
            {
                return Redirect("/home");
            }

            return Redirect("/login");
        }

測試用例:


        [TestMethod()]
        public async Task LoginTest1()
        {
            var authenticationService = new Mock<IAuthenticationService>();
            //設置AuthenticateAsync為success
            authenticationService.Setup(s => s.AuthenticateAsync(It.IsAny<HttpContext>(), It.IsAny<string>()))
                .ReturnsAsync(AuthenticateResult.Success(new AuthenticationTicket(new System.Security.Claims.ClaimsPrincipal(), "")));
            var sp = new Mock<IServiceProvider>();
            sp.Setup(s => s.GetService(typeof(IAuthenticationService)))
                .Returns(() => {
                    return authenticationService.Object;
                });

            var ctrl = new AccountController();
            ctrl.ControllerContext = new ControllerContext();
            ctrl.ControllerContext.HttpContext = new DefaultHttpContext();
            ctrl.ControllerContext.HttpContext.RequestServices = sp.Object;

            var act = await ctrl.Login();
            Assert.IsNotNull(act);
            Assert.IsInstanceOfType(act, typeof(RedirectResult));
            var rd = act as RedirectResult;
            Assert.AreEqual("/home", rd.Url);
            //設置AuthenticateAsync為fail
            authenticationService.Setup(s => s.AuthenticateAsync(It.IsAny<HttpContext>(), It.IsAny<string>()))
               .ReturnsAsync(AuthenticateResult.Fail(""));

            act = await ctrl.Login();
            Assert.IsNotNull(act);
            Assert.IsInstanceOfType(act, typeof(RedirectResult));
            rd = act as RedirectResult;
            Assert.AreEqual("/login", rd.Url);

        }

Filter進行測試

我們寫Controller的時候往往需要配合很多Filter使用,所以Filter的測試也很重要。下面演示下如何對Fitler進行測試。

    public class MyFilter: ActionFilterAttribute
    {
        public override void OnActionExecuting(ActionExecutingContext context)
        {
            if (context.HttpContext.Request.Path.Value.Contains("/abc/"))
            {
                context.Result = new ContentResult() {
                    Content = "拒絕訪問"
                };
            }

            base.OnActionExecuting(context);
        }
    }

對Filter的測試最主要的是模擬ActionExecutingContext參數,以及其中的HttpContext等,然後對預期進行Assert。

       [TestMethod()]
        public void OnActionExecutingTest()
        {
            var filter = new MyFilter();
            var actContext = new ActionContext(new DefaultHttpContext(),new RouteData(), new ActionDescriptor());
            actContext.HttpContext.Request.Path = "/abc/123";
            var listFilters = new List<IFilterMetadata>();
            var argDict = new Dictionary<string, object>();
            var actExContext = new ActionExecutingContext(
                actContext ,
                listFilters ,
                argDict ,
                new AccountController()
                );
             filter.OnActionExecuting(actExContext);

            Assert.IsNotNull(actExContext.Result);
            Assert.IsInstanceOfType(actExContext.Result, typeof(ContentResult));
            var cr = actExContext.Result as ContentResult;
            Assert.AreEqual("拒絕訪問", cr.Content);

            actContext = new ActionContext(new DefaultHttpContext(), new RouteData(), new ActionDescriptor());
            actContext.HttpContext.Request.Path = "/1/123";
            listFilters = new List<IFilterMetadata>();
            argDict = new Dictionary<string, object>();
            actExContext = new ActionExecutingContext(
                actContext,
                listFilters,
                argDict,
                new AccountController()
                );
            filter.OnActionExecuting(actExContext);
            Assert.IsNull(actExContext.Result);
        }

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

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

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

※想知道購買電動車哪裡補助最多?台中電動車補助資訊懶人包彙整

南投搬家公司費用,距離,噸數怎麼算?達人教你簡易估價知識!

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

※超省錢租車方案

聚甘新

文本挖掘之情感分析(一)

一、文本挖掘  

     文本挖掘則是對文本進行處理,從中挖掘出來文本中有用的信息和關鍵的規則,在文本挖掘領域應用最往廣泛的是對文本進行分類和聚類,其挖掘的方法分為無監督學習和監督學習。文本挖掘還可以劃分為7大類:關鍵詞提取、文本摘要、文本主題模型、文本聚類、文本分類、觀點提取、情感分析。

   關鍵詞提取:對長文本的內容進行分析,輸出能夠反映文本關鍵信息的關鍵詞。

   文本摘要:許多文本挖掘應用程序需要總結文本文檔,以便對大型文檔或某一主題的文檔集合做出簡要概述。

   文本聚類:主要是對未標註的文本進行標註,常見的有 K均值聚類和層次聚類。

   文本分類:文本分類使用監督學習的方法,以對未知數據的分類進行預測的機器學習方法。

   文本主題模型 LDA:LDA(Latent Dirichlet Allocation)是一種文檔主題生成模型,也稱為一個三層貝恭弘=叶 恭弘斯概率模型,包含詞、主題和文檔三層結構,該模型可以用於獲取語料的主題提取和對不同類別的文檔進行分類。

   觀點抽取:對文本(主要針對評論)進行分析,抽取出核心觀點,並判斷極性(正負面),主要用於電商、美食、酒店、汽車等評論進行分析。

   情感分析:對文本進行情感傾向判斷,將文本情感分為正向、負向、中性。用於口碑分析、話題監控、輿情分析。

   因為自己的論文寫的是關於情感分析方面的內容,因此打算接下來主要寫情感分析系列的內容,今天主要寫關於情感分析的介紹以及發展史。

二、情感分析

1. 含義

     情感分析主要是通過分析人們對於服務、產品、事件、話題來挖掘出說話人/作者觀點、情感、情緒等的研究。情感分析按照研究內容的不同,可以分為:意見挖掘 / 意見提取 / 主觀性分析 / 情感傾向分析、情感情緒分析、情感打分等。情感傾向問題,即是指挖掘出一段語料中說話人/作者對於某一話題/事件所持有的態度,如褒義、貶義、中性、兩者兼有。情感情緒,則是將情感傾向進行更進一步的細化,依據“大連理工大學的情感詞彙本體庫”可知,可以將情感傾向可以細化為:“喜歡”、“憤怒”、“討厭”等具體的7個大類——21個小類別。情感打分,即根據情感態度對於某一事物進行評分,如淘寶系統的1-5分。 文本中的情感分析還可以分為:顯式情感、隱式情感,顯式情感是指包含明顯的情感詞語(如:高興、漂亮、討厭等),隱式情感則是指不包含情感詞語的情感文本,如:“這個杯子上面有一層灰”。由於隱式情感分析難度較大,因此目前的工作多集中在顯式情感分析領域。

     情感分析按照不同的分析對象,可以分為:文章級別的情感分析、句子級別的情感分析、詞彙級別的情感分析。按照不同的研究內容以及研究的粒度的不同,其研究情感分析的方法也有很大的變化。

     目前的情感分析研究可歸納為:情感資源構建、情感元素抽取、情感分類及情感分析應用系統;

     情感資源構建:情感資源一般來說有:情感詞典、情感語料庫。情感詞典的構建即是將現有的、整理好的情感詞典資源進行整合,比如中文情感詞典有:大連理工大學的情感詞彙本體庫、知網Hownet情感詞典、台灣大學的NTUSD簡體中文情感詞典等,根據不同的需求,應用這些情感詞典。情感語料庫,則是我們要分析的文本,如關於新聞的文本、微博評論文本、商品評論文本、電影評論文本等,這些語料的獲取可以是尋找已經整理好的數據,或者自己爬蟲獲取。推薦一個比較全的中文語料庫網站:中文NLP語料庫。

    情感元素抽取:情感元素抽取則是從語料中抽取出來能夠代表說話人/作者情感態度問題的詞彙,也稱為細粒度情感分析。語料中的評價對象和表達抽取是情感元素抽取的核心內容。評價對象是指語料中被討論的主題,比如對於商品評論來說,用戶常提起的“外觀”、“快遞”、“包裝”等方面;表達抽取主要針對顯式情感表達的文本,是指文本抽取出來能夠代表說話人/作者情感、情緒、意見等的詞彙,比如“漂亮”、“贊同”、“不贊同”等。一般來說,評價對象和表達抽取也可以作為相互獨立的兩個任務。一般來說,分析這兩者的方法有:基於規則、基於機器學習。對於評價對象來說,現如今使用最多的方法是利用主題模型中的LDA(Latent Dirichlet Allocation)模型進行分析;對於表達抽取則有:深度學習的方法、基於JST (Joint Sentiment/Topic )模型的方法等。

     情感分類:情感分類則是將文本分為一個具體的類別,比如情感傾向分析,則是將文檔分為:褒義、貶義、中性等。一般來說,進行情感分類的方法有,基於情感詞典、基於機器學習。基於情感詞典,最典型的方法則是基於知網Hownet情感詞典的So-Hownet指標進行情感分類,基於機器學習的方法則有監督學習方法、半監督學習方法等。

    針對於情感分析,現已經存在一些專有平台,如:基於Boson 數據的情感分析平台,基於產品評論的平台Google Shopping。情感分析除了在電商平台應用廣泛之外,情感分析技術還被引入到對話機器人領域。例如,微軟的“小冰”機器人 可以通過分析用戶的文本輸入和表情貼圖,理解用戶當前的情緒狀況,並據此回復文本或者語音等情感回應。部分研究機構還將情感分析技術融入實體機器人中。

 2. 發展史

     V. H. 和 K. R. McKeown 於 1997 年發表的論文 [1],該論文使用對數線性回歸模型從大量語料庫中識別形容詞的正面或負面語義,同時藉助該模型對語料中出現的形容詞進行分類預測。

     Peter Turney在 2002年在論文 [2] 提出了一種無監督學習的算法,其可以很好的將語料中的詞語分類成正面情感詞和負面情感詞。

    2002 年 Bo Pang 等人在論文 [3] 中使用了傳統的機器學習方法對電影評論數據進行分類,同時也驗證了機器學習的方法的確要比之前基於規則的方法要優。

    2003 年 Blei 等人在論文 [4] 中提出了 LDA(Latent Dirichlet Allocation)模型,在之後的情感分析領域的工作中,很多學者/研究人員都使用主題模型來進行情感分析,當然也不只是基於主題模型來進行情感分析研究,還有很多利用深度學習方法來進行情感分析的研究。

   Lin 和 He在 2009 年的論文 [5] 提出了一種基於主題模型的模型 —JST(Joint Sentiment/Topic),其有效的將情感加入到了經典的主題模型當中,因此利用該模型可以獲取到不同情感極性標籤下不同主題的分佈情況。傳統的主題模型獲取文檔的主題以及詞的分佈情況,但並沒有關注到情感的存在,因此基於該模型可以對文檔的情感傾向進行分析。利用 JST 模型可以有效的直接將語料的主題、情感信息挖掘出來,同時 JST 模型還考慮到了主題、文檔、情感、詞之間的聯繫。

    基於對於語義和句法的考慮,Jo 和 H.OH 在 2011 年提出了 ASUM(Aspect and Sentiment Unification Model)模型,該模型和 JST 模型很相似都是四層的貝恭弘=叶 恭弘斯網絡結構 [6] 。

    基於神經網絡的語義組合算法被驗證是一種非常有效的特徵學習手段,2013年,Richard Socher和Christopher Potts等人提出多個基於樹結構的Recursive Neural Network,該方法通過迭代運算的方式學習變量長度的句子或短語的語義表示,在斯坦福情感分析樹庫(Stanford Sentiment Treebank)上驗證了該方法的有效性 [7]。Nal Kalchbrenner等人描述了一個卷積體繫結構,稱為動態卷積神經網絡(DCNN),他們採用它來進行句子的語義建模。 該網絡使用動態k-Max池,這是一種線性序列的全局池操作。 該網絡處理不同長度的輸入句子,並在句子上引入能夠明確捕獲短程和長程關係的特徵圖。 網絡不依賴於解析樹,並且很容易適用於任何語言。該模型在句子級情感分類任務上取得了非常出色的效果[8]。2015年,Kai Sheng Tai,Richard Socher, Christopher D. Manning在序列化的LSTM (Long Short-Term Memory)模型的基礎上加入了句法結構的因素,該方法在句法分析的結果上進行語義組合,在句子級情感分類和文本蘊含任務(text entailment)上都取得了很好的效果[9]。

   2016年,Qiao Qian, Xiaoyan Zhu等人在LSTM和Bi-LSTM模型的基礎上加入四種規則約束,這四種規則分別是: Non-Sentiment Regularizer,Sentiment Regularizer, Negation Regularizer, Intensity Regularizer,利用語言資源和神經網絡相結合來提升情感分類問題的精度。

  除了上面的一些研究,關於情感分析領域的應用仍然有很多,比如:2015 年鄭祥雲等人通過主題模型提取出來圖書館用戶的主題信息,最後利用這些信息來進行個性化圖書的有效推薦。將 JST 模型中直接引入了情感詞典作為外部先驗知識來對新聞文本進行分析,獲取其中的主旨句,並對主旨句進行情感打分,同時利用情感主旨句來代替全文,這樣能夠使得用戶更有效、更快速的閱讀文章。

  總的來說,情感分析在很多的領域被應用,當然情感分析也有很多的局限性,就是過多的依賴於語料庫信息,同時還需要使用自然語言、人工智能的方法來能夠最大化的挖掘出來其中的信息。

 

 參考文獻:

 [1] :Predicting the semantic orientation of adjectives

 [2]:  Thumbs up or thumbs down? Semantic orientation applied to unsupervised classification of reviews 

 [3] : Thumbs up? Sentiment Classification using Machine Learning Techniques

 [4] :   Latent Dirichlet Allocation

 [5] : Joint sentiment/topic model for sentiment analysis

 [6] : Aspect and sentiment unification model for online review analysis

 [7] : Recursive Deep Models for Semantic Compositionality Over a Sentiment Treebank

 [8]:  A Convolutional Neural Network for Modelling Sentences

 [9]: Improved Semantic Representations From Tree-Structured Long Short-Term Memory Networks

 [10] : Linguistically Regularized LSTMs for Sentiment Classification

 

 

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

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

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

※想知道購買電動車哪裡補助最多?台中電動車補助資訊懶人包彙整

南投搬家公司費用,距離,噸數怎麼算?達人教你簡易估價知識!

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

※超省錢租車方案

聚甘新