自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Llama-2 vs. Llama-3:利用微型基準測試(井字游戲)評估大模型 原創(chuàng) 精華

發(fā)布于 2024-7-4 13:41
瀏覽
0收藏

編者按: 如何更好地評估和比較不同版本的大語言模型?傳統(tǒng)的學術基準測試固然重要,但往往難以全面反映模型在實際應用場景中的表現(xiàn)。在此背景下,本文作者別出心裁,通過讓 Llama-2 和 Llama-3 模型進行井字游戲對決,為我們提供了一個新穎而有趣的模型評估視角。

此文不僅展示了一種創(chuàng)新的模型比較方法,更揭示了當前大語言模型在處理看似簡單的空間邏輯任務時所面臨的挑戰(zhàn)。讓我們得以一窺不同參數(shù)規(guī)模模型的表現(xiàn)差異,以及新一代模型相較前代的進步與不足。

尤為值得關注的是,即便是參數(shù)量達到 70B 的大模型,在面對井字游戲這樣的基礎任務時仍會出現(xiàn)一些令人意外的錯誤。這一發(fā)現(xiàn)不僅為大語言模型的能力邊界劃定提供了新的參考,也為未來模型的優(yōu)化方向指明了道路。

我們希望這篇文章能夠啟發(fā)讀者思考:在評估人工智能模型時,我們是否應該更多地關注那些看似簡單卻能深入考察模型認知能力的任務?同時,如何設計更多類似“井字游戲”的“微型基準測試“,以更加全面而直觀地評估模型性能?


作者 | Dmitrii Eliuseev

編譯 | 岳揚


Llama-2 vs. Llama-3:利用微型基準測試(井字游戲)評估大模型-AI.x社區(qū)

Image by Solstice Hannan, Unsplash(https://unsplash.com/@darkersolstice)


就在我撰寫這篇文章的大約一周前,Meta 推出了新的開源模型 Llama-3[1] 。他們宣稱這是“當前在 8B 與 70B 參數(shù)量級下的最好模型”。通過 HuggingFace 平臺的模型頁面[2]可以看到,Llama-3 8B 在 MMLU(Massive Multitask Language Understanding) 基準測試上的表現(xiàn),以 66.6 的得分超越了 Llama-2 7B 的 45.7 ;而在 CommonSense QA(dataset for commonsense question answering)上進行評估,Llama-3 同樣領先,分別以 72.6 和 57.6 的得分戰(zhàn)勝了對手。有一款經過特殊指令數(shù)據(jù)微調(instruction-tuned)的 Llama-3 8B 模型尤其值得一提,在數(shù)學基準測試中的表現(xiàn)得分從 3.8 躍升至 30.0,這一進步令人印象深刻。


通過學術基準測試(Academic benchmarks)進行大模型評估固然很重要,但親眼見證它們的實際表現(xiàn)豈不更加直觀且更有趣?答案是肯定的,而且這種體驗往往妙趣橫生。設想一下,如果讓兩個模型進行一場經典的井字棋對決(tic-tac-toe game),勝負究竟如何?在接下來的游戲環(huán)節(jié)中,我將全面測試 7B、8B以及70B 等參數(shù)規(guī)格的模型。與此同時,我還會記錄下模型的性能指標及系統(tǒng)配置要求。

話不多說,讓我們即刻啟程,一探究竟!

01 加載模型

為了全面測試這些模型,我選擇使用 Python 庫Llama-cpp[3] 進行測試,該工具的一大優(yōu)點在于其既能適應 CPU 環(huán)境,也能在 GPU 上高效運行。我們需要并行運行兩個 LLM。好消息是,無論是 7B 還是 8B 的模型,都能在 Google Colab 的 16GB GPU 環(huán)境中順暢運行。然而,當面對 70B 參數(shù)級別的龐大模型時,我們不得不退而求其次,轉而使用 CPU 進行測試,因為即便是頂級的 NVIDIA A100 顯卡,其內存容量也難以承擔起同時運行兩個此類巨無霸模型的重任。

首先需要我們先動手安裝 Llama-cpp,緊接著下載 7B 與 8B 參數(shù)級別的這兩個模型。至于 70B 參數(shù)級別的模型,其操作流程基本一致,唯一的區(qū)別僅在于替換其下載鏈接而已。

!CMAKE_ARGS="-DLLAMA_CUBLAS=on" FORCE_CMAKE=1 pip3 install llama-cpp-python -U
!pip3 install huggingface-hub hf-transfer sentence-transformers


!export HF_HUB_ENABLE_HF_TRANSFER="1" && huggingface-cli download TheBloke/Llama-2-7B-Chat-GGUF llama-2-7b-chat.Q4_K_M.gguf --local-dir /content --local-dir-use-symlinks False
!export HF_HUB_ENABLE_HF_TRANSFER="1" && huggingface-cli download QuantFactory/Meta-Llama-3-8B-Instruct-GGUF Meta-Llama-3-8B-Instruct.Q4_K_M.gguf --local-dir /content --local-dir-use-symlinks False

模型下載完成后,接下來就需要正式啟動這些模型了:

from llama_cpp import Llama


llama2 = Llama(
      model_path="/content/llama-2-7b-chat.Q4_K_M.gguf",
      n_gpu_layers=-1,
      n_ctx=1024,
      echo=False
)
llama3 = Llama(
      model_path="/content/Meta-Llama-3-8B-Instruct.Q4_K_M.gguf",
      n_gpu_layers=-1,
      n_ctx=1024,
      echo=False
)

接下來,我們著手創(chuàng)建一個函數(shù),用于處理和執(zhí)行各種提示詞信息:

def llm_make_move(model: Llama, prompt: str) -> str:
    """ Call a model with a prompt """
    res = model(prompt, stream=False, max_tokens=1024, temperature=0.8)
    return res["choices"][0]["text"]

02 Prompts

現(xiàn)在,我們來編寫代碼實現(xiàn)井字游戲(Tic-Tac-Toe)。在棋盤上交替放置“X”和“O”,首位成功在任意一行、一列或對角線上連成一線的玩家即為勝者:

Llama-2 vs. Llama-3:利用微型基準測試(井字游戲)評估大模型-AI.x社區(qū)

Image source Wikipedia(https://en.wikipedia.org/wiki/Tic-tac-toe)

正如我們所見,這個游戲對于人類來說非常簡單,但對語言模型而言可能頗具挑戰(zhàn);要走出正確的一步棋,需要理解棋盤空間、物體之間的關系,甚至還會涉及一些簡單的數(shù)學知識。

首先,我們將棋盤編碼為一個二維數(shù)組。同時也會創(chuàng)建一個函數(shù)方法用于將棋盤轉換成字符串形式:

board = [["E", "E", "E"],
         ["E", "E", "E"],
         ["E", "E", "E"]]

def board_to_string(board_data: List) -> str:
    """ Convert board to the string representation """
    return "\n".join([" ".join(x) for x in board_data])

輸出結果如下:

E E E
E E E
E E E

現(xiàn)在,我們可以創(chuàng)建模型提示詞(model prompts)了:

sys_prompt1 = """You play a tic-tac-toe game. You make a move by placing X, 
                 your opponent plays by placing O. Empty cells are marked 
                 with E. You can place X only to the empty cell."""
sys_prompt2 = """You play a tic-tac-toe game. You make a move by placing O, 
                 your opponent plays by placing X. Empty cells are marked 
                 with E. You can place O only to the empty cell."""
game_prompt = """What is your next move? Think in steps. 
                 Each row and column should be in range 1..3. Write
                 the answer in JSON as {"ROW": ROW, "COLUMN": COLUMN}."""

在這里,我為模型 1 和模型 2 分別創(chuàng)建了兩個提示詞(prompt)。我們可以看到,這兩個句子幾乎是相同的。唯一不同的是,第一個模型在“棋盤”上放置“X”,而第二個模型則放置“O”。

Llama-2 和 Llama-3 的提示詞格式有所不同:

template_llama2 = f"""<s>[INST]<<SYS>>{sys_prompt1}<</SYS>>
Here is the board image:
__BOARD__\n
{game_prompt}
[/INST]"""

template_llama3 = f"""<|begin_of_text|>
<|start_header_id|>system<|end_header_id|>{sys_prompt2}<|eot_id|>
<|start_header_id|>user<|end_header_id|>
Here is the board image:
__BOARD__\n
{game_prompt}
<|eot_id|>
<|start_header_id|>assistant<|end_header_id|>"""

當然,我們可以創(chuàng)建兩個函數(shù)方法來利用這些提示詞(prompts),其中一個函數(shù)方法針對 Llama-2 ,另一個則針對 Llama-3 。

def make_prompt_llama2(board: List) -> str:
    """ Make Llama-2 prompt """
    return template_llama2.replace("__BOARD__", board_to_string(board))


def make_prompt_llama3(board: List) -> str:
    """ Make Llama-3 prompt """
    return template_llama3.replace("__BOARD__", board_to_string(board))

03 Coding the Game

我們已經為構建該井字游戲(Tic-Tac-Toe)準備好了所有的提示詞信息,接下來該進入此游戲的編碼階段了。在某一個提示詞中,我要求模型以 JSON 格式提供模型響應。在實際操作中,模型可以回答這個問題:

My next move would be to place my X in the top-right corner, on cell (3, 1).
{
"ROW": 3,
"COLUMN": 1
}

現(xiàn)在,我們開始著手設計一個函數(shù)方法,用于從這類字符串中抽取出 JSON 數(shù)據(jù):

def extract_json(response: str) -> Optional[dict]:
    """ Extract dictionary from a response string """
    try:
        # Models sometimes to a mistake, fix: {ROW: 1, COLUMN: 2} => {"ROW": 1, "COLUMN": 2}
        response = response.replace('ROW:', '"ROW":').replace('COLUMN:', '"COLUMN":')
        # Extract json from a response
        pos_end = response.rfind("}")
        pos_start = response.rfind("{")
        return json.loads(response[pos_start:pos_end+1])
    except Exception as exp:
        print(f"extract_json::cannot parse output: {exp}")
    return None

結果發(fā)現(xiàn),LLaMA-2 生成的模型響應并非總是有效的 JSON 格式;它經常會生成類似 “{ROW: 3, COLUMN: 3}” 這樣的模型響應。如上述代碼塊所示,在這種情況下,我會補全字符串中的缺失的引號,確保其格式正確。

獲得棋盤的行數(shù)和列數(shù)后,我們就能對該棋盤進行更新了:

def make_move(board_data: List, move: Optional[dict], symb: str):
    """ Update board with a new symbol """
    row, col = int(move["ROW"]), int(move["COLUMN"])
    if 1 <= row <= 3 and 1 <= col <= 3:
        if board_data[row - 1][col - 1] == "E":
            board_data[row - 1][col - 1] = symb
        else:
            print(f"Wrong move: cell {row}:{col} is not empty")
    else:
        print("Wrong move: incorrect index")

在更新棋盤狀態(tài)后,下一步應當判斷游戲是否達到結束條件。

def check_for_end_game(board_data: List) -> bool:
    """ Check if there are no empty cells available """
    return board_to_string(board_data).find("E") == -1

def check_for_win(board_data: List) -> bool:
    """ Check if the game is over """
    # Check Horizontal and Vertical lines
    for ind in range(3):
        if board_data[ind][0] == board_data[ind][1] == board_data[ind][2] and board_data[ind][0] != "E":
            print(f"{board_data[ind][0]} win!")
            return True
        if board_data[0][ind] == board_data[1][ind] == board_data[2][ind] and board_data[0][ind] != "E":
            print(f"{board_data[0][ind]} win!")
            return True
    # Check Diagonals
    if board_data[0][0] == board_data[1][1] == board_data[2][2] and board_data[1][1] != "E" or \
       board_data[2][0] == board_data[1][1] == board_data[0][2] and board_data[1][1] != "E":
        print(f"{board_data[1][1]} win!")
        return True
    return False

在此代碼邏輯中,會循環(huán)檢查棋盤的水平線、垂直線和對角線,判斷是否出現(xiàn)勝利的一方。也許可能存在更為簡潔的解法,但當前這種方法足以應對目前的需求。

現(xiàn)在,所有必要組件都已準備完畢。接下來,我們將這些組件整合在一起:

num_wins1, num_wins2 = 0, 0
times_1, times_2 = [], []


def run_game():
    """ Run a game between two models """
    board = [["E", "E", "E"],
             ["E", "E", "E"],
             ["E", "E", "E"]]

    moves_limit = 20
    for step in range(moves_limit):
        print(f"Step {step+1}")

        # Move: Model-1
        t_start = time.monotonic()
        prompt = make_prompt_llama2(board)
        result_str = llm_make_move(llama2, prompt)
        times_1.append(time.monotonic() - t_start)

        new_data = extract_json(result_str)
        if new_data is not None:
            make_move(board, new_data, symb="X")
            if check_for_win(board):
                print('**Model 1 Won**')
                num_wins1 += 1
                break
            if check_for_end_game(board):
                break

        # Move: Model-2
        t_start = time.monotonic()
        prompt = make_prompt_llama3(board)
        result_str = llm_make_move(llama3, prompt)
        times_2.append(time.monotonic() - t_start)

        new_data = extract_json(result_str)
        if new_data is not None:
            make_move(board, new_data, symb="O")
            if check_for_win(board):
                print('**Model 2 Won**')
                num_wins2 += 1
                break
            if check_for_end_game(board):
                break
        print()

同時,我還記錄了每個步驟的執(zhí)行耗時,以及各個模型在游戲中的獲勝次數(shù)。


04 Results

說到實驗結果,確實很有趣。

對于參數(shù)規(guī)模為 7B 和 8B 的模型,完成井字游戲似乎比較有挑戰(zhàn)性。7B 的 Llama-2 模型雖然對游戲規(guī)則有所認知,但它卻沒能準確理解棋盤坐標的含義,導致常常將“X”標記置于不當之處。

下面是一些具體的 Prompt 與模型響應示例:

>>> Prompt:

<s>[INST]<<SYS>>You play a tic-tac-toe game. You make a move by placing X, 
your opponent plays by placing O. Empty cells are marked with E.
You can place X only to the empty cell.<</SYS>>
Here is the board image:
X X O
X O E
E E E

What is your next move? Think in steps. 
Each row and column should be in range 1..3. 
Write the answer in JSON as {"ROW": ROW, "COLUMN": COLUMN}.
[/INST]

>>> Response:

Since there are no empty cells on the board, I will place my X in the 
center cell: { "ROW": 2, "COLUMN": 1 }.

根據(jù)上文的響應內容,我們可以看到,這段模型響應中存在多個錯誤。首先,棋盤上還有許多空位可選;其次,坐標 (2,1) 并不是棋盤的中心;最后,給出的殘局中,初始狀態(tài)那個位置本身就有棋子,并非空缺。

相比之下,參數(shù)規(guī)模為 70B 的 LLaMA-2 模型整體表現(xiàn)更佳,然而它也并非完美無瑕,依舊存在不少錯誤。以下為一個極具代表性的 prompt 與模型響應案例:

>>> Prompt:

<s>[INST]<<SYS>>You play a tic-tac-toe game. You make a move by placing X, 
your opponent plays by placing O. Empty cells are marked with E.
You can place X only to the empty cell.<</SYS>>
Here is the board image:
O E E
E X E
E E E

...

>>> Response:

My next move would be to place my X in the center cell, which is empty.
Here is the updated board:

O E E
E X X
E E E

JSON representation of my move: {"ROW": 2, "COLUMN": 2}

可以看到,參數(shù)規(guī)格為 70B 的模型確實找到了“中心”位置,但相關“棋子”?的位置放置決策卻是錯的;該模型似乎并未“意識到”中間的格子其實已經被占用了。該模型甚至嘗試重新“描繪”棋盤,但這番“修改”同樣也是錯誤的。

令人啼笑皆非的是,ChatGPT 3.5 面對同一問題也給出了錯誤解答,同樣得出了中心位置為 {"ROW": 2, "COLUMN": 2} 的結論。不過,LLaMA-3 70B 卻成功避免了這個陷阱。即便如此,它還是會犯類似的錯誤,偶爾會在已經有“棋子”的格子里再次放置“棋子”。遺憾的是,我沒有統(tǒng)計每款模型的具體錯誤次數(shù),這是一個值得后續(xù)關注的改進點。

如果用柱狀圖來展示,7B 和 8B 模型的表現(xiàn)數(shù)據(jù)大致如下:

Llama-2 vs. Llama-3:利用微型基準測試(井字游戲)評估大模型-AI.x社區(qū)

Game score for 7B and 8B models, Image by author

結果顯而易見:Llama-3 以 10:0 的大比分獲勝!

同時,我們可以觀察到兩組模型在搭載 16 GB NVIDIA T4 GPU 的設備上的推理耗時情況:

Llama-2 vs. Llama-3:利用微型基準測試(井字游戲)評估大模型-AI.x社區(qū)

Llama-2 vs. Llama-3:利用微型基準測試(井字游戲)評估大模型-AI.x社區(qū)

Inference time for 7B and 8B models, Image by author

略有不足的是,Llama-3 的運行速度相比前一代模型略慢(分別為 2.5 秒和 4.3 秒)。然而實際上,4.3 秒的響應時間已經足夠優(yōu)秀了,因為大多數(shù)情況下會采用流式處理(streaming),并且用戶通常也不會期待立刻獲得即時回答。

至于參數(shù)規(guī)格為 70B 的 Llama-2 模型,它的表現(xiàn)更佳,能夠勝出兩次,但即便如此,在絕大多數(shù)情況下,Llama-3 仍然占據(jù)了上風。最終,在推理速度這方面,Llama-3 以 8:2 的比分獲勝!

Llama-2 vs. Llama-3:利用微型基準測試(井字游戲)評估大模型-AI.x社區(qū)

Game score for 70B models, Image by author

使用 CPU 進行大模型的推理運算時,由于 CPU 的計算能力和并行處理能力相對有限,其推理速度自然不會很快:

Llama-2 vs. Llama-3:利用微型基準測試(井字游戲)評估大模型-AI.x社區(qū)

Inference time, Image by author

完成十局游戲大約會耗費一個小時。雖然這個速度對于生產環(huán)境來說并不理想,但在測試階段還可以吧。有一點很有趣,Llama-cpp 采用了一種內存映射文件(memory-mapped file)的方式來加載模型,即便同時處理兩個 70B 參數(shù)級別的模型,其內存占用也控制在了 12GB 以內。這就表明,在僅配備 16GB RAM 的個人電腦上,我們同樣能夠順利地測試兩個 70B 模型(可惜這一招在 GPU 上行不通)。


05 Conclusion

在本文中,我安排兩組語言模型進行了一場別開生面的井字游戲對戰(zhàn)。有趣的是,這個看似簡單的“基準測試”實際上極具挑戰(zhàn)性。其考驗的不僅僅是模型對游戲規(guī)則的掌握,還涉及到了坐標系統(tǒng)以及使用字符串形式表達“空間”和“抽象思維”的能力,以此模擬二維棋盤。

從比賽結果來看,LLaMA-3 明顯是贏家。顯然,這款模型的表現(xiàn)更為出色,但我必須承認,兩款模型都在游戲中犯了很多錯誤。這一現(xiàn)象引人深思,暗示著即便是當前的大語言模型,在面對這個小巧卻非正式的“基準測試”時也會感到棘手,本文提出的 “Tic-Tac-Toe Battle” 基準測試無疑可為未來其他大模型的測試提供參考。


文中鏈接

[1]??https://ai.meta.com/blog/meta-llama-3/??

[2]??https://huggingface.co/meta-llama/Meta-Llama-3-70B-Instruct??

[3]??GitHub - abetlen/llama-cpp-python: Python bindings for llama.cpp??


Thanks for reading!


————

Dmitrii Eliuseev

Python/IoT developer and data engineer, data science and electronics enthusiast

??https://www.linkedin.com/in/dmitrii-eliuseev/??


原文鏈接:

??https://towardsdatascience.com/llama-2-vs-llama-3-a-tic-tac-toe-battle-between-models-7301962ca65d??

?著作權歸作者所有,如需轉載,請注明出處,否則將追究法律責任
收藏
回復
舉報
回復
相關推薦