成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

面向深度學習的文本預處理方法

譯文
人工智能 深度學習
如今,深度學習引起了人們極大的興趣,尤其是自然語言處理(NLP)。不久前,Kaggle公司開展一場自然語言處理(NLP)競賽,其名稱為“Quora不真誠問題挑戰(Quora Question insincerity Challenge)”。

[[432936]]

【51CTO.com快譯】如今,深度學習引起了人們極大的興趣,尤其是自然語言處理(NLP)。不久前,Kaggle公司開展一場自然語言處理(NLP)競賽,其名稱為“Quora不真誠問題挑戰(Quora Question insincerity Challenge)”。這個競賽指出解決文本分類問題,其目的是通過競賽以及Kaggle專家提供的寶貴內核,使其變得更容易理解。

首先從解釋競賽中的文本分類問題開始。

文本分類是自然語言處理中的一項常見任務,它將不確定長度的文本序列轉換為文本類別。那么文本分類有什么作用?可以:

  • 了解評論時的情緒
  • 在Facebook等平臺上查找有害評論
  • 在Quora上查找不真誠的問題,而目前Kaggle公司正在進行的一項競賽
  • 在網站上查找虛假評論
  • 確定文本廣告是否會被點擊

現在,這些問題都有一些共同點。而從機器學習的角度來看,這些問題本質上是相同的,只是目標標簽發生了變化,并沒有其他的變化。話雖如此,業務知識的添加可以幫助使這些模型更加健壯,這就是在預處理數據以進行測試分類時想要包含的內容。

雖然本文關注的預處理管道主要圍繞深度學習,但其中大部分也適用于傳統的機器學習模型。

首先,在完成所有步驟之前,先了解一下文本數據深度學習管道的流程,以便更進一步了解整個過程。

通常從清理文本數據和執行基本 事件驅動架構(EDA)開始。在這里,嘗試通過清理數據來提高數據質量。還嘗試通過刪除詞匯表外(OOV)的單詞來提高Word2Vec嵌入的質量。前兩個步驟之間通常沒有什么順序,并且通常在這兩個步驟之間來回切換。

接下來,為可以輸入深度學習模型的文本創建一個表示。然后開始創建模型并訓練它們。最后,在此使用適當的指標評估模型,并獲得領導者的批準以部署模型。如果這些術語現在沒有多大意義,那么不要擔心,可以嘗試通過本文闡述的過程來解釋它們。

在這里,先談談單詞嵌入。在為深度學習模型預處理數據時,就必須考慮一下。

Word2Vec嵌入入門

現在需要有一種方法來表示詞匯中的單詞。一種方法是使用one-hot編碼的單詞向量,但這并不是一個很好的選擇。其一個主要原因是one-hot單詞向量無法準確表達不同單詞之間的相似度,例如余弦相似度。

鑒于one-hot編碼向量的結構,不同單詞之間的相似度總是為0。另一個原因是,隨著詞匯量的增加,這些one-hot編碼向量變得非常大。

Word2Vec通過提供單詞的固定長度向量表示以及捕獲不同單詞之間的相似性和類比關系,克服了上述困難。

Word2vec單詞向量的學習方式允許學習不同的類比。它使人們能夠對以前不可能的單詞進行代數運算。例如:什么是國王——男人+女人?出來是女王。

Word2Vec向量也幫助找出單詞之間的相似性。如果試圖找到與“good”相似的詞,會發現awesome、great等。正是word2vec的這一特性使其對于文本分類非常寶貴。現在的深度學習網絡可以明白“good”和“great”本質上是含義相似的詞。

因此,簡單來說,word2vec為單詞創建向量。因此,對字典中的每個單詞都有一個d維向量。通常使用其他人在維基百科、推特等大型文本語料庫上訓練后提供的預訓練詞向量。最常用的預訓練詞向量是具有300維詞向量的Glove和Fasttext。而在這篇文章中將使用Glove。

文本數據的基本預處理技術

在大多數情況下,觀察到的文本數據并不完全干凈。來自不同來源的數據具有不同的特征,這使得文本預處理成為分類管道中最重要的步驟之一。

例如,來自Twitter的文本數據與Quora或某些新聞/博客平臺上的文本數據完全不同,因此需要區別對待。有用的是,將在本文中討論的技術對于在自然語言處理(NLP)中可能遇到的任何類型的數據都足夠通用。

(1)清除特殊字符和刪除標點符號

預處理管道很大程度上取決于將用于分類任務的word2vec嵌入。原則上,預處理應該與訓練詞嵌入之前使用的預處理相匹配。由于大多數嵌入不提供標點符號和其他特殊字符的向量值,因此要做的第一件事就是去除文本數據中的特殊字符。這些是Quora不真誠問題數據中存在的一些特殊字符,使用替換功能來擺脫這些特殊字符。

#將看到的所有文本分類方法都會用到的一些預處理。

Python

  1. 1 puncts = [',''.''"'':'')''(''-''!''?''|'';', "'", '$', '&', '/', '[', ']', '>', '%', '=', '#', '*', '+', '\\', '',  '~', '@', '£',  '·', '_', '{', '}', '©', '^', '®', '`',  '<', '', '°', '', '', '',  '', '', '×', '§', '', '', ' ', '', '½', 'à', '',  '', '', '', '', '', 'â', '', '', '¢', '²', '¬', '', '', '', '±', '¿', '', '', '¦', '', '', '¥', '', '', '', '',  '', '', '¼', '', '', '', '', '', '', '', '¨', '', '', '', 'é', '¯', '', '¤', '', 'è', '¸', '¾', 'Ã', '', '', '',  '', '', '', '', '', '', '»', '', '', '', '', '³', '', '', '', '', '', '', '', 'ï', 'Ø', '¹', '', '', '√', 

Python

  1. 1def clean_text(x):    x = str(x)    for punct in puncts:        if punct in x:            x = x.replace(punct, '')    return  

這也可以在一個簡單的正則表達式的幫助下完成。但是人們通常喜歡上述做事方式,因為它有助于理解從數據中刪除的字符類型。

Python

  1. 1def clean_numbers(x):    if bool(re.search(r'\d', x)):        x = re.sub('[0-9]{5,}''#####', x)        x = re.sub('[0-9]{4}''####', x)        x = re.sub('[0-9]{3}''###', x)        x = re.sub('[0-9]{2}''##', x)    return x 

(2)清除數字

為什么要用#s替換數字?因為大多數嵌入都像這樣預處理了它們的文本。

Python小技巧:在下面的代碼中使用if語句來預先檢查文本中是否存在數字。就像if總是比re.sub命令快,而且大部分文本都不包含數字。

Python

  1. 1 def clean_numbers(x):    if bool(re.search(r'\d', x)):    x = re.sub('[0-9]{5,}''#####', x)         

(3)刪除拼寫錯誤

找出數據中的拼寫錯誤總是有幫助的。由于word2vec中不存在這些詞的嵌入,應該用正確的拼寫替換單詞以獲得更好的嵌入覆蓋率。

以下代碼工件是對Peter Norvig的拼寫檢查器的改編。它使用單詞的word2vec排序來近似單詞概率,因為谷歌word2vec顯然在訓練語料庫中按照頻率降序排列單詞。可以使用它來找出擁有的數據中的一些拼寫錯誤的單詞。

以下是來自Quora問題相似性挑戰中的CPMP腳本。

Python

  1. 1 import re from collections import Counter import gensim import heapq from operator import itemgetter from multiprocessing import Pool  
  2. 2model = gensim.models.KeyedVectors.load_word2vec_format('../input/embeddings/GoogleNews-vectors-negative300/GoogleNews-vectors-negative300.bin',                                                         binary=True) words = model.index2word  
  3. 3 w_rank = {} for i,word in enumerate(words):    w_rank[word] = i  
  4. 4 WORDS = w_rank  
  5. 5 def words(text): return re.findall(r'\w+', text.lower())  
  6. 6 def P(word):     "Probability of `word`."    # use inverse of rank as proxy    # returns 0 if the word isn't in the dictionary    return - WORDS.get(word, 0)  
  7. 7 def correction(word):     "Most probable spelling correction for word."    return max(candidates(word), key=P)  
  8. 8 def candidates(word):     "Generate possible spelling corrections for word."    return (known([word]) or known(edits1(word)) or known(edits2(word)) or [word])  
  9. 9 def known(words):     "The subset of `words` that appear in the dictionary of WORDS."    return set(w for w in words if w in WORDS)  
  10. 10 def edits1(word):    "All edits that are one edit away from `word`."    letters    = 'abcdefghijklmnopqrstuvwxyz'    splits     = [(word[:i], word[i:])    for i in range(len(word) + 1)]    deletes    = [L + R[1:]               for L, R in splits if R]    transposes = [L + R[1] + R[0] + R[2:] for L, R in splits if len(R)>1]    replaces   = [L + c + R[1:]           for L, R in splits if R for c in letters]    inserts    = [L + c + R               for L, R in splits for c in letters]    return set(deletes + transposes + replaces + inserts)  
  11. 11 def edits2(word):     "All edits that are two edits away from `word`."    return (e2 for e1 in edits1(word) for e2 in edits1(e1))  
  12. 12 def build_vocab(texts):    sentences = texts.apply(lambda x: x.split()).values    vocab = {}    for sentence in sentences:        for word in sentence:            try:                vocab[word] += 1            except KeyError:                vocab[word] = 1    return vocab  
  13. 13 vocab = build_vocab(train.question_text)  
  14. 14 top_90k_words = dict(heapq.nlargest(90000, vocab.items(), key=itemgetter(1)))  
  15. 15 pool = Pool(4) corrected_words = pool.map(correction,list(top_90k_words.keys()))  
  16. 16 for word,corrected_word in zip(top_90k_words,corrected_words):    if word!=corrected_word:        print 

一旦完成了查找拼寫錯誤的數據,接下來要做的就是使用拼寫錯誤映射和正則表達式函數來替換它們。

Python

  1. 1 mispell_dict = {'colour''color''centre''center''favourite''favorite''travelling''traveling''counselling''counseling''theatre''theater''cancelled''canceled''labour''labor''organisation''organization''wwii''world war 2''citicise''criticize''youtu ''youtube ''Qoura''Quora''sallary''salary''Whta''What''narcisist''narcissist''howdo''how do''whatare''what are''howcan''how can''howmuch''how much''howmany''how many''whydo''why do''doI''do I''theBest''the best''howdoes''how does''mastrubation''masturbation''mastrubate''masturbate'"mastrubating"'masturbating''pennis''penis''Etherium''Ethereum''narcissit''narcissist''bigdata''big data''2k17''2017''2k18''2018''qouta''quota''exboyfriend''ex boyfriend''airhostess''air hostess'"whst"'what''watsapp''whatsapp''demonitisation''demonetization''demonitization''demonetization''demonetisation''demonetization' 

Python

  1. 1def _get_mispell(mispell_dict):    mispell_re = re.compile('(%s)' % '|'.join(mispell_dict.keys()))    return mispell_dict, mispell_re  
  2. 2 mispellings, mispellings_re = _get_mispell(mispell_dict) def replace_typical_misspell(text):    def replace(match):       return mispellings[match.group(0)]    return mispellings_re.sub(replace, text)  
  3. 3 # Usage replace_typical_misspell("Whta is demonitisation")  

(4)消除縮略語

縮略語是采用撇號書寫的單詞。縮略語的例子是“ain’t”或“aren’t”。因為想標準化文本,所以擴展這些縮略語是有意義的。下面使用壓縮映射和正則表達式函數完成這項工作。

Python

  1. 1 contraction_dict = {"ain't""is not""aren't""are not","can't""cannot""'cause""because""could've""could have""couldn't""could not""didn't""did not",  "doesn't""does not""don't""do not""hadn't""had not""hasn't""has not""haven't""have not""he'd""he would","he'll""he will""he's""he is""how'd""how did""how'd'y""how do you""how'll""how will""how's""how is",  "I'd""I would""I'd've""I would have""I'll""I will""I'll've""I will have","I'm""I am""I've""I have""i'd""i would""i'd've""i would have""i'll""i will",  "i'll've""i will have","i'm""i am""i've""i have""isn't""is not""it'd""it would""it'd've""it would have""it'll""it will""it'll've""it will have","it's""it is""let's""let us""ma'am""madam""mayn't""may not""might've""might have","mightn't""might not","mightn't've""might not have""must've""must have""mustn't""must not""mustn't've""must not have""needn't""need not""needn't've""need not have","o'clock""of the clock""oughtn't""ought not""oughtn't've""ought not have""shan't""shall not""sha'n't""shall not""shan't've""shall not have""she'd""she would""she'd've""she would have""she'll""she will""she'll've""she will have""she's""she is""should've""should have""shouldn't""should not""shouldn't've""should not have""so've""so have","so's""so as""this's""this is","that'd""that would""that'd've""that would have""that's""that is""there'd""there would""there'd've""there would have""there's""there is""here's""here is","they'd""they would""they'd've""they would have""they'll""they will""they'll've""they will have""they're""they are""they've""they have""to've""to have""wasn't""was not""we'd""we would""we'd've""we would have""we'll""we will""we'll've""we will have""we're""we are""we've""we have""weren't""were not""what'll""what will""what'll've""what will have""what're""what are",  "what's""what is""what've""what have""when's""when is""when've""when have""where'd""where did""where's""where is""where've""where have""who'll""who will""who'll've""who will have""who's""who is""who've""who have""why's""why is""why've""why have""will've""will have""won't""will not""won't've""will not have""would've""would have""wouldn't""would not""wouldn't've""would not have""y'all""you all""y'all'd""you all would","y'all'd've""you all would have","y'all're""you all are","y'all've""you all have","you'd""you would""you'd've""you would have""you'll""you will""you'll've""you will have""you're""you are""you've""you have"

Python

  1. 1 def _get_contractions(contraction_dict):    contraction_re = re.compile('(%s)' % '|'.join(contraction_dict.keys()))    return contraction_dict, contraction_re  
  2. 2 contractions, contractions_re = _get_contractions(contraction_dict)  
  3. 3 def replace_contractions(text):    def replace(match):        return contractions[match.group(0)]    return contractions_re.sub(replace, text)  
  4. 4 # Usage replace_contractions("this's a text with contraction"

除了上述技術外,還有其他文本預處理技術,如詞干提取、詞形還原和停用詞去除。由于這些技術不與深度學習NLP模型一起使用,在這里不會討論它們。

表示:序列創建

使深度學習成為自然語言處理(NLP)的“go-to”選擇的原因之一是,實際上不必從文本數據中人工設計特征。深度學習算法將一系列文本作為輸入,像人類一樣學習文本結構。由于機器不能理解單詞,因此它們期望以數字形式提供數據。所以想將文本數據表示為一系列數字。

要了解這是如何完成的,需要對Keras Tokenizer功能有所了解。可以使用任何其他分詞器,但Keras分詞器是一種流行的選擇。

(1)標記器

簡單來說,標記器(tokenizer)是一個將句子拆分成單詞的實用函數。keras.preprocessing.text.Tokenizer將文本標記(拆分)為標記(單詞),同時僅保留文本語料庫中出現次數最多的單詞。

Python

  1. 1#Signature: Tokenizer(num_words=None, filters='!"#$%&()*+,-./:;<=>?@[\\]^_`{|}~\t\n'lower=True, split=' ', char_level=False, oov_token=None, document_count=0, **kwargs) 

num_words參數僅在文本中保留預先指定的單詞數。這很有幫助,因為不希望這個模型通過考慮很少出現的單詞而產生大量噪音。在現實世界的數據中,使用num_words參數留下的大多數單詞通常是拼寫錯誤的。在默認情況下,標記器還會過濾一些不需要的標記并將文本轉換為小寫。

一旦適合數據的標記器還會保留一個單詞索引(可以用來為單詞分配唯一編號的單詞字典),可以通過以下方式訪問它:

  1. tokenizer.word_index 

索引字典中的單詞按頻率排序。

所以使用標記器的整個代碼如下:

Python

  1. from keras.preprocessing.text import Tokenizer ## Tokenize the sentences tokenizer = Tokenizer(num_words=max_features) tokenizer.fit_on_texts(list(train_X)+list(test_X)) train_X = tokenizer.texts_to_sequences(train_X) test_X = tokenizer.texts_to_sequences(test_X) 

其中train_X和test_X是語料庫中的文檔列表。

(2)序列預處理

通常模型期望每個序列(每個訓練示例)具有相同的長度(相同數量的單詞/標記)。可以使用maxlen參數來控制它。

例如:

Python

  1. train_X = pad_sequences(train_X, maxlen=maxlen) test_X = pad_sequences(test_X, maxlen=maxlen) 

現在訓練數據包含一個數字列表。每個列表具有相同的長度。還有word_index,它是文本語料庫中出現次數最多的單詞的字典。

(3)嵌入富集

如上所述,將使用GLoVE Word2Vec嵌入來解釋富集。GLoVE預訓練向量在維基百科語料庫上進行訓練。

這意味著數據中可能出現的某些詞可能不會出現在嵌入中。那么怎么處理呢?先加載Glove Embeddings。

Python

  1. 1 def load_glove_index():    EMBEDDING_FILE = '../input/embeddings/glove.840B.300d/glove.840B.300d.txt'    def get_coefs(word,*arr): return word, np.asarray(arr, dtype='float32')[:300]    embeddings_index = dict(get_coefs(*o.split(" ")) for o in open(EMBEDDING_FILE))    return embeddings_index  
  2. 2 glove_embedding_index = load_glove_index() 

確保將下載這些GLoVE向量的文件夾的路徑。

這個glove_embedding_index包含什么?它只是一個字典,其中鍵是詞,值是詞向量,而一個長度為300的np.array,其字典的長度大約是10億。由于只需要word_index中單詞的嵌入,將創建一個只包含所需嵌入的矩陣。

Python

  1. 1 def create_glove(word_index,embeddings_index):    emb_mean,emb_std = -0.005838499,0.48782197    all_embs = np.stack(embeddings_index.values())    embed_size = all_embs.shape[1]    nb_words = min(max_features, len(word_index))    embedding_matrix = np.random.normal(emb_mean, emb_std, (nb_words, embed_size))    count_found = nb_words    for word, i in tqdm(word_index.items()):       if i >= max_features: continue       embedding_vector = embeddings_index.get(word)       if embedding_vector is not None:             embedding_matrix[i] =  embedding_vector       else:                count_found-=1    print("Got embedding for ",count_found," words.")    return embedding_matrix 

上面的代碼工作正常,但有沒有一種方法可以讓利用GLoVE中的預處理來發揮優勢?

是的。在為glove進行預處理時,創作者沒有將單詞轉換為小寫。這意味著它包含“USA”、“usa”和“Usa”等單詞的多種變體。這也意味著在某些情況下,雖然存在像“Word”這樣的單詞,但不存在小寫形式的類似物,即“word”。

在這里可以通過使用下面的代碼來解決這種情況。

Python

  1. 1 def create_glove(word_index,embeddings_index):    emb_mean,emb_std = -0.005838499,0.48782197    all_embs = np.stack(embeddings_index.values())    embed_size = all_embs.shape[1]    nb_words = min(max_features, len(word_index))    embedding_matrix = np.random.normal(emb_mean, emb_std, (nb_words, embed_size))     count_found = nb_words    for word, i in tqdm(word_index.items()):        if i >= max_features: continue        embedding_vector = embeddings_index.get(word)        if embedding_vector is not None:             embedding_matrix[i] =  embedding_vector        else:            if word.islower():                # try to get the embedding of word in titlecase if lowercase is not present                embedding_vector = embeddings_index.get(word.capitalize())                if embedding_vector is not None:                     embedding_matrix[i] = embedding_vector                else:                    count_found-=1            else:                count_found-=1    print("Got embedding for ",count_found," words.")    return embedding_matrix 

上面只是一個例子,說明如何利用嵌入知識來獲得更好的覆蓋率。有時,根據問題的不同,人們還可以通過使用一些領域知識和自然語言處理(NLP)技能向嵌入中添加額外信息來獲得價值。

例如,可以通過在Python中的TextBlob包中添加單詞的極性和主觀性,向嵌入本身添加外部知識。

Python

  1. from textblob import TextBlob word_sent = TextBlob("good").sentiment print(word_sent.polarity,word_sent.subjectivity) # 0.7 0.6 

可以使用TextBlob獲取任何單詞的極性和主觀性。因此,可以嘗試將這些額外信息添加到嵌入中。

Python

  1. 1 def create_glove(word_index,embeddings_index):    emb_mean,emb_std = -0.005838499,0.48782197    all_embs = np.stack(embeddings_index.values())    embed_size = all_embs.shape[1]    nb_words = min(max_features, len(word_index))    embedding_matrix = np.random.normal(emb_mean, emb_std, (nb_words, embed_size+4))        count_found = nb_words    for word, i in tqdm(word_index.items()):        if i >= max_features: continue        embedding_vector = embeddings_index.get(word)        word_sent = TextBlob(word).sentiment        # Extra information we are passing to our embeddings        extra_embed = [word_sent.polarity,word_sent.subjectivity]        if embedding_vector is not None:             embedding_matrix[i] =  np.append(embedding_vector,extra_embed)        else:            if word.islower():                embedding_vector = embeddings_index.get(word.capitalize())                if embedding_vector is not None:                     embedding_matrix[i] = np.append(embedding_vector,extra_embed)                else:                    embedding_matrix[i,300:] = extra_embed                    count_found-=1            else:                embedding_matrix[i,300:] = extra_embed                count_found-=1    print("Got embedding for ",count_found," words.")    return embedding_matrix 

工程嵌入是在后期從深度學習模型中獲得更好性能的重要組成部分。通常,會在項目階段多次重新訪問這部分代碼,同時嘗試進一步改進的模型。在這里可以展示很多創造力,以提高對word_index的覆蓋率,并在嵌入中包含額外的功能。

更多工程特性

嵌入矩陣的文本預處理方法

人們總是可以添加句子特定的特征,如句子長度、唯一詞的數量等,作為另一個輸入層,為深度神經網絡提供額外的信息。

例如,創建了這些額外的特征,作為Quora Insincerity分類挑戰的特征工程管道的一部分。

Python

  1. 1 def add_features(df):    df['question_text'] = df['question_text'].progress_apply(lambda x:str(x))    df["lower_question_text"] = df["question_text"].apply(lambda x: x.lower())    df['total_length'] = df['question_text'].progress_apply(len)    df['capitals'] = df['question_text'].progress_apply(lambda comment: sum(1 for c in comment if c.isupper()))    df['caps_vs_length'] = df.progress_apply(lambda row: float(row['capitals'])/float(row['total_length']),                                axis=1)    df['num_words'] = df.question_text.str.count('\S+')    df['num_unique_words'] = df['question_text'].progress_apply(lambda comment: len(set(w for w in comment.split())))    df['words_vs_unique'] = df['num_unique_words'] / df['num_words']     return df 

結論

自然語言處理(NLP)在深度學習領域仍然是一個非常有趣的問題,因此希望更多的人進行大量的實驗,看看哪些有效,哪些無效。而試圖為任何自然語言處理(NLP)問題的深度學習神經網絡的預處理步驟可以提供有益的視角。

原文標題:Text Preprocessing Methods for Deep Learning,作者:Kevin Vu

【51CTO譯稿,合作站點轉載請注明原文譯者和出處為51CTO.com】

責任編輯:華軒 來源: 51CTO
相關推薦

2018-04-04 10:19:32

深度學習

2024-01-31 08:09:53

預處理器代碼C++

2021-03-28 08:57:57

Python 文本數據

2020-12-23 11:08:10

Python代碼文本

2024-12-20 13:00:00

Python文本清洗預處理

2020-11-06 17:20:14

PythonBAT代碼

2019-11-14 21:21:50

數據挖掘數據處理數據分析

2021-10-28 09:00:00

深度學習人工智能技術

2017-08-24 09:35:06

深度學習向量化Hash Trick

2023-05-26 08:39:44

深度學習Alluxio

2017-08-03 16:20:42

深度學習文本摘要遞歸神經網絡

2021-11-12 15:16:32

深度學習數據合成人工智能

2011-08-04 10:38:17

Objective-C 預處理程序

2017-04-29 10:16:14

機器學習數據清洗數據整理

2017-05-02 08:40:36

機器學習預處理整理

2024-05-17 13:17:39

2025-03-07 08:00:00

數據數據集集神經網絡數據預處理

2020-04-29 16:49:33

機器學習人工智能計算機

2015-06-17 14:28:15

Java查詢處理方法

2009-08-07 17:41:40

C#預處理
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 国产第一页在线播放 | 国产精品www| 综合色播 | 欧美一区2区三区4区公司 | 国产玖玖| 成人不卡视频 | 久久久噜噜噜www成人网 | 久亚州在线播放 | 欧美极品一区二区 | k8久久久一区二区三区 | 亚洲精品电影网在线观看 | 欧美精品一 | 亚洲一区二区三区在线免费 | 亚洲精品二区 | 久久99蜜桃综合影院免费观看 | 日韩免费一区二区 | 97人人澡人人爽91综合色 | 成人乱人乱一区二区三区软件 | 欧美综合一区 | 在线伊人网 | 日韩中文字幕一区二区三区 | 成人精品鲁一区一区二区 | 免费视频一区二区三区在线观看 | 激情欧美一区二区三区中文字幕 | 欧美在线视频免费 | 91在线资源 | 亚洲一二三在线观看 | 日韩毛片免费看 | 国产高清在线精品一区二区三区 | 欧美久久久久 | 麻豆国产一区二区三区四区 | 密色视频 | 日本一卡精品视频免费 | 欧美日批| 在线观看不卡av | www.yw193.com| 国产午夜精品视频 | 中文字幕人成乱码在线观看 | 国产成人精品一区二区三区网站观看 | 日本精品在线观看 | 日韩成人一区二区 |