日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

浅谈文本生成或者文本翻译解码策略《转》

發布時間:2023/12/20 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 浅谈文本生成或者文本翻译解码策略《转》 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

原文鏈接,感謝原作者

目錄

一、文本生成和翻譯的基本流程

翻譯類模型的訓練和解碼

訓練過程?

解碼過程

生成類模型的訓練和解碼(GPT系列)

訓練過程

解碼過程

二、解碼策略

1、貪心搜索(greedy search)

2、beam_search集束搜索

3、隨機sampling

4、Top-K Sampling和Top-p (nucleus) sampling

Top-K Sampling

Top-p (nucleus) sampling

?三、transformer中的解碼使用


? ? ? ? 文本生成和文本翻譯的效果不僅僅在于模型層面的好壞,同時預測階段的解碼策略也是比較重要,不同的解碼策略得出的效果也是不同的。經過學者們多年的研究,目前就我所知的文本生成相關的解碼策略主要有貪心搜索(greedy search)、beam_search集束搜索、隨機sampling、top-k sampling和Top-p Sampling,今天我們主要聊聊這幾種文本解碼策略算法。

一、文本生成和翻譯的基本流程

翻譯類模型的訓練和解碼

訓練過程?

翻譯類任務的流程是一個src輸入對應一個tag輸入,一般而言,src長度和tag長度不一樣的;一個簡單的流程圖如下圖所示:

模型訓練的結果是和tag長度一樣的一個向量,output[T,B,D]經過一個分類全連接層得到[T,B]的概率分布,這個就和tag的輸入[T,B]計算loss;

解碼過程

如下圖所示,模型訓練好以后,解碼的初始就是src的embedding加上tag端的起始字符<cls>等特殊的字符,解碼輸出得到第一個字符token然后把這個token添加到tag端輸入,繼續解碼得到第二個token......重復不斷的解碼,每一次解碼都是需要過一次模型推理,所以比較耗時;只到碰到結束字符或者最大長度。

生成類模型的訓練和解碼(GPT系列)

訓練過程

GPT模型的訓練過程直接輸入一段自然文本,然后輸出其embedding,然后再經過一個分類器,得到logits[B,L,V];同時把輸入文本作為標簽,計算交叉熵損失。模型的輸入就是inputids [B,L]-------->embedding[B,L,D]------->logits[B,L,V]。

?

解碼過程

同上面類似也是把當前解碼結果token和之前的tokens合并起來作為輸入解碼得到下一個token。

二、解碼策略

? ? 上面通過示意圖簡單的解釋了一下生成類任務的模型訓練和解碼過程以及中間的向量維度變化,最后解碼的結果好壞出了和模型本身有關,同時也與采用什么樣的解碼策略也是很相關的。

1、貪心搜索(greedy search)

預測階段得到的概率分布,連接全連接層后,可以得到一個序列的概率分布[(B*S),vocab_size]——含義就是每個字在詞表上的概率分布,共有B*S個字。怎么樣通過這個概率分布得到最合理的序列。一種很直觀的做法就是從每個字的概率分布中取它的最大概率的那個可能性,直到整個序列完成或者發現終止符[SEP]。簡單實現,代碼如下:

  • def gen_nopeek_mask(length):
  • """
  • Returns the nopeek mask
  • Parameters:
  • length (int): Number of tokens in each sentence in the target batch
  • Returns:
  • mask (arr): tgt_mask, looks like [[0., -inf, -inf],
  • [0., 0., -inf],
  • [0., 0., 0.]]
  • """
  • mask = torch.triu(torch.ones(length, length))
  • mask = mask.float().masked_fill(mask == 0, float('-inf')).masked_fill(mask == 1, float(0.0))
  • return mask
  • def greedy_search_decode(model, src,src_key_padding_mask, max_len:int = 64, start_symbol:int = 1):
  • """
  • :param model: Transformer model
  • :param src: the encoder input
  • :param max_len: 序列最大長度
  • :return:ys 這個就是預測的具體序列
  • 解碼的時候這幾個mask是不能夠少的
  • """
  • src_mask = gen_nopeek_mask(src.shape[1]).to(device)
  • memory_key_padding_mask = src_key_padding_mask
  • #最開始的字符[CLS]在詞表的位置是1
  • ys = torch.ones(1, 1).fill_(start_symbol).type_as(src.data)
  • for i in range(max_len-1):
  • tar_mask = gen_nopeek_mask(ys.shape[1]).to(device)
  • out = model.forward(src, ys, src_key_padding_mask=src_key_padding_mask, tgt_key_padding_mask=None,src_mask=src_mask,tar_mask=tar_mask,memory_key_padding_mask=memory_key_padding_mask)
  • #預測結果out,選取最后一個概率分布
  • out = out[:,-1,:]
  • #得到最大的那個概率的index,就是該次預測的字在詞表的index
  • _, next_word = torch.max(out, dim=1)
  • next_word = next_word.data[0]
  • if next_word != 2:
  • #如果沒有預測出終止符[SEP]
  • #把這次預測的結果和以前的結果cat起來,再次循環迭代預測
  • ys = torch.cat([ys, torch.ones(1, 1).type_as(src.data).fill_(next_word)], dim=1)
  • else:
  • break
  • return ys
  • 上面實現的缺陷就是不能并行的解碼batch>1的情形,可以適當修改適應并行處理,每次batch內的數據每次解碼后,做一個判定,是否batch內的每一行數據都出現了結束字符。判定代碼就是:

    (ys == 2).sum(1).bool().all()

    判定ys的每一行是否出現過2(結束符號)這個元素

    解碼完整代碼如下圖

  • def greedy_search_decode(model, src, src_key_padding_mask, max_len: int = 64, start_symbol: int = 1, bs:int=32):
  • """
  • :param model: Transformer model
  • :param src: the encoder input
  • :param max_len: 序列最大長度
  • :return:ys 這個就是預測的具體序列
  • 解碼的時候這幾個mask是不能夠少的
  • """
  • src_mask = gen_nopeek_mask(src.shape[1]).to(device)
  • memory_key_padding_mask = src_key_padding_mask
  • # 最開始的字符[CLS]在詞表的位置是1
  • ys = torch.ones(bs, 1).fill_(start_symbol).type_as(src.data)
  • for i in range(max_len - 1):
  • tar_mask = gen_nopeek_mask(ys.shape[1]).to(device)
  • out = model.forward(src, ys, src_key_padding_mask=src_key_padding_mask, tgt_key_padding_mask=None,
  • src_mask=src_mask, tar_mask=tar_mask, memory_key_padding_mask=memory_key_padding_mask)
  • # 預測結果out,選取最后一個概率分布
  • out = out[:, -1, :]
  • # 得到最大的那個概率的index,就是該次預測的字在詞表的index
  • _, next_word = torch.max(out, dim=1)
  • next_word = next_word.data[0]
  • ys = torch.cat([ys, next_word], dim=1)
  • #判定一個batch內是不是所有的都解碼完成了
  • if (ys == 2).sum(1).bool().all():
  • break
  • return ys
  • 解碼舉例如下

    ?the nice woman 是每個時間步當前的最佳選擇概率為0.5*0.4=0.2,但是從圖上看概率最大的結果并不是這個the dog has 才具有整句最大的概率0.4*0.9 = 0.36;很明顯的貪心搜索(greedy search)的缺點就是得出的序列并不一定具有整句最大概率,它很有可能遺漏掉一個比較小的當前概率后面的非常大概率的序列。為了避免這種情況,學者們提出了beam_search算法。

    2、beam_search集束搜索

    為了避免上述貪心搜索遺漏掉后面大概率的序列,beam search算法提出每次都保留當前最大的beam_num個結果。把當前beam_num個結果分別輸入到模型中進行解碼,每個序列又新生成v個新結果,共計beam_num*v個結果,排序選擇最佳的beam_num個結果;然后重復上述過程,直到解碼完成,最后從beam_num個結果選擇出概率積最大的那個序列。——即每一步解碼過程中都是保留前beam_num個最大的結果,最后才得出概率最大的那個。

    以beam_num為2進行舉例,圖片來自——(全面了解Beam Search 1)

    第一步解碼,我們選擇概率最大的兩個單詞[A, C],然后分別帶入第二步解碼,分別得到[AA, AB, AC, AD, AE, CA, CB, CC, CD, CE] 10種情況,這里僅保留最優的兩種情況[AB, CE],然后再繼續帶入第三步解碼,以此類推.....最后得到整體概率最大的序列。

    bs=1時,實現beam search還是比較簡單的,直接在貪心搜索的代碼上做修改,記錄當前最佳的beam_num個序列以及得分,然后每一步結果從beam_num*v的結果中做排序得到新的beam_num個結果。

    當bs>1的時候,要實現一個高效的beam search還是比較麻煩的,參考了全面了解Beam Search 1和世界第一NLP實現庫huggingface的transformers中的源碼,修改如下的beam search代碼:

  • import torch
  • import torch.nn.functional as F
  • from einops import rearrange
  • """
  • batch_size為n 這樣的處理
  • """
  • class BeamHypotheses(object):
  • def __init__(self,num_beams,max_length,length_penalty):
  • self.max_length=max_length-1 # ignoringbos_token
  • self.length_penalty=length_penalty # 長度懲罰的指數系數
  • self.num_beams=num_beams # beamsize
  • self.beams=[] # 存儲最優序列及其累加的log_probscore
  • self.worst_score=1e9 # 將worst_score初始為無窮大。
  • def __len__(self):
  • return len(self.beams)
  • def add(self,hyp,sum_logprobs):
  • score=sum_logprobs / len(hyp) ** self.length_penalty # 計算懲罰后的score
  • if len(self) < self.num_beams or score > self.worst_score:
  • # 如果類沒裝滿num_beams個序列
  • # 或者裝滿以后,但是待加入序列的score值大于類中的最小值
  • # 則將該序列更新進類中,并淘汰之前類中最差的序列
  • self.beams.append((score, hyp))
  • if len(self) > self.num_beams:
  • sorted_scores=sorted([(s,idx)for idx, (s, _) in enumerate(self.beams)])
  • del self.beams[sorted_scores[0][1]]
  • self.worst_score = sorted_scores[1][0]
  • else:
  • # 如果沒滿的話,僅更新worst_score
  • self.worst_score = min(score, self.worst_score)
  • def is_done(self,best_sum_logprobs,cur_len):
  • # 當解碼到某一層后,該層每個結點的分數表示從根節點到這里的log_prob之和
  • # 此時取最高的log_prob,如果此時候選序列的最高分都比類中最低分還要低的話
  • # 那就沒必要繼續解碼下去了。此時完成對該句子的解碼,類中有num_beams個最優序列。
  • if len(self) < self.num_beams:
  • return False
  • else:
  • cur_score = best_sum_logprobs / cur_len ** self.length_penalty
  • ret = self.worst_score >= cur_score
  • return ret
  • def gen_nopeek_mask(length):
  • """
  • Returns the nopeek mask
  • Parameters:
  • length (int): Number of tokens in each sentence in the target batch
  • Returns:
  • mask (arr): tgt_mask, looks like [[0., -inf, -inf],
  • [0., 0., -inf],
  • [0., 0., 0.]]
  • """
  • mask = rearrange(torch.triu(torch.ones(length, length)) == 1, 'h w -> w h')
  • mask = mask.float().masked_fill(mask == 0, float('-inf')).masked_fill(mask == 1, float(0.0))
  • return mask
  • def beam_sizing(num_beams,src,src_key_padding_mask):
  • #為了滿足beam_search 算法在解碼的時候的使用,需要進行數據復制——按行進行復制,復制num_beams份
  • temp1 = src
  • temp2 = src_key_padding_mask
  • for i in range(num_beams-1):
  • temp1 = torch.cat([temp1,src],dim=0)
  • temp2 = torch.cat([temp2,src_key_padding_mask],dim=0)
  • index = 0
  • for i in range(src.shape[0]):
  • for _ in range(num_beams):
  • temp1[index,...] = src[i,...]
  • temp2[index,...] = src_key_padding_mask[i,...]
  • index += 1
  • src = temp1
  • src_key_padding_mask = temp2
  • return src,src_key_padding_mask
  • def beam_search(device,model,src,src_key_padding_mask,sos_token_id:int=1,pad_token_id:int=0,eos_token_id:int = 2,max_length:int = 20,num_beams:int =6,vocab_size:int=5993):
  • batch_size = src.shape[0]
  • src_mask = gen_nopeek_mask(src.shape[1]).to(device)
  • src,src_key_padding_mask = beam_sizing(num_beams,src,src_key_padding_mask)
  • memory_key_padding_mask = src_key_padding_mask
  • beam_scores = torch.zeros((batch_size, num_beams)).to(device) # 定義scores向量,保存累加的log_probs
  • beam_scores[:, 1:] = -1e9 # 需要初始化為-inf
  • beam_scores = beam_scores.view(-1) # 展開為(batch_size * num_beams)
  • done = [False for _ in range(batch_size)] # 標記每個輸入句子的beam search是否完成
  • generated_hyps = [
  • BeamHypotheses(num_beams, max_length, length_penalty=0.7)
  • for _ in range(batch_size)
  • ] # 為每個輸入句子定義維護其beam search序列的類實例
  • # 初始輸入: (batch_size * num_beams, 1)個sos token
  • input_ids = torch.full((batch_size * num_beams, 1), sos_token_id, dtype=torch.long).to(device)
  • cur_len = 1
  • while cur_len < max_length:
  • tar_mask = gen_nopeek_mask(input_ids.shape[1]).to(device)
  • memory_key_padding_mask = src_key_padding_mask
  • outputs,_= model.forward(src, input_ids, src_key_padding_mask=src_key_padding_mask, tgt_key_padding_mask=None,src_mask=src_mask,tar_mask=tar_mask,memory_key_padding_mask=memory_key_padding_mask)
  • # 取最后一個timestep的輸出 (batch_size*num_beams, vocab_size)
  • next_token_logits = outputs[:, -1, :]
  • scores = F.log_softmax(next_token_logits, dim=-1) # log_softmax
  • next_scores = scores + beam_scores[:, None].expand_as(scores) # 累加上以前的scores
  • next_scores = next_scores.view(
  • batch_size, num_beams * vocab_size
  • ) # 轉成(batch_size, num_beams * vocab_size), 如上圖所示
  • # 取topk,這里一定要取2*num_beams個最大值,才能保證后續下一批次每個batch內會有num_beams個需要處理的
  • next_scores, next_tokens = torch.topk(next_scores, 2*num_beams, dim=1, largest=True, sorted=True)
  • # 下一個時間步整個batch的beam列表
  • # 列表中的每一個元素都是三元組
  • # (分數, token_id, beam_id)
  • next_batch_beam = []
  • for batch_idx in range(batch_size):
  • if done[batch_idx]:
  • # 當前batch的句子都解碼完了,那么對應的num_beams個句子都繼續pad
  • next_batch_beam.extend([(0, pad_token_id, 0)] * num_beams) # pad the batch
  • continue
  • next_sent_beam = [] # 保存三元組(beam_token_score, token_id, effective_beam_id)
  • for beam_token_rank, (beam_token_id, beam_token_score) in enumerate(
  • zip(next_tokens[batch_idx], next_scores[batch_idx])
  • ):
  • beam_id = beam_token_id // vocab_size # 1
  • token_id = beam_token_id % vocab_size # 1
  • # 上面的公式計算beam_id只能輸出0和num_beams-1, 無法輸出在(batch_size, num_beams)中的真實id
  • # 如上圖, batch_idx=0時,真實beam_id = 0或1; batch_idx=1時,真實beam_id如下式計算為2或3
  • # batch_idx=1時,真實beam_id如下式計算為4或5
  • effective_beam_id = batch_idx * num_beams + beam_id
  • # 如果遇到了eos, 則講當前beam的句子(不含當前的eos)存入generated_hyp
  • if (eos_token_id is not None) and (token_id.item() == eos_token_id):
  • is_beam_token_worse_than_top_num_beams = beam_token_rank >= num_beams
  • if is_beam_token_worse_than_top_num_beams:
  • continue
  • generated_hyps[batch_idx].add(
  • input_ids[effective_beam_id].clone(), beam_token_score.item(),
  • )
  • else:
  • # 保存第beam_id個句子累加到當前的log_prob以及當前的token_id
  • next_sent_beam.append((beam_token_score, token_id, effective_beam_id))
  • if len(next_sent_beam) == num_beams:
  • break
  • # 當前batch是否解碼完所有句子
  • done[batch_idx] = done[batch_idx] or generated_hyps[batch_idx].is_done(
  • next_scores[batch_idx].max().item(), cur_len
  • ) # 注意這里取當前batch的所有log_prob的最大值
  • # 每個batch_idx, next_sent_beam中有num_beams個三元組(假設都不遇到eos)
  • # batch_idx循環后,extend后的結果為num_beams * batch_size個三元組
  • next_batch_beam.extend(next_sent_beam)
  • # 如果batch中每個句子的beam search都完成了,則停止
  • if all(done):
  • break
  • # 準備下一次循環(下一層的解碼)
  • # beam_scores: (num_beams * batch_size)
  • # beam_tokens: (num_beams * batch_size)
  • # beam_idx: (num_beams * batch_size)
  • # 這里beam idx shape不一定為num_beams * batch_size,一般是小于等于
  • # 因為有些beam id對應的句子已經解碼完了 (下面假設都沒解碼完)
  • # print('next_batch_beam',len(next_batch_beam))
  • beam_scores = beam_scores.new([x[0] for x in next_batch_beam])
  • beam_tokens = input_ids.new([x[1] for x in next_batch_beam])
  • beam_idx = input_ids.new([x[2] for x in next_batch_beam])
  • # 取出有效的input_ids, 因為有些beam_id不在beam_idx里面,
  • # 因為有些beam id對應的句子已經解碼完了
  • # print('beam_idx',beam_idx)
  • # print('next_scores.shape',next_scores.shape)
  • #以下代碼是核心的必須添加上
  • input_ids = input_ids[beam_idx, :] # (num_beams * batch_size, seq_len)
  • src = src[beam_idx,...]
  • src_key_padding_mask = src_key_padding_mask[beam_idx,...]
  • # (num_beams * batch_size, seq_len) ==> (num_beams * batch_size, seq_len + 1)
  • input_ids = torch.cat([input_ids, beam_tokens.unsqueeze(1)], dim=-1)
  • cur_len = cur_len + 1
  • # 注意有可能到達最大長度后,仍然有些句子沒有遇到eos token,這時done[batch_idx]是false
  • for batch_idx in range(batch_size):
  • if done[batch_idx]:
  • continue
  • for beam_id in range(num_beams):
  • # 對于每個batch_idx的每句beam,都執行加入add
  • # 注意這里已經解碼到max_length長度了,但是并沒有遇到eos,故這里全部要嘗試加入
  • effective_beam_id = batch_idx * num_beams + beam_id
  • final_score = beam_scores[effective_beam_id].item()
  • final_tokens = input_ids[effective_beam_id]
  • generated_hyps[batch_idx].add(final_tokens, final_score)
  • # 經過上述步驟后,每個輸入句子的類中保存著num_beams個最優序列
  • # 下面選擇若干最好的序列輸出
  • # 每個樣本返回幾個句子
  • output_num_return_sequences_per_batch = num_beams #一定要小于num_beams
  • output_batch_size = output_num_return_sequences_per_batch * batch_size
  • # 記錄每個返回句子的長度,用于后面pad
  • sent_lengths = input_ids.new(output_batch_size)
  • best = []
  • best_score = []
  • # retrieve best hypotheses
  • for i, hypotheses in enumerate(generated_hyps):
  • # x: (score, hyp), x[0]: score
  • sorted_hyps = sorted(hypotheses.beams, key=lambda x: x[0])
  • for j in range(output_num_return_sequences_per_batch):
  • effective_batch_idx = output_num_return_sequences_per_batch * i + j
  • temp = sorted_hyps.pop()
  • best_hyp = temp[1]
  • best_s = temp[0]
  • sent_lengths[effective_batch_idx] = len(best_hyp)
  • best.append(best_hyp)
  • best_score.append(best_s)
  • if sent_lengths.min().item() != sent_lengths.max().item():
  • sent_max_len = min(sent_lengths.max().item() + 1, max_length)
  • # fill pad
  • decoded = input_ids.new(output_batch_size, sent_max_len).fill_(pad_token_id)
  • # 填充內容
  • for i, hypo in enumerate(best):
  • decoded[i, : sent_lengths[i]] = hypo
  • if sent_lengths[i] < max_length:
  • decoded[i, sent_lengths[i]] = eos_token_id
  • else:
  • # 否則直接堆疊起來
  • decoded = torch.stack(best).type(torch.long)
  • # (output_batch_size, sent_max_len) ==> (batch_size*output_num_return_sequences_per_batch, sent_max_len)
  • best_score = torch.tensor(best_score).type_as(next_scores)
  • return decoded,best_score
  • 雖然解決上貪心搜索的缺陷,但是beam search解碼策略也有它的缺陷。從實際使用效果來看,beam search很容易重復的出現之前的字符,尤其是在文本生成任務上,機器翻譯上效果還行。

    ?How to generate text: using different decoding methods for language generation with Transformers中給出的例子可以看出在生成很短的一句話后,就開始重復了。為了解決這個問題,學者們提出了隨機sampling的算法

    3、隨機sampling

    隨機采樣顧名思義就是對在解碼的時候,在下一個token生成的時候,直接隨機的進行采樣。對于greedy方法的好處是,我們生成的文字開始有了一些隨機性,不會總是生成很機械的回復了。存在的問題就很明顯了——生成的話術上下文不連貫,語義上可能相互矛盾、也是容易出現一些奇怪的詞。

    4、Top-K Sampling和Top-p (nucleus) sampling

    論文The Curious Case of Neural Text Degeneration中提出一個很有意思的語言現象——

    人類的語言總是出人意料的,并不是如同beam search中選擇語言模型中概率最大的序列。就是beam search解碼策略的結果less surprising!為此論文就基于Top-K Sampling改進得到了核采樣Top-p (nucleus) sampling,下面就來聊一聊Top-K Sampling和Top-p (nucleus) sampling。

    Top-K Sampling

    這個是在隨機sampling的基礎上改進而來,既然在整個loghits概率分布上做隨機采樣會導致上下文不連貫,語義上可能相互矛盾、出現奇怪詞語等問題,那能不能選取概率最大的K個token,重新形成概率分布,然后再做多項式分布抽樣。思想很簡單,torch實現起來也不困難。實際使用效果在GPT2模型上得到了很高的提升,GPT2生成的語句非常通順流利,且重復token大幅度減少。

    ?如圖顯示的就是K=6的時候,解碼第一步6個token占據了整體tokens的三分之二,第二步則占用了99%,并且這些token都是比較合理的,同時采樣的時候也采用了多項式隨機采樣——這樣的話就會得到比較通順流利的話語,也沒有重復的詞和奇怪的詞。

    該方法的難點在于K值如何選取

    每一步解碼過程中,logits的概率分布都是不一樣的,在動態改變,固定的K值有可能造成取到的token是低概率的不合理的token;另外K取值過大又會和之前的隨機sampling一樣生成的話術上下文不連貫,語義上可能相互矛盾、也是容易出現一些奇怪的詞;K過小的話,又會導致生成的語句多樣性變差,less surprising!最好是K能動態的適應每一步解碼的logits!為此有學者提出了核采樣Top-p (nucleus) sampling

    Top-p (nucleus) sampling

    和Top-K Sampling不同的去一個固定的K值,Top-p (nucleus) sampling對整個logits從大到小累積概率,只要累積概率大于一個閾值,就把這些選取的token構成新的分布,然后采取多項式抽樣,得到解碼的next token!

    示例中累積概率閾值p = 0.92 ,第一步解碼中采樣從9個token中進行;第二步解碼從3個token中進行;這樣就可以動態的適應logtis,采取不同的K值。不過有一個點就是累積概率閾值P也是不溶于確定的,大多采用經驗值。

    當然從使用效果上來講,Top-K Sampling和Top-p (nucleus) sampling都是比較不錯的;當然實際使用過程中也是可以把Top-p (nucleus) sampling和Top-K Sampling結合起來,避免概率很小的token作為候選者,同時也保持動態性。

    top-k和top-p 過濾代碼:

  • def top_k_top_p_filtering_batch(logits, top_k=0, top_p=0.0, filter_value=-float('Inf')):
  • """ Filter a distribution of logits using top-k and/or nucleus (top-p) filtering
  • Args:
  • logits: logits distribution shape (vocabulary size)
  • top_k > 0: keep only top k tokens with highest probability (top-k filtering).
  • top_p > 0.0: keep the top tokens with cumulative probability >= top_p (nucleus filtering).
  • Nucleus filtering is described in Holtzman et al. (http://arxiv.org/abs/1904.09751)
  • From: https://gist.github.com/thomwolf/1a5a29f6962089e871b94cbd09daf317
  • """
  • top_k = min(top_k, logits.size(-1)) # Safety check
  • if top_k > 0:
  • # Remove all tokens with a probability less than the last token of the top-k
  • # torch.topk()返回最后一維最大的top_k個元素,返回值為二維(values,indices)
  • # ...表示其他維度由計算機自行推斷
  • for i in range(logits.shape[0]):
  • indices_to_remove = logits[i] < torch.topk(logits[i], top_k)[0][..., -1, None]
  • logits[i][indices_to_remove] = filter_value # 對于topk之外的其他元素的logits值設為負無窮
  • if top_p > 0.0:
  • for i in range(logits.shape[0]):
  • sorted_logits, sorted_indices = torch.sort(logits[i], descending=True) # 對logits進行遞減排序
  • cumulative_probs = torch.cumsum(F.softmax(sorted_logits, dim=-1), dim=-1)
  • # Remove tokens with cumulative probability above the threshold
  • sorted_indices_to_remove = cumulative_probs > top_p
  • # Shift the indices to the right to keep also the first token above the threshold
  • sorted_indices_to_remove[..., 1:] = sorted_indices_to_remove[..., :-1].clone()
  • sorted_indices_to_remove[..., 0] = 0
  • indices_to_remove = sorted_indices[sorted_indices_to_remove]
  • logits[i][indices_to_remove] = filter_value
  • return logits
  • 然后直接調用該過濾算法進行解碼

  • curr_input_tensor = input_ids.to(device)
  • generated = []
  • for index in range(args.max_len):
  • outputs = model(input_ids=curr_input_tensor)
  • next_token_logits = outputs[0][:,-1:]
  • # 對于已生成的結果generated中的每個token添加一個重復懲罰項,降低其生成概率
  • if index>=1:
  • for i in range(gen_finall.shape[0]):
  • gen_token_ids = gen_finall[i].clone()
  • gen_token_ids = list(set(gen_token_ids.detach().cpu().tolist()))
  • for id in gen_token_ids:
  • next_token_logits[i:i+1,:,id:id+1] /= args.repetition_penalty
  • next_token_logits = next_token_logits / args.temperature
  • # 對于[UNK]的概率設為無窮小,也就是說模型的預測結果不可能是[UNK]這個token
  • token_unk_id = tokenizer.convert_tokens_to_ids('[UNK]')
  • next_token_logits[:,:,token_unk_id:token_unk_id+1] = -float('Inf')
  • #進行top-k和top-p過濾
  • filtered_logits = top_k_top_p_filtering_batch(next_token_logits, top_k=args.topk, top_p=args.topp)
  • # torch.multinomial表示從候選集合中無放回地進行抽取num_samples個元素,權重越高,抽到的幾率越高,返回元素的下標
  • next_token = curr_input_tensor[:,-1:].clone()
  • for i in range(next_token.shape[0]):
  • next_token[i] = torch.multinomial(F.softmax(filtered_logits[i].squeeze(0), dim=-1), num_samples=1)
  • generated.append(next_token)
  • gen_finall = torch.cat(generated,dim=1)
  • # print('gen_finall',gen_finall)
  • # print('tokenizer.sep_token_id',tokenizer.sep_token_id)
  • # print((gen_finall==tokenizer.sep_token_id))
  • # print((gen_finall==tokenizer.sep_token_id).sum(1))
  • # print((gen_finall==tokenizer.sep_token_id).sum(1).bool())
  • # print((gen_finall==tokenizer.sep_token_id).sum(1).bool().all())
  • #batch內所有都解碼完成
  • if (gen_finall==tokenizer.sep_token_id).sum(1).bool().all():
  • break
  • curr_input_tensor = torch.cat((curr_input_tensor, next_token), dim=1)
  • ?三、transformer中的解碼使用

    前文聊了文本生成和翻譯的基本流程、解碼策略的一些基本原理和思想以及解碼策略的實現,當然更優雅的用法就是直接調用世界第一NLP實現庫huggingface的transformers中關于文本翻譯類或者生成類的解碼函數。generation_utils.py提供了多種解碼方式greedy search、beam search、sampling(直接隨機sampling、top-K和Top-P)、beam_sample(beam_search+top-K和Top-P)和group_beam。至于其他的一些功能,需要讀者自己去閱讀源碼。

    解碼很簡單,代碼如下,加載模型,喂入數據,解碼,得到結果。

  • from transformers import AutoTokenizer, AutoModelForSeq2SeqLM
  • import os
  • os.environ['CUDA_VISIBLE_DEVICES'] = '1'
  • from tqdm import tqdm
  • from torch.utils.data import DataLoader
  • import torch
  • from data_reader.dataReader_zh2en import DataReader
  • if __name__ == '__main__':
  • tokenizer = AutoTokenizer.from_pretrained("./pretrained_models/MarianMTModel_zh2en")
  • model = AutoModelForSeq2SeqLM.from_pretrained("./pretrained_models/MarianMTModel_zh2en")
  • dataset = DataReader(tokenizer, filepath='data/test_sample.csv')
  • test_dataloader = DataLoader(dataset=dataset,batch_size=4)
  • device = 'cuda' if torch.cuda.is_available() else 'cpu'
  • model.to(device)
  • finanl_result = []
  • for batch in tqdm(test_dataloader,desc='translation prediction'):
  • for k, v in batch.items():
  • batch[k] = v.to(device)
  • batch = {'input_ids': batch['input_ids'], 'attention_mask': batch['attention_mask']}
  • # Perform the translation and decode the output
  • translation = model.generate(**batch, top_k=5, num_return_sequences=1,num_beams=1)
  • batch_result = tokenizer.batch_decode(translation, skip_special_tokens=True)
  • finanl_result.extend(batch_result)
  • print(len(finanl_result))
  • for res in finanl_result:
  • print(res.replace('[','').replace(']',''))
  • 下文以翻譯類任務為例,采用基于transformer架構的MarianMT模型,MarianMTModel_zh2en中文到英文的模型參數。

    完整代碼如下

  • import pandas as pd
  • from datasets import load_dataset
  • from transformers import AutoTokenizer, AutoModelForSeq2SeqLM
  • import os
  • os.environ['CUDA_VISIBLE_DEVICES'] = '1'
  • from tqdm import tqdm
  • from torch.utils.data import DataLoader
  • import torch
  • from data_reader.dataReader_zh2en import DataReader
  • if __name__ == '__main__':
  • tokenizer = AutoTokenizer.from_pretrained("./pretrained_models/MarianMTModel_zh2en")
  • model = AutoModelForSeq2SeqLM.from_pretrained("./pretrained_models/MarianMTModel_zh2en")
  • dataset = DataReader(tokenizer, filepath='data/test_sample.csv')
  • test_dataloader = DataLoader(dataset=dataset,batch_size=4)
  • device = 'cuda' if torch.cuda.is_available() else 'cpu'
  • model.to(device)
  • finanl_result = []
  • for batch in tqdm(test_dataloader,desc='translation prediction'):
  • for k, v in batch.items():
  • batch[k] = v.to(device)
  • batch = {'input_ids': batch['input_ids'], 'attention_mask': batch['attention_mask']}
  • # Perform the translation and decode the output
  • #greedy
  • greedy_translation = model.generate(**batch,num_return_sequences = 1)
  • greedy_batch_result = tokenizer.batch_decode(greedy_translation, skip_special_tokens=True)
  • finanl_result.append(greedy_batch_result)
  • #beam_search
  • beam_translation = model.generate(**batch, num_return_sequences=1, num_beams=5)
  • beam_batch_result = tokenizer.batch_decode(beam_translation, skip_special_tokens=True)
  • finanl_result.append(beam_batch_result)
  • #sampling
  • sample_translation = model.generate(**batch, do_sample=True, num_return_sequences=1)
  • sample_batch_result = tokenizer.batch_decode(sample_translation, skip_special_tokens=True)
  • finanl_result.append(sample_batch_result)
  • #top-k
  • topk_translation = model.generate(**batch, top_k=5, num_return_sequences=1)
  • topk_batch_result = tokenizer.batch_decode(topk_translation, skip_special_tokens=True)
  • finanl_result.append(topk_batch_result)
  • # top-p
  • topp_translation = model.generate(**batch, top_p=0.92, num_return_sequences=1)
  • topp_batch_result = tokenizer.batch_decode(topp_translation, skip_special_tokens=True)
  • finanl_result.append(topp_batch_result)
  • # top-k和top-p
  • topktopp_translation = model.generate(**batch, top_k=5, top_p=0.92, num_return_sequences=1)
  • topktopp_batch_result = tokenizer.batch_decode(topktopp_translation, skip_special_tokens=True)
  • finanl_result.append(topktopp_batch_result)
  • # top-k和top-p+beam_search
  • beamtopktopp_translation = model.generate(**batch, top_k=5, top_p=0.92, num_return_sequences=1, num_beams=5)
  • beamtopktopp_batch_result = tokenizer.batch_decode(beamtopktopp_translation, skip_special_tokens=True)
  • finanl_result.append(beamtopktopp_batch_result)
  • decodes_policys = ['greedy search','beam_search','sampling','top-k','top-p','top-k和top-p','top-k和top-p+beam_search']
  • test_sample = ['【由富氏隱孢子蟲引起的皮膚真菌病】。','[十二指腸轉換手術中的減肥手術:體重變化和相關的營養缺乏]。','[宮腔鏡研究數字圖像的觀察者間診斷協議]。']
  • print(len(finanl_result))
  • for i in range(3):
  • print(test_sample[i])
  • for ele,de_ty in zip(finanl_result,decodes_policys):
  • print(ele[i].replace('[','').replace(']',''))
  • print('*'*100)
  • 翻譯src文本

  • 【由富氏隱孢子蟲引起的皮膚真菌病】。
  • [十二指腸轉換手術中的減肥手術:體重變化和相關的營養缺乏]
  • [宮腔鏡研究數字圖像的觀察者間診斷協議]
  • 不同解碼策略得到的結果對比

  • 【由富氏隱孢子蟲引起的皮膚真菌病】。
  • Skin fungi caused by Fung's Invisible Spores.
  • Skin fungus disease caused by Fung's Invisible Spores.
  • Skin fungi caused by Fung's spores.
  • Skin fungi caused by Fung's Invisible Spores.
  • Skin fungi caused by Fung's Invisible Spores.
  • Skin fungi caused by Fung's Invisible Spores.
  • Skin fungus disease caused by Fung's Invisible Spores.
  • ****************************************************************************************************
  • [十二指腸轉換手術中的減肥手術:體重變化和相關的營養缺乏]。
  • Twelve reference to fertility reduction in intestinal conversion operations: changes in body weight and associated nutritional deficiencies.
  • Twelve reference to fertility reduction in intestinal conversion operations: changes in body weight and associated nutritional deficiencies.
  • Liith finger intestinal conversion operations with dietary loss: weight changes and associated nutritional deficiencies.
  • Twelve reference to fertility reduction in intestinal conversion operations: changes in body weight and associated nutritional deficiencies.
  • Twelve reference to fertility reduction in intestinal conversion operations: changes in body weight and associated nutritional deficiencies.
  • Twelve reference to fertility reduction in intestinal conversion operations: changes in body weight and associated nutritional deficiencies.
  • Twelve reference to fertility reduction in intestinal conversion operations: changes in body weight and associated nutritional deficiencies.
  • ****************************************************************************************************
  • [宮腔鏡研究數字圖像的觀察者間診斷協議]。
  • Observer-to-observer protocol for the study of digital images in the court cavity mirrors.
  • Observer-to-observer protocol for the study of digital images in the court cavity mirrors.
  • Observatorial protocol for the study of digital images in the uterine cavity mirror.
  • Observer-to-observer protocol for the study of digital images in the court cavity mirrors.
  • Observer-to-observer protocol for the study of digital images in the court cavity mirrors.
  • Observer-to-observer protocol for the study of digital images in the court cavity mirrors.
  • Observer-to-observer protocol for the study of digital images in the court cavity mirrors.
  • 翻譯任務來看結果差異不是很大,不過也有一些差異。

    參考文獻

    How to generate text: using different decoding methods for language generation with Transformers

    Nucleus Sampling與文本生成中的不同解碼策略比較

    Seq2Seq解碼策略-概念

    全面了解Beam Search

    The Curious Case of Neural Text Degeneration

    總結

    以上是生活随笔為你收集整理的浅谈文本生成或者文本翻译解码策略《转》的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

    中文字幕在线看片 | 成人免费视频网站 | 2023亚洲精品国偷拍自产在线 | 国产色妞影院wwwxxx | 免费特级黄毛片 | 久久成年人网站 | 激情视频在线高清看 | 精品国产_亚洲人成在线 | 日韩av视屏在线观看 | 免费亚洲电影 | 日韩在线三级 | 色偷偷88888欧美精品久久久 | 精品a视频 | 婷婷色视频 | 日韩成人中文字幕 | 色婷婷88av视频一二三区 | 91视频下载 | 91精品视频一区 | 五月天丁香视频 | 婷婷亚洲五月色综合 | 2019av在线视频 | 7777xxxx | 色91在线| av一本久道久久波多野结衣 | 久久久亚洲电影 | 日韩一级电影在线 | 亚洲干视频在线观看 | 在线看小早川怜子av | 中国一级特黄毛片大片久久 | 亚洲2019精品 | 国产中文字幕精品 | 在线免费中文字幕 | 久操中文字幕在线观看 | 免费在线激情电影 | 波多野结衣在线视频一区 | 午夜精品久久久久久久爽 | 亚洲成a人片综合在线 | 日日爱夜夜爱 | 久久网址| 在线免费91| 日韩免费一区 | 国产精品一区二区av麻豆 | 精品日韩视频 | 欧美激情视频在线免费观看 | 97av在线视频| 国产成人精品亚洲日本在线观看 | 色婷婷狠狠五月综合天色拍 | 欧美日韩视频一区二区三区 | 狠狠色丁香久久综合网 | 天天插天天干天天操 | 国产精品99精品久久免费 | 69视频网站| 日本久久中文字幕 | 亚洲精品在线观看视频 | 久久综合中文色婷婷 | 国产精品午夜久久 | 欧美精品免费视频 | 五月导航| 中文字幕在线播放第一页 | 国产 日韩 中文字幕 | 国产精品入口a级 | 玖玖视频国产 | 91在线91拍拍在线91 | 婷婷.com| 六月丁香激情网 | 超碰公开在线 | 久久国产网站 | 久草视频在线免费看 | 中文字幕亚洲五码 | 日本久久高清视频 | 国产成人1区 | 久草精品视频 | 99在线免费视频 | 在线性视频日韩欧美 | 国产精品乱码一区二区视频 | 国产精品video爽爽爽爽 | 中文字幕综合在线 | 欧美淫视频 | 午夜精品一区二区三区免费视频 | 超碰在线公开免费 | 欧美精品久久久久a | 1024在线看片 | 奇米影视8888在线观看大全免费 | 亚洲91av| 久久香蕉影视 | 中文在线字幕免费观看 | 永久免费精品视频 | 久久免费视频精品 | 欧美 日韩 性 | 啪啪激情网 | 久草在线观 | 综合网久久 | 亚洲精品中文字幕在线观看 | 国产在线视频一区二区三区 | 国产精品国产三级国产aⅴ无密码 | 国产精品美女久久久网av | 91九色视频导航 | 天天夜夜操 | 国产精品情侣视频 | 精品久久一区二区三区 | 久久久久久久久精 | 国产精品成人久久 | 中文字幕 国产 一区 | 色综合久久久久综合体桃花网 | 美女免费电影 | 蜜臀久久99静品久久久久久 | 久久最新 | 国产在线色 | 91精品久久久久久久久久入口 | 中文字幕超清在线免费 | 色综合久久久久综合 | 久久午夜电影网 | 亚洲精品mv在线观看 | 国产女人18毛片水真多18精品 | 天天撸夜夜操 | 精品亚洲成a人在线观看 | 久久综合免费视频影院 | 成人影视免费看 | 天天干天天干天天 | 久久激情五月婷婷 | 一区二区三区在线影院 | 在线国产欧美 | av色综合 | 欧美一区二区在线 | 欧美视频18 | 黄色网www| 国产精品久久久久久久久免费看 | 人人插人人艹 | 中文字幕乱码在线播放 | 国产精品igao视频网入口 | 天堂av在线免费 | 男女激情免费网站 | 亚洲国产片 | 91亚洲网| 韩国av一区二区三区在线观看 | 国产日韩在线一区 | 日本在线成人 | 久久久免费高清视频 | 麻豆视频免费网站 | a视频在线观看 | av在线播放网址 | 在线看片视频 | 国产五月色婷婷六月丁香视频 | 麻豆视频免费播放 | 国产免费一区二区三区网站免费 | 天天干夜夜想 | 欧美最爽乱淫视频播放 | 91精品国产麻豆国产自产影视 | 免费福利影院 | 毛片视频网址 | 久久免费国产精品 | 激情偷乱人伦小说视频在线观看 | 在线观看av中文字幕 | 日韩在线一二三区 | 综合亚洲视频 | 免费看亚洲毛片 | 亚洲天堂网在线播放 | 丁香花中文字幕 | 国产一级a毛片视频爆浆 | 精品伊人久久久 | 超碰97在线资源站 | 亚洲国产三级在线观看 | 高清av网站 | 久久99国产综合精品 | 中文字幕精品视频 | 久久激情视频 久久 | 在线免费看黄网站 | 蜜臀av在线一区二区三区 | 婷婷色中文| 亚洲午夜精品一区二区三区电影院 | 国产免费又爽又刺激在线观看 | 国产一区二区在线免费播放 | 综合久久久久 | 日韩免费在线观看视频 | 天天色图| 九月婷婷人人澡人人添人人爽 | ww视频在线观看 | 久久成人在线 | 狠狠躁日日躁 | 亚洲精欧美一区二区精品 | 日韩视频一区二区 | 亚洲精品动漫久久久久 | 亚洲精品高清视频 | 亚洲永久av | 午夜.dj高清免费观看视频 | 亚洲精品久久久蜜臀下载官网 | 欧美日韩3p | 97超碰在线久草超碰在线观看 | 色五月色开心色婷婷色丁香 | 最近日本韩国中文字幕 | 超碰在线日韩 | 国产国语在线 | 麻豆国产露脸在线观看 | 国产精品手机在线 | 日韩免费在线观看视频 | 成人免费视频播放 | 激情在线免费视频 | 欧美色图一区 | 91精品国产91 | 国产一区二区三区免费在线观看 | 国产亚洲婷婷免费 | 免费高清看电视网站 | 亚洲欧美日韩精品久久奇米一区 | 中文字幕免费高清在线观看 | 久久国产精品99久久久久久丝袜 | 久久成人毛片 | 国产精品21区 | 二区视频在线 | 中文字幕精品三区 | 色婷婷国产 | 在线看不卡av | 中文字幕首页 | 97超碰精品| 在线观看你懂的网址 | 色.www| 九九热免费观看 | 91在线免费播放 | 久久激情综合网 | 亚洲精品一区二区三区四区高清 | 日韩理论影院 | 国内小视频 | 精品国偷自产国产一区 | 免费高清在线视频一区· | 国产精品99免费看 | 超碰最新网址 | 久久亚洲电影 | 国产成人精品一区二三区 | 国产va在线观看免费 | 亚洲视频 中文字幕 | 波多野结衣久久资源 | 欧美韩国在线 | av蜜桃在线 | 日本久久成人中文字幕电影 | 国产欧美精品一区aⅴ影院 99视频国产精品免费观看 | www.狠狠插.com| 国产精品 日韩精品 | 国产精品女人网站 | 91在线蜜桃臀 | 奇米网444| 一级片观看 | 亚洲国产电影在线观看 | 欧美精品第一 | 色人久久| 亚洲aⅴ乱码精品成人区 | 少妇做爰k8经典 | 精品免费视频 | 久久久久国产a免费观看rela | 黄av在线 | 日韩视频免费 | 四虎成人精品 | 99精品免费在线 | 男女全黄一级一级高潮免费看 | 亚洲欧美在线视频免费 | 97免费在线观看视频 | 欧美日韩中文在线视频 | 99久久精品国产欧美主题曲 | 中文字幕资源站 | 韩日av一区二区 | 日韩视频在线不卡 | 亚洲高清视频在线观看免费 | 97操碰| 婷婷网址 | 国产视频1区2区3区 久久夜视频 | 国产精彩在线视频 | 人人添人人澡 | 久草在线国产 | 久久69av | 国产精品免费观看网站 | 久久精品视频中文字幕 | 国产在线1区| 中文字幕成人在线 | 午夜精品久久久久久久久久久久久久 | 午夜av激情 | 国产老妇av | 国产一级在线观看 | 91麻豆精品| 在线免费观看视频你懂的 | 91视频免费视频 | 亚洲精品456在线播放第一页 | 亚洲精品影视在线观看 | 在线观看中文字幕 | 国产999在线| 欧美少妇的秘密 | 国产成人免费高清 | 国产精品区二区三区日本 | 成人永久视频 | 鲁一鲁影院 | 欧美精品久久久久久久久久 | 在线免费观看黄色 | 日韩中文字幕免费在线播放 | 1024手机基地在线观看 | 欧美a性| 最近日本字幕mv免费观看在线 | 国产视频一 | 日韩av高清在线观看 | 久久久片 | 久久久人人人 | 超碰在线日韩 | 国产精品久久久久久一区二区 | www久久99 | 麻豆传媒一区二区 | 欧美日韩在线观看一区二区三区 | 狠狠色丁香婷婷综合橹88 | 国产一区私人高清影院 | 射射射综合网 | 九九免费在线视频 | 亚洲精品在线视频 | 99久免费精品视频在线观看 | 五月天亚洲综合小说网 | 国产美女主播精品一区二区三区 | 久久99热这里只有精品国产 | 国产精品9区 | 免费国产黄线在线观看视频 | 国产99在线免费 | 最近中文字幕mv免费高清在线 | 精品黄色片 | 国产精成人品免费观看 | 最新国产精品亚洲 | 白丝av在线 | 99久精品 | 成人黄色短片 | 国产一级免费在线观看 | 亚洲国产精品电影 | 亚洲国产日韩精品 | 国产视频1区2区3区 久久夜视频 | 国产精品亚洲人在线观看 | 黄色片网站大全 | www.av小说| 日本一区二区免费在线观看 | a天堂一码二码专区 | 亚洲黄色av| 久久新| 一区免费视频 | 亚洲精品乱码久久久久久蜜桃动漫 | 欧美婷婷色| 欧美日韩精品在线视频 | 在线观看视频一区二区三区 | 久久亚洲婷婷 | 在线午夜av | 久久免费高清视频 | 波多野结衣电影一区二区 | 精品久久综合 | 97久久精品午夜一区二区 | 日本久久久亚洲精品 | 国产精品免费麻豆入口 | 久久草网站 | 毛片网在线 | 国产精品一区二区久久久 | 在线国产福利 | 免费亚洲电影 | 97精品国产 | 国产69精品久久久久9999apgf | 在线视频区| 亚洲另类交 | 中文国产字幕 | 91精品在线免费视频 | 亚洲精品在线观看网站 | 91九色精品女同系列 | 国产精品嫩草影院99网站 | 91人人视频在线观看 | 久草在线观看 | av中文字幕在线观看网站 | 国产麻豆果冻传媒在线观看 | 97在线免费 | 国产成a人亚洲精v品在线观看 | 免费成人结看片 | 在线观看黄网站 | 中文在线亚洲 | 国产精品久久久一区二区三区网站 | 久久精品欧美视频 | 欧美一区二区三区在线播放 | 欧美一级性生活视频 | 天天草天天操 | 国产色婷婷精品综合在线手机播放 | 国产资源网 | 国产一级二级在线播放 | 日本精品久久久久中文字幕 | 四虎影视精品永久在线观看 | 西西444www大胆高清视频 | 91精品啪| 国产精品va | 久久一视频 | 91精品免费看 | 成人a级免费视频 | 在线观看国产www | 久久在线看 | 久久精品96| 一本一本久久a久久精品综合 | 国产淫a | 天堂网一区二区 | 成人资源在线 | 最新av网址在线观看 | 激情五月六月婷婷 | 超碰国产在线观看 | 91传媒在线看 | 黄色三级av| 亚洲性少妇性猛交wwww乱大交 | mm1313亚洲精品国产 | 亚洲国产中文字幕在线观看 | 国产无吗一区二区三区在线欢 | 日韩无在线 | 91av中文 | 免费黄色av片 | 免费国产在线观看 | 国产一级精品视频 | 日韩视频一二三区 | 黄色1级毛片 | 久久精品一区二区三区视频 | 91精品国产乱码久久 | 国产亚洲精品日韩在线tv黄 | 91成人免费在线视频 | 亚洲视屏| 手机在线看a | 韩国精品在线观看 | 日本精品小视频 | 天天干天天操天天拍 | 精品福利视频在线观看 | 最近高清中文字幕 | 精品国产乱子伦一区二区 | 永久免费看av | 国产一区黄色 | 97成人在线视频 | 在线国产小视频 | 国产资源在线免费观看 | 一区在线观看视频 | www.狠狠色 | 中文字幕在线视频精品 | 亚洲精品中文字幕视频 | 一区二区三区电影 | 四虎5151久久欧美毛片 | 九九亚洲视频 | 91精品国产91久久久久久三级 | 国产一区二区免费在线观看 | 国产96视频 | 天天干.com | 免费在线播放av电影 | 久草a视频 | 午夜久久视频 | 99久高清在线观看视频99精品热在线观看视频 | 国产污视频在线观看 | 91中文字幕在线播放 | 午夜黄网 | a√天堂中文在线 | 亚洲年轻女教师毛茸茸 | 国产精品久久一区二区无卡 | 亚洲免费在线看 | 91久久久久久久一区二区 | 国产中文字幕91 | 国产操在线 | 黄网站色视频 | 亚洲每日更新 | 色欲综合视频天天天 | 黄网站app在线观看免费视频 | 97碰碰精品嫩模在线播放 | 中国一级特黄毛片大片久久 | 精品久久在线 | 夜夜骑首页 | 国产1区在线观看 | 国产午夜三级一区二区三 | 亚洲综合色播 | 成人黄色大片在线免费观看 | 五月黄色 | 最新av网址在线观看 | 亚洲成人家庭影院 | 国产日韩一区在线 | 日韩三级视频在线看 | 国产色道 | 国产又粗又猛又爽又黄的视频先 | 成人蜜桃视频 | 国产日韩在线一区 | 国产精品video爽爽爽爽 | 国产精品电影在线 | 国内精品久久久久影院一蜜桃 | 国产一区91 | 狠狠的日 | 国产尤物视频在线 | 精品美女久久久久久免费 | 四虎国产精品成人免费影视 | 国产一区二区电影在线观看 | 中文字幕一区在线观看视频 | 在线看一区二区 | 最新国产一区二区三区 | 国产成人精品aaa | 中文字幕在线视频国产 | 亚洲一区二区三区四区在线视频 | 在线观看视频国产一区 | 九九日九九操 | av经典在线 | 国产精品白浆视频 | 少妇搡bbbb搡bbb搡忠贞 | 97精品在线视频 | 亚洲人成人99网站 | 久久久久一区 | 香蕉视频免费在线播放 | 精品国产一区二区三区在线观看 | 国产一区成人在线 | 中文字幕影片免费在线观看 | 欧美精品视| 久草久草久草久草 | 91在线文字幕 | 日韩亚洲国产精品 | 91亚洲夫妻 | 久久免费毛片视频 | 久久久国产精品电影 | 免费在线观看av电影 | av成人黄色| 97视频免费观看2区 亚洲视屏 | 免费欧美高清视频 | 久草在线中文视频 | 欧美在线不卡一区 | 久久免费片 | 国产精品日韩在线播放 | 97免费在线视频 | 97天堂 | www狠狠| 天天夜夜亚洲 | 在线观av | 99精品视频免费观看视频 | 国产精品女同一区二区三区久久夜 | 91麻豆精品国产91久久久更新时间 | 五月天天在线 | 久草在线免 | 丁香六月天 | 色婷婷av一区二 | 久久99精品久久只有精品 | 国产欧美中文字幕 | 久草香蕉在线视频 | 色综合天天综合 | 免费看一级 | 精品久久久久久久久中文字幕 | 国内精品毛片 | 亚洲资源在线 | 国产视频在线观看一区 | 亚洲乱码在线观看 | 在线播放一区二区三区 | 亚洲色视频| 97超碰总站 | 天天综合导航 | 久久久久久久国产精品视频 | 亚洲激情综合 | 天天射天天做 | 色香天天| 美女国产在线 | 亚洲激情视频在线 | 久草99 | 久久人人爽爽 | 伊人婷婷综合 | 亚洲一区久久久 | 国产精品毛片一区视频播 | 成人黄色在线 | 欧美久久久久久久久久久久 | 99精品视频在线免费观看 | 黄色小说视频在线 | 日韩av午夜在线观看 | 去看片| 亚洲精品在线资源 | 97超碰精品 | 久久69av | 免费黄色网止 | 天天干天天上 | 成人免费大片黄在线播放 | 免费福利视频导航 | 久久精品国产美女 | 99国产精品久久久久老师 | 国产品久精国精产拍 | 免费看片成年人 | 天天操夜 | 久久天堂精品视频 | 中文字幕色在线 | 久草在线在线 | 91精品天码美女少妇 | 国产精品初高中精品久久 | 99热最新在线 | 99久久99久久精品国产片 | 特黄特黄的视频 | 日韩欧美在线国产 | 欧美日韩亚洲在线观看 | 日韩精品视频在线观看网址 | 黄色a大片 | 日本精品视频在线播放 | 激情av五月婷婷 | 在线导航av| 国产精品久久久区三区天天噜 | 国产一级片免费播放 | 91av在线免费观看 | 欧美一区二区三区在线播放 | 亚洲精品视频一二三 | 久久成年人网站 | 香蕉在线观看 | 日本免费久久高清视频 | 亚洲深夜影院 | 国产精品12| 天天综合网久久综合网 | 在线观看精品黄av片免费 | 国产精品不卡av | 精品主播网红福利资源观看 | 一二区电影 | 在线观看视频你懂 | 久久精品高清 | 97在线看 | 91久久丝袜国产露脸动漫 | 一区二区 不卡 | 久久视频在线视频 | 欧美日韩一区二区在线观看 | 久久国产视频网 | 最新午夜 | 91精品视频在线播放 | 国内揄拍国内精品 | 波多野结衣在线观看一区二区三区 | 精品一区二区免费在线观看 | 国产欧美精品一区aⅴ影院 99视频国产精品免费观看 | 亚洲精品乱码久久久久久按摩 | 久久情网 | 一级成人免费 | 人人dvd | 亚洲天堂网视频 | 中文av在线播放 | 日韩中文字幕免费在线观看 | 超碰av免费| 国产色综合| 91麻豆文化传媒在线观看 | 免费av在线播放 | 黄色精品免费 | 亚洲激情 在线 | 国产精品永久在线观看 | 91亚洲在线观看 | 国产精品美乳一区二区免费 | 97在线看| 国产精品高潮呻吟久久av无 | 高清国产午夜精品久久久久久 | 中文字幕制服丝袜av久久 | 伊人婷婷 | 看国产黄色片 | 日本久久99 | 国产99久久99热这里精品5 | 亚洲欧洲国产日韩精品 | 国产欧美精品一区aⅴ影院 99视频国产精品免费观看 | 永久免费毛片在线观看 | 丁香婷婷综合激情五月色 | 国产一区二区在线观看免费 | 久久国内免费视频 | 国产一区在线免费 | 久久久精品国产一区二区电影四季 | 91成人免费视频 | 性色av一区二区 | 国产精品一区二区免费 | 精品国产99| 久草在线最新视频 | 亚洲老妇xxxxxx | 色综合久久久久网 | 91一区二区三区久久久久国产乱 | 色精品视频 | 亚洲精品一区二区久 | av电影一区二区三区 | 国产伦精品一区二区三区四区视频 | 欧美精品一区二区性色 | 狠狠干狠狠艹 | 96精品视频 | 国产一级一级国产 | 97精品久久 | 国产精品黑丝在线观看 | 久久久国产99久久国产一 | 国产高清视频色在线www | 丁香九月激情综合 | 九九热免费精品视频 | 国产黄色免费在线观看 | 亚洲精品在线二区 | 国产无套精品久久久久久 | 日日干av | 国产91对白在线播 | 国产中文伊人 | 色噜噜日韩精品一区二区三区视频 | 久久精品99国产精品酒店日本 | 看av免费| 麻豆一区二区三区视频 | 天天色宗合| 久久精品人人做人人综合老师 | 91在线播放综合 | 中文字幕 第二区 | 国产女做a爱免费视频 | 欧美a级一区二区 | 人人干干人人 | 亚洲开心色 | 国产123区在线观看 国产精品麻豆91 | 人成在线免费视频 | 国产精品区二区三区日本 | 国产精品久久电影网 | 国产亚洲欧美精品久久久久久 | 五月综合网站 | 色综合久久久久综合体 | 黄色在线观看免费网站 | 国产成人福利在线 | 天堂黄色片 | 国产香蕉视频在线观看 | 日日夜夜91 | 久久视频国产精品免费视频在线 | 午夜视频在线观看一区二区 | 国产高清视频在线播放一区 | 欧美在线视频一区二区三区 | 91精品国自产在线观看欧美 | 国产精品久免费的黄网站 | 亚洲午夜av电影 | 精品视频网站 | 国产在线高清 | 精品视频成人 | 日韩区欠美精品av视频 | 亚洲精品91天天久久人人 | 久久不射电影院 | 精品在线一区二区三区 | 久久 在线 | 久久国精品 | 精品久久久久久综合 | 国产成人久久av977小说 | 五月婷婷黄色 | 欧美一级性 | av免费高清观看 | 国内精品99| 亚洲天堂自拍视频 | 成人羞羞视频在线观看免费 | 日韩av中文| 麻豆国产精品va在线观看不卡 | 日韩免费av网址 | 亚洲精品在线免费播放 | 中文字幕成人网 | 欧美最新大片在线看 | 色在线网站 | 国产成人精品亚洲 | 丁香激情五月婷婷 | 亚洲精品视频在线免费播放 | 久久久91精品国产一区二区精品 | 黄色国产大片 | 天天操网 | 欧美日韩国产精品一区二区三区 | 国产成人精品午夜在线播放 | 伊人久久电影网 | 九九免费在线视频 | 成人午夜av电影 | 激情久久影院 | 一级欧美黄 | 天天射天天干天天操 | 精品国产_亚洲人成在线 | 国产日韩欧美在线看 | 丁香婷婷综合色啪 | 97在线公开视频 | 久久综合欧美精品亚洲一区 | 国产手机在线精品 | 国产精品一区在线观看你懂的 | 蜜臀av性久久久久av蜜臀妖精 | 成人久久18免费网站 | 99久久国产免费看 | 欧美久久99 | 精品免费在线视频 | 色婷婷激情 | 天天干天天在线 | 91九色在线| 一级全黄毛片 | 一区二区三区日韩在线 | 中文字幕一区二区三区久久 | 国产亚洲精品久久久久久网站 | 黄色一级性片 | 久久免费视频观看 | 免费亚洲电影 | 精品久久久久久久久久久院品网 | 91九色精品国产 | 婷婷久操| 婷婷在线播放 | 国产精品久久久区三区天天噜 | 精品亚洲欧美无人区乱码 | 日本中文字幕电影在线免费观看 | 五月综合色婷婷 | 91色蜜桃 | 激情久久久久 | 午夜精品福利一区二区 | 99产精品成人啪免费网站 | 国产毛片久久久 | 亚洲精品欧美精品 | 中文字幕五区 | 久久久免费播放 | 国产剧情久久 | 精品国产一区二区三区久久久蜜臀 | 色在线高清| 国产三级午夜理伦三级 | 国产精品久久久久国产精品日日 | www.久久色.com| 免费日韩一区 | 久久综合九色99 | 国产精品一区免费看8c0m | 久热色超碰 | 日日草视频 | 天天干夜夜夜 | 亚洲国产精品女人久久久 | 精品国产电影一区二区 | 国产精品综合在线观看 | 亚洲欧美成人在线 | 中文字幕免费在线看 | 香蕉视频4aa | 免费观看一级特黄欧美大片 | 国产在线观看地址 | 国产二区免费视频 | 亚洲资源在线 | 91一区二区在线 | 日韩av一区二区在线 | 在线观看91视频 | 日韩和的一区二在线 | 日韩精选在线观看 | 天天色天天操天天爽 | 色射色 | 成人av免费播放 | 狠狠色丁香婷婷综合久久片 | 欧美巨大 | 久精品视频在线 | 亚洲欧洲精品在线 | 91麻豆精品国产91久久久更新时间 | 免费视频91 | 最新免费av在线 | 91传媒在线观看 | 久草在线在线精品观看 | 一区二区不卡视频在线观看 | 久久不射电影院 | 天天操天天操天天操天天 | 四虎精品成人免费网站 | 99精品久久精品一区二区 | 久久久久久高潮国产精品视 | 婷婷色在线观看 | 免费看污在线观看 | 中文字幕三区 | 中文理论片 | 日韩色一区二区三区 | 成年人黄色免费看 | 一区二区三区久久精品 | 中文字幕免费在线看 | 色天天天| 日韩在线视频免费看 | 国产又粗又猛又爽又黄的视频先 | 狠狠色丁香 | 免费看在线看www777 | 国产激情小视频在线观看 | 一级黄网 | 国产a视频免费观看 | 日韩精品视频在线观看网址 | 国产精品一区二区在线免费观看 | 97精品久久 | 狠狠狠干狠狠 | 国产手机在线观看 | 亚洲精品美女在线观看 | 国产1区2| 久久99国产精品自在自在app | 婷婷色网址 | 亚洲欧美日韩国产精品一区午夜 | 久久夜色网 | 网站免费黄 | 婷婷在线资源 | 四虎国产永久在线精品 | 婷婷在线网站 | 人人精久| 免费在线观看成人av | 成人av在线网 | 免费av视屏 | 国产伦理一区二区三区 | 亚洲午夜在线视频 | 九九久久国产 | freejavvideo日本免费 | 超碰最新网址 | 韩国三级在线一区 | 日韩av进入| 欧美性生活久久 | 狠狠躁日日躁夜夜躁av | 日韩在线观看网址 | 韩国精品一区二区三区六区色诱 | 国产精品国产三级国产aⅴ入口 | 99热九九这里只有精品10 | 国产视频在线播放 | 国内99视频 | 久久99精品国产一区二区三区 | 国产免费三级在线观看 | 国产精品专区一 | 中文在线字幕免费观看 | 国产原创在线观看 | 日韩另类在线 | 91精品啪在线观看国产81旧版 | 久久无码av一区二区三区电影网 | 精品国内 | 久久免费电影网 | 欧美99久久| 在线播放一区二区三区 | 在线av资源 | 亚洲欧美日韩在线一区二区 | 久久精品视频中文字幕 | 欧美极度另类 | 国产精品视频在线看 | 日日弄天天弄美女bbbb | 国产中文伊人 | av爱干| 激情五月婷婷网 | 免费能看的黄色片 | 伊人伊成久久人综合网小说 | av先锋中文字幕 | 国产精品99久久久久的智能播放 | 成年人黄色在线观看 | 美女视频黄在线 | 99久久久久国产精品免费 | 国产精品色婷婷视频 | 免费观看第二部31集 | 久久99国产综合精品免费 | 久久狠狠一本精品综合网 | 高潮毛片无遮挡高清免费 | 中文字幕在线看片 | 一二三区高清 | av电影免费在线看 | 日本中文字幕在线播放 | 国产精品入口66mio女同 | 国产一区视频免费在线观看 | av日韩国产| 国产18精品乱码免费看 | 国产精品99视频 | 五月天久久 | 在线播放 日韩专区 | 国产成人一区二区三区影院在线 | 国产精品午夜免费福利视频 | 国产一区精品在线观看 | www.天天成人国产电影 | 亚洲欧美视屏 | 久久精选视频 | 国产精品 中文字幕 亚洲 欧美 | 日本成人黄色片 | 日韩中午字幕 | 亚洲 欧美 另类人妖 | 96精品在线 | 99热在线网站 | 九九久久视频 | 国产黄免费在线观看 | 岛国av在线不卡 | 特级黄录像视频 | 欧美精品首页 | 不卡视频在线看 | 久久av影院| 国产探花视频在线播放 | 久久精品国产精品亚洲精品 | 成年人国产精品 | 国产精品普通话 | 91在线蜜桃臀 | 午夜精品影院 | 1区2区视频| 免费观看一级 | 久久三级毛片 | 蜜臀av性久久久久蜜臀av | 麻豆果冻剧传媒在线播放 | 伊人亚洲综合网 | 麻豆视频国产在线观看 | 免费在线观看视频一区 | 激情网站五月天 | 日本特黄特色aaa大片免费 | 中文字幕av有码 | 在线国产片 | 国产精品99久久免费黑人 | 久久精品日韩 | 伊人久久国产 | 免费黄色网址大全 | 精品日韩视频 | 免费大片av | 精品免费观看视频 | 亚洲六月丁香色婷婷综合久久 | 国产一区在线精品 | 国产.精品.日韩.另类.中文.在线.播放 | 欧美日韩国产一区二区在线观看 | 日韩最新理论电影 | 啪啪资源 | 欧美精品在线一区 | 日韩在线免费不卡 | 欧美极品少妇xbxb性爽爽视频 | 中文字幕乱偷在线 | 色偷偷中文字幕 | 五月天天色| 99精品视频观看 | av高清不卡 | 免费在线观看黄网站 | 中文字幕a∨在线乱码免费看 | 欧美久久久久久久久中文字幕 | 日韩精品网址 | 亚洲精品小区久久久久久 | av一级在线| 亚洲午夜精品久久久 | 最近日本中文字幕a | 国产视频精品久久 | 天天操狠狠操夜夜操 | 狠狠色丁香久久综合网 | 五月天久久久久久 | 日本精品一区二区三区在线观看 | 久草网视频 | 99精品在线视频播放 | 亚洲精品大全 | 欧美一级片免费 | 成人小视频在线观看免费 | 国产精品美乳一区二区免费 | 免费中文字幕在线观看 | 亚洲草视频 | 在线只有精品 | 亚洲片在线 |