原創博客,轉載請聯系博主!
希望我思考問題的思路,也可以給大家一些啟發或者反思!
問題背景:
現在我們的手上有一組沒有明確規律,但是分布有明顯聚簇現象的樣本點,如下圖所示:
圖中數據集是顯然是個3維的數據集,包括橫縱坐標和色彩(高度),由於數據的分布比較不均勻,我們選擇分布比較典型的[300,305)區間的數據點進行處理
我們的目的是找出這個數據空間中數據比較集中的部分,根據肉眼對樣本的初步觀察,這篇文章將討論一個從橫軸的維度對數據較密集的區域進行識別的一個輕量算法,其實也就是找出數據空間中的所謂“條狀物”。
算法思路:
其實如果不限制處理數據的維度,那么一個更准確的算法思路是使用非圓形聚類算法對數據樣本進行處理,經過實驗結果也確實符合我們的想法。
在這里我們的思路是這樣的:
1.首先使用核密度估計算法對樣本區間進行一個直觀的統計
2.對樣本進行歸一化
3.對處理后的樣本做求導數(這里為了追求效率使用向后差分)
4.通過對樣本的統計結果使用有限狀態自動機進行掃描,得到一個記錄的峰值的結果
這里為了客觀衡量算法的效率和准確度我們使用一個 加速比 和 過濾比 作為標准。
過濾比: =得到的“條狀物”中的樣本的個數/樣本的全部個數
加速比: =得到的“條狀物”的橫軸長度/整個樣本橫軸區間長度
由於核密度估計的核函數有很多種選擇,包括高斯核,伽馬核,三角核,矩形核等,我們這里選擇相對比較平滑的高斯核核函數對樣本進行核密度估計統計,而且帶寬的選擇也有兩種一個是迭代計算的,結果擬合得比較真實准確但是速度比較慢,另一種是非迭代計算的,計算速度很快但是結果也過於“平滑”。如下圖所示:
非迭代計算核密度估計:
迭代計算核密度估計:
時間消耗對比也非常明顯:
所以我們處理的策略是: 用非迭代的核密度估計處理大區間的數據,當區間的長度小於一個閾值的時候,使用迭代的核密度估計對數據進行准確的擬合。
梳理下來總的思路可以用下圖來表示:
1.對過大的區間進行等分成“足夠小”的大區間
2.對分割后的區間進行遞歸的“統計+尋峰” (一個普通的遞歸處理,將起點放入peakStart數組中,終點放入peakEnd數組中)
自動機尋峰的思路是這樣的:
在對樣本進行歸一化處理和差分求導之后,根據對樣本的觀察,我們大致了解了這個樣本之中峰的大致的形狀,由此人工地去設定三個閾值作為自動機尋峰算法的參數:
第一個參數是判斷峰開始的斜率閾值
第二個參數是判斷到達峰頂的斜率閾值
第三個參數是判斷峰結束的斜率閾值
設定這三個閾值是為了防止數據中的快速抖動(平滑/“降噪“后也難以避免)導致自動狀態的錯誤或者出現過多細碎的"小峰"的狀況,如下圖所示是自動機的狀態轉換圖:
下圖是一次自動機尋峰之后的處理結果:
以下是這個算法對幾個不同的樣本區間進行處理的結果plot圖:
以及過濾比和加速比的結果:
實現代碼(R實現):
由於項目中的一些其他原因,盡管這個算法表現不錯,但最后也沒有運用到項目中去,也就沒有深入去做優化和修改。
R代碼在我的github中: https://github.com/yue9944882/R_Util/tree/master/FSM_scan_peak
想更細節了解歡迎聯系我的郵箱或者評論!