<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                # 四、邏輯回歸 在上一章中,我們已經看到了一種將現實的一部分建模為線性函數的方法,該函數具有獨立變量,并且偏差最小化了誤差函數。 除了某些非常明確定義的問題(預期結果是連續的變量和函數)之外,這種特殊的分析還不夠。 但是,如果我們面對具有定性因變量的數據,將會發生什么? 例如,是否存在確定的特征; 受試者有金色的頭發嗎? 病人以前有病嗎? 這些是我們將在本章中處理的問題。 # 問題描述 線性回歸旨在解決的問題不是基于連續函數的值預測,這一次,我們想知道樣本屬于確定類別的可能性。 在本章中,我們將依靠線性模型的一般化來解決回歸問題,但最終目標是解決分類問題,我們必須應用標簽或將觀察集中的所有元素分配給預定義的組。 ![Problem description](https://img.kancloud.cn/84/c7/84c768b1d3826937ec82444fb74761df_566x338.jpg) 在上圖中,我們可以看到如何對舊問題和新問題進行分類。 第一個(線性回歸)可以想象為值不斷增長的連續體。 另一個是基于`x`值的輸出只能具有兩個不同值的域。 在第二張圖的特定情況下,我們可以看到對其中一個選項的特定偏向極端:在左側,`y`值偏向 0,在右側偏向 1。 鑒于即使在進行回歸從而尋找連續值的情況下,這種項也可能有些棘手,實際上,最終目標是為具有離散變量的分類問題建立預測。 此處的關鍵是要了解我們將獲得與類有關的項目的概率,而不是完全離散的值。 # sigmoid 函數的前身 -- 對率(Logit)函數 在研究邏輯函數之前,我們將回顧該函數所基于的原始函數,并為其提供一些更一般的屬性。 本質上,當我們談論`logit`函數時,我們正在使用隨機變量`p`的函數,更具體地說,是與伯努利分布相對應的函數。 ## 伯努利分布 在解釋理論細節之前,值得注意的是伯努利分布是一個隨機變量,它具有: * 取值為 0 且失敗概率為`q = 1 - p` * 取值為 1,成功概率為`p` 可以表示如下(對于具有伯努利分布的隨機變量`X`): ![Bernoulli distribution](https://img.kancloud.cn/b2/4d/b24d5951b6caba54c541eb3805209bcd_566x62.jpg) 這是一種概率分布,它將以二元選項的形式表示事件的發生概率,就像我們要表示自己的變量(特征的存在,事件的發生,現象的因果關系等)一樣。 ## 鏈接函數 在嘗試建立廣義線性模型時,我們要從線性函數開始,并從因變量開始,獲取到概率分布的映射。 由于選項具有二元性質,因此通常選擇的分布是最近提到的伯努利分布,而傾向于 logistic 函數的鏈接函數是`logit`函數。 ## Logit 函數 我們可以利用的可能變量之一是`p`等于 1 的幾率的自然對數。 此函數稱為`logit`函數: ![Logit function](https://img.kancloud.cn/72/06/72064f7719e2252699c82844267b6239_454x150.jpg) 我們也可以將`logit`函數稱為對數奇數函數,因為對于給定的概率`p`,我們正在計算賠率的對數`(p/1-p)`: ![Logit function](https://img.kancloud.cn/ab/65/ab65d5fcebaad21a2b19b7ecc849afd0_184x322.jpg) 因此,正如我們可以直觀地推斷出的那樣,用自變量的組合替換`X`,無論它們的值是什么,用從負無窮大到無窮大的任何出現替換`X`,我們將響應縮放到`0`和`1`。 ## Logit 反函數的重要性 假設我們計算`logit`函數的逆。 這將使我們編寫以下函數: ![The importance of the logit inverse](https://img.kancloud.cn/d5/42/d5427108a471981841c8da42484ed4e1_566x82.jpg) 此函數是`sigmoid`函數。 # sigmoid 函數 邏輯函數將幫助我們在新的回歸任務中表示二元類別。 在下圖中,您將找到`sigmoid`函數的圖形表示: ![The logistic function](https://img.kancloud.cn/cb/ff/cbff77c72331afa4e68af7713bf64993_566x378.jpg) 邏輯函數或 Sigmoid 的圖形表示 ## Logistic 函數作為線性建模的泛化 邏輯函數`δ(t)`定義如下: ![Logistic function as a linear modeling generalization](https://img.kancloud.cn/44/8e/448e76b514ca06baecb36d08bca1fe69_442x138.jpg) 該方程式的正常解釋是`t`代表一個簡單的自變量。 但是,我們將改進此模型,并假定`t`是單個解釋變量`x`的線性函數(對`t`是多個解釋變量的線性組合的情況進行類似處理)。 然后,我們將`t`表示為: ![Logistic function as a linear modeling generalization](https://img.kancloud.cn/a8/96/a896165fec5f550e78ae3e924b59c9bb_208x67.jpg) ### 最終估計的回歸方程 因此,我們從以下等式開始: ![Final estimated regression equation](https://img.kancloud.cn/e2/af/e2af3f2142b7e4b0a815c070952d1e99_566x135.jpg) 使用所有這些元素,我們可以計算回歸方程,這將為我們提供回歸概率: ![Final estimated regression equation](https://img.kancloud.cn/2a/c7/2ac767be40b95fd0da4e6ecc3069b182_300x138.jpg) 下圖將顯示如何將從任意范圍的映射最終轉換為范圍`[0, 1]`,該范圍可以解釋為表示事件發生的概率`p`: ![Final estimated regression equation](https://img.kancloud.cn/1e/1a/1e1a09f64abb50e78bc61a716152517c_566x121.jpg) 什么影響會改變線性函數的參數? 它們是將更改`sigmoid`函數的中心斜率和從零開始的位移的值,從而使其可以更精確地減小回歸值與實際數據點之間的誤差。 ## Logistic 函數的屬性 函數空間中的每條曲線都可以通過可能適用的目標來描述。 對于 logistic 函數,它們是: * 根據一個或多個獨立變量對事件的概率`p`進行建模。 例如,鑒于先前的資格,被授予獎品的可能性。 * 對確定的觀測值進行估計(這是回歸部分)`p`,與事件未發生的可能性有關。 * 預測自變量變化對二元響應的影響。 * 通過計算某項屬于確定類別的概率對觀察進行分類。 ### 損失函數 在上一節中,我們看到了近似的`p^`函數,該函數將對樣本屬于特定類別的概率進行建模。 為了衡量我們對解的近似程度,我們將尋找精心選擇的損失函數。 該損失函數表示為: ![Loss function](https://img.kancloud.cn/93/14/931416e84694b03b7553fa9b7cedd681_566x61.jpg) 該損失函數的主要特性是它不會以類似的方式懲罰誤差,當誤差增加到遠遠超過 0.5 時,誤差懲罰因子會漸近增長。 ## 多類應用 -- softmax 回歸 到目前為止,我們僅針對兩個類的情況進行分類,或者以概率語言對事件發生概率`p`進行分類。 在要決定兩個以上類別的情況下,有兩種主要方法: 一對一,一對剩余。 * 第一種技術包括計算許多模型,這些模型代表每個類別相對于所有其他類別的概率。 * 第二個由一組概率組成,其中我們代表一個類別相對于所有其他類別的概率。 * 第二種方法是`softmax`回歸的輸出格式,它是 n 個類的邏輯回歸的概括。 因此,為了訓練樣本,我們將使用句柄`y(i)ε{1,...,K},`將二元標簽`( y(i)ε{0,1})`更改為向量標簽,其中`K`是類別數,標簽`Y`可以采用`K`不同的值, 而不是只有兩個。 因此,對于這種特定技術,給定測試輸入`X`,我們想要針對`k=1,...,K`的每個值估計`P`(`y=k|x`)的概率。 `softmax`回歸將輸出`K`維向量(其元素總和為 1),從而為我們提供了`K`估計的概率。 在下圖中,我們表示在單類和多類邏輯回歸的概率映射上發生的映射: ![Multiclass application - softmax regression](https://img.kancloud.cn/b6/e9/b6e9038b4b8c493acc3e9e6be9774277_156x179.jpg) ### 成本函數 `softmax`函數的成本函數是自適應的交叉熵函數,該函數不是線性的,因此對大階函數差異的懲罰要比對小階函數的懲罰更大。 ![Cost function](https://img.kancloud.cn/5b/14/5b14d4fbf4c5204bde66cbc2fc3b8ae9_566x111.jpg) 在這里,`c`是類別編號,`I`是各個訓練樣本索引,`yc`對于期望的類別為 1,對于其余類別為 0。 擴展這個方程,我們得到以下結果: ![Cost function](https://img.kancloud.cn/ab/93/ab935b15dbf95780efbbc08c83ac066f_566x213.jpg) ### 迭代方法的數據標準化 正如我們將在以下各節中看到的那樣,對于邏輯回歸,我們將使用`gradient descent`方法來最小化成本函數。 ![Data normalization for iterative methods](https://img.kancloud.cn/3d/d1/3dd1642c2c63eb7fbe7fd310183c13a3_373x583.jpg) 此方法對特征數據的形式和分布非常敏感。 因此,我們將進行一些預處理,以便獲得更好,更快的收斂結果。 我們將把這種方法的理論原因留給其他書籍,但我們將總結其原因,即通過歸一化可以平滑誤差表面,使迭代`gradient descent`更快地達到最小誤差。 ### 輸出的單熱表示 為了將`softmax`函數用作回歸函數,我們必須使用一種稱為單熱編碼的編碼。 這種編碼形式只是將變量的數字整數值轉換為數組,其中將值列表轉換為數組列表,每個數組的長度與該列表的最大值相同,并且每個數組的表示方式是在值的索引上添加 1,其余元素保持為 0。 例如,這將是單熱編碼形式的列表`[1, 3, 2, 4]`的表示形式: ```py [[0 1 0 0 0] [0 0 0 1 0] [0 0 1 0 0] [0 0 0 0 1]] ``` # 示例 1 -- 單變量 logistic 回歸 在第一個示例中,我們將使用單變量 logistic 回歸(患者年齡)來估計心臟病的概率。 ## 有用的庫和方法 從 0.8 版開始,TensorFlow 提供了一種生成熱點的方法。 用于此生成的函數是`tf.one_hot`,其形式如下: ```py tf.one_hot(indices, depth, on_value=1, off_value=0, axis=None, dtype=tf.float32, name=None) ``` 此函數生成通用的單熱編碼數據結構,該結構可以指定值,生成軸,數據類型等。 在生成的張量中,索引的指示值將采用`on_value`(默認值為`1`),其他值將具有`off_value`(默認`0`)。 `Dtype`是生成的張量的數據類型; 默認值為`float32`。 `depth`變量定義每個元素將具有多少列。 我們假設它在邏輯上應該為`max(indices) + 1`,但也可以將其切掉。 ### TensorFlow 的 softmax 實現 在 TensorFlow 中應用`softmax`回歸的方法包括`tf.nn.log_softmax, with the following form:` ```py tf.nn.log_softmax(logits, name=None) ``` 在這里,參數為: * `logits`:張量必須為以下類型之一:`float32`,`float64` 形狀為`[batch_size, num_classes]`的 2D * `name`:操作的名稱(可選) 此函數返回具有與`logits`相同類型和形狀的張量。 ## 數據集說明和加載 我們將討論的第一種情況是我們要擬合邏輯回歸的方法,僅測量一個變量,并且只有兩個可能的結果。 ### CHDAGE 數據集 對于第一個簡單的示例,我們將使用一個非常簡單且經過研究的數據集,該數據集以在書中出版而聞名。 應用邏輯回歸第三版,David W. Hosmer Jr.,Stanley Lemeshow,Rodney X. Sturdivant,作者:Wiley。 列出`age`的年限(AGE),以及對心臟病風險因素進行假設性研究的 100 名受試者是否患有嚴重冠心病(CHD)的證據。 該表還包含一個標識符變量(ID)和一個年齡組變量(AGEGRP)。 結果變量是 CHD,它用`0`值編碼以表示不存在 CHD,或用`1`編碼以指示其存在于個體中。 通常,可以使用任何兩個值,但是我們發現使用零和一最為方便。 我們將此數據集稱為 CHDAGE 數據。 #### CHDAGE 數據集格式 CHDAGE 數據集是一個兩列的 CSV 文件,我們將從外部倉庫下載該文件。 在第 1 章(探索和轉換數據)中,我們使用了本機 TensorFlow 方法來讀取數據集。 在本章中,我們將使用一個互補且流行的庫來獲取數據。 進行此新添加的原因是,鑒于數據集只有 100 個元組,實際上只需要一行讀取即可,而且`pandas`庫提供了免費但簡單但強大的分析方法 。 因此,在該項目的第一階段,我們將開始加載 CHDAGE 數據集的實例,然后將打印有關數據的重要統計信息,然后進行預處理。 在對數據進行一些繪制之后,我們將構建一個由激活函數組成的模型,該激活函數將在特殊情況下成為`softmax`函數,在特殊情況下它將變為標準邏輯回歸。 那就是只有兩個類別(疾病的存在與否)。 #### 數據集加載和預處理實現 首先,我們導入所需的庫,并指示所有`matplotlib`程序都將內聯(如果我們使用 Jupyter): ```py >>> import pandas as pd >>> import numpy as np >>> %matplotlib inline >>> import matplotlib.pyplot as plt ``` 然后,我們讀取數據并要求`pandas`檢查有關數據集的重要統計信息: ```py >>> df = pd.read_csv("data/CHD.csv", header=0) >>> print df.describe() ``` ```py age chd count 100.000000 100.00000 mean 44.380000 0.43000 std 11.721327 0.49757 min 20.000000 0.00000 25% 34.750000 0.00000 50% 44.000000 0.00000 75% 55.000000 1.00000 max 69.000000 1.000000 ``` 然后,我們繼續繪制數據以了解數據: ```py plt.figure() # Create a new figure plt.scatter(df['age'],df['chd']) #Plot a scatter draw of the random datapoints ``` ![Dataset loading and preprocessing implementation](https://img.kancloud.cn/4b/7a/4b7a8bda5938f23eebbad36d28a49f81_385x258.jpg) ## 模型架構 在這里,我們從以下變量開始,描述將在其中構建模型元素的代碼部分: ```py learning_rate = 0.8 #Learning speed batch_size = 100 #number of samples for the batch display_step = 2 #number of steps before showing progress ``` 在這里,我們為圖創建初始變量和占位符,即單變量`x`和`y`浮點值: ```py x = tf.placeholder("float", [None, 1]) # Placeholder for the 1D data y = tf.placeholder("float", [None, 2]) # Placeholder for the classes (2) ``` 現在,我們將創建線性模型變量,隨著模型擬合的進行,將對其進行修改和更新: ```py W = tf.Variable(tf.zeros([1, 2])) b = tf.Variable(tf.zeros([2])) ``` 最后,我們將對線性函數應用`softmax`操作來構建激活函數: ```py activation = tf.nn.softmax(tf.matmul(x, W) + b) ``` ## 損失函數描述和優化器循環 在這里,我們僅將互相關函數定義為`loss`函數,并定義`optimizer`操作,即`gradient descent`。 以下各章將對此進行解釋; 現在,您可以看到它是一個黑框,它將改變變量,直到損失最小: ```py cost = tf.reduce_mean(-tf.reduce_sum(y*tf.log(activation), reduction_indices=1)) optimizer = tf.train.GradientDescentOptimizer(learning_rate).minimize(cost) #Iterate through all the epochs for epoch in range(training_epochs): avg_cost = 0\. total_batch = 400/batch_size # Loop over all batches for i in range(total_batch): # Transform the array into a one hot format temp=tf.one_hot(indices = df['chd'].values, depth=2, on_value = 1, off_value = 0, axis = -1 , name = "a") batch_xs, batch_ys =(np.transpose([df['age']])-44.38)/11.721327, temp # Fit training using batch data sess.run(optimizer, feed_dict={x: batch_xs.astype(float), y: batch_ys.eval()}) # Compute average loss, suming the corrent cost divided by the batch total number avg_cost += sess.run(cost, feed_dict={x: batch_xs.astype(float), y: batch_ys.eval()})/total_batch ``` ## 停止條件 一旦根據訓練周期對數據進行了訓練,該過程將簡單地停止。 ## 結果描述 這將是程序的輸出: ```py Epoch: 0001 cost= 0.638730764 [ 0.04824295 -0.04824295] [[-0.17459483 0.17459483]] Epoch: 0002 cost= 0.589489654 [ 0.08091066 -0.08091066] [[-0.29231569 0.29231566]] Epoch: 0003 cost= 0.565953553 [ 0.10427245 -0.10427245] [[-0.37499282 0.37499279]] Epoch: 0004 cost= 0.553756475 [ 0.12176144 -0.12176143] [[-0.43521613 0.4352161 ]] Epoch: 0005 cost= 0.547019333 [ 0.13527818 -0.13527818] [[-0.48031801 0.48031798]] ``` ### 擬合函數的跨周期表示 在下圖中,我們表示了擬合函數在不同周期之間的進展: ![Fitting function representations across epochs](https://img.kancloud.cn/72/c1/72c1986fbc27078bdaacee79f95b33c0_566x378.jpg) ## 完整源代碼 這是完整的源代碼: ```py import pandas as pd import numpy as np get_ipython().magic(u'matplotlib inline') import matplotlib.pyplot as plt import tensorflow as tf df = pd.read_csv("data/CHD.csv", header=0) # Parameters learning_rate = 0.2 training_epochs = 5 batch_size = 100 display_step = 1 sess = tf.Session() b=np.zeros((100,2)) # tf Graph Input x = tf.placeholder("float", [None, 1]) y = tf.placeholder("float", [None, 2]) # Create model # Set model weights W = tf.Variable(tf.zeros([1, 2])) b = tf.Variable(tf.zeros([2])) # Construct model activation = tf.nn.softmax(tf.matmul(x, W) + b) # Minimize error using cross entropy cost = tf.reduce_mean(-tf.reduce_sum(y*tf.log(activation), reduction_indices=1)) # Cross entropy optimizer = tf.train.GradientDescentOptimizer(learning_rate).minimize(cost) # Gradient Descent # Initializing the variables init = tf.initialize_all_variables() # Launch the graph with tf.Session() as sess: tf.train.write_graph(sess.graph, './graphs','graph.pbtxt') sess.run(init) writer = tf.train.SummaryWriter('./graphs', sess.graph) #Initialize the graph structure graphnumber=321 #Generate a new graph plt.figure(1) #Iterate through all the epochs for epoch in range(training_epochs): avg_cost = 0\. total_batch = 400/batch_size # Loop over all batches for i in range(total_batch): # Transform the array into a one hot format temp=tf.one_hot(indices = df['chd'].values, depth=2, on_value = 1, off_value = 0, axis = -1 , name = "a") batch_xs, batch_ys = (np.transpose([df['age']])-44.38)/11.721327, temp # Fit training using batch data sess.run(optimizer, feed_dict={x: batch_xs.astype(float), y: batch_ys.eval()}) # Compute average loss, suming the corrent cost divided by the batch total number avg_cost += sess.run(cost, feed_dict={x: batch_xs.astype(float), y: batch_ys.eval()})/total_batch # Display logs per epoch step if epoch % display_step == 0: print "Epoch:", '%05d' % (epoch+1), "cost=", "{:.8f}".format(avg_cost) #Generate a new graph, and add it to the complete graph trX = np.linspace(-30, 30, 100) print (b.eval()) print (W.eval()) Wdos=2*W.eval()[0][0]/11.721327 bdos=2*b.eval()[0] # Generate the probabiliy function trY = np.exp(-(Wdos*trX)+bdos)/(1+np.exp(-(Wdos*trX)+bdos) ) # Draw the samples and the probability function, whithout the normalization plt.subplot(graphnumber) graphnumber=graphnumber+1 #Plot a scatter draw of the random datapoints plt.scatter((df['age']),df['chd']) plt.plot(trX+44.38,trY) #Plot a scatter draw of the random datapoints plt.grid(True) #Plot the final graph plt.savefig("test.svg") ``` ### 圖形表示 使用 TensorBoard 工具,我們將看到操作鏈。 請注意,在一半的操作圖中,我們定義了主要的全局操作(“小數點”)以及應用于其余項的梯度操作,這是進行`loss`函數最小化所必需的。 這是接下來幾章要討論的主題。 ![Graphical representation](https://img.kancloud.cn/9d/44/9d4418dd54bf260bd12441a091c679a1_350x570.jpg) # 示例 2 -- skflow 中的單變量 logistic 回歸 在此示例中,我們將探索單變量示例域,但是這次我們將使用來自新庫的幫助,該庫為我們簡化了模型構建,稱為`skflow`。 ## 有用的庫和方法 在機器學習庫領域中,有很多選擇。 最知名的之一是`sklearn`,我們在第 2 章聚類中討論過。 在 TensorFlow 發布之后的很早,一個新的貢獻庫就出現了,叫做`skflow`,其主要目的是模擬`sklearn`的接口和工作流程,在這個 TensorFlow 會話環境中工作更簡潔。 在下面的示例中,我們將使用`skflow`接口重復先前回歸的分析。 在示例中,我們還將看到 skflow 如何為回歸模型自動生成詳細且組織良好的圖,只需將日志目錄設置為參數即可。 ## 數據集說明 使用`pandas`庫,數據集加載階段與前面的示例相同: ```py import pandas as pd df = pd.read_csv("data/CHD.csv", header=0) print df.describe() ``` ## 模型架構 這是`my_model`的代碼段: ```py def my_model(X, y): return skflow.models.logistic_regression(X, y) X1 =a.fit_transform(df['age'].astype(float)) y1 = df['chd'].values classifier = skflow.TensorFlowEstimator(model_fn=my_model, n_classes=2) ``` 在這里,我們可以使用`softmax`分類器查看邏輯回歸階段的詳細視圖: ![Model architecture](https://img.kancloud.cn/0d/fb/0dfbadd40e6c26bf2ab7060ac37d43de_521x581.jpg) ![Model architecture](https://img.kancloud.cn/87/9b/879b291129fdcc723cb4aa3cae455ceb_566x240.jpg) ## 結果描述 ```py score = metrics.accuracy_score(df['chd'].astype(float), classifier.predict(X)) print("Accuracy: %f" % score) ``` 輸出結果可觀(為了簡化模型)74% 的準確率: ```py Accuracy: 0.740000 ``` ## 完整源代碼 這是完整的源代碼: ```py import tensorflow.contrib.learn as skflow from sklearn import datasets, metrics, preprocessing import numpy as np import pandas as pd df = pd.read_csv("data/CHD.csv", header=0) print df.describe() def my_model(X, y): return skflow.models.logistic_regression(X, y) a = preprocessing.StandardScaler() X1 =a.fit_transform(df['age'].astype(float)) y1 = df['chd'].values classifier = skflow.TensorFlowEstimator(model_fn=my_model, n_classes=2) classifier.fit(X1,y1 , logdir='/tmp/logistic') score = metrics.accuracy_score(df['chd'].astype(float), classifier.predict(X)) print("Accuracy: %f" % score) ``` # 總結 在本章中,我們學習了一種新的建模技術,即邏輯函數,并從一種簡單的分類任務入手。 我們還學習了一種通過`pandas`庫讀取基于文本的數據的新方法。 此外,我們還看到了與`skflow`庫一起使用的經典工作流的一種補充方法。 在下一章中,我們將開始處理更復雜的架構,并進入 TensorFlow 庫擅長的領域:訓練,測試和最終實現神經網絡以解決實際問題。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看