主頁(yè) > 知識(shí)庫(kù) > PHP局部異常因子算法-Local Outlier Factor(LOF)算法的具體實(shí)現(xiàn)解析

PHP局部異常因子算法-Local Outlier Factor(LOF)算法的具體實(shí)現(xiàn)解析

熱門標(biāo)簽:天津電銷外呼系統(tǒng)違法嗎 銀行信貸電話機(jī)器人 滄州電銷外呼系統(tǒng)價(jià)格 合肥ai電銷機(jī)器人費(fèi)用 溫州外呼系統(tǒng)招商 凱立德地鐵站地圖標(biāo)注 上海400客服電話怎么申請(qǐng) 手機(jī)外呼系統(tǒng)什么原理 400電話個(gè)人能不能辦理

這兩天在完善自己系統(tǒng)的過(guò)程中要實(shí)現(xiàn)一個(gè)查找異常的功能,于是在朋友的指點(diǎn)下學(xué)習(xí)并實(shí)現(xiàn)了異常點(diǎn)查找的一個(gè)基本算法“局部異常因子算法-Local Outlier Factor(LOF)算法”。

首先,找相關(guān)說(shuō)明看看這是個(gè)什么東西吧。

我參考了這一篇文章: 異常點(diǎn)/離群點(diǎn)檢測(cè)算法——LOF

大致明白了lof算法是在講什么,我的理解還有很多不完善的地方,不過(guò)還是作為一個(gè)初學(xué)者寫出來(lái)供大家批評(píng)指正。

根據(jù)我的理解大致描述如下:

1、 k-distance,點(diǎn)p的第k距離就是距離點(diǎn)p第k遠(yuǎn)的那個(gè)點(diǎn)的距離,k可以是任意值。在實(shí)際生活中可能會(huì)這樣:小明說(shuō)“小紅家是離我家第五近的,小趙、小錢、小孫、小李家都比她家離我家近”所以此處小紅家距離小明家的距離就是小明家k為5時(shí)的第k距離。

2、k-distance neighborhood of p,第k距離領(lǐng)域,按照上面的例子就是{小趙、小錢、小孫、小李、小紅},把離p最近的k個(gè)點(diǎn)放入一個(gè)數(shù)組就是第k距離領(lǐng)域了。

3、reach-distance:可達(dá)距離。點(diǎn)o到點(diǎn)p的第k可達(dá)距離分兩種情況,一種是p在o的第k距離領(lǐng)域那個(gè)數(shù)組中,這時(shí)候可達(dá)距離等于第k距離,第二種就是p離點(diǎn)o比較遠(yuǎn),不在o的第k距離領(lǐng)域中,此時(shí)的可達(dá)距離即為真實(shí)距離。依然使用上述的例子,小趙家在小明家的第k鄰域中,所以可達(dá)距離就是第k距離,就是小紅家的距離,而二狗子家里小明家很遠(yuǎn),可達(dá)距離就是真實(shí)距離了。

4、local reachability density:局部可達(dá)密度。點(diǎn)p的局部可達(dá)密度是指點(diǎn)p第k距離鄰域中所有成員到點(diǎn)p的可達(dá)距離的平均值的倒數(shù),有點(diǎn)復(fù)雜,不過(guò)多讀幾遍還是蠻好理解的,就不舉例子了。

5、local outlier factor:局部離群因子。點(diǎn)p的局部離群因子即為領(lǐng)域中所有點(diǎn)的局部可達(dá)密度的平均數(shù)比點(diǎn)p的局部可達(dá)密度,不做解釋。
到這里為止就是我對(duì)lof算法的一個(gè)大致理解,具體講解還要看上面我參考的那篇文章,寫的很清楚。

接下來(lái)我找了網(wǎng)上的一篇對(duì)此算法的實(shí)現(xiàn),很遺憾沒(méi)有php版本,于是我就找到了這篇文章:基于密度的局部離群點(diǎn)檢測(cè)(lof算法) (Java 實(shí)現(xiàn))

如題所示,是一篇Java實(shí)現(xiàn),于是我就在大神的基礎(chǔ)上對(duì)其進(jìn)行修改,改成了一個(gè)php的版本。因?yàn)閷?duì)迭代器理解的不是很好,所以迭代器實(shí)現(xiàn)部分改成了一般函數(shù),有機(jī)會(huì)再進(jìn)行完善。

如下:

?php
 
 
	class DataNode {  
	private  $nodeName; // 樣本點(diǎn)名  
    private  $dimensioin; // 樣本點(diǎn)的維度  
    private  $kDistance; // k-距離  
    private  $kNeighbor = array();// k-領(lǐng)域  
    private $distance; // 到給定點(diǎn)的歐幾里得距離  
    private $reachDensity;// 可達(dá)密度  
    private $reachDis;// 可達(dá)距離  
  
    private $lof;// 局部離群因子  
  
    public function __construct() {  
	
				$num = func_num_args();   //獲得參數(shù)個(gè)數(shù)
                $args = func_get_args();   //獲得參數(shù)列表數(shù)組
                switch($num){
                        case 0:
                              
                                break;
                        case 2:
                                $this->__call('__construct2', $args);
                                break;
                }
       
    }  
	
	 public function __call($name, $arg) //根據(jù)函數(shù)名調(diào)用函數(shù)
        {
                return call_user_func_array(array($this, $name), $arg);
        }
	
	 public function __construct2($nodeName, $dimensioin)
        {
                $this->nodeName = $nodeName;  
				$this->dimensioin = $dimensioin;  
        }
  
    public function getNodeName() {  
        return $this->nodeName;  
    }  
  
    public function setNodeName($nodeName) {  
        $this->nodeName = $nodeName;  
    }  
  
    public function getDimensioin() {  
        return $this->dimensioin;  
    }  
  
    public function setDimensioin($dimensioin) {  
        $this->dimensioin = $dimensioin;  
    }  
  
    public function getkDistance() {  
        return $this->kDistance;  
    }  
  
    public function setkDistance($kDistance) {  
        $this->kDistance = $kDistance;  
    }  
  
    public function getkNeighbor() {  
        return  $this->kNeighbor;  
    }  
  
    public function setkNeighbor($kNeighbor) {  
        $this->kNeighbor = $kNeighbor;  
    }  
  
    public function getDistance() {  
        return $this->distance;  
    }  
  
    public function setDistance($distance) {  
        $this->distance = $distance;  
    }  
  
    public function getReachDensity() {  
        return  $this->reachDensity;  
    }  
  
    public function setReachDensity($reachDensity) {  
        $this->reachDensity = $reachDensity;  
    }  
  
    public function getReachDis() {  
        return $this->reachDis;  
    }  
  
    public function setReachDis($reachDis) {  
        $this->reachDis = $reachDis;  
    }  
  
    public function getLof() {  
        return $this->lof;  
    }  
  
    public function setLof($lof) {  
        $this->lof = $lof;  
    }  
  
}
 
 
 
 
 
	class OutlierNodeDetect {  
    private static $INT_K = 5;//正整數(shù)K  
  
    // 1.找到給定點(diǎn)與其他點(diǎn)的歐幾里得距離  
    // 2.對(duì)歐幾里得距離進(jìn)行排序,找到前5位的點(diǎn),并同時(shí)記下k距離  
    // 3.計(jì)算每個(gè)點(diǎn)的可達(dá)密度  
    // 4.計(jì)算每個(gè)點(diǎn)的局部離群點(diǎn)因子  
    // 5.對(duì)每個(gè)點(diǎn)的局部離群點(diǎn)因子進(jìn)行排序,輸出。  
    public function getOutlierNode($allNodes) {  
        $kdAndKnList =  $this->getKDAndKN($allNodes); 
         $this->calReachDis($kdAndKnList);  
         $this->calReachDensity($kdAndKnList);  
         $this->calLof($kdAndKnList);  
        //降序排序  
         $kdAndKnList = $this->rsortArr($kdAndKnList);
  
        return $kdAndKnList;  
    }  
  
    /** 
     * 計(jì)算每個(gè)點(diǎn)的局部離群點(diǎn)因子 
     * @param kdAndKnList 
     */  
    private function calLof($kdAndKnList) {  
         foreach($kdAndKnList as $node):   
            $tempNodes = $node->getkNeighbor();  
            $sum = 0.0;   
            foreach($tempNodes as $tempNode):  
                $rd = $this->getRD($tempNode->getNodeName(), $kdAndKnList);  
                $sum = $rd / $node->getReachDensity() + $sum;  
            endforeach;  
            $sum = $sum / (double) self::$INT_K;  
            $node->setLof($sum);  
         endforeach;  
    }  
  
    /** 
     * 計(jì)算每個(gè)點(diǎn)的可達(dá)距離 
     * @param kdAndKnList 
     */  
    private function calReachDensity($kdAndKnList) { 
        foreach($kdAndKnList as $node):  
            $tempNodes = $node->getkNeighbor();  
            $sum = 0.0;  
            $rd = 0.0;  
			foreach($tempNodes as $tempNode):  			
                $sum = $tempNode->getReachDis() + $sum;  
            endforeach;  
            $rd = (double) self::$INT_K / $sum;  
            $node->setReachDensity($rd);  
        endforeach;  
    }  
      
    /** 
     * 計(jì)算每個(gè)點(diǎn)的可達(dá)密度,reachdis(p,o)=max{ k-distance(o),d(p,o)} 
     * @param kdAndKnList 
     */  
    private function calReachDis($kdAndKnList) { 
		//for (DataNode node : kdAndKnList) {
       foreach($kdAndKnList as $node):  
            $tempNodes = $node->getkNeighbor();  
            //for (DataNode tempNode : tempNodes) {  
            foreach($tempNodes as $tempNode):  
                //獲取tempNode點(diǎn)的k-距離  
                $kDis = $this->getKDis($tempNode->getNodeName(), $kdAndKnList); 
				 
                if ($kDis  $tempNode->getDistance()) {  
                    $tempNode->setReachDis($tempNode->getDistance());  
                } else {  
                    $tempNode->setReachDis($kDis);  
                }  
            endforeach;  
        endforeach;  
    }  
  
    /** 
     * 獲取某個(gè)點(diǎn)的k-距離(kDistance) 
     * @param nodeName 
     * @param nodeList 
     * @return 
     */  
    private function getKDis($nodeName,$nodeList) {  
        $kDis = 0;  
        //for (DataNode node : nodeList) {  
        foreach($nodeList as $node):  
            if ($this->strcomp(trim($nodeName),trim($node->getNodeName()))) {  
                $kDis =$node->getkDistance();  
                break;  
            }  
        endforeach;  
        return $kDis;  
  
    }  
	
	
	private	function strcomp($str1,$str2){ 
		if($str1 == $str2){ 
			return TRUE; 
		}else{ 
			return FALSE; 
		} 
	} 
  
    /** 
     * 獲取某個(gè)點(diǎn)的可達(dá)距離 
     * @param nodeName 
     * @param nodeList 
     * @return 
     */  
    private function getRD($nodeName, $nodeList) {  
        $kDis = 0;  
        //for (DataNode node : nodeList) {  
        foreach($nodeList as $node):  
            //if (nodeName.trim().equals(node.getNodeName().trim())) {  
            if ($this->strcomp(trim($nodeName),trim($node->getNodeName()))) {  
                $kDis = $node->getReachDensity();  
                break;  
            }  
        endforeach;  
        return $kDis;  
  
    }  
      
    /** 
     * 計(jì)算給定點(diǎn)NodeA與其他點(diǎn)NodeB的歐幾里得距離(distance),并找到NodeA點(diǎn)的前5位NodeB,然后記錄到NodeA的k-領(lǐng)域(kNeighbor)變量。 
     * 同時(shí)找到NodeA的k距離,然后記錄到NodeA的k-距離(kDistance)變量中。 
     * 處理步驟如下: 
     * 1,計(jì)算給定點(diǎn)NodeA與其他點(diǎn)NodeB的歐幾里得距離,并記錄在NodeB點(diǎn)的distance變量中。 
     * 2,對(duì)所有NodeB點(diǎn)中的distance進(jìn)行升序排序。 
     * 3,找到NodeB點(diǎn)的前5位的歐幾里得距離點(diǎn),并記錄到到NodeA的kNeighbor變量中。 
     * 4,找到NodeB點(diǎn)的第5位距離,并記錄到NodeA點(diǎn)的kDistance變量中。 
     * @param allNodes 
     * @return ListNode> 
     */  
    private function getKDAndKN($allNodes) {  
        $kdAndKnList = array();  
        for ($i = 0 ; $i   count($allNodes); $i++) {  
            $tempNodeList = array();
            $nodeA = new DataNode($allNodes[$i]->getNodeName(), $allNodes[$i]->getDimensioin());  
            //1,找到給定點(diǎn)NodeA與其他點(diǎn)NodeB的歐幾里得距離,并記錄在NodeB點(diǎn)的distance變量中。  
            for ($j = 0; $j  count($allNodes); $j++) {  
                $nodeB = new DataNode($allNodes[$j]->getNodeName(), $allNodes[$j]->getDimensioin());  
                //計(jì)算NodeA與NodeB的歐幾里得距離(distance)  
                $tempDis = $this->getDis($nodeA, $nodeB);  
                $nodeB->setDistance($tempDis);
				array_push($tempNodeList,$nodeB);				
                //$tempNodeList.add(nodeB);  
            }  
            //2,對(duì)所有NodeB點(diǎn)中的歐幾里得距離(distance)進(jìn)行升序排序。
			$tempNodeList = $this->sortArr($tempNodeList);  			
				
					
			$neighArr = array();
            for ($k = 1; $k = self::$INT_K; $k++) {  
                //3,找到NodeB點(diǎn)的前5位的歐幾里得距離點(diǎn),并記錄到到NodeA的kNeighbor變量中。 
				array_push(	$neighArr ,$tempNodeList[$k]);	
					
                if ($k == self::$INT_K - 1) {  
                    //4,找到NodeB點(diǎn)的第5位距離,并記錄到NodeA點(diǎn)的kDistance變量中。  
                    $nodeA->setkDistance($tempNodeList[$k]->getDistance());
                }  
            }  
			
			$nodeA->setkNeighbor($neighArr);
            array_push($kdAndKnList,$nodeA);  
        }  
		
        return $kdAndKnList;  
    }  
      
    /** 
     * 計(jì)算給定點(diǎn)A與其他點(diǎn)B之間的歐幾里得距離。 
     * 歐氏距離的公式: 
     * d=sqrt( ∑(xi1-xi2)^2 ) 這里i=1,2..n 
     * xi1表示第一個(gè)點(diǎn)的第i維坐標(biāo),xi2表示第二個(gè)點(diǎn)的第i維坐標(biāo) 
     * n維歐氏空間是一個(gè)點(diǎn)集,它的每個(gè)點(diǎn)可以表示為(x(1),x(2),...x(n)), 
     * 其中x(i)(i=1,2...n)是實(shí)數(shù),稱為x的第i個(gè)坐標(biāo),兩個(gè)點(diǎn)x和y=(y(1),y(2)...y(n))之間的距離d(x,y)定義為上面的公式. 
     * @param A 
     * @param B 
     * @return 
     */  
    private function getDis($A, $B) {  
        $dis = 0.0;  
        $dimA = $A->getDimensioin();  
        $dimB = $B->getDimensioin();  
        if (count($dimA) == count($dimB)) {  
            for ($i = 0; $i  count($dimA); $i++) {  
                $temp = pow($dimA[$i] - $dimB[$i], 2);  
                $dis = $dis + $temp;  
            }  
            $dis = pow($dis, 0.5);  
        }  
        return $dis;  
    }  
	
	
    //Distance比較
    private function compareAandB($arr,$A, $B) {  
        if(($arr[$A]->getDistance()-$arr[$B]->getDistance())0)     
                return -1;    
            else if(($arr[$A]->getDistance()-$arr[$B]->getDistance())>0)    
                return 1;    
            else return 0;   
    }  
  
    //lof比較
    private function compareAandBLof($arr,$A, $B) { 
			
        if(($arr[$A]->getLof()-$arr[$B]->getLof())0)     
                return -1;    
            else if(($arr[$A]->getLof()-$arr[$B]->getLof())>0)    
                return 1;    
            else return 0;   
    }  
  
    private function changeAandB($arr,$A, $B) {  
        $tempChange =  $arr[$A]; 
		$arr[$A] = $arr[$B];
		$arr[$B] = $tempChange;
		return $arr;
    }  
  //Distance升序
    private function sortArr($arr) { 
		for($i = 0;$i  count($arr);$i ++){
			for($j = $i + 1;$j  count($arr);$j ++){
				if($this->compareAandB($arr,$i, $j)>0){
					$arr=$this->changeAandB($arr,$i, $j);
				}
			}
		}
		return $arr;
    }  
  //lof降序
    private function rsortArr($arr) { 
		for($i = 0;$i  count($arr);$i ++){
			for($j = $i + 1;$j  count($arr);$j ++){
				if($this->compareAandBLof($arr,$i, $j)0){
					$arr=$this->changeAandB($arr,$i, $j);
						
				}
			}
		}
		return $arr;
    }  
  
 
    public static function main() {  
           
  
        $dpoints = array();  
  
        $a = array( 2, 3 );  
        $b = array( 2, 4 );  
        $c = array( 1, 4 );  
        $d = array( 1, 3 );  
        $e = array( 2, 2 );  
        $f = array( 3, 2 );  
  
        $g = array( 8, 7 );  
        $h = array( 8, 6 );  
        $i = array( 7, 7 );  
        $j = array( 7, 6 );  
        $k = array( 8, 5 );  
  
        $l = array( 100, 2 );// 孤立點(diǎn)  
  
        $m = array( 8, 20 );  
        $n = array( 8, 19 );  
        $o = array( 7, 18 );  
        $p = array( 7, 17 );  
        $yichen = array( 8, 21 ); 
  
        array_push($dpoints,new DataNode("a", $a));  
        array_push($dpoints,new DataNode("b", $b));  
        array_push($dpoints,new DataNode("c", $c));  
        array_push($dpoints,new DataNode("d", $d));  
        array_push($dpoints,new DataNode("e", $e));  
        array_push($dpoints,new DataNode("f", $f));  
  
        array_push($dpoints,new DataNode("g", $g));  
        array_push($dpoints,new DataNode("h", $h));  
        array_push($dpoints,new DataNode("i", $i));  
        array_push($dpoints,new DataNode("j", $j));  
        array_push($dpoints,new DataNode("k", $k));  
  
        array_push($dpoints,new DataNode("l", $l));  
  
        array_push($dpoints,new DataNode("m", $m));  
        array_push($dpoints,new DataNode("n", $n));  
        array_push($dpoints,new DataNode("o", $o));  
        array_push($dpoints,new DataNode("p", $p));  
        array_push($dpoints,new DataNode("yichen", $yichen));  
  
        $lof = new OutlierNodeDetect();  
  
        $nodeList = $lof->getOutlierNode($dpoints);
		
 
		foreach($nodeList as $node):   
           echo($node->getNodeName() . "--" . round($node->getLof(),4));
		   echo("br>");
        endforeach;  
  
       
  
    }  
}
 
OutlierNodeDetect::main();
 
?>

到此這篇關(guān)于PHP局部異常因子算法-Local Outlier Factor(LOF)算法的具體實(shí)現(xiàn)解析的文章就介紹到這了,更多相關(guān)PHP局部異常因子算法-Local Outlier Factor(LOF)算法內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

您可能感興趣的文章:
  • java排序算法圖文詳解
  • Python 語(yǔ)言實(shí)現(xiàn)六大查找算法
  • Java實(shí)現(xiàn)雪花算法的原理和實(shí)戰(zhàn)教程
  • c++ Bellman-Ford算法的具體實(shí)現(xiàn)
  • Java實(shí)現(xiàn)常見(jiàn)排序算法的優(yōu)化
  • 異常點(diǎn)/離群點(diǎn)檢測(cè)算法——LOF解析

標(biāo)簽:酒泉 七臺(tái)河 洛陽(yáng) 溫州 白城 赤峰 怒江 金華

巨人網(wǎng)絡(luò)通訊聲明:本文標(biāo)題《PHP局部異常因子算法-Local Outlier Factor(LOF)算法的具體實(shí)現(xiàn)解析》,本文關(guān)鍵詞  PHP,局部,異常,因子,算法,;如發(fā)現(xiàn)本文內(nèi)容存在版權(quán)問(wèn)題,煩請(qǐng)?zhí)峁┫嚓P(guān)信息告之我們,我們將及時(shí)溝通與處理。本站內(nèi)容系統(tǒng)采集于網(wǎng)絡(luò),涉及言論、版權(quán)與本站無(wú)關(guān)。
  • 相關(guān)文章
  • 下面列出與本文章《PHP局部異常因子算法-Local Outlier Factor(LOF)算法的具體實(shí)現(xiàn)解析》相關(guān)的同類信息!
  • 本頁(yè)收集關(guān)于PHP局部異常因子算法-Local Outlier Factor(LOF)算法的具體實(shí)現(xiàn)解析的相關(guān)信息資訊供網(wǎng)民參考!
  • 推薦文章