2014-04-21 40 views
0

我需要爲Bleu度量標準中的評估創建一個字對,三聯體等列表。 Bleu以unigrams(單個單詞)開始,並且上升到N-grams - N在運行時指定。在Bleu中創建用於評估的字對,三聯體等

例如,給出的句子 「以色列官員負責機場安全」

對於對unigram這純粹是詞的列表。對於二元語法這將是

Israeli officials 
officials are 
are responsible 
responsible for 
for airport 
airport security 

相關的八卦是

Israeli officials are 
officials are responsible 
are responsible for 
responsible for aiport 
for airport security 

我編寫工作布魯硬編碼的n元語法4和暴力迫使對unigram等的計算,這是醜陋的地獄,此外,我需要能夠在運行時提供N.

該正試圖產生對/三元組等的片段 -

String current = ""; 
    int temp = 0; 
    for (int i = 0; i < goldWords.length - N_GRAM_ORDER; i++) { 
     current = current + ":" + goldWords[i]; 
     while (temp < N_GRAM_ORDER) { 
      current = current + ":" + goldWords[temp + i]; 
      temp++; 
     } 
     goldNGrams.add(current); 
     current = ""; 
     temp = 0; 
    } 
} 

編輯 - 所以從這個片斷的輸出應爲雙字母組 -

israeli:officials 
officials:are 
are:responsible 
responsible:for 
for:airport 
airport:security 

哪裏goldWords是含有字符串數組將單個詞彙變成NGrams。 我一直在修補這個循環好幾天,畫出關係等,它只是不會點擊我。任何人都可以看到我做錯了什麼?通過所有的話

String current = ""; 
for (int i = 0; i < goldWords.length(); i++){ 
    for (int j = 0; j < N_GRAM_ORDER; j++){ 
      if (i + j < goldWords.length()) 
       current += ":" + goldWords[i + j]; 
    } 
    goldNGrams.add(current); 
    current = ""; 
} 

所以,通過第一字循環迭代外被收錄,內循環迭代:

+0

如果我理解這個正確的,你只是受了多少空間有突破一串字,對嗎?難道你不能這樣做:使用String.split將輸入字符串拆分爲一個單詞數組,然後使用循環將它們重新組合爲N個。拋出一個命令行參數來確定N,並且你設置了 –

+0

你將'goldWords [i]'加到'current'字符串兩次。一旦初始化'current'時,再次使用while循環的第一次迭代。 – deanosaur

+0

@MarshallTigerus字符串數組goldWords是原文句子,分成單個單詞。問題是正確地結合它們。 – Saf

回答

1

我會改變這樣的:

String current = ""; 
int temp = 0; 
for (int i = 0; i < goldWords.length - N_GRAM_ORDER; i++) { 
    current = current + ":" + goldWords[i]; 
    while (temp < N_GRAM_ORDER) { 
     current = current + ":" + goldWords[temp + i]; 
     temp++; 
    } 
    goldNGrams.add(current); 
    current = ""; 
    temp = 0; 
} 
} 

本被包括在內。需要注意的一點是,if語句用於防止出現數組越界錯誤。如果你只想要完整的n元組,​​那麼這應該移到內部for循環之外。

隨着if語句它在哪裏,你會得到:如果你想

Israeli:officials 
officials:are 
are:responsible 
responsible:for 
for:airport 
airport:security 
security 

Israeli:officials 
officials:are 
are:responsible 
responsible:for 
for:airport 
airport:security 

相反,試試這個代碼:

String current = ""; 
for (int i = 0; i < goldWords.length(); i++){ 
    if (i + N_GRAM_ORDER < goldWords.length()){ 
     for (int j = 0; j < N_GRAM_ORDER; j++){ 
       current += ":" + goldWords[i + j]; 
     } 
    } 
    goldNGrams.add(current); 
    current = ""; 
} 

(上面的代碼在沒有根據編譯器檢查它的情況下完成,因此可能會出現Off By One或Minor語法錯誤,但驗證它它會讓你接近)。

+0

謝謝,你發佈的第一個片段完全是我需要,它只是需要稍微更新,以獲得最後一項 - 如果(i + j Saf

+0

不利於編譯器方便,我couldn不測試它。 –

1

下面是使用String []來收集ngrams而不是字符串的替代方法。我改變了外部for循環的迭代次數,以確保它捕獲最後一個n-gram。

public static List<String[]> ngrams(String[] gold, int n_length) { 
    List<String[]> list = new ArrayList<String[]>(); 
    for (int i = 0; i < gold.length - (n_length-1); i++) { 
     String[] ngram = new String[n_length]; 
     for(int j = 0; j < n_length; j++) { 
      ngram[j] = gold[i+j]; 
     } 
     list.add(ngram); 
    } 
    return list; 
} 
+0

如果我也可以將其標記爲答案,那麼它也會以不同的方式滿足我的需求 - 非常感謝。 – Saf

1

根據N_GRAM編程輸出

int N_GRAM_ORDER = 3, temp = 0, i; 
     for (i = 0; i <= goldWords.length - N_GRAM_ORDER; i += N_GRAM_ORDER) { 
      while (temp < N_GRAM_ORDER) { 
       current = current + ":" + goldWords[temp + i]; 
       temp++; 

      } 
      goldGrams.add(current); 
      current = ""; 
      temp = 0; 
     } 

     if ((temp + i) < goldWords.length) { 
      temp += i; 
      while (temp < goldWords.length) { 

       current = current + ":" + goldWords[temp++]; 

      } 
      goldGrams.add(current); 

     } 

    } 

輸出

Israeli:officials:are 
responsible:for:airport 
security