• <source id="kqqcq"></source>
  • <legend id="kqqcq"></legend>
    首頁
    讀書
    網課

    Windows系統下Qwen2.5大模型的實踐教程

    好鄰居 2024-12-26 18:23:34

    名人博客

    程序學到昏 個人主頁 (csdn.net)



    cover

    從零開始:Windows系統下Qwen2.5大模型的實踐教程(一)

    本文將基于Windows系統和CPU環境,使用Qwen2.5系列模型,詳細實踐從大型語言模型的下載、部署到微調的全過程。

     程序學到昏 ?·? 2024-11-10 11:41:51 發布

    本文將基于Windows系統和CPU環境,使用Qwen2.5系列模型,詳細實踐從大型語言模型的下載、部署到微調的全過程。

    1、環境配置

    1.1、部署開發環境

    本地開發環境:windows

    (1)python開發環境

    ①pycharm 安裝pycharm(community版本):www.jetbrains.com/pycharm/dow…

    ②anaconda 安裝anaconda:清華鏡像源,選擇合適的版本,例如:Anaconda3-2024.06-1-Windows-x86_64.exe 下載anaconda完成后,windows系統下點擊exe文件一路nex即可安裝完成。

    ③配置anaconda環境變量(非必須): 假設你的anaconda安裝地址為:D:\soft\anaconda;進入系統高級配置,添加系統變量:

    在這里插入圖片描述

    然后點擊Path,添加如下變量:

    %ANACONDA_HOME% 
    %ANACONDA_HOME%\Scripts 
    %ANACONDA_HOME%\Library\mingw-w64\bin%ANACONDA_HOME%\Library\usr\bin 
    %ANACONDA_HOME%\Library\bin

    配置完成后,使用conda --version可以看到anaconda已經安裝完成:

    在這里插入圖片描述

    ④anaconda使用:
    一些簡單的命令,幫助我們使用它:

    # 安裝一個新的anaconda環境,名為qwen1.5-4b,python版本為3.10conda create -n qwen1.5-4b python=3.10# 查詢安裝的anaconda環境conda env list# 手動切換anaconda環境conda activate qwen1.5-4b# 關閉anaconda環境conda deactivate# 檢查python的版本(當前conda環境下的)python --version

    在我們新建完名為qianwen的conda虛擬環境后,去pycharm的setting->Python Interpreter中導入創建好的conda環境即可:

    在這里插入圖片描述

    1.2、大模型下載

    huggingface:略

    modelscape,魔搭社區提供了相應的組件來供使用者下載:

    # 安裝ModelScopepip install modelscope# 下載完整模型repomodelscope download --model qwen/Qwen2.5-1.5B# 下載單個文件(以README.md為例)modelscope download --model qwen/Qwen2.5-1.5B README.md

    示例如下:

    我在base的conda環境下進行安裝相應組件,然后調用modelscope命令進行下載,且該組件具備斷點續傳的功能,如果當前網絡不佳,可以殺死命令行,重新執行命令,已下載的文件內容不會丟失,可以繼續在進度條附近開始下載任務。

    在這里插入圖片描述

    2、大模型部署使用

    2.1、概述

    使用:

    import torchfrom flask import Flaskfrom flask import requestfrom transformers import (AutoTokenizer, AutoModelForCausalLM, AutoModel,
                              Qwen2ForCausalLM, Qwen2Tokenizer)# 參數max_new_tokens: int = 512  # 生成響應時最大的新token數
    system_prompt = "你是一個專門分類新聞標題的分析模型。你的任務是判斷給定新聞短文本標題的分類。"user_template_prompt = ("請評估以下網購評論的情感,不要返回0或1以外的任何信息,不要返回你的思考過程。"
                            "輸入正面評論輸出1,輸入負面評論輸出0。輸入如下:{}\n請填寫你的輸出")
    eos_token_id = [151645, 151643]
    
    app = Flask(__name__)
    model_path = "D:\project\llm\Qwen2.5-1.5B"# tokenizer = AutoTokenizer.from_pretrained(model_path)tokenizer = Qwen2Tokenizer.from_pretrained(model_path)# model = AutoModelForCausalLM.from_pretrained(model_path, device_map='cpu').eval()model = Qwen2ForCausalLM.from_pretrained(model_path, device_map='cpu').eval()# 非流式請求@app.route('/chat', methods=["POST"])
    def chat():
        # 系統設定和prompt
        req_json = request.json
        content = user_template_prompt.format(req_json['message'])
        messages = [
            {"role": "system", "content": system_prompt},
            {"role": "user", "content": content}
        ]    print("input: " + content)
        input_ids = tokenizer.apply_chat_template(messages,                                              tokenize=False,                                              add_generation_prompt=True)
        inputs = tokenizer([input_ids], return_tensors="pt").to(model.device)
        generated_ids = model.generate(
            inputs.input_ids,        max_new_tokens=max_new_tokens,        eos_token_id=eos_token_id,  # 結束令牌,模型生成這個token時,停止生成
        )
        generated_ids = [
            output_ids[len(inputs):] for inputs, output_ids in zip(inputs.input_ids, generated_ids)
        ]    print(f"generated_ids=\n{generated_ids}")
        response = tokenizer.batch_decode(generated_ids, skip_special_tokens=True)[0]    print(response)
        # 使用占位符拼接字符串
        return responseif __name__ == '__main__':
        app.run(port=8080, host="0.0.0.0")

    其中用到的Qwen2ForCausalLM替換了AutoModelForCausalLM,是一個基于Transformer結構的decoder-only模型,它是Qwen大模型的第二代架構。

    2.2、參數

    通常來說參數越大的大模型。其中需要關注到的一些問題以及使用上需要注意的地方:

    ①apply_chat_template

    用在會話中,告訴大模型接下來應該生成新的東西,并且包含了整個會話的上下文信息。使用如下:

    input_ids = tokenizer.apply_chat_template(messages,  # 輸入的純文本信息
                                              tokenize=False,  # 告訴大模型暫時不需要分詞
                                              add_generation_prompt=True)  # 添加一個特殊的標記,告訴大模型接下來應該生成新的文本內容。

    輸出如下:

    在這里插入圖片描述

    '<|im_start|>system你是一個專門評估網購評論情感的分析模型。你的任務是判斷給定評論是正面還是負面。<|im_end|>
    <|im_start|>user請評估以下網購評論的情感,不要返回0或1以外的任何信息,不要返回你的思考過程。如果是正面評論返回1,如果是負面評論返回0:不錯!挺合適<|im_end|>
    <|im_start|>assistant'
    ②eos_token_id

    設定了大模型生成文本的分割符,其中eos_token_id = [151645, 151643],兩個id的含義分別是:

    tokenizer.convert_ids_to_tokens(151645)    # <|im_end|>
    tokenizer.convert_ids_to_tokens(151643)    # <|endoftext|>
    tokenizer.convert_ids_to_tokens(1773)      # 。

    這兩個標記與輸入中的標記保持一致。若不設置該值,在未達到最大返回token數之前,對話將不會自動終止,大模型可能會進行不必要的自問自答。

    在這里插入圖片描述

    為了控制大模型可能產生的不穩定輸出,設置停用詞是一種有效手段。除了使用 eos_token_id 外,還可以采用以下方法:

    generation_config = GenerationConfig(use_cache=True,                                     repetition_penalty=repetition_penalty,                                     do_sample=False,  # 取消采樣,使用貪心策略,輸出是確定的
                                         stop_strings="}")generated_ids = model.generate(input_ids,                               tokenizer=tokenizer,                               generation_config=generation_config)

    對于模型的推理參數,可以統一放置在 GenerationConfig 中。通過 stop_strings 參數(其值可為字符串或字符串列表)來設置停用詞。在上例中,將 } 設為停用詞,這在要求大模型返回JSON數據時尤為有效,能夠有效避免大模型在輸出完整JSON數據后繼續進行不必要的推理。

    ③repetition_penalty

    使用如下:

    repetition_penalty float = 1.2  # 用于懲罰重復生成相同token的參數generated_ids = model.generate(
        inputs.input_ids,
        max_new_tokens=max_new_tokens,
        repetition_penalty=repetition_penalty,  # 解決問題后面有過多重復問答)

    某些時候,大模型也會持續重復之前的對話,直到生成的token數等于max_new_tokens為止。情況如下:

    在這里插入圖片描述

    這個值不宜過低或過高:過低不生效;過高會導致大模型不敢生成正確答案,因為輸入的prompt中攜帶了正確答案。目前看1.2是一個比較合適的值。

    ④skip_special_tokens=True

    這個告訴分詞器在解碼時跳過任何特殊的標記,如結束標記end-of-sequence token或其他模型特定的標記。

    由于我們在上面調用model時設置了停用詞,在大模型推理到停用詞就會返回輸出。如果不設置該參數,則效果如下:

    1<|endoftext|>

    優化參數之后,效果如下:



    gpt-4oqwen2.5-1.5bqwen2.5-1.5b_修改后qwen2.5-1.5b_微調后qwen2.5-3bqwen2.5-3b_修改后
    二元分類
    0.96幾乎無法輸出規定格式的結果0.93<暫未微調>0.620.91
    多元分類樣本100條0.93
    0.670.90.120.72

    樣本1000條0.785
    0.5790.796

    2.3、總結

    1. 本章節主要關注qwen2.5-1.5b_修改后的結果,有兩個主要成果:
      1.1、修改了上述等啟動參數之后,大模型能夠正常輸出預期的結果
      1.2、對于相對簡單的人呢無

    2. 下一章節將進行qwen2.5-1.5b模型的微調

    2.3.1、最終代碼

    最終代碼如下:

    import torchfrom flask import Flaskfrom flask import requestfrom transformers import (AutoTokenizer, AutoModelForCausalLM, AutoModel,
                              Qwen2ForCausalLM, Qwen2Tokenizer)from peft import PeftModel# 參數max_new_tokens: int = 64  # 生成響應時最大的新token數temperature: float = 0.6  # 控制生成文本的隨機性top_p: float = 0.9  # 用于概率限制的參數,有助于控制生成文本的多樣性top_k: int = 32  # 控制生成過程中每一步考慮的最可能token的數量repetition_penalty: float = 1.2  # 用于懲罰重復生成相同token的參數system_template_prompt = "你是一個專門評估網購評論情感的分析模型。你的任務是判斷給定評論是正面還是負面。"system_prompt = "你是一個專門分類新聞標題的分析模型。你的任務是判斷給定新聞短文本標題的分類。"user_template_prompt = ("請評估以下評論,不要返回0或1以外的任何信息,不要返回你的思考過程。"
                            "如果是正面評論輸出1,是反面評論輸出0。輸入如下:{}\n請填寫你的輸出:")
    user_prompt = ("請將以下新聞短文本標題分類到以下類別之一:故事、文化、娛樂、體育、財經、房產、汽車、教育、"
                   "科技、軍事、旅游、國際、股票、農業、游戲。輸入如下:\n{}\n請填寫你的輸出:")
    eos_token_id = [151645, 151643]
    
    app = Flask(__name__)
    lora_model_path = "./output/Qwen2.5-1.5b/checkpoint-100"model_path = "D:\project\llm\Qwen2.5-1.5B"# 從指定路徑加載大模型的分詞器(tokenizer),用于加載預訓練的文本處理模型(Tokenizer),以便將文本數據轉換為模型可以接受的輸入格式。tokenizer = Qwen2Tokenizer.from_pretrained(model_path)# AutoModelForCausalLM更適合語言大模型model = Qwen2ForCausalLM.from_pretrained(model_path, device_map='cpu').eval()# 非流式請求@app.route('/chat_old', methods=["POST"])def chat_old():    # 系統設定和prompt
        req_json = request.json
        content = user_template_prompt.format(req_json['message'])
        messages = [
            {"role": "system", "content": system_template_prompt},
            {"role": "user", "content": content}
        ]    # 使用tokenizer將整個會話轉換成模型可以理解的input_ids,并將這些input_ids輸入到模型
        # tokenize=False 表示不要立即分詞,只是使用apply_chat_template將會話進行格式化
        input_ids = tokenizer.apply_chat_template(messages,
                                                  tokenize=False,
                                                  add_generation_prompt=True)    print(f"input:{input_ids}")
        inputs = tokenizer([input_ids], return_tensors="pt").to(model.device)
        generated_ids = model.generate(
            inputs.input_ids,
            max_new_tokens=max_new_tokens,
            repetition_penalty=repetition_penalty,  # 解決問題后面有過多重復問答(對重復token的懲罰)
            eos_token_id=eos_token_id,  # 結束令牌,模型生成這個token時,停止生成
        )
        generated_ids = [
            output_ids[len(inputs):] for inputs, output_ids in zip(inputs.input_ids, generated_ids)
        ]    print(f"generated_ids=\n{generated_ids}")
        response = tokenizer.batch_decode(generated_ids, skip_special_tokens=True)[0]
        response = response.encode('utf-8', errors='ignore').decode('utf-8')    print(response)    # 使用占位符拼接字符串
        return response@app.route('/chat', methods=["POST"])def chat():    # 系統設定和prompt
        req_json = request.json
        prompt = user_prompt.format(req_json['message'])    print(prompt)    # 非會話的輸入方式,將單句話進行分詞成token ids
        inputs = tokenizer(prompt, return_tensors="pt")
        input_ids = inputs.input_ids    # Generate
        generate_ids = model.generate(input_ids=input_ids,
                                      bos_token_id=151645,  # 開始令牌(在生成文本時,模型會在輸入序列的末尾添加這個令牌,以指示新生成的文本的開始。)
                                      max_new_tokens=len(input_ids) + 1,
                                      repetition_penalty=repetition_penalty)    print(generate_ids)
        response = tokenizer.batch_decode(generate_ids, skip_special_tokens=True)[0]    print(response)    # # 去掉response中的包含prompt的文本
        response = response[len(prompt):]    return response.strip()    
    
    if __name__ == '__main__':
        app.run(port=8080, host="0.0.0.0")
    2.3.2、數據集

    數據集如下:

    二元分類數據集:電商平臺評論數據集

    多元分類數據集:今日頭條文本分類數據集 / 數據集 / HyperAI超神經

    其他:天池數據集、ChineseNlpCorpus


    聲明:本網站所提供的信息僅供參考之用,并不代表本網站贊同其觀點,也不代表本網站對其真實性負責。 




    分享到:
    最新評論(0)
    更多
    匿名者
    頂樓
    肉人妻丰满av无码久久不卡_国产成人精品无码片区_国产69精品久久久久9999_国产内射XXXXX
  • <source id="kqqcq"></source>
  • <legend id="kqqcq"></legend>