国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

2023年的深度學(xué)習(xí)入門指南(19) - LLaMA 2源碼解析

這篇具有很好參考價值的文章主要介紹了2023年的深度學(xué)習(xí)入門指南(19) - LLaMA 2源碼解析。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

2023年的深度學(xué)習(xí)入門指南(19) - LLaMA 2源碼解析

上一節(jié)我們學(xué)習(xí)了LLaMA 2的補全和聊天兩種API的使用方法。本節(jié)我們來看看LLaMA 2的源碼。

補全函數(shù)text_completion源碼解析

上一節(jié)我們講了LLaMA 2的編程方法。我們來復(fù)習(xí)一下:

    generator = Llama.build(
        ckpt_dir=ckpt_dir,
        tokenizer_path=tokenizer_path,
        max_seq_len=max_seq_len,
        max_batch_size=max_batch_size,
    )

    prompts = [
        "上下五千年,英雄萬萬千。黃沙百戰(zhàn)穿金甲,不破樓蘭終不還",
    ]
    results = generator.text_completion(
        prompts,
        max_gen_len=max_gen_len,
        temperature=temperature,
        top_p=top_p,
    )

我們先來看看text_completion函數(shù)的參數(shù)是什么意思,該函數(shù)的原型為:

def text_completion(
self,
prompts: List[str],
temperature: float = 0.6,
top_p: float = 0.9,
max_gen_len: Optional[int] = None,
logprobs: bool = False,
echo: bool = False,
) -> List[CompletionPrediction]:

我們來看下這些參數(shù)的含義:

  • prompts:這是一個字符串列表,每個字符串都是一個用于生成文本的提示。
  • temperature(默認(rèn)值為0.6):這是一個控制生成文本隨機性的參數(shù)。溫度值越高,生成的文本就越隨機;溫度值越低,生成的文本就越傾向于最可能的輸出。
  • top_p(默認(rèn)值為0.9):這是一個控制生成文本多樣性的參數(shù),它設(shè)定了從最高概率的詞開始,累計到總概率超過top_p的詞為止,然后從這些詞中隨機選擇一個詞作為生成的詞。這種方法也被稱為nucleus sampling或top-p sampling。
  • max_gen_len:可選參數(shù),表示生成的文本的最大長度。如果未指定,那么將使用模型參數(shù)中的最大序列長度減1。
  • logprobs(默認(rèn)值為False):如果為True,那么在返回的結(jié)果中會包含生成的每個詞的對數(shù)概率。
  • echo(默認(rèn)值為False):這是一個控制是否在生成的文本中包含輸入提示的參數(shù)。

參數(shù)明白了之后我們看text_completion完整實現(xiàn):

    def text_completion(
        self,
        prompts: List[str],
        temperature: float = 0.6,
        top_p: float = 0.9,
        max_gen_len: Optional[int] = None,
        logprobs: bool = False,
        echo: bool = False,
    ) -> List[CompletionPrediction]:
        if max_gen_len is None:
            max_gen_len = self.model.params.max_seq_len - 1
        prompt_tokens = [self.tokenizer.encode(x, bos=True, eos=False) for x in prompts]
        generation_tokens, generation_logprobs = self.generate(
            prompt_tokens=prompt_tokens,
            max_gen_len=max_gen_len,
            temperature=temperature,
            top_p=top_p,
            logprobs=logprobs,
            echo=echo,
        )
        if logprobs:
            return [
                {
                    "generation": self.tokenizer.decode(t),
                    "tokens": [self.tokenizer.decode(x) for x in t],
                    "logprobs": logprobs_i,
                }
                for t, logprobs_i in zip(generation_tokens, generation_logprobs)
            ]
        return [{"generation": self.tokenizer.decode(t)} for t in generation_tokens]

總結(jié)起來就三步,這個text_completion其實就是generate的包裝函數(shù):

  • 編碼:調(diào)用tokenizer.encode
  • 生成:調(diào)用generate
  • 解碼:調(diào)用tokenizer.decode

分詞

2023年的深度學(xué)習(xí)入門指南(19) - LLaMA 2源碼解析,深度學(xué)習(xí),llama,人工智能

import os
from logging import getLogger
from typing import List

from sentencepiece import SentencePieceProcessor


logger = getLogger()


class Tokenizer:
    def __init__(self, model_path: str):
        # reload tokenizer
        assert os.path.isfile(model_path), model_path
        self.sp_model = SentencePieceProcessor(model_file=model_path)
        logger.info(f"Reloaded SentencePiece model from {model_path}")

        # BOS / EOS token IDs
        self.n_words: int = self.sp_model.vocab_size()
        self.bos_id: int = self.sp_model.bos_id()
        self.eos_id: int = self.sp_model.eos_id()
        self.pad_id: int = self.sp_model.pad_id()
        logger.info(
            f"#words: {self.n_words} - BOS ID: {self.bos_id} - EOS ID: {self.eos_id}"
        )
        assert self.sp_model.vocab_size() == self.sp_model.get_piece_size()

    def encode(self, s: str, bos: bool, eos: bool) -> List[int]:
        assert type(s) is str
        t = self.sp_model.encode(s)
        if bos:
            t = [self.bos_id] + t
        if eos:
            t = t + [self.eos_id]
        return t

    def decode(self, t: List[int]) -> str:
        return self.sp_model.decode(t)

首先是用到了分詞組件SentencePieceProcessor。SentencePieceProcessor是SentencePiece庫中的一個組件,它實現(xiàn)了子詞(subword)tokenize和detokenize的功能。

其主要作用包括:

  • 將文本tokenize成子詞(subword)。SentencePiece 使用的數(shù)據(jù)驅(qū)動方法,可以學(xué)習(xí)文本的詞匯表并將文本tokenize成子詞單元。
  • 將子詞detokenize合并成原始文本??梢詫okenize后的子詞序列重新合并為原始文本。
  • 提供vocab管理??梢垣@得tokenize的子詞詞匯表等信息。
  • 支持多種語言文本的tokenize和detokenize。
  • 提供高效的實現(xiàn)。底層使用C++實現(xiàn),可以快速處理大規(guī)模文本。
  • 提供多種模型選擇,如BPE、unigram等。
  • 支持自定義訓(xùn)練子詞化模型。

好,下面我們回到這段代碼本身。這段代碼實現(xiàn)了一個基于SentencePiece的Tokenizer類,可以進行文本的tokenize和detokenize。

主要邏輯:

  • 在初始化時加載SentencePiece模型文件model_path。
  • 獲取模型的詞匯表大小n_words,以及特殊token的id(bos_id,eos_id,pad_id)。
  • encode方法可以將字符串文本s tokenize成id列表。可以選擇在開始加入bos_id,結(jié)尾加入eos_id。
  • decode方法可以將id列表解碼還原為字符串文本。

這樣就構(gòu)建了一個封裝SentencePiece tokenize/detokenize的Tokenizer類??梢约虞d自定義的SentencePiece模型,然后就可以方便地對文本進行子詞化處理。

這種方式可以重復(fù)使用已訓(xùn)練好的SentencePiece模型,為下游NLP任務(wù)提供可靠的tokenize和detokenize功能。

最后我們再講一講幾個特殊的符號bos_id、eos_id和pad_id:

  • bos_id: 開始符(Beginning of Sentence)的id。用于表示一個序列的開始。
  • eos_id: 結(jié)束符(End of Sentence)的id。用于表示一個序列的結(jié)束。
  • pad_id: 填充符(Padding)的id。當(dāng)需要將多個序列長度對齊時,可以使用pad_id在較短序列后面填充。

聊天函數(shù)chat_completion

在進入generate函數(shù)之前,我們再看看chat_completion是如何實現(xiàn)的。

    def chat_completion(
        self,
        dialogs: List[Dialog],
        temperature: float = 0.6,
        top_p: float = 0.9,
        max_gen_len: Optional[int] = None,
        logprobs: bool = False,
    ) -> List[ChatPrediction]:
        if max_gen_len is None:
            max_gen_len = self.model.params.max_seq_len - 1
        prompt_tokens = []
        for dialog in dialogs:
            if dialog[0]["role"] != "system":
                dialog = [
                    {
                        "role": "system",
                        "content": DEFAULT_SYSTEM_PROMPT,
                    }
                ] + dialog
            dialog = [
                {
                    "role": dialog[1]["role"],
                    "content": B_SYS
                    + dialog[0]["content"]
                    + E_SYS
                    + dialog[1]["content"],
                }
            ] + dialog[2:]
            assert all([msg["role"] == "user" for msg in dialog[::2]]) and all(
                [msg["role"] == "assistant" for msg in dialog[1::2]]
            ), (
                "model only supports 'system', 'user' and 'assistant' roles, "
                "starting with 'system', then 'user' and alternating (u/a/u/a/u...)"
            )
            dialog_tokens: List[int] = sum(
                [
                    self.tokenizer.encode(
                        f"{B_INST} {(prompt['content']).strip()} {E_INST} {(answer['content']).strip()} ",
                        bos=True,
                        eos=True,
                    )
                    for prompt, answer in zip(
                        dialog[::2],
                        dialog[1::2],
                    )
                ],
                [],
            )
            assert (
                dialog[-1]["role"] == "user"
            ), f"Last message must be from user, got {dialog[-1]['role']}"
            dialog_tokens += self.tokenizer.encode(
                f"{B_INST} {(dialog[-1]['content']).strip()} {E_INST}",
                bos=True,
                eos=False,
            )
            prompt_tokens.append(dialog_tokens)

        generation_tokens, generation_logprobs = self.generate(
            prompt_tokens=prompt_tokens,
            max_gen_len=max_gen_len,
            temperature=temperature,
            top_p=top_p,
            logprobs=logprobs,
        )
        if logprobs:
            return [
                {
                    "generation": {
                        "role": "assistant",
                        "content": self.tokenizer.decode(t),
                    },
                    "tokens": [self.tokenizer.decode(x) for x in t],
                    "logprobs": logprobs_i,
                }
                for t, logprobs_i in zip(generation_tokens, generation_logprobs)
            ]
        return [
            {"generation": {"role": "assistant", "content": self.tokenizer.decode(t)}}
            for t in generation_tokens
        ]

我們先看一下參數(shù):

  • dialogs:一個對話列表,其中每個對話都是一個字典列表,表示一段對話。
  • temperature:一個浮點數(shù),表示生成文本時使用的溫度。默認(rèn)值為 0.6。
  • top_p:一個浮點數(shù),表示生成文本時使用的 top-p 采樣。默認(rèn)值為 0.9。
  • max_gen_len:一個可選的整數(shù),表示生成文本的最大長度。如果未指定,則使用模型參數(shù)中的最大序列長度減一。
  • logprobs:一個布爾值,表示是否返回生成文本的對數(shù)概率。默認(rèn)值為 False。
    函數(shù)返回一個 ChatPrediction 列表,其中每個元素都是一個字典,包含生成的回復(fù)和相關(guān)信息。

函數(shù)首先檢查 max_gen_len 是否為 None,如果是,則將其設(shè)置為模型參數(shù)中的最大序列長度減一。然后,對于每個對話,函數(shù)執(zhí)行以下操作:

  • 如果第一條消息的角色不是 “system”,則在對話的開頭添加一條默認(rèn)的系統(tǒng)提示。
  • 將第一條和第二條消息合并為一條消息,并更新對話。
  • 檢查對話中消息的角色是否符合要求(即以 “system” 開始,然后交替出現(xiàn) “user” 和 “assistant”)。
  • 對于每一組相鄰的提示和回答(即每兩條消息),使用 tokenizer 對其進行編碼,并將編碼后的 token 連接起來。
  • 檢查最后一條消息是否來自用戶。
  • 對最后一條消息進行編碼,并將編碼后的 token 添加到 token 列表中。

接下來,函數(shù)調(diào)用 generate 方法生成回復(fù),并根據(jù) logprobs 參數(shù)的值返回相應(yīng)的結(jié)果。如果 logprobs 為 True,則返回包含生成回復(fù)、token 和對數(shù)概率的字典列表;否則,返回僅包含生成回復(fù)的字典列表。這些生成回復(fù)都具有 “assistant” 角色,并使用 tokenizer 進行解碼。

總體來說,只是增加了對于對話角色的業(yè)務(wù)邏輯處理,核心還是調(diào)用generate函數(shù)。

溫度與top p采樣

在進入講解generate函數(shù)之前,我們先講一個小知識點,就是溫度temperature的作用。我們看下面的代碼:

            if temperature > 0:
                probs = torch.softmax(logits[:, -1] / temperature, dim=-1)
                next_token = sample_top_p(probs, top_p)
            else:
                next_token = torch.argmax(logits[:, -1], dim=-1)

temperature 是一個超參數(shù),用于控制生成文本的多樣性。當(dāng) temperature 較高時,概率分布更加平坦,因此采樣出的標(biāo)記更具多樣性。當(dāng) temperature 較低時,概率分布更加尖銳,因此采樣出的標(biāo)記更傾向于概率最大的那個。當(dāng) temperature 等于 0 時,直接選擇概率最大的標(biāo)記。

2023年的深度學(xué)習(xí)入門指南(19) - LLaMA 2源碼解析,深度學(xué)習(xí),llama,人工智能

那么,sample_top_p是如何實現(xiàn)的呢?我把解說寫在代碼注釋里面了:

def sample_top_p(probs, p):
    # 這行代碼將輸入的概率 probs 按照降序排序。probs_sort 是排序后的概率,probs_idx 是對應(yīng)的索引。
    probs_sort, probs_idx = torch.sort(probs, dim=-1, descending=True)
    # 這行代碼計算 probs_sort 的累積和。累積和是從第一個元素開始,依次將序列中的每個元素與前面所有元素的和相加得到的。
    probs_sum = torch.cumsum(probs_sort, dim=-1)
    # 這行代碼生成一個布爾掩碼,用于指示哪些累積和減去當(dāng)前概率的值大于 p。這用于確定哪些概率應(yīng)該被設(shè)為0,以保證被抽樣的概率和不超過 p。
    mask = probs_sum - probs_sort > p
    # 這行代碼使用上述生成的掩碼,將那些使累積和減去當(dāng)前概率的值大于 p 的 probs_sort 中的元素設(shè)為0。
    probs_sort[mask] = 0.0
    # 這行代碼將 probs_sort 中的每個元素除以它們的和,以便重新歸一化概率分布。
    probs_sort.div_(probs_sort.sum(dim=-1, keepdim=True))
    # 這行代碼從歸一化的 probs_sort 中抽取一個樣本。torch.multinomial 是PyTorch中的多項式分布抽樣函數(shù),它根據(jù)每個元素的權(quán)重抽取樣本。
    next_token = torch.multinomial(probs_sort, num_samples=1)
    # 這行代碼使用 torch.gather 函數(shù)從 probs_idx 中收集對應(yīng) next_token 的索引,這樣就能得到原始概率 probs 中對應(yīng)的索引。
    next_token = torch.gather(probs_idx, -1, next_token)
    return next_token

總的來說,sample_top_p保留了按概率高低排序的大致分布,但過濾了長尾部分的低概率噪聲。然后從重歸一化的分布中采樣,既保證了質(zhì)量,又增加了適當(dāng)?shù)碾S機性。

generate函數(shù)

好,我們終于開始探索最核心的生成函數(shù)上了:

    @torch.inference_mode()
    def generate(
        self,
        prompt_tokens: List[List[int]],
        max_gen_len: int,
        temperature: float = 0.6,
        top_p: float = 0.9,
        logprobs: bool = False,
        echo: bool = False,
    ) -> Tuple[List[List[int]], Optional[List[List[float]]]]:

首先是這個函數(shù)的參數(shù),其實我們已經(jīng)比較熟悉了。包括輸入的提示 tokens(prompt_tokens),最大生成長度(max_gen_len),溫度參數(shù)(temperature,影響生成文本的隨機性), top_p(用于決定采樣過程中保留的 token 集合的概率閾值,也被稱為 “nucleus sampling”),是否返回每個 token 的對數(shù)概率(logprobs),以及是否將輸入的提示返回(echo)。

        params = self.model.params
        bsz = len(prompt_tokens)
        assert bsz <= params.max_batch_size, (bsz, params.max_batch_size)

        min_prompt_len = min(len(t) for t in prompt_tokens)
        max_prompt_len = max(len(t) for t in prompt_tokens)
        assert max_prompt_len <= params.max_seq_len
        total_len = min(params.max_seq_len, max_gen_len + max_prompt_len)

        pad_id = self.tokenizer.pad_id
        tokens = torch.full((bsz, total_len), pad_id, dtype=torch.long, device="cuda")
        for k, t in enumerate(prompt_tokens):
            tokens[k, : len(t)] = torch.tensor(t, dtype=torch.long, device="cuda")
        if logprobs:
            token_logprobs = torch.zeros_like(tokens, dtype=torch.float)

        prev_pos = 0
        eos_reached = torch.tensor([False] * bsz, device="cuda")
        input_text_mask = tokens != pad_id

接著,根據(jù)提供的 prompt_tokens 初始化一個 tokens 張量,長度為 total_len,并填充模型的 pad_id。然后,將 prompt_tokens 的內(nèi)容復(fù)制到 tokens 張量的對應(yīng)位置。

        for cur_pos in range(min_prompt_len, total_len):
            logits = self.model.forward(tokens[:, prev_pos:cur_pos], prev_pos)
            if logprobs:
                token_logprobs[:, prev_pos + 1 : cur_pos + 1] = -F.cross_entropy(
                    input=logits.transpose(1, 2),
                    target=tokens[:, prev_pos + 1 : cur_pos + 1],
                    reduction="none",
                    ignore_index=pad_id,
                )
            if temperature > 0:
                probs = torch.softmax(logits[:, -1] / temperature, dim=-1)
                next_token = sample_top_p(probs, top_p)
            else:
                next_token = torch.argmax(logits[:, -1], dim=-1)

            next_token = next_token.reshape(-1)
            # only replace token if prompt has already been generated
            next_token = torch.where(
                input_text_mask[:, cur_pos], tokens[:, cur_pos], next_token
            )
            tokens[:, cur_pos] = next_token
            eos_reached |= (~input_text_mask[:, cur_pos]) & (
                next_token == self.tokenizer.eos_id
            )
            prev_pos = cur_pos
            if all(eos_reached):
                break

然后,對于 tokens 張量中的每一個位置,計算下一個 token 的 logits,并基于這些 logits 生成下一個 token。如果 logprobs 參數(shù)為真,則計算每個 token 的對數(shù)概率。如果溫度大于 0,則使用 softmax 函數(shù)和溫度參數(shù)對 logits 進行縮放,然后使用 top-p 采樣生成下一個 token。否則,直接選擇 logits 最大的 token。新生成的 token 會替換 tokens 張量中的對應(yīng)位置。

如果生成的 token 是結(jié)束標(biāo)記(eos_id),則更新 eos_reached 標(biāo)記。如果所有的序列都已經(jīng)生成了結(jié)束標(biāo)記,則停止生成。

        if logprobs:
            token_logprobs = token_logprobs.tolist()
        out_tokens, out_logprobs = [], []
        for i, toks in enumerate(tokens.tolist()):
            # cut to max gen len
            start = 0 if echo else len(prompt_tokens[i])
            toks = toks[start : len(prompt_tokens[i]) + max_gen_len]
            probs = None
            if logprobs:
                probs = token_logprobs[i][start : len(prompt_tokens[i]) + max_gen_len]
            # cut to eos tok if any
            if self.tokenizer.eos_id in toks:
                eos_idx = toks.index(self.tokenizer.eos_id)
                toks = toks[:eos_idx]
                probs = probs[:eos_idx] if logprobs else None
            out_tokens.append(toks)
            out_logprobs.append(probs)
        return (out_tokens, out_logprobs if logprobs else None)

最后,如果 logprobs 參數(shù)為真,則將 token_logprobs 轉(zhuǎn)換為列表。然后,對于 tokens 張量中的每一行(即每一個生成的序列),如果 echo 參數(shù)為假,則去掉提示部分。然后,如果存在結(jié)束標(biāo)記,則去掉結(jié)束標(biāo)記之后的部分。最后,返回生成的 tokens 和對數(shù)概率(如果 logprobs 參數(shù)為真)。

這個函數(shù)返回的是一個元組,第一個元素是一個列表,包含每一個生成的 token 序列。第二個元素是一個列表,包含每一個生成的對數(shù)概率序列(如果 logprobs 參數(shù)為真)。

build構(gòu)造函數(shù)

最后我們再說下構(gòu)造Llama的部分:

    @staticmethod
    def build(
        ckpt_dir: str,
        tokenizer_path: str,
        max_seq_len: int,
        max_batch_size: int,
        model_parallel_size: Optional[int] = None,
    ) -> "Llama":
        if not torch.distributed.is_initialized():
            torch.distributed.init_process_group("nccl")
        if not model_parallel_is_initialized():
            if model_parallel_size is None:
                model_parallel_size = int(os.environ.get("WORLD_SIZE", 1))
            initialize_model_parallel(model_parallel_size)

        local_rank = int(os.environ.get("LOCAL_RANK", 0))
        torch.cuda.set_device(local_rank)

        # seed must be the same in all processes
        torch.manual_seed(1)

        if local_rank > 0:
            sys.stdout = open(os.devnull, "w")

        start_time = time.time()
        checkpoints = sorted(Path(ckpt_dir).glob("*.pth"))
        assert len(checkpoints) > 0, f"no checkpoint files found in {ckpt_dir}"
        assert model_parallel_size == len(
            checkpoints
        ), f"Loading a checkpoint for MP={len(checkpoints)} but world size is {model_parallel_size}"
        ckpt_path = checkpoints[get_model_parallel_rank()]
        checkpoint = torch.load(ckpt_path, map_location="cpu")
        with open(Path(ckpt_dir) / "params.json", "r") as f:
            params = json.loads(f.read())

        model_args: ModelArgs = ModelArgs(
            max_seq_len=max_seq_len,
            max_batch_size=max_batch_size,
            **params,
        )
        tokenizer = Tokenizer(model_path=tokenizer_path)
        model_args.vocab_size = tokenizer.n_words
        torch.set_default_tensor_type(torch.cuda.HalfTensor)
        model = Transformer(model_args)
        model.load_state_dict(checkpoint, strict=False)
        print(f"Loaded in {time.time() - start_time:.2f} seconds")

        return Llama(model, tokenizer)

雖然這么一大段,但其實都是一些初始化的工作。

  • 分布式設(shè)置:首先,這段代碼檢查是否已經(jīng)初始化了 PyTorch 的分布式環(huán)境,如果沒有則進行初始化。然后,檢查是否已經(jīng)初始化了模型并行環(huán)境,如果沒有,則獲取環(huán)境變量 WORLD_SIZE 的值作為模型并行的大小,并進行初始化。

  • 設(shè)備設(shè)置:獲取環(huán)境變量 LOCAL_RANK 的值作為本地排名,并設(shè)置當(dāng)前設(shè)備為該排名對應(yīng)的 GPU。

  • 隨機種子設(shè)置:為了確保所有進程生成的隨機數(shù)相同,設(shè)置隨機種子為 1。

  • 標(biāo)準(zhǔn)輸出設(shè)置:如果本地排名大于 0,則將標(biāo)準(zhǔn)輸出重定向到空設(shè)備,即不顯示任何輸出。

  • 加載模型檢查點:找到檢查點目錄中的所有檢查點文件,并按照文件名排序。然后,根據(jù)模型并行的排名選擇一個檢查點文件,并加載該檢查點。然后,加載模型參數(shù)。

  • 構(gòu)建模型和分詞器:使用加載的模型參數(shù)和提供的 max_seq_len 和 max_batch_size 構(gòu)建模型參數(shù)對象。然后,加載分詞器,并設(shè)置模型參數(shù)的詞匯表大小為分詞器的詞匯表大小。然后,設(shè)置默認(rèn)的張量類型為半精度浮點型(以節(jié)省內(nèi)存和計算資源)。然后,構(gòu)建 Transformer 模型,并加載模型檢查點。

  • 最后,構(gòu)建一個 Llama 對象,包含加載的模型和分詞器,并返回該對象。

小結(jié)

本節(jié)我們學(xué)習(xí)了LLaMA 2的源碼,包括補全函數(shù)text_completion和聊天函數(shù)chat_completion的實現(xiàn),以及它們的真正實現(xiàn)generate函數(shù)的原理。我們還學(xué)習(xí)了溫度temperature和top p采樣的原理。

對于沒有搞到深度學(xué)習(xí)生成的同學(xué),可能有一點難度。

LLaMA的代碼還差一部分就是模型的部分,我們放到下一節(jié)來講。要不然知識點太多大家容易大腦缺氧:)文章來源地址http://www.zghlxwxcb.cn/news/detail-616145.html

到了這里,關(guān)于2023年的深度學(xué)習(xí)入門指南(19) - LLaMA 2源碼解析的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

  • 2023年的深度學(xué)習(xí)入門指南(9) - SIMD和通用GPU編程

    2023年的深度學(xué)習(xí)入門指南(9) - SIMD和通用GPU編程

    深度學(xué)習(xí)從一開始就跟GPU有不解之緣,因為算力是深度學(xué)習(xí)不可或缺的一部分。 時至今日,雖然多任務(wù)編程早已經(jīng)深入人心,但是很多同學(xué)還沒有接觸過CPU上的SIMD指令,更不用說GPGPU的編程。這一篇我們先給SIMD和GPU編程掃個盲,讓大家以后用到的時候有個感性認(rèn)識。 從多線

    2024年02月02日
    瀏覽(27)
  • 2023年的深度學(xué)習(xí)入門指南(6) - 在你的電腦上運行大模型

    2023年的深度學(xué)習(xí)入門指南(6) - 在你的電腦上運行大模型

    上一篇我們介紹了大模型的基礎(chǔ),自注意力機制以及其實現(xiàn)Transformer模塊。因為Transformer被PyTorch和TensorFlow等框架所支持,所以我們只要能夠配置好框架的GPU或者其他加速硬件的支持,就可以運行起來了。 而想運行大模型,恐怕就沒有這么容易了,很有可能你需要一臺Linux電腦

    2024年02月16日
    瀏覽(24)
  • 2023年的深度學(xué)習(xí)入門指南(26) - 在自己電腦上運行通義千問7b模型

    2023年的深度學(xué)習(xí)入門指南(26) - 在自己電腦上運行通義千問7b模型

    通過量化,通義千問4位量化的模型大小為5.86G,可以在3060等小于16G的家用GPU上也可以運行起來。 通義千問7b提供了4位量化好的Qwen/Qwen-7B-Chat-Int4模型,我們直接調(diào)用就好。 首先安裝依賴包: 如果你是Linux環(huán)境的話,可以安裝下Flash-Attention來加速: Windows下暫時還用不了,這個

    2024年02月10日
    瀏覽(24)
  • 測牛學(xué)堂:2023軟件測試入門學(xué)習(xí)指南(測試方法之邊界值法)

    邊界值分析法 邊界值:輸入數(shù)據(jù)是一個有序的集合或者范圍的時候,處于集合范圍的邊界上的值。 邊界值的幾個常用的概念: 上點:邊界上的點。比如條件是(1,9)那么上點就是2和9 離點:開區(qū)間的離點,就是反方向去取。(1,9) 的離點,就是2和8 內(nèi)點:范圍內(nèi)除了上點和

    2023年04月25日
    瀏覽(21)
  • 手把手帶你入門深度學(xué)習(xí)(一):保姆級Anaconda和PyTorch環(huán)境配置指南

    手把手帶你入門深度學(xué)習(xí)(一):保姆級Anaconda和PyTorch環(huán)境配置指南

    B站:馬上就更?。?!_bilibili CSDN:手把手帶你入門深度學(xué)習(xí)(一):保姆級Anaconda和PyTorch環(huán)境配置指南_百年后封筆-CSDN博客 Github:封筆 公眾號:百年后封筆 你好,我是封筆! 如今深度學(xué)習(xí)技術(shù)的不斷演進,我們的生活發(fā)生著翻天覆地的變化,無論是計算機視覺、自然語言處

    2024年02月08日
    瀏覽(96)
  • kotlin入門教程指南(2023最新)

    kotlin入門教程指南(2023最新)

    Kotlin 是一個基于 JVM 的新的編程語言,目前在國外非常火熱,并且在一步步走向國內(nèi)市場 Kotlin有以下好處: 強大的IDE。而且是JetBrains第一方支持,不是3年更新一次的第三方插件; 庫多生態(tài)強。Kotlin的設(shè)計者非常重視和Java的互操作,所以Kotlin號稱可以無縫銜接所有Java庫。

    2024年02月14日
    瀏覽(37)
  • 立體匹配入門指南(8):視差圖、深度圖、點云

    立體匹配入門指南(8):視差圖、深度圖、點云

    本篇是比較簡單的基礎(chǔ)概念,剛?cè)腴T的朋友可能是需要的。 視差圖 三維點云 首先,我們要介紹下這三個概念。 視差(disparity) 視差 d d d 等于同名點對在左視圖的列坐標(biāo)減去在右視圖上的列坐標(biāo),是 像素單位 d = x l ? x r d=x_l-x_r d = x l ? ? x r ? 立體視覺里,視差概念在極

    2023年04月08日
    瀏覽(61)
  • 【機器學(xué)習(xí)學(xué)習(xí)】第一天:入門指南

    引言 當(dāng)今社會,機器學(xué)習(xí)技術(shù)已經(jīng)被廣泛應(yīng)用于許多領(lǐng)域,如自然語言處理、圖像處理和金融分析等。然而,機器學(xué)習(xí)這一領(lǐng)域需要掌握大量的數(shù)學(xué)知識和編程技能,因此對于初學(xué)者來說,可能會感到非常困難。本文將為初學(xué)者提供一份機器學(xué)習(xí)入門指南,幫助他們了解機器

    2024年02月02日
    瀏覽(26)
  • 一位計科學(xué)長寫給 2023 級計算機類和人工智能專業(yè)的同學(xué)們的程序設(shè)計入門指南

    一位計科學(xué)長寫給 2023 級計算機類和人工智能專業(yè)的同學(xué)們的程序設(shè)計入門指南

    本指南內(nèi)容較多,但你們?nèi)裟苣托淖x完,你們將收獲很多…… 歡迎訪問作者的主頁:Xi Xu’s Home Page 什么是程序設(shè)計和程序設(shè)計語言? 程序設(shè)計 1 (programming),或稱編程,是給程序解決出特定問題的過程,軟件開發(fā)過程中的重要步驟。程序設(shè)計方法往往以某種程序設(shè)計語言

    2024年02月16日
    瀏覽(25)
  • 前端學(xué)習(xí)路線指南:從入門到精通【①】

    作為一個前端開發(fā)者,學(xué)習(xí)前端技術(shù)是必不可少的。然而,由于前端領(lǐng)域的廣闊和不斷演進的技術(shù)棧,對于初學(xué)者來說可能會感到困惑。本篇文章將為你提供一個清晰的前端學(xué)習(xí)路線,幫助你系統(tǒng)地掌握前端開發(fā)技能,并成為一名優(yōu)秀的前端工程師。 HTML和CSS基礎(chǔ) 在開始前端

    2024年02月08日
    瀏覽(28)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包