欧美三区_成人在线免费观看视频_欧美极品少妇xxxxⅹ免费视频_a级毛片免费播放_鲁一鲁中文字幕久久_亚洲一级特黄

DBSCAN算法python實現(附完整數據集和代碼)

系統 1984 0

目錄:

一、算法思路

二、算法實現

三、算法實現過程中遇到的問題

四、算法運行結果

?

一、算法思路

DBSCAN算法的核心是“延伸”。先找到一個未訪問的點p,若該點是核心點,則創建一個新的簇C,將其鄰域中的點放入該簇,并遍歷其鄰域中的點,若其鄰域中有點q為核心點,則將q的鄰域內的點也劃入簇C,直到C不再擴展。直到最后所有的點都標記為已訪問。

點p通過密度可達來擴大自己的“地盤”,實際上就是簇在“延伸”。

?

圖示網站:https://www.naftaliharris.com/blog/visualizing-dbscan-clustering/ 可以看一下簇是如何延伸的。

二、算法實現

1、計算兩點之間的距離

            
              # 計算兩個點之間的歐式距離,參數為兩個元組
def dist(t1, t2):
    dis = math.sqrt((np.power((t1[0]-t2[0]),2) + np.power((t1[1]-t2[1]),2)))
    # print("兩點之間的距離為:"+str(dis))
    return dis


            
          

2、讀取文件,加載數據集

            
              def loadDataSet(fileName, splitChar='\t'):
    dataSet = []
    with open(fileName) as fr:
        for line in fr.readlines():
            curline = line.strip().split(splitChar)
            fltline = list(map(float, curline))
            dataSet.append(fltline)
    return dataSet


            
          

?

3、DBSCAN算法實現

1、標記點是否被訪問:我設置了兩個列表,一個存放未訪問的點unvisited,一個存放已訪問的點visited。每次訪問一個點,unvisited列表remove該點,visited列表append該點,以此來實現點的標記改變。

2、C作為輸出結果,初始時是一個長度為所有點的個數的值全為-1的列表。之后修改點對應的索引的值來設置點屬于哪個簇。

            
               DBSCAN算法,參數為數據集,Eps為指定半徑參數,MinPts為制定鄰域密度閾值
def dbscan(Data, Eps, MinPts):
    num = len(Data)  # 點的個數
    # print("點的個數:"+str(num))
    unvisited = [i for i in range(num)]  # 沒有訪問到的點的列表
    # print(unvisited)
    visited = []  # 已經訪問的點的列表
    C = [-1 for i in range(num)]
    # C為輸出結果,默認是一個長度為num的值全為-1的列表
    # 用k來標記不同的簇,k = -1表示噪聲點
    k = -1
    # 如果還有沒訪問的點
    while len(unvisited) > 0:
        # 隨機選擇一個unvisited對象
        p = random.choice(unvisited)
        unvisited.remove(p)
        visited.append(p)
        # N為p的epsilon鄰域中的對象的集合
        N = []
        for i in range(num):
            if (dist(Data[i], Data[p]) <= Eps):# and (i!=p):
                N.append(i)
        # 如果p的epsilon鄰域中的對象數大于指定閾值,說明p是一個核心對象
        if len(N) >= MinPts:
            k = k+1
            # print(k)
            C[p] = k
            # 對于p的epsilon鄰域中的每個對象pi
            for pi in N:
                if pi in unvisited:
                    unvisited.remove(pi)
                    visited.append(pi)
                    # 找到pi的鄰域中的核心對象,將這些對象放入N中
                    # M是位于pi的鄰域中的點的列表
                    M = []
                    for j in range(num):
                        if (dist(Data[j], Data[pi])<=Eps): #and (j!=pi):
                            M.append(j)
                    if len(M)>=MinPts:
                        for t in M:
                            if t not in N:
                                N.append(t)
                # 若pi不屬于任何簇,C[pi] == -1說明C中第pi個值沒有改動
                if C[pi] == -1:
                    C[pi] = k
        # 如果p的epsilon鄰域中的對象數小于指定閾值,說明p是一個噪聲點
        else:
            C[p] = -1

    return C
            
          

#

三、算法實現過程中遇到的問題

代碼思路非常簡單,讓我以為實現起來也很簡單。結果拖拖拉拉半個多月才終于將算法改好。

算法實現過程中遇到的問題其實是小問題,但是導致的結果非常嚴重。因為不起眼所以才難以察覺。

這是剛開始我運行算法得到的結果(Eps為10,MinPts為10):

DBSCAN算法python實現(附完整數據集和代碼)_第1張圖片

Eps為2,MinPts為10(我改了點的大小):

DBSCAN算法python實現(附完整數據集和代碼)_第2張圖片

可以看出圖中顏色特別多,實際上就是聚成的簇太多,可實際上目測應該只有七八個簇。這是為什么呢?

原來是變量k的重復使用問題。

前面我用k來標識不同的簇,后面(如下圖)我又將k變成了循環變量,注意M列表中都是整數,代表點在數據集中的索引,所以實際上是k在整數列表中遍歷,覆蓋掉了前面用來標識不同簇的k值,導致每次運行出來k取值特別多(如下下圖)。

DBSCAN算法python實現(附完整數據集和代碼)_第3張圖片

DBSCAN算法python實現(附完整數據集和代碼)_第4張圖片

?

四、運行結果

DBSCAN算法python實現(附完整數據集和代碼)_第5張圖片

?

附數據集

鏈接:數據集788個點
提取碼:rv06
?

附完整代碼

            
              # encoding:utf-8
import matplotlib.pyplot as plt
import random
import numpy as np
import math
from sklearn import datasets

list_1 = []
list_2 = []
# 數據集一:隨機生成散點圖,參數為點的個數
# def scatter(num):
#     for i in range(num):
#         x = random.randint(0, 100)
#         list_1.append(x)
#         y = random.randint(0, 100)
#         list_2.append(y)
#     print(list_1)
#     print(list_2)
#     data = list(zip(list_1, list_2))
#     print(data)
#     #plt.scatter(list_1, list_2)
#     #plt.show()
#     return data
#scatter(50)

def loadDataSet(fileName, splitChar='\t'):
    dataSet = []
    with open(fileName) as fr:
        for line in fr.readlines():
            curline = line.strip().split(splitChar)
            fltline = list(map(float, curline))
            dataSet.append(fltline)
    return dataSet

# 計算兩個點之間的歐式距離,參數為兩個元組
def dist(t1, t2):
    dis = math.sqrt((np.power((t1[0]-t2[0]),2) + np.power((t1[1]-t2[1]),2)))
    # print("兩點之間的距離為:"+str(dis))
    return dis

# dis = dist((1,1),(3,4))
# print(dis)


# DBSCAN算法,參數為數據集,Eps為指定半徑參數,MinPts為制定鄰域密度閾值
def dbscan(Data, Eps, MinPts):
    num = len(Data)  # 點的個數
    # print("點的個數:"+str(num))
    unvisited = [i for i in range(num)]  # 沒有訪問到的點的列表
    # print(unvisited)
    visited = []  # 已經訪問的點的列表
    C = [-1 for i in range(num)]
    # C為輸出結果,默認是一個長度為num的值全為-1的列表
    # 用k來標記不同的簇,k = -1表示噪聲點
    k = -1
    # 如果還有沒訪問的點
    while len(unvisited) > 0:
        # 隨機選擇一個unvisited對象
        p = random.choice(unvisited)
        unvisited.remove(p)
        visited.append(p)
        # N為p的epsilon鄰域中的對象的集合
        N = []
        for i in range(num):
            if (dist(Data[i], Data[p]) <= Eps):# and (i!=p):
                N.append(i)
        # 如果p的epsilon鄰域中的對象數大于指定閾值,說明p是一個核心對象
        if len(N) >= MinPts:
            k = k+1
            # print(k)
            C[p] = k
            # 對于p的epsilon鄰域中的每個對象pi
            for pi in N:
                if pi in unvisited:
                    unvisited.remove(pi)
                    visited.append(pi)
                    # 找到pi的鄰域中的核心對象,將這些對象放入N中
                    # M是位于pi的鄰域中的點的列表
                    M = []
                    for j in range(num):
                        if (dist(Data[j], Data[pi])<=Eps): #and (j!=pi):
                            M.append(j)
                    if len(M)>=MinPts:
                        for t in M:
                            if t not in N:
                                N.append(t)
                # 若pi不屬于任何簇,C[pi] == -1說明C中第pi個值沒有改動
                if C[pi] == -1:
                    C[pi] = k
        # 如果p的epsilon鄰域中的對象數小于指定閾值,說明p是一個噪聲點
        else:
            C[p] = -1

    return C


# 數據集二:788個點
dataSet = loadDataSet('788points.txt', splitChar=',')
C = dbscan(dataSet, 2, 14)
print(C)
x = []
y = []
for data in dataSet:
    x.append(data[0])
    y.append(data[1])
plt.figure(figsize=(8, 6), dpi=80)
plt.scatter(x,y, c=C, marker='o')
plt.show()
# print(x)
# print(y)
            
          

?


更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 五月婷婷丁香综合网 | 亚洲欧美第一页 | 亚洲一区二区三区四区精品 | 一区二区三区免费在线观看 | 日韩成人免费在线视频 | 天天摸天天添 | 欧美黄色片一级 | 欧美专区在线视频 | 亚洲av一级毛片特黄大片 | 亚洲国产精品一区二区第一页 | 黄色电影在线免费观看 | 奇米奇米777 | 美国三级日本三级久久99 | 9191av| 波多野结衣中文在线观看 | 午夜资源 | 免费一区 | 日韩欧美国产一区二区 | 成年人在线播放 | 波多野结衣高清在线播放 | 亚洲精品99| 日本欧美一二三区色视频 | 欧美一进一出 | 午夜直播在线 | 四虎tv在线观看884aa | 欧美成人观看 | 一区二区国产在线观看 | 一级做a爰片久久毛片 | 欧美欧美欧美欧美 | 国产无遮挡一级毛片 | 我不卡在线观看 | 很黄很色又爽很黄很色又爽 | 啪啪在线看 | 国产精品亚洲第一区二区三区 | 日本私人色多多 | 男人添女人下面免费网站 | 四虎影在线永久免费四虎地址8848aa | 一区二区三区四区在线观看视频 | 免费啪视频在线观看免费的 | 欧美性一区 | 亚洲国产日本 |