日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > windows >内容正文

windows

聊聊ChatGLM中P-tuning v2的应用

發(fā)布時(shí)間:2024/1/11 windows 63 coder
生活随笔 收集整理的這篇文章主要介紹了 聊聊ChatGLM中P-tuning v2的应用 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

論文PDF地址:https://arxiv.org/pdf/2110.07602.pdf

轉(zhuǎn)載請(qǐng)備注出處:https://www.cnblogs.com/zhiyong-ITNote/

P-Tuning v2

摘錄自第三部分

桔色塊指代可訓(xùn)練的prompt embedding;藍(lán)色塊是由固定(凍結(jié))的預(yù)訓(xùn)練語言模型 存儲(chǔ)或計(jì)算的embedding。

Deep Prompt Tuning

continuous prompts(連續(xù)提示) 僅僅能夠插入到input embedding序列層。如此,有兩個(gè)問題:首先由于序列長(zhǎng)度的約束限制,可調(diào)參數(shù)的數(shù)量有限。其次,輸入的embedding對(duì)模型預(yù)測(cè)有間接的影響。
為了解決這些問題,P-Tuning v2使用deep prompt tuning的方案。正如上圖的b部分,prompt作為prefix token插入到不同的層中。一方面,p-tuning v2有更多可調(diào)的特定任務(wù)參數(shù)(從 0.01% 到 0.1%~3%),擴(kuò)大了任務(wù)的容量也提高了參數(shù)效率;另一方面,添加到更深層的prompt對(duì)模型的預(yù)測(cè)會(huì)有更多直接的影響。

轉(zhuǎn)載請(qǐng)備注出處:https://www.cnblogs.com/zhiyong-ITNote/

理解

在P-tuning v2的方案中,從圖直觀來看,有兩個(gè)關(guān)鍵的點(diǎn):

  1. prompts會(huì)加在序列的前端,而不僅僅是插入到input embedding
  2. 每一層都會(huì)插入prompts

v2版本主要基于p-tuning和prefix-tuning技術(shù)。prompt 向量是在模型的 embedding 層與其他輸入 token 的 embedding 相拼接的,且通過在預(yù)訓(xùn)練模型的每一層引入可訓(xùn)練的 prompt 向量來提高模型對(duì)特定任務(wù)的適應(yīng)性。
p-tuning主要是利用一個(gè)prompt encoder,將prompt先encoder再與input embedding進(jìn)行拼接。
prefix-tuning是在Transformer的Encoder和Decoder的網(wǎng)絡(luò)中都加了一些特定的前綴。
而基于這兩種技術(shù)的v2版本,則是將兩者結(jié)合。在embedding與transformer模塊都做了prompt向量的插入。
ChatGLM中,首先要對(duì)prompt做encode,作為前綴prefix拼接插入到input embedding與transformer模型中。


# 轉(zhuǎn)載請(qǐng)備注出處:https://www.cnblogs.com/zhiyong-ITNote/

class PrefixEncoder(torch.nn.Module):
    """
    The torch.nn model to encode the prefix
    Input shape: (batch-size, prefix-length)
    Output shape: (batch-size, prefix-length, 2*layers*hidden)
    """

    def __init__(self, config):
        super().__init__()
        self.prefix_projection = config.prefix_projection
        if self.prefix_projection:
            # Use a two-layer MLP to encode the prefix
            self.embedding = torch.nn.Embedding(config.pre_seq_len, config.hidden_size)
            self.trans = torch.nn.Sequential(
                torch.nn.Linear(config.hidden_size, config.hidden_size),
                torch.nn.Tanh(),
                torch.nn.Linear(config.hidden_size, config.num_layers * config.hidden_size * 2)
            )
        else:
            self.embedding = torch.nn.Embedding(config.pre_seq_len, config.num_layers * config.hidden_size * 2)

    def forward(self, prefix: torch.Tensor):
        if self.prefix_projection:
            prefix_tokens = self.embedding(prefix)
            past_key_values = self.trans(prefix_tokens)
        else:
            past_key_values = self.embedding(prefix)
        return past_key_values

在ChatGLMModel中調(diào)用并插入到每一個(gè)transformer模型層中。

class ChatGLMModel(ChatGLMPreTrainedModel):
    '''
    省略其它....
    '''
    def __init__(self, config: ChatGLMConfig, empty_init=True):
        if self.pre_seq_len is not None:
            for param in self.parameters():
                param.requires_grad = False
            self.prefix_tokens = torch.arange(self.pre_seq_len).long()
            # encode prompt
            self.prefix_encoder = PrefixEncoder(config)
            self.dropout = torch.nn.Dropout(0.1)

    # 調(diào)用prompt
	def get_prompt(self, batch_size, device, dtype=torch.half):
        prefix_tokens = self.prefix_tokens.unsqueeze(0).expand(batch_size, -1).to(device)
        # 調(diào)用prompt并返回
        past_key_values = self.prefix_encoder(prefix_tokens).type(dtype)
        past_key_values = past_key_values.view(
            batch_size,
            self.pre_seq_len,
            self.num_layers * 2,
            self.num_attention_heads,
            self.hidden_size // self.num_attention_heads
        )
        # seq_len, b, nh, hidden_size
        past_key_values = self.dropout(past_key_values)
        past_key_values = past_key_values.permute([2, 1, 0, 3, 4]).split(2)
        # past_key_values = [(v[0], v[1]) for v in past_key_values]
        return past_key_values

    # 返回transformer模型
    def get_layer(layer_id):
        return GLMBlock(
            self.hidden_size,
            self.num_attention_heads,
            self.layernorm_epsilon,
            layer_id,
            inner_hidden_size=self.inner_hidden_size,
            hidden_size_per_attention_head=self.hidden_size_per_attention_head,
            layernorm=LayerNorm,
            use_bias=True,
            params_dtype=self.params_dtype,
            position_encoding_2d=self.position_encoding_2d,
            empty_init=empty_init
        )
                
	def forward(
            self,
            input_ids: Optional[torch.LongTensor] = None,
            position_ids: Optional[torch.LongTensor] = None,
            attention_mask: Optional[torch.Tensor] = None,
            past_key_values: Optional[Tuple[Tuple[torch.Tensor, torch.Tensor], ...]] = None,
            inputs_embeds: Optional[torch.LongTensor] = None,
            use_cache: Optional[bool] = None,
            output_attentions: Optional[bool] = None,
            output_hidden_states: Optional[bool] = None,
            return_dict: Optional[bool] = None,
    ) -> Union[Tuple[torch.Tensor, ...], BaseModelOutputWithPast]:
    	# 其它代碼
        if past_key_values is None:
            if self.pre_seq_len is not None:
                # 調(diào)用prompt
                past_key_values = self.get_prompt(batch_size=input_ids.shape[0], device=input_ids.device,
                                                  dtype=inputs_embeds.dtype)
            else:
                past_key_values = tuple([None] * len(self.layers))

            if attention_mask is None:
                attention_mask = self.get_masks(
                    input_ids,
                    device=input_ids.device
                )
    	# 其它代碼
    	for i, layer in enumerate(self.layers):

            if output_hidden_states:
                all_hidden_states = all_hidden_states + (hidden_states,)
            # 準(zhǔn)備參數(shù)傳遞到layer
            layer_past = past_key_values[i]
        	# 每個(gè)layer 是一個(gè)GLMBlock即transformer模型層
            if self.gradient_checkpointing and self.training:
                # 將prompt傳遞到每個(gè)層中
                layer_ret = torch.utils.checkpoint.checkpoint(
                    layer,
                    hidden_states,
                    position_ids,
                    attention_mask,
                    torch.tensor(i),
                    layer_past,
                    use_cache,
                    output_attentions
                )
            else:
                layer_ret = layer(
                    hidden_states,
                    position_ids=position_ids,
                    attention_mask=attention_mask,
                    layer_id=torch.tensor(i),
                    layer_past=layer_past,
                    use_cache=use_cache,
                    output_attentions=output_attentions
                )
        # 其它代碼

參考

大模型微調(diào)之P-tuning方法解析

通俗解讀大模型微調(diào)(Fine Tuning)

轉(zhuǎn)載請(qǐng)備注出處:https://www.cnblogs.com/zhiyong-ITNote/

總結(jié)

以上是生活随笔為你收集整理的聊聊ChatGLM中P-tuning v2的应用的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。