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