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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

经典算法笔记:无监督算法(聚类、降维)

發布時間:2025/3/8 编程问答 49 豆豆
生活随笔 收集整理的這篇文章主要介紹了 经典算法笔记:无监督算法(聚类、降维) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

本文是吳恩達老師的機器學習課程[1]的筆記和代碼復現部分(聚類、降維)。

作者:黃海廣[2]

備注:筆記和作業(含數據、原始作業文件)、視頻都在github[3]中下載。

我將陸續將課程筆記和課程代碼發布在公眾號“機器學習初學者”,敬請關注。這個是第四部分:無監督學習,是原教程的第8周,包含了筆記和作業代碼(原課程作業是?OCTAVE的,這里是復現?python?代碼)

第一部分:回歸

第二部分:邏輯回歸

第三部分:支持向量機

本文作業代碼[4]可以下載完整版

筆記的markdown 文件[5]

筆記的pdf 文件[6]

筆記部分目錄

十三、聚類(Clustering)

13.1 無監督學習:簡介

參考視頻: 13 - 1 - Unsupervised Learning_ Introduction (3 min).mkv

在這個視頻中,我將開始介紹聚類算法。這將是一個激動人心的時刻,因為這是我們學習的第一個非監督學習算法。我們將要讓計算機學習無標簽數據,而不是此前的標簽數據。

那么,什么是非監督學習呢?在課程的一開始,我曾簡單的介紹過非監督學習,然而,我們還是有必要將其與監督學習做一下比較。

在一個典型的監督學習中,我們有一個有標簽的訓練集,我們的目標是找到能夠區分正樣本和負樣本的決策邊界,在這里的監督學習中,我們有一系列標簽,我們需要據此擬合一個假設函數。與此不同的是,在非監督學習中,我們的數據沒有附帶任何標簽,我們拿到的數據就是這樣的:

在這里我們有一系列點,卻沒有標簽。因此,我們的訓練集可以寫成只有,…..一直到。我們沒有任何標簽。因此,圖上畫的這些點沒有標簽信息。也就是說,在非監督學習中,我們需要將一系列無標簽的訓練數據,輸入到一個算法中,然后我們告訴這個算法,快去為我們找找這個數據的內在結構給定數據。我們可能需要某種算法幫助我們尋找一種結構。圖上的數據看起來可以分成兩個分開的點集(稱為簇),一個能夠找到我圈出的這些點集的算法,就被稱為聚類算法。

這將是我們介紹的第一個非監督學習算法。當然,此后我們還將提到其他類型的非監督學習算法,它們可以為我們找到其他類型的結構或者其他的一些模式,而不只是簇。

我們將先介紹聚類算法。此后,我們將陸續介紹其他算法。那么聚類算法一般用來做什么呢?

在這門課程的早些時候,我曾經列舉過一些應用:比如市場分割。也許你在數據庫中存儲了許多客戶的信息,而你希望將他們分成不同的客戶群,這樣你可以對不同類型的客戶分別銷售產品或者分別提供更適合的服務。社交網絡分析:事實上有許多研究人員正在研究這樣一些內容,他們關注一群人,關注社交網絡,例如FacebookGoogle+,或者是其他的一些信息,比如說:你經常跟哪些人聯系,而這些人又經常給哪些人發郵件,由此找到關系密切的人群。因此,這可能需要另一個聚類算法,你希望用它發現社交網絡中關系密切的朋友。我有一個朋友正在研究這個問題,他希望使用聚類算法來更好的組織計算機集群,或者更好的管理數據中心。因為如果你知道數據中心中,那些計算機經常協作工作。那么,你可以重新分配資源,重新布局網絡。由此優化數據中心,優化數據通信。

最后,我實際上還在研究如何利用聚類算法了解星系的形成。然后用這個知識,了解一些天文學上的細節問題。好的,這就是聚類算法。這將是我們介紹的第一個非監督學習算法。在下一個視頻中,我們將開始介紹一個具體的聚類算法。

13.2 K-均值算法

參考視頻: 13 - 2 - K-Means Algorithm (13 min).mkv

K-均值是最普及的聚類算法,算法接受一個未標記的數據集,然后將數據聚類成不同的組。

K-均值是一個迭代算法,假設我們想要將數據聚類成 n 個組,其方法為:

首先選擇個隨機的點,稱為聚類中心cluster centroids);

對于數據集中的每一個數據,按照距離個中心點的距離,將其與距離最近的中心點關聯起來,與同一個中心點關聯的所有點聚成一類。

計算每一個組的平均值,將該組所關聯的中心點移動到平均值的位置。

重復步驟 2-4 直至中心點不再變化。

下面是一個聚類示例:

迭代 1 次

迭代 3 次

迭代 10 次

用μ,μ,...,μ?來表示聚類中心,用,,...,來存儲與第個實例數據最近的聚類中心的索引,K-均值算法的偽代碼如下:

Repeat { for?i?=?1?to?mc(i)?:=?index?(form?1?to?K)?of?cluster?centroid?closest?to?x(i)for k = 1 to Kμk?:=?average?(mean)?of?points?assigned?to?cluster?k }

算法分為兩個步驟,第一個for循環是賦值步驟,即:對于每一個樣例,計算其應該屬于的類。第二個for循環是聚類中心的移動,即:對于每一個類,重新計算該類的質心。

K-均值算法也可以很便利地用于將數據分為許多不同組,即使在沒有非常明顯區分的組群的情況下也可以。下圖所示的數據集包含身高和體重兩項特征構成的,利用K-均值算法將數據分為三類,用于幫助確定將要生產的 T-恤衫的三種尺寸。

13.3 優化目標

參考視頻: 13 - 3 - Optimization Objective (7 min).mkv

K-均值最小化問題,是要最小化所有的數據點與其所關聯的聚類中心點之間的距離之和,因此 K-均值的代價函數(又稱畸變函數 Distortion function)為:

其中代表與最近的聚類中心點。我們的的優化目標便是找出使得代價函數最小的?,,...,和,,...,:

回顧剛才給出的:K-均值迭代算法,我們知道,第一個循環是用于減小引起的代價,而第二個循環則是用于減小引起的代價。迭代的過程一定會是每一次迭代都在減小代價函數,不然便是出現了錯誤。

13.4 隨機初始化

參考視頻: 13 - 4 - Random Initialization (8 min).mkv

在運行 K-均值算法的之前,我們首先要隨機初始化所有的聚類中心點,下面介紹怎樣做:

  • 我們應該選擇$K

  • 隨機選擇個訓練實例,然后令個聚類中心分別與這個訓練實例相等

  • K-均值的一個問題在于,它有可能會停留在一個局部最小值處,而這取決于初始化的情況。

    為了解決這個問題,我們通常需要多次運行K-均值算法,每一次都重新進行隨機初始化,最后再比較多次運行K-均值的結果,選擇代價函數最小的結果。這種方法在較小的時候(2--10)還是可行的,但是如果較大,這么做也可能不會有明顯地改善。

    13.5 選擇聚類數

    參考視頻: 13 - 5 - Choosing the Number of Clusters (8 min).mkv

    沒有所謂最好的選擇聚類數的方法,通常是需要根據不同的問題,人工進行選擇的。選擇的時候思考我們運用K-均值算法聚類的動機是什么,然后選擇能最好服務于該目的標聚類數。

    當人們在討論,選擇聚類數目的方法時,有一個可能會談及的方法叫作“肘部法則”。關于“肘部法則”,我們所需要做的是改變值,也就是聚類類別數目的總數。我們用一個聚類來運行K 均值聚類方法。這就意味著,所有的數據都會分到一個聚類里,然后計算成本函數或者計算畸變函數。代表聚類數字。

    我們可能會得到一條類似于這樣的曲線。像一個人的肘部。這就是“肘部法則”所做的,讓我們來看這樣一個圖,看起來就好像有一個很清楚的肘在那兒。好像人的手臂,如果你伸出你的胳膊,那么這就是你的肩關節、肘關節、手。這就是“肘部法則”。你會發現這種模式,它的畸變值會迅速下降,從 1 到 2,從 2 到 3 之后,你會在 3 的時候達到一個肘點。在此之后,畸變值就下降的非常慢,看起來就像使用 3 個聚類來進行聚類是正確的,這是因為那個點是曲線的肘點,畸變值下降得很快,之后就下降得很慢,那么我們就選。當你應用“肘部法則”的時候,如果你得到了一個像上面這樣的圖,那么這將是一種用來選擇聚類個數的合理方法。

    例如,我們的 T-恤制造例子中,我們要將用戶按照身材聚類,我們可以分成 3 個尺寸:,也可以分成 5 個尺寸,這樣的選擇是建立在回答“聚類后我們制造的 T-恤是否能較好地適合我們的客戶”這個問題的基礎上作出的。

    聚類參考資料:

    1.相似度/距離計算方法總結

    (1). 閔可夫斯基距離Minkowski/(其中歐式距離:)

    (2). 杰卡德相似系數(Jaccard):

    (3). 余弦相似度(cosine similarity):

    維向量和的夾角記做,根據余弦定理,其余弦值為:

    (4). Pearson 皮爾遜相關系數:?

    Pearson 相關系數即將、坐標向量各自平移到原點后的夾角余弦。

    2.聚類的衡量指標

    (1). 均一性:

    類似于精確率,一個簇中只包含一個類別的樣本,則滿足均一性。其實也可以認為就是正確率(每個 聚簇中正確分類的樣本數占該聚簇總樣本數的比例和)

    (2). 完整性:

    類似于召回率,同類別樣本被歸類到相同簇中,則滿足完整性;每個聚簇中正確分類的樣本數占該 類型的總樣本數比例的和

    (3). V-measure:

    均一性和完整性的加權平均

    (4). 輪廓系數

    樣本的輪廓系數:

    簇內不相似度:計算樣本到同簇其它樣本的平均距離為,應盡可能小。

    簇間不相似度:計算樣本到其它簇的所有樣本的平均距離,應盡可能大。

    輪廓系數:值越接近 1 表示樣本聚類越合理,越接近-1,表示樣本應該分類到 另外的簇中,近似為 0,表示樣本應該在邊界上;所有樣本的的均值被成為聚類結果的輪廓系數。

    (5). ARI

    數據集共有個元素, 兩個聚類結果分別是:

    和的元素個數為:


    記:

    十四、降維(Dimensionality Reduction)

    14.1 動機一:數據壓縮

    參考視頻: 14 - 1 - Motivation I_ Data Compression (10 min).mkv

    這個視頻,我想開始談論第二種類型的無監督學習問題,稱為降維。有幾個不同的的原因使你可能想要做降維。一是數據壓縮,后面我們會看了一些視頻后,數據壓縮不僅允許我們壓縮數據,因而使用較少的計算機內存或磁盤空間,但它也讓我們加快我們的學習算法。

    但首先,讓我們談論降維是什么。作為一種生動的例子,我們收集的數據集,有許多,許多特征,我繪制兩個在這里。

    假設我們未知兩個的特征::長度:用厘米表示;:是用英寸表示同一物體的長度。

    所以,這給了我們高度冗余表示,也許不是兩個分開的特征和,這兩個基本的長度度量,也許我們想要做的是減少數據到一維,只有一個數測量這個長度。這個例子似乎有點做作,這里厘米英寸的例子實際上不是那么不切實際的,兩者并沒有什么不同。

    將數據從二維降至一維:假使我們要采用兩種不同的儀器來測量一些東西的尺寸,其中一個儀器測量結果的單位是英寸,另一個儀器測量的結果是厘米,我們希望將測量的結果作為我們機器學習的特征。現在的問題的是,兩種儀器對同一個東西測量的結果不完全相等(由于誤差、精度等),而將兩者都作為特征有些重復,因而,我們希望將這個二維的數據降至一維。

    從這件事情我看到的東西發生在工業上的事。如果你有幾百個或成千上萬的特征,它是它這往往容易失去你需要的特征。有時可能有幾個不同的工程團隊,也許一個工程隊給你二百個特征,第二工程隊給你另外三百個的特征,第三工程隊給你五百個特征,一千多個特征都在一起,它實際上會變得非常困難,去跟蹤你知道的那些特征,你從那些工程隊得到的。其實不想有高度冗余的特征一樣。

    多年我一直在研究直升飛機自動駕駛。諸如此類。如果你想測量——如果你想做,你知道,做一個調查或做這些不同飛行員的測試——你可能有一個特征:,這也許是他們的技能(直升機飛行員),也許可能是飛行員的愛好。這是表示他們是否喜歡飛行,也許這兩個特征將高度相關。你真正關心的可能是這條紅線的方向,不同的特征,決定飛行員的能力。

    將數據從三維降至二維:這個例子中我們要將一個三維的特征向量降至一個二維的特征向量。過程是與上面類似的,我們將三維向量投射到一個二維的平面上,強迫使得所有的數據都在同一個平面上,降至二維的特征向量。

    這樣的處理過程可以被用于把任何維度的數據降到任何想要的維度,例如將 1000 維的特征降至 100 維。

    正如我們所看到的,最后,這將使我們能夠使我們的一些學習算法運行也較晚,但我們會在以后的視頻提到它。

    14.2 動機二:數據可視化

    參考視頻: 14 - 2 - Motivation II_ Visualization (6 min).mkv

    在許多及其學習問題中,如果我們能將數據可視化,我們便能尋找到一個更好的解決方案,降維可以幫助我們。

    假使我們有有關于許多不同國家的數據,每一個特征向量都有 50 個特征(如GDP,人均GDP,平均壽命等)。如果要將這個 50 維的數據可視化是不可能的。使用降維的方法將其降至 2 維,我們便可以將其可視化了。

    這樣做的問題在于,降維的算法只負責減少維數,新產生的特征的意義就必須由我們自己去發現了。

    14.3 主成分分析問題

    參考視頻: 14 - 3 - Principal Component Analysis Problem Formulation (9 min). mkv

    主成分分析(PCA)是最常見的降維算法。

    PCA中,我們要做的是找到一個方向向量(Vector direction),當我們把所有的數據都投射到該向量上時,我們希望投射平均均方誤差能盡可能地小。方向向量是一個經過原點的向量,而投射誤差是從特征向量向該方向向量作垂線的長度。

    下面給出主成分分析問題的描述:

    問題是要將維數據降至維,目標是找到向量,,...,使得總的投射誤差最小。主成分分析與線性回顧的比較:

    主成分分析與線性回歸是兩種不同的算法。主成分分析最小化的是投射誤差(Projected Error),而線性回歸嘗試的是最小化預測誤差。線性回歸的目的是預測結果,而主成分分析不作任何預測。

    上圖中,左邊的是線性回歸的誤差(垂直于橫軸投影),右邊則是主要成分分析的誤差(垂直于紅線投影)。

    PCA將個特征降維到個,可以用來進行數據壓縮,如果 100 維的向量最后可以用 10 維來表示,那么壓縮率為 90%。同樣圖像處理領域的KL 變換使用PCA做圖像壓縮。但PCA 要保證降維后,還要保證數據的特性損失最小。

    PCA技術的一大好處是對數據進行降維的處理。我們可以對新求出的“主元”向量的重要性進行排序,根據需要取前面最重要的部分,將后面的維數省去,可以達到降維從而簡化模型或是對數據進行壓縮的效果。同時最大程度的保持了原有數據的信息。

    PCA技術的一個很大的優點是,它是完全無參數限制的。在PCA的計算過程中完全不需要人為的設定參數或是根據任何經驗模型對計算進行干預,最后的結果只與數據相關,與用戶是獨立的。

    但是,這一點同時也可以看作是缺點。如果用戶對觀測對象有一定的先驗知識,掌握了數據的一些特征,卻無法通過參數化等方法對處理過程進行干預,可能會得不到預期的效果,效率也不高。

    14.4 主成分分析算法

    參考視頻: 14 - 4 - Principal Component Analysis Algorithm (15 min).mkv

    PCA 減少維到維:

    第一步是均值歸一化。我們需要計算出所有特征的均值,然后令?μ。如果特征是在不同的數量級上,我們還需要將其除以標準差?。

    第二步是計算協方差矩陣covariance matrix):?

    第三步是計算協方差矩陣的特征向量eigenvectors):

    Octave 里我們可以利用奇異值分解singular value decomposition)來求解,[U, S, V]= svd(sigma)。

    對于一個?維度的矩陣,上式中的是一個具有與數據之間最小投射誤差的方向向量構成的矩陣。如果我們希望將數據從維降至維,我們只需要從中選取前個向量,獲得一個維度的矩陣,我們用表示,然后通過如下計算獲得要求的新特征向量:

    其中是維的,因此結果為維度。注,我們不對方差特征進行處理。

    14.5 選擇主成分的數量

    參考視頻: 14 - 5 - Choosing The Number Of Principal Components (13 min).mkv

    主要成分分析是減少投射的平均均方誤差:

    訓練集的方差為:

    我們希望在平均均方誤差與訓練集方差的比例盡可能小的情況下選擇盡可能小的值。

    如果我們希望這個比例小于 1%,就意味著原本數據的偏差有 99%都保留下來了,如果我們選擇保留 95%的偏差,便能非常顯著地降低模型中特征的維度了。

    我們可以先令,然后進行主要成分分析,獲得和,然后計算比例是否小于 1%。如果不是的話再令,如此類推,直到找到可以使得比例小于 1%的最小?值(原因是各個特征之間通常情況存在某種相關性)。

    還有一些更好的方式來選擇,當我們在Octave中調用“svd”函數的時候,我們獲得三個參數:[U, S, V] = svd(sigma)。

    其中的是一個的矩陣,只有對角線上有值,而其它單元都是 0,我們可以使用這個矩陣來計算平均均方誤差與訓練集方差的比例:

    也就是:

    在壓縮過數據后,我們可以采用如下方法來近似地獲得原有的特征:

    14.6 重建的壓縮表示

    參考視頻: 14 - 6 - Reconstruction from Compressed Representation (4 min).mkv

    在以前的視頻中,我談論PCA作為壓縮算法。在那里你可能需要把 1000 維的數據壓縮 100 維特征,或具有三維數據壓縮到一二維表示。所以,如果這是一個壓縮算法,應該能回到這個壓縮表示,回到你原有的高維數據的一種近似。

    所以,給定的,這可能 100 維,怎么回到你原來的表示,這可能是 1000 維的數組?

    PCA算法,我們可能有一個這樣的樣本。如圖中樣本,。我們做的是,我們把這些樣本投射到圖中這個一維平面。然后現在我們需要只使用一個實數,比如,指定這些點的位置后他們被投射到這一個三維曲面。給定一個點,我們怎么能回去這個原始的二維空間呢?為 2 維,為 1 維,,相反的方程為:,。如圖:

    如你所知,這是一個漂亮的與原始數據相當相似。所以,這就是你從低維表示回到未壓縮的表示。我們得到的數據的一個之間你的原始數據?,我們也把這個過程稱為重建原始數據。

    當我們認為試圖重建從壓縮表示??的初始值。所以,給定未標記的數據集,您現在知道如何應用PCA,你的帶高維特征和映射到這的低維表示。這個視頻,希望你現在也知道如何采取這些低維表示,映射到備份到一個近似你原有的高維數據。

    現在你知道如何實施應用PCA,我們將要做的事是談論一些技術在實際使用PCA很好,特別是,在接下來的視頻中,我想談一談關于如何選擇。

    14.7 主成分分析法的應用建議

    參考視頻: 14 - 7 - Advice for Applying PCA (13 min).mkv

    假使我們正在針對一張 100×100 像素的圖片進行某個計算機視覺的機器學習,即總共有 10000 個特征。

  • 第一步是運用主要成分分析將數據壓縮至 1000 個特征

  • 然后對訓練集運行學習算法

  • 在預測時,采用之前學習而來的將輸入的特征轉換成特征向量,然后再進行預測

  • 注:如果我們有交叉驗證集合測試集,也采用對訓練集學習而來的。

    錯誤的主要成分分析情況:一個常見錯誤使用主要成分分析的情況是,將其用于減少過擬合(減少了特征的數量)。這樣做非常不好,不如嘗試正則化處理。原因在于主要成分分析只是近似地丟棄掉一些特征,它并不考慮任何與結果變量有關的信息,因此可能會丟失非常重要的特征。然而當我們進行正則化處理時,會考慮到結果變量,不會丟掉重要的數據。

    另一個常見的錯誤是,默認地將主要成分分析作為學習過程中的一部分,這雖然很多時候有效果,最好還是從所有原始特征開始,只在有必要的時候(算法運行太慢或者占用太多內存)才考慮采用主要成分分析。

    代碼部分:

    機器學習練習 4 - K-means 和 PCA(主成分分析)

    代碼修改并注釋:黃海廣,haiguang2000@qq.com

    在本練習中,我們將實現 K-means 聚類,并使用它來壓縮圖像。 我們將從一個簡單的 2D 數據集開始,以了解 K-means 是如何工作的,然后我們將其應用于圖像壓縮。 我們還將對主成分分析進行實驗,并了解如何使用它來找到面部圖像的低維表示。

    K-means 聚類

    我們將實施和應用 K-means 到一個簡單的二維數據集,以獲得一些直觀的工作原理。 K-means 是一個迭代的,無監督的聚類算法,將類似的實例組合成簇。 該算法通過猜測每個簇的初始聚類中心開始,然后重復將實例分配給最近的簇,并重新計算該簇的聚類中心。 我們要實現的第一部分是找到數據中每個實例最接近的聚類中心的函數。

    import numpy as np import pandas as pd import matplotlib.pyplot as plt import seaborn as sb from?scipy.io?import?loadmat def find_closest_centroids(X, centroids):m = X.shape[0]k = centroids.shape[0]idx = np.zeros(m)for i in range(m):min_dist = 1000000for j in range(k):dist = np.sum((X[i,:] - centroids[j,:]) ** 2)if dist < min_dist:min_dist = distidx[i] = jreturn idx

    讓我們來測試這個函數,以確保它的工作正常。 我們將使用練習中提供的測試用例。

    data = loadmat('data/ex7data2.mat') X = data['X'] initial_centroids = initial_centroids = np.array([[3, 3], [6, 2], [8, 5]])idx = find_closest_centroids(X, initial_centroids) idx[0:3] array([0., 2., 1.])

    輸出與文本中的預期值匹配(記住我們的數組是從零開始索引的,而不是從一開始索引的,所以值比練習中的值低一個)。 接下來,我們需要一個函數來計算簇的聚類中心。 聚類中心只是當前分配給簇的所有樣本的平均值。

    data2 = pd.DataFrame(data.get('X'), columns=['X1', 'X2']) data2.head()
    X1X201234
    1.8420804.607572
    5.6585834.799964
    6.3525793.290854
    2.9040174.612204
    3.2319794.939894
    sb.set(context="notebook", style="white") sb.lmplot('X1', 'X2', data=data2, fit_reg=False) plt.show() def compute_centroids(X, idx, k):m, n = X.shapecentroids = np.zeros((k, n))for i in range(k):indices = np.where(idx == i)centroids[i,:] = (np.sum(X[indices,:], axis=1) / len(indices[0])).ravel()return centroids compute_centroids(X, idx, 3) array([[2.42830111, 3.15792418],[5.81350331, 2.63365645],[7.11938687, 3.6166844 ]])

    此輸出也符合練習中的預期值。 下一部分涉及實際運行該算法的一些迭代次數和可視化結果。 這個步驟是由于并不復雜,我將從頭開始構建它。 為了運行算法,我們只需要在將樣本分配給最近的簇并重新計算簇的聚類中心。

    def run_k_means(X, initial_centroids, max_iters):m, n = X.shapek = initial_centroids.shape[0]idx = np.zeros(m)centroids = initial_centroidsfor i in range(max_iters):idx = find_closest_centroids(X, centroids)centroids = compute_centroids(X, idx, k)return idx, centroids idx, centroids = run_k_means(X, initial_centroids, 10) cluster1 = X[np.where(idx == 0)[0],:] cluster2 = X[np.where(idx == 1)[0],:] cluster3 = X[np.where(idx == 2)[0],:]fig, ax = plt.subplots(figsize=(12,8)) ax.scatter(cluster1[:,0], cluster1[:,1], s=30, color='r', label='Cluster 1') ax.scatter(cluster2[:,0], cluster2[:,1], s=30, color='g', label='Cluster 2') ax.scatter(cluster3[:,0], cluster3[:,1], s=30, color='b', label='Cluster 3') ax.legend() plt.show()

    我們跳過的一個步驟是初始化聚類中心的過程。 這可以影響算法的收斂。 我們的任務是創建一個選擇隨機樣本并將其用作初始聚類中心的函數。

    def init_centroids(X, k):m, n = X.shapecentroids = np.zeros((k, n))idx = np.random.randint(0, m, k)for i in range(k):centroids[i,:] = X[idx[i],:]return centroids init_centroids(X, 3) array([[0.99253246, 5.01567424],[6.63060699, 3.01502301],[4.88804332, 5.50670795]]) from sklearn.cluster import KMeans#導入kmeans庫model = KMeans(n_clusters=3, n_init=100, n_jobs=-1) model.fit(data2) KMeans(algorithm='auto', copy_x=True, init='k-means++', max_iter=300,n_clusters=3, n_init=100, n_jobs=-1, precompute_distances='auto',random_state=None, tol=0.0001, verbose=0) centroids = model.cluster_centers_ print(centroids.shape)C = model.predict(data2) print(C.shape) (3, 2) (300,) centroids[C].shape (300, 2)

    肘部法則

    當人們在討論,選擇聚類數目的方法時,有一個可能會談及的方法叫作“肘部法則”。關于“肘部法則”,我們所需要做的是改變 K 值,也就是聚類類別數目的總數。我們用一個聚類來運行 K 均值聚類方法。這就意味著,所有的數據都會分到一個聚類里,然后計算成本函數或者計算畸變函數 J。K 代表聚類數字。

    我們可能會得到一條類似于這樣的曲線。像一個人的肘部。這就是“肘部法則”所做的,讓我們來看這樣一個圖,看起來就好像有一個很清楚的肘在那兒。好像人的手臂,如果你伸出你的胳膊,那么這就是你的肩關節、肘關節、手。這就是“肘部法則”。你會發現這種模式,它的畸變值會迅速下降,從 1 到 2,從 2 到 3 之后,你會在 2 的時候達到一個肘點。在此之后,畸變值就下降的非常慢,看起來就像使用 3 個聚類來進行聚類是正確的,這是因為那個點是曲線的肘點,畸變值下降得很快,K=2 之后就下降得很慢,那么我們就選 K=2。當你應用“肘部法則”的時候,如果你得到了一個像下面這樣的圖,那么這將是一種用來選擇聚類個數的合理方法。

    import numpy as np from sklearn.cluster import KMeans from scipy.spatial.distance import cdist import matplotlib.pyplot as pltc1x = np.random.uniform(0.5, 1.5, (1, 10)) c1y = np.random.uniform(0.5, 1.5, (1, 10)) c2x = np.random.uniform(3.5, 4.5, (1, 10)) c2y = np.random.uniform(3.5, 4.5, (1, 10)) x = np.hstack((c1x, c2x)) y = np.hstack((c1y, c2y)) X = np.vstack((x, y)).TK = range(1, 10) meanDispersions = [] for k in K:kmeans = KMeans(n_clusters=k)kmeans.fit(X)meanDispersions.append(sum(np.min(cdist(X, kmeans.cluster_centers_, 'euclidean'), axis=1)) / X.shape[0])plt.plot(K, meanDispersions, 'bx-') plt.xlabel('k') plt.ylabel('Average Dispersion') plt.title('Selecting k with the Elbow Method') plt.show() #導入相應的包 import scipy import scipy.cluster.hierarchy as sch from scipy.cluster.vq import vq,kmeans,whiten import numpy as np import matplotlib.pylab as plt import pandas as pd from sklearn import preprocessing from sklearn.decomposition import PCA newData=np.load("data/filename.npy") newData array([[-1.18945132, -0.31092235],[ 2.06415695, -0.74854414],[-1.43769023, -0.80669682],[-3.23039706, 0.84519783],[ 2.36892693, -0.44480961],[ 0.28997221, 2.79266758],[ 1.2099519 , -0.00638496],[-2.09689459, -0.22796377],[ 5.50091159, -0.14275827],[-3.47948639, -0.94978548]]) #1. 層次聚類 #生成點與點之間的距離矩陣,這里用的歐氏距離: disMat = sch.distance.pdist(newData,'euclidean') #進行層次聚類: Z=sch.linkage(disMat,method='average') #將層級聚類結果以樹狀圖表示出來并保存為plot_dendrogram.png P=sch.dendrogram(Z)

    dbscan 密度聚類

    import numpy as np import matplotlib.pyplot as plt from sklearn.datasets.samples_generator import make_blobs # from .agglomerative_clustering import test_AgglomerativeClustering,test_AgglomerativeClustering_nclusters,test_AgglomerativeClustering_linkage # from .dbscan import test_DBSCAN,test_DBSCAN_epsilon,test_DBSCAN_min_samples # from chapters.Cluster_EM.gmm import test_GMM,test_GMM_cov_type,test_GMM_n_components # from .kmeans import test_Kmeans,test_Kmeans_n_init,test_Kmeans_nclustersdef create_data(centers,num=100,std=0.7):'''生成用于聚類的數據集:param centers: 聚類的中心點組成的數組。如果中心點是二維的,則產生的每個樣本都是二維的。:param num: 樣本數:param std: 每個簇中樣本的標準差:return: 用于聚類的數據集。是一個元組,第一個元素為樣本集,第二個元素為樣本集的真實簇分類標記'''X, labels_true = make_blobs(n_samples=num, centers=centers, cluster_std=std)return X,labels_true def plot_data(*data):'''繪制用于聚類的數據集:param data: 可變參數。它是一個元組。元組元素依次為:第一個元素為樣本集,第二個元素為樣本集的真實簇分類標記:return: None'''X,labels_true=datalabels=np.unique(labels_true)fig=plt.figure()ax=fig.add_subplot(1,1,1)colors='rgbyckm' # 每個簇的樣本標記不同的顏色for i,label in enumerate(labels):position=labels_true==labelax.scatter(X[position,0],X[position,1],label="cluster %d"%label,color=colors[i%len(colors)])ax.legend(loc="best",framealpha=0.5)ax.set_xlabel("X[0]")ax.set_ylabel("Y[1]")ax.set_title("data")plt.show() from sklearn import cluster from sklearn.metrics import adjusted_rand_score import matplotlib.pyplot as plt plt.figure(figsize=(12,12)) def test_DBSCAN(*data):'''測試 DBSCAN 的用法:param data: 可變參數。它是一個元組。元組元素依次為:第一個元素為樣本集,第二個元素為樣本集的真實簇分類標記:return: None'''X,labels_true=dataclst=cluster.DBSCAN()predicted_labels=clst.fit_predict(X)print("ARI:%s"% adjusted_rand_score(labels_true,predicted_labels))print("Core sample num:%d"%len(clst.core_sample_indices_)) def test_DBSCAN_epsilon(*data):'''測試 DBSCAN 的聚類結果隨 eps 參數的影響:param data: 可變參數。它是一個元組。元組元素依次為:第一個元素為樣本集,第二個元素為樣本集的真實簇分類標記:return: None'''X,labels_true=dataepsilons=np.logspace(-1,1.5)ARIs=[]Core_nums=[]for epsilon in epsilons:clst=cluster.DBSCAN(eps=epsilon)predicted_labels=clst.fit_predict(X)ARIs.append( adjusted_rand_score(labels_true,predicted_labels))Core_nums.append(len(clst.core_sample_indices_))## 繪圖fig=plt.figure()ax=fig.add_subplot(1,2,1)ax.plot(epsilons,ARIs,marker='+')ax.set_xscale('log')ax.set_xlabel(r"$\epsilon$")ax.set_ylim(0,1)ax.set_ylabel('ARI')ax=fig.add_subplot(1,2,2)ax.plot(epsilons,Core_nums,marker='o')ax.set_xscale('log')ax.set_xlabel(r"$\epsilon$")ax.set_ylabel('Core_Nums')fig.suptitle("DBSCAN")plt.show() def test_DBSCAN_min_samples(*data):'''測試 DBSCAN 的聚類結果隨 min_samples 參數的影響:param data: 可變參數。它是一個元組。元組元素依次為:第一個元素為樣本集,第二個元素為樣本集的真實簇分類標記:return: None'''X,labels_true=datamin_samples=range(1,100)ARIs=[]Core_nums=[]for num in min_samples:clst=cluster.DBSCAN(min_samples=num)predicted_labels=clst.fit_predict(X)ARIs.append( adjusted_rand_score(labels_true,predicted_labels))Core_nums.append(len(clst.core_sample_indices_))## 繪圖fig=plt.figure()ax=fig.add_subplot(1,2,1)ax.plot(min_samples,ARIs,marker='+')ax.set_xlabel( "min_samples")ax.set_ylim(0,1)ax.set_ylabel('ARI')ax=fig.add_subplot(1,2,2)ax.plot(min_samples,Core_nums,marker='o')ax.set_xlabel( "min_samples")ax.set_ylabel('Core_Nums')fig.suptitle("DBSCAN")plt.show()centers=[[1,1],[2,2],[1,2],[10,20]] # 用于產生聚類的中心點 X,labels_true=create_data(centers,1000,0.5) # 產生用于聚類的數據集 X array([[0.81394428, 0.97283296],[2.39126942, 1.39691895],[0.52294212, 2.28195147],...,[0.07392303, 0.23407894],[0.92014917, 1.63693107],[0.95976852, 1.00443603]]) labels_true array([0, 1, 2, 1, 2, 2, 3, 3, 3, 3, 3, 2, 2, 1, 1, 0, 0, 0, 2, 1, 3, 1,0, 1, 1, 1, 1, 0, 1, 2, 3, 2, 3, 1, 0, 1, 3, 2, 3, 2, 2, 2, 2, 3,2, 2, 2, 0, 1, 3, 0, 2, 1, 0, 2, 2, 3, 2, 2, 1, 3, 3, 1, 2, 2, 0,1, 3, 1, 0, 2, 0, 0, 0, 0, 1, 0, 1, 0, 3, 0, 3, 0, 1, 2, 2, 0, 1,1, 3, 0, 1, 0, 3, 0, 0, 1, 3, 3, 3, 0, 1, 0, 1, 0, 1, 1, 2, 2, 2,1, 1, 3, 2, 2, 2, 2, 1, 2, 1, 1, 0, 2, 0, 1, 1, 1, 1, 1, 3, 2, 0,0, 1, 3, 1, 0, 3, 3, 2, 3, 1, 1, 2, 1, 0, 2, 3, 0, 1, 3, 2, 2, 2,0, 2, 2, 0, 3, 0, 1, 0, 3, 3, 0, 0, 3, 2, 3, 1, 3, 0, 0, 1, 0, 1,3, 3, 3, 1, 3, 2, 3, 2, 0, 0, 2, 1, 1, 2, 3, 1, 2, 3, 0, 3, 1, 0,0, 1, 3, 2, 1, 1, 0, 3, 1, 2, 2, 3, 0, 0, 2, 2, 1, 3, 3, 0, 2, 0,0, 2, 1, 0, 3, 0, 1, 3, 2, 2, 0, 0, 3, 3, 2, 2, 1, 3, 0, 1, 3, 1,2, 2, 0, 3, 0, 2, 2, 2, 2, 2, 1, 2, 0, 2, 0, 0, 2, 3, 1, 3, 3, 3,3, 3, 3, 0, 1, 3, 2, 0, 1, 2, 2, 3, 0, 1, 1, 0, 3, 0, 3, 1, 2, 2,3, 0, 0, 3, 1, 0, 3, 2, 2, 0, 3, 2, 1, 0, 3, 3, 2, 1, 0, 1, 3, 3,0, 1, 2, 0, 3, 3, 0, 2, 0, 0, 0, 2, 3, 0, 2, 3, 1, 2, 1, 1, 3, 3,1, 2, 2, 0, 0, 2, 0, 3, 1, 3, 1, 2, 2, 1, 2, 0, 0, 1, 2, 1, 1, 1,0, 0, 1, 3, 2, 3, 3, 0, 3, 1, 1, 1, 0, 3, 1, 1, 3, 1, 3, 0, 3, 3,1, 0, 2, 0, 0, 2, 2, 1, 2, 3, 2, 2, 0, 2, 2, 1, 3, 1, 1, 2, 3, 1,3, 2, 3, 2, 1, 3, 3, 0, 1, 1, 3, 2, 1, 1, 2, 3, 1, 3, 0, 3, 0, 2,3, 0, 0, 2, 3, 2, 3, 0, 0, 3, 3, 3, 0, 0, 2, 3, 2, 3, 3, 0, 2, 3,2, 3, 0, 1, 1, 1, 3, 0, 3, 0, 1, 0, 3, 0, 3, 1, 2, 2, 2, 1, 2, 0,3, 0, 0, 1, 0, 0, 3, 0, 2, 3, 3, 1, 0, 2, 1, 0, 2, 3, 0, 1, 2, 1,3, 0, 1, 2, 2, 3, 2, 1, 0, 1, 2, 3, 2, 3, 1, 2, 3, 0, 1, 2, 2, 2,3, 0, 3, 1, 1, 1, 2, 1, 1, 0, 0, 1, 1, 0, 3, 3, 0, 1, 1, 3, 1, 3,2, 2, 0, 3, 1, 0, 2, 1, 0, 2, 3, 1, 0, 1, 2, 3, 2, 2, 0, 0, 0, 1,0, 0, 0, 3, 3, 2, 0, 0, 2, 2, 1, 2, 1, 0, 0, 1, 0, 2, 3, 1, 1, 3,3, 1, 3, 3, 3, 1, 2, 0, 2, 1, 3, 3, 1, 1, 1, 0, 1, 3, 3, 3, 1, 1,2, 1, 2, 1, 0, 3, 1, 0, 1, 1, 2, 3, 1, 0, 1, 0, 1, 0, 3, 0, 0, 3,3, 0, 1, 3, 2, 3, 3, 3, 3, 2, 3, 2, 3, 2, 0, 3, 2, 0, 0, 2, 2, 0,1, 0, 2, 1, 0, 2, 2, 0, 0, 1, 0, 1, 0, 3, 3, 3, 1, 2, 3, 1, 0, 1,3, 3, 0, 1, 3, 2, 3, 3, 0, 0, 0, 3, 2, 1, 0, 0, 2, 3, 0, 0, 2, 0,3, 1, 3, 3, 3, 2, 1, 2, 3, 0, 1, 3, 3, 2, 3, 2, 2, 2, 1, 3, 0, 2,3, 2, 1, 2, 3, 3, 1, 1, 0, 0, 1, 2, 1, 1, 2, 3, 2, 0, 1, 0, 0, 3,2, 3, 1, 1, 2, 3, 1, 1, 0, 3, 2, 0, 1, 3, 2, 2, 0, 0, 1, 0, 3, 2,1, 0, 1, 3, 0, 3, 3, 3, 1, 2, 2, 0, 2, 2, 2, 0, 0, 0, 3, 2, 0, 0,1, 0, 1, 1, 2, 1, 0, 3, 0, 0, 3, 3, 3, 3, 2, 1, 0, 1, 2, 3, 1, 0,0, 0, 1, 1, 1, 3, 1, 0, 3, 2, 2, 2, 2, 2, 1, 2, 3, 1, 3, 0, 1, 2,3, 1, 0, 0, 0, 1, 2, 3, 2, 2, 3, 3, 2, 1, 0, 2, 2, 2, 2, 3, 1, 0,1, 2, 0, 0, 2, 1, 2, 0, 0, 2, 1, 0, 0, 2, 3, 0, 1, 2, 0, 3, 1, 2,1, 0, 3, 2, 0, 1, 0, 0, 3, 1, 2, 0, 0, 2, 2, 1, 1, 2, 3, 2, 3, 0,0, 2, 3, 2, 1, 0, 0, 3, 0, 0, 2, 3, 3, 3, 1, 3, 0, 2, 2, 3, 2, 1,0, 3, 3, 0, 1, 3, 3, 2, 2, 2, 3, 3, 2, 3, 2, 1, 3, 3, 3, 2, 0, 1,2, 1, 3, 1, 1, 1, 0, 1, 1, 0, 2, 1, 2, 2, 1, 3, 0, 2, 0, 1, 2, 1,1, 0, 3, 0, 2, 1, 1, 0, 1, 1, 0, 1, 0, 1, 2, 3, 1, 3, 3, 2, 1, 2,2, 1, 2, 3, 2, 2, 0, 3, 0, 1, 0, 0, 3, 1, 3, 1, 0, 2, 1, 2, 2, 2,3, 0, 3, 2, 1, 3, 1, 0, 2, 0]) test_DBSCAN(X,labels_true) # 調用 test_DBSCAN 函數 ARI:0.3326689255565291 Core sample num:990 test_DBSCAN_epsilon(X,labels_true) # 調用 test_DBSCAN_epsilon 函數 test_DBSCAN_min_samples(X,labels_true) # 調用 test_DBSCAN_min_samples 函數 import numpy as np import matplotlib.pyplot as plt from sklearn import datasets %matplotlib inline X1, y1=datasets.make_circles(n_samples=5000, factor=.6,noise=.05) X2, y2 = datasets.make_blobs(n_samples=1000, n_features=2, centers=[[1.2,1.2]], cluster_std=[[.1]],random_state=9)X = np.concatenate((X1, X2)) plt.scatter(X[:, 0], X[:, 1], marker='o') plt.show() from sklearn.cluster import KMeans y_pred = KMeans(n_clusters=3, random_state=9).fit_predict(X) plt.scatter(X[:, 0], X[:, 1], c=y_pred) plt.show() from sklearn.cluster import DBSCAN y_pred = DBSCAN().fit_predict(X) plt.scatter(X[:, 0], X[:, 1], c=y_pred) plt.show() y_pred = DBSCAN(eps = 0.1).fit_predict(X) plt.scatter(X[:, 0], X[:, 1], c=y_pred) plt.show() y_pred = DBSCAN(eps = 0.1, min_samples = 4).fit_predict(X) plt.scatter(X[:, 0], X[:, 1], c=y_pred) plt.show()

    Principal component analysis(主成分分析)

    PCA 是在數據集中找到“主成分”或最大方差方向的線性變換。 它可以用于降維。 在本練習中,我們首先負責實現 PCA 并將其應用于一個簡單的二維數據集,以了解它是如何工作的。 我們從加載和可視化數據集開始。

    data?=?loadmat('data/ex7data1.mat') X = data['X']fig, ax = plt.subplots(figsize=(12,8)) ax.scatter(X[:, 0], X[:, 1]) plt.show()

    PCA 的算法相當簡單。 在確保數據被歸一化之后,輸出僅僅是原始數據的協方差矩陣的奇異值分解。

    def pca(X):# normalize the featuresX = (X - X.mean()) / X.std()# compute the covariance matrixX = np.matrix(X)cov = (X.T * X) / X.shape[0]# perform SVDU, S, V = np.linalg.svd(cov)return U, S, V U, S, V = pca(X) U, S, V (matrix([[-0.79241747, -0.60997914],[-0.60997914, 0.79241747]]),array([1.43584536, 0.56415464]),matrix([[-0.79241747, -0.60997914],[-0.60997914, 0.79241747]])) print(X.shape) print(U.shape) print(S.shape) print(V.shape) (50, 2) (2, 2) (2,) (2, 2)

    現在我們有主成分(矩陣 U),我們可以用這些來將原始數據投影到一個較低維的空間中。 對于這個任務,我們將實現一個計算投影并且僅選擇頂部 K 個分量的函數,有效地減少了維數。

    def project_data(X, U, k):U_reduced = U[:,:k]return np.dot(X, U_reduced) Z?=?project_data(X,?U,?1)

    我們也可以通過反向轉換步驟來恢復原始數據。

    def recover_data(Z, U, k):U_reduced = U[:,:k]return np.dot(Z, U_reduced.T) X_recovered?=?recover_data(Z,?U,?1) fig, ax = plt.subplots(figsize=(12,8)) ax.scatter(list(X_recovered[:, 0]), list(X_recovered[:, 1])) plt.show()

    請注意,第一主成分的投影軸基本上是數據集中的對角線。 當我們將數據減少到一個維度時,我們失去了該對角線周圍的變化,所以在我們的再現中,一切都沿著該對角線。

    參考資料

    [1]?機器學習課程:?https://www.coursera.org/course/ml
    [2]?黃海廣:?https://github.com/fengdu78
    [3]?github:?https://github.com/fengdu78/Coursera-ML-AndrewNg-Notes
    [4]?作業代碼:?https://github.com/fengdu78/Coursera-ML-AndrewNg-Notes/blob/master/codeex7-kmeans%20and%20PCA/ML-Exercise7.ipynb
    [5]?markdown 文件:?https://github.com/fengdu78/Coursera-ML-AndrewNg-Notes/blob/master/markdown/week8.md
    [6]?pdf 文件:?https://github.com/fengdu78/Coursera-ML-AndrewNg-Notes/blob/master/機器學習個人筆記完整版v5.4-A4打印版.pdf

    關于本站

    “機器學習初學者”公眾號由是黃海廣博士創建,黃博個人知乎粉絲23000+,github排名全球前100名(33000+)。本公眾號致力于人工智能方向的科普性文章,為初學者提供學習路線和基礎資料。原創作品有:吳恩達機器學習個人筆記、吳恩達深度學習筆記等。

    往期精彩回顧

    • 那些年做的學術公益-你不是一個人在戰斗

    • 適合初學者入門人工智能的路線及資料下載

    • 吳恩達機器學習課程筆記及資源(github標星12000+,提供百度云鏡像)

    • 吳恩達深度學習筆記及視頻等資源(github標星8500+,提供百度云鏡像)

    • 《統計學習方法》的python代碼實現(github標星7200+)

    • 機器學習的數學精華(在線閱讀版)

    備注:加入本站微信群或者qq群,請回復“加群

    加入知識星球(4300+用戶,ID:92416895),請回復“知識星球

    總結

    以上是生活随笔為你收集整理的经典算法笔记:无监督算法(聚类、降维)的全部內容,希望文章能夠幫你解決所遇到的問題。

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

    主站蜘蛛池模板: 国产精品国产三级国产传播 | 亚洲精品天堂在线观看 | 日本韩国视频 | c逼| 精品人妻一区二区三区四区不卡 | 亚洲逼院 | 国产成人一区二区三区小说 | 激情欧美一区二区三区精品 | 国产又粗又猛又黄又爽 | 欧美成年人网站 | 日本成人在线网站 | 97超碰人人看 | 欧美激情在线 | 日本va在线观看 | 欧美又黑又粗 | 中文字幕25页 | 国产人妻人伦精品1国产盗摄 | 国产色拍 | 午夜老司机免费视频 | 亚洲第一成人av | 亚洲综合在线观看视频 | 色又黄又爽 | 综合亚洲网 | 欧美做受| 日韩有码视频在线 | caoporn免费在线 | 欧美日韩亚洲系列 | 在线免费毛片 | 中文天堂资源在线 | 亚洲精品偷拍 | 日本成人综合 | 日韩网站在线观看 | 成人依依网| 久久国产精品免费观看 | 丁香婷婷综合网 | 69视频入口| 99精品国产成人一区二区 | 在线视频一区二区三区四区 | 啪啪在线视频 | caoprom超碰 | 在线观看av一区二区 | 欧洲女同同性吃奶 | 另类综合网| 未满十八18禁止免费无码网站 | 一本大道久久久久精品嫩草 | 五月激情婷婷综合 | 久一久久| 久久久久久爱 | 国产高清在线视频观看 | 日韩有码中文字幕在线 | 免费观看亚洲视频 | 在线观看涩涩 | 亚洲欧美乱综合图片区小说区 | 九七av| 热玖玖 | 九九色综合 | 一级aaaa毛片 | 在线观看av免费 | 一女二男一黄一片 | 男人天堂av电影 | 久久伊人精品视频 | 91av一区二区三区 | 亚洲精品男女 | 国产精品无码av在线有声小说 | 国产免费a级片 | 久久99视频精品 | 久久国产这里只有精品 | 成人午夜福利视频 | 天干夜夜爽爽日日日日 | 在线观看中文字幕第一页 | 中文人妻av久久人妻18 | 日韩在线资源 | 东京热加勒比无码少妇 | 国产精品片 | 欧美一级一区二区 | 国产精品果冻传媒 | 大又大又粗又硬又爽少妇毛片 | 色8久久| 在线观看av一区 | 国产精久 | 在线观看国产三级 | 日本国产精品一区 | 91蝌蚪91九色白浆 | 欧美黑人性生活 | 欧美日韩亚洲成人 | 中文字幕亚洲无线码在线一区 | 精品色 | 久久精品高清 | 日本女优一区 | 国产一级爽片 | 国产熟妇搡bbbb搡bbbb | 香蕉视频99 | 色婷婷激情网 | 综合色婷婷 | 狐狸视频污 | 在线观看av毛片 | 国产成人免费片在线观看 | 人人干人人艹 | 在线视频日韩欧美 |