2021年5月25日 星期二

[學習筆記]分群_Clustering

某個供應商交的貨時常參差不齊但大多是能用,想貨品分類成尺寸接近的群組較能妥善運用,因此開始有了學習分群的想法...



分群應用情境

    在大部分工業應用情境中,產品有絕對的允收標準,比方設計者將公差帶定義出來,製作者選擇具有合格重現性的設備、製程,將參數瞄準公差中心尺寸製作,因而確保大部分的產品都落在公差帶內;而接收者進行檢測,依據設計公差判定是否允收,如同棒球的好球帶般,落在範圍內允收,範圍外判退,界線值本身是靜態的,每次能通過允收的產品不存在批次間的差異。

    但在某些場合,實務上可能不存在分類產品的絕對標準參考,比方說農產品,每個季節、年度、甚至同塊農地不同區域生長的作物不太可能有著類似的尺寸;又或是通過熱處理、化學處理的薄板金製程,製作程序固定但礙於經濟效益,下槽參數難以調整一致,即使是同批產品也可能具有一定落差。

    總和來說,在製程參數複雜且難以維持的情況下,不同批次的產品中心值可能是不同的。此時我們可能會比較想用相對標準來分選產品,將看起來較為一致、均勻、彼此類似的產品以群組圈選出來,此時的標準則根據該批次產品自身分布狀態決定,而非外在的客觀標準。

分群計算概念

    產品自身的分布情形既然是個數據組,能用常態分佈嘗試表達出單一群體特徵,透過計算出中心值、標準差,並且按68-95-99法則我們可以知道在中心值左右1個標準差內的密度是相對密集的,因為其他剩餘區域雖然涵蓋多個標準差,但地廣人稀,只包含了32%的案例。

    倘若假設樣本是由N個群體混合出來的數據組,也就是說我們希望算出N個群體特徵,也就是帶有N中心值以及與其對應的標準差,此時就可以應用分群演算法,目標是找到各個群組中心,能作為鄰近資料點的代表,其中最經典的做法就是K-mean。

    K-mean分群的步驟大致是,給定希望的分群數目,比方剛才提到的N,接著K-mean隨機選取N個中心值,接著計算每個數據點對N個中心值的距離,然後比較該數據點離哪個中心值最近,將該數據點圈粉到最近的中心值。

    每個數據點都被圈粉後,再次計算、並更新N個中心值,接著再做一次上述的比較與歸類動作。

    一直做到前次-當次中心值變動的程度小於某範圍就是收斂完成。

從以下學到深入淺出解釋:

https://chih-sheng-huang821.medium.com/%E6%A9%9F%E5%99%A8%E5%AD%B8%E7%BF%92-%E9%9B%86%E7%BE%A4%E5%88%86%E6%9E%90-k-means-clustering-e608a7fe1b43

簡單玩玩看分群

    設定兩個平均值,與隨機變數範圍跑出數組,並標定編號;看看分群後是否能還原原本的群體,使用工具如下:


  1. 用來產生數值的Python code,核心想法是random.gauss()產出兩組常態分布數據組
  2.   from random import random,uniform,gauss
    from statistics import stdev
    import matplotlib.pyplot as plt
    
    
    def gen_dataset(mean=0,var=1,amount=100):
        return [gauss(mean,var) for x in range(amount)] #generate normal distribution
    
    #tag each data point with a serial number
    def tag_data(data,begin_index=0):
        return [r'{},{:.3f}'.format(begin_index+ index,data[index]) for index in range(len(data))]
    
    def avg_and_sd(data):
        return sum(data)/len(data),stdev(data)
    
    set1= gen_dataset(mean=0,var=1,amount=50)
    set2= gen_dataset(mean=2,var=1,amount=50)
    
    #output to file would be easier to copy-paste to online tool
    f = open('output.txt','w')
    f.write('\n'.join(tuple(tag_data(set1))))
    f.close()
    
    print(avg_and_sd(set1))
    print(avg_and_sd(set2))
      
  3. 用來分類的線上服務,給定分群數量後按下"Clustering"就會幫你分群,缺點是無法複製資料與下載 : https://people.revoledu.com/kardi/tutorial/kMean/Online-K-Means-Clustering.html

測試資料 : 

  1. 群組A,均值0,標準差1;
  2. 群組B,均值2,標準差1。

跑完以後長這樣:


跑完以後發現 : 

  1. 在兩群體間交集區域的資料點被強制歸類到A'或B',有零星的資料脫離了原本的群組;想像起來合理,在原本群體離群較遠的資料,有可能是比較靠近對面群組的
  2. 由於分群強制資料點選邊站,分類後的平均值會跟原本的不一樣,有時候隔比較遠、有時候平移

結論是,在兩群組交集較大的時候無法準確還原本來的群體,反之,若均值隔很遠,標準差又很小的情況就很容易還原。


後記 : 尚在學習如何使用Python計算分群


沒有留言:

張貼留言