Aicup2021 農業文章文字標註及辨識 比賽心得與報告

2021-12-17
15 min read

基本資訊

  • 隊伍名稱 : Rule-Based Method
  • 最終成績 : 7th
    • 0.8063660 7/118 precision : 0.82608 recall : 0.78756

Preprocessing

  • 先針對主辦單位所提供的excel檔,創造出一個替換的dictionary
    • 比如說 ,就把斜紋夜盜、黑蟲、行軍蟲…全部換成斜紋夜蛾,方面後續model使用
  • 對每篇文章利用ckiptagger做斷詞
    • 在斷詞的時候要使用 coerce_dictionary 這個參數,這個參數可以讓主辦單位提供的keywords,被強制斷出來,不然可能會發生 “黑蟲” 被斷成 [“黑” “蟲”]
  • 把斷好詞的結果做keywords的替換
    • ex: 把所有 “黑蟲” 換成 “斜紋夜盜” 這樣
    • 在這一步的時候要注意一些特別case,避免被重複替換到
  • 針對每篇文章,取出該篇文章所有出現的keyword集合
    • 比如說 1.txt這篇文章 keyword_set = [“黑點病”,“降雨”,“文旦柚”,“鋅錳乃浦”]

Method

在這邊我們一開始的思路有幾種

  • Model-free rule-based method
  • Information retrieval (資訊檢索) 的方法
    • 用TFIDF,BM25之類方式做相似度比對
    • Deep Learning based的資訊檢索方法
  • Deep Learning based 的 Binary Classification
  • 以及我在比賽最後一天想到的,我們個人認為很有創意的方法

另外在這個比賽有些重點

  • Label非對稱,A是B的reference,不代表B是A的reference
    • 非對稱代表我們的演算法/model 會需要學習到A->B 跟 B->A的差異!!
      • A->B的這個 -> 符號可以想像成判斷B是不是A的reference,反之B->A代表判斷A是不是B的reference
    • 光是這點就可以知道TFIDF,BM25 這種相似度分數是對稱的算法表現應該不會很好
  • Label只有提供"是reference (positive)"
    • 根據主辦單位所說,只要沒有列出來的全部都代表非相關(negative)

Model-free rule-based method

這個想法是我們肉眼觀察資料後發現的

  • 在提供中的Label中,兩篇文章幾乎都有出現重複的關鍵字,即在講同一件事情
    • 可能都是在講水稻這個植物,或著是都是在講要如何防治某種害蟲

因此我們認為可以使用set similarity的演算法,來比較兩篇文章中的keyword 集合相似度,在演算法的選擇中我們一開始是選用 Jaccard similarity,針對兩兩文章得到一個相似度分數,並設定一個threshold,若相似度分數大於threshold,則將這兩篇文章互相視為reference,也就是說這個方法出來的結果會是對稱的。

透過設定threshold=0.6 大概可以得到 F1score = 0.5的表現

  • 在選擇相似度算法的時候可以考慮不同算法,像是Jaccard similarity的缺點就是相似度分數與兩篇文章的keyword set size無關,因此有試過另外的這些set similarity的演算法
    • Overlap coefficient
    • Sørensen–Dice coefficient

Information retrieval Method

TFIDF + cosine similarity、BM25

這兩個方法都是根據文章中出現的Term來使用演算法計算相似度,並不會考慮到文章的語意關係(假設TFIDF使用1-gram)。但是這兩個方法都只能給出兩個文章的相似分數,並不能直接告訴我們是否為"是reference"還是"不是reference",因此我們也需要決定一個threshold,實際的算法如下

假設有500篇文章,每篇文章都能取得其對於其他499篇文章的TFIDF(with cosine similarity)、BM25相似度分數,至於怎麼選threshold,我們嘗試了以下幾個方法

  • 將其餘499篇文章的相似度分數normalize到0-1之間,設定一個threshold ex: >0.8,將大於threshold的文章視為reference
    • 這個做法會有問題,對於一些文章來說,不會有reference document,若採用normalize + threshold,可能會大量降低precision,找到大量False positive data
  • 針對499篇文章的相似度分數,算出mean, std,設定threshold為 mean + k * std,其中k是可以調的參數
    • 此方法的想法是抓出相似分數遠大於平均值的那些document來當作reference document
    • 此方法對比上面的方法雖然能提升precision,但還是沒有很好XD

這兩個方法雖然經過嘗試沒有得到很好的表現,其根本原因可能還是因為無法解決Label非對稱性的關係

Deep Learning based Information Retrieval Method

這邊主要是希望通過BERT之類的Language Model來得到更好的representation,目前比較常見的做法是將每篇單獨的document丟到BERT之後利用[CLS] pooling,得到一個vector,代表high-level的document representation,再利用例如cosine-similarity之類的相似度算法,得到兩兩文章的相似度分數,再利用上面有提到過的選threshold方法來選出reference document。

我們主要是參考了Dense Passage Retrieval for Open-Domain Question AnsweringColBERT: Efficient and Effective Passage Search via Contextualized Late Interaction over BERT這兩篇論文來實作並訓練,其中可能在input部分與算相似度部分略作改進。

解決Label非對稱問題

參考了ColBERT的方法,我們針對文章的input做了設計

原本架構可能是

  • A的input是 [CLS] content of A [SEP]
    • 此 [CLS] token 叫做 [CLS_A],代表經過BERT後得到A的embedding
  • B的input是 [CLS] content of B [SEP]
    • 此 [CLS] token 叫做 [CLS_B],代表經過BERT後得到B的embedding

如果input還是這樣的話還是會有問題,因為在計算A->B 與 B->A時,得到的[CLS_A]與[CLS_B]是相同的!

因此我們將Input分別針對A->B,與B->A做不同設計

  • 當要判斷A->B時
    • A的input是 [CLS] [Test] content of A [SEP]
      • 此 [CLS] token 叫做 [CLS_A],代表經過BERT後得到A的embedding
      • 此時 [Test] token代表著我們告訴BERT,A現在是屬於被test的角色
    • B的input是 [CLS] [Ref] content of B [SEP]
      • 此 [CLS] token 叫做 [CLS_B],代表經過BERT後得到B的embedding
      • 此時 [Ref] token代表著我們告訴BERT,B現在是屬於被ref的角色

因為BERT的特性,在input加入[Test]或是[Ref]時所得到的[CLS]embedding會不一樣,因此在A->B與B->A時,A與B會得到不同的[CLS] embedding,相似度分數也就不一樣了,也解決了非對稱的問題

結果

我們調了調參數Deep learning based的方式最好可以到0.70x-0.71x(印象中),TFIDF跟BM25忘記了XD,但比較確定的是利用input設計解決非對稱效果好滿多的,我記得有提升大概5-7%

Deep Learning based Binary Classification

因為上面說的幾種方法都還是會遇到一個問題,就是要自己設置threshold,來決定哪些文章是reference,因此要解決這個問題就是train一個binray的classifier來讓model直接告訴我們哪些文章是positive,哪些文章是negative!

我們這邊使用的是BERT的SequenceClassifier,input大概會像是

  • A -> B
    • [CLS] content of A [SEP] content of B [SEP]
  • B -> A
    • [CLS] content of B [SEP] content of A [SEP]
  • 再利用[CLS]接一個linear layer,做binary classification

可以看到這樣的模型設計有幾個優點

  • 能利用到BERT的attention,學習到兩篇文章的語意資訊
  • 能利用到BERT的attention,學習到非對稱的資訊
    • 可能 A -> B 的 Label = True,但是B -> A 的 Label = False
    • 透過這種input可能可以讓BERT學習到非對稱的原因

實作中上遇到幾個問題

  • 文章長度限制

    • BERT的max_length限制在512,但是經過統計,每篇文章的平均長度也是差不多500,因此如果要把兩篇串在一起勢必會超過長度
    • 這邊的作法就是把兩邊文章分別捨棄掉後半部分,可能讓A長度限制在250,B長度限制在250,這樣就不會超過長度
    • 直接捨棄可能不是最好的作法,但我們時間有限,如果可以的話可以試試slide window之類的切割方法,同時也可以達到data augmentataion的效果
  • negative的選擇

    • 因為主辦單位只有提供給我們“positive"的label,且他有說只要不是positive,就通通都是negative
    • 很明顯的,這樣資料會非常imbalance (negative data »> positive data)
    • 解決辦法是,分別去sample hard negative 以及 rand negative
      • hard negative
        • 意思就是指,讓模型比較難以分辨的negative,舉例來說可以選擇兩篇文章keyword set similarity 分數很高,但其實Label 是positive的這些data,來當作hard negative
      • rand negative
        • 最簡單的方式,隨機sample一些文章,當作negative,只要小心不要sample到positive的data就好
    • 根據我們的實驗,如果只用hard negative 或只用 rand negative,表現都沒有一起使用來的好。
    • 在training的時候可以使用cross entropy的weight,會更好train
  • threshold的選擇

    • 一般來講binray分類通常是用argmax決定,就是比較negative跟positive的logistic哪個比較高就是哪個
    • 可以改成過一個softmax,設定說可能大於threshold = 0.7,才當作positive
    • threshold也是要調整的參數,一般來講調越高就是precision越高,recall會變低,反之亦然

改進方法

我們在實驗過程中發現了一個可以改進的方法,想法是說,我們透過肉眼觀察主辦單位提供的keyword是很重要的資訊,那我們就想辦法把這個knowledge告訴BERT!

做法我們採用非常簡單的方式為

  • 將 keyword set of A (document A 裡面出現的keywords之集合)與content of A concat 起來
    • A -> B
      • [CLS] keyword set of A ; content of A [SEP] keyword set of B ; content of B [SEP]
    • B -> A
      • [CLS] keyword set of B ; content of B [SEP] keyword set of A ; content of A [SEP]
    • 其中 ; 代表 concat!

這個方式我們認為算是可以告訴BERT比較重要的token資訊,這方法非常簡單且有效!

Ensemble

非常有效提升表現的方法,我們可以通過多Train幾顆Model來做ensemble

  • 因為在訓練多顆model的時候,每顆model所選取的random negative也會不一樣,所以有點類似boosting(?),可以讓每顆model看到不同的random negative,學習更多廣泛更不同的資訊。

至於ensemble的方式我們嘗試了

  • soft voting(最後是用這個)
    • 將不同model output的logits相加取平均
  • hard voting
    • 每個model投票是positive / negative
    • 可能設定過半數才是positive之類的

結果

如果沒有做keyword concat的話大概是落在0.70x左右,如果加上keyword concat可以提升到0.78x(public leaderboard),提升超級多,再加上ensemble可以提昇1%左右的分數達到0.79x這樣。這也是最後我們選擇使用的方法!

很有創意的方法

這個方法的靈感是,我們在比賽最後發現,主辦單位提供的data,其實有大量的句子/段落是重複的

比如說這篇文章是在training的1.txt

夏日乾燥炎熱的氣候,正是許多農作物害蟲好發的時機,花蓮區農業改良場籲請農民注意斜紋夜盜及甜菜夜蛾的防治,以免造成作物損失。隨著氣溫增高,許多農作物害蟲也隨之變得活躍,由監測數據顯示宜蘭地區開始出現夜蛾類害蟲的高峰,其中包括斜紋夜蛾和甜菜夜蛾。斜紋夜蛾一般人稱「黑肚蟲」,其食性幾乎是見綠就吃,是種植蔬菜的農友最傷腦筋的害蟲之一。另外青蔥產區除了斜紋夜蛾之外,還有甜菜夜蛾危害,孵化的幼蟲藏匿於蔥管內啃食青蔥,而炎熱的天氣更加速這兩種害蟲繁衍,為了減輕其所造成的嚴重經濟損失,行政院農業委員會花蓮區農業改良場呼籲花蓮宜蘭地區的農友持續進行防治工作,切勿輕忽大意。1.大量誘殺雄蟲:懸掛性費洛蒙誘蟲盒於園區外圍,藉由大量誘殺雄蟲,降低雌蟲的交尾機率,可使族群密度受到壓抑。懸掛距離為20-50公尺,大面積共同懸掛效果更佳。2.摘除卵塊:若發現葉背有毛狀卵塊,則摘除葉片,此動作可瞬間清除300-500顆即將孵化的卵粒。3.蘇力菌防治幼蟲:輪流噴施不同廠牌的蘇力菌降低幼蟲密度,蘇力菌可有效殺死初齡的夜蛾幼蟲,亦為對環境安全的微生物製劑,對人體無害。另一方面,蘇力菌也能與殺蟲農藥混合施用,可省工並降低抗藥性的發生。4.合理使用農藥:防治夜蛾的藥劑很多,應參考植物保護手冊推薦藥劑,輪流施用兩種以上藥劑避免抗藥性產生,同時應遵守安全採收期及施用倍數等使用方法,避免造成農藥殘留。

但是我們將這句

大量誘殺雄蟲:懸掛性費洛蒙誘蟲盒於園區外圍

在private搜尋可以找到8.txt

夏日乾燥炎熱的氣候,正是許多農作物害蟲好發的時機,花蓮區農業改良場籲請農民注意斜紋夜蛾及甜菜夜蛾的防治,以免造成作物損失。隨著氣溫增高,許多農作物害蟲也隨之變得活躍,由監測數據顯示宜蘭地區斜紋夜蛾及甜菜夜蛾族群數量逐漸攀升。斜紋夜蛾一般人稱「黑肚蟲」,其食性極廣,見綠就吃,是種植蔬菜的農友最傷腦筋的害蟲之一。另青蔥產區除了斜紋夜蛾之外,還有甜菜夜蛾危害,孵化的幼蟲藏匿於蔥管內啃食青蔥,而炎熱的天氣更加速這兩種害蟲繁衍。1.大量誘殺雄蟲:懸掛性費洛蒙誘蟲盒於園區外圍,藉由大量誘殺雄蟲,降低雌蟲的交尾機率,使族群密度受到壓抑。懸掛距離為20-50公尺,大面積共同懸掛效果更佳。2.摘除卵塊:若發現葉背有毛狀卵塊,則摘除葉片後帶離田區丟棄,此動作可瞬間清除300-500顆即將孵化的卵粒。3.微生物製劑防治幼蟲:輪流噴施不同廠牌的蘇力菌或核多角體病毒等對環境安全、對人體無害的微生物製劑以降低幼蟲密度。另一方面,蘇力菌也能與殺蟲農藥混合施用,可省工並降低抗藥性的發生。4.合理使用農藥:防治夜蛾的藥劑很多,應參考植物保護手冊推薦藥劑,選擇2種以上藥劑輪流施用避免抗藥性產生,同時應遵守安全採收期及施用倍數等使用方法,避免造成農藥殘留。

以及 17.txt

年初至今,常有達25℃以上高溫,且降雨少,為適合蟲害滋生及蔓延。宜蘭縣1月至2月中旬監測斜紋夜蛾及甜菜夜蛾,密度已達紅黃藍燈警戒標準。(一)斜紋夜蛾警戒區如下:壯圍鄉、宜蘭市、員山鄉、三星鄉。(二)甜菜夜蛾預警區:壯圍鄉、宜蘭市。請上述地區種植蔬菜農友特別注意進行防範此兩種夜蛾,以降低作物損失。1.大量誘殺雄蟲:懸掛性費洛蒙誘蟲盒於園區外圍,藉由大量誘殺雄蟲,降低雌蟲的交尾機率,壓制夜蛾族群密度。懸掛時距離約50公尺,大面積蔬菜產區若共同懸掛,則防治效果更佳。2.摘除卵塊:若發現葉背有毛狀卵塊,則摘除葉片,此動作可瞬間清除300-500顆即將孵化的卵粒。3.蘇力菌防治幼蟲:蘇力菌可有效殺死初齡的夜蛾幼蟲,亦為對環境安全的微生物製劑;另一方面,蘇力菌也能與其他殺蟲劑混合施用,可省工並降低抗藥性發生。然因蘇力菌容易被日光分解而降低活性,建議儘量選擇於傍晚日落時施用效果較佳。4.合理使用農藥:防治夜蛾的藥劑很多,請依作物別參考農藥資訊服務網(https://pesticide.baphiq.gov.tw/web/Insecticides_MenuItem5_5.aspx)推薦藥劑,輪流施用不同作用機制的藥劑避免產生抗藥性,同時應遵守安全採收期及施用倍數,避免造成農藥殘留問題。

可以發現兩篇文章似乎都在講同件事情,尤其是8.txt與1.txt 根本一模一樣

所以有一個大膽的想法,我們可以在testing data中,對每一篇文章,去找出在training set中跟他最像的文章,其中最像的意思是相似度必須要滿足

  • 大量句子/段落重複
  • keyword set相似 (在講同種植物,害蟲,農藥)
  • 語意類似

如果能夠找出跟他很像的文章(集合),就再把training的那篇文章的reference文章,用同樣的方法對應到testing data上面!

舉個例子 詳細來說假設training set有 A-Z 這麼多文章,testing set 有 a-z這麼多篇文章 其中 A 的 reference 是 [B, C, D] 我們拿到資料後要做的第一件事情是,把testing set map到training set上面 也就是針對a,用相似度算法找出在training set中與其相似度最高的文章(先假設都是1 to 1 mapping) 假設很剛好的,演算法告訴我們a與A 有大量的句子段落重複、keyword set也很像、也都是相同的語意 那我們要怎麼找出 a 的 reference呢? 就是把 B, C, D mapping 到 testing data上面!!就可以把它當作a的 reference了

當然有一些要注意的問題

  • 這個mapping 不太可能設計成1 to 1,應該會設計成many to many

這個model最需要設計的地方就是mapping的方式,因為要符合

  • 大量句子/段落重複
    • 這邊通常會出現比如說預防稻熱病有三點 1) 2) 3)
    • 發通報的人通常都直接複製貼上
  • keyword set相似 (在講同種植物,害蟲,農藥)
  • 語意類似
    • 因為可能防治方法會變,所以還要去抓到語意的資訊!

如果真的能解決mapping的問題,我們來看一下這個想法有什麼好處

  • inference極快,只需要算mapping就好了!!
  • 不用管label怎麼標的!只需要在乎mapping方式

我們在比賽最後一天有寫出來,但是只寫了一個簡單版本的1to1 mapping,相似度是直接用字串相似度比對,分數大概只有0.33,但我認為很有淺力,如果能改善mapping那邊以及相似度算法做改進,應該可以獲得不錯的成績