亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

Python實(shí)現(xiàn)Mean Shift算法

系統(tǒng) 2798 0

? ? ? ?聲明:代碼的運(yùn)行環(huán)境為Python3。Python3與Python2在一些細(xì)節(jié)上會(huì)有所不同,希望廣大讀者注意。本博客以代碼為主,代碼中會(huì)有詳細(xì)的注釋。相關(guān)文章將會(huì)發(fā)布在我的個(gè)人博客專欄《Python從入門到深度學(xué)習(xí)》,歡迎大家關(guān)注~


? ? ? ?在K-Means算法中,聚類的類別個(gè)數(shù)需要提前指定,對(duì)于類別個(gè)數(shù)未知的數(shù)據(jù)集,K-Means算法和K-Means++算法將很難對(duì)其進(jìn)行求解,所以需要一些能夠處理未知類別個(gè)數(shù)的算法來(lái)處理此類問(wèn)題。Mean Shift算法,又稱作均值漂移算法,它跟K-Means算法一樣,都是基于聚類中心的聚類算法,不同的是,它不需要提前指定聚類中心的個(gè)數(shù),聚類中心是通過(guò)在給定區(qū)域中樣本的均值來(lái)確定的,通過(guò)不斷更新聚類中心,直至聚類中心不再改變?yōu)橹埂?

一、Mean Shift向量與核函數(shù)

1、Mean Shift向量

? ? ? ?對(duì)于給定的n維空間 中的m個(gè)樣本點(diǎn) ,對(duì)于其中的一個(gè)樣本X,其Mean Shift的向量為:

? ? ? ?其中, 指的是一個(gè)半徑為h的高維球區(qū)域, 定義為:

2、核函數(shù)

? ? ? ?通過(guò)上述方式求出的Mean Shift向量時(shí)存在問(wèn)題的,即在 區(qū)域內(nèi)每一個(gè) 對(duì)樣本X的貢獻(xiàn)是一樣的,然而實(shí)際上,每一個(gè)樣本 對(duì)樣本X的貢獻(xiàn)是不一樣的,我們可以通過(guò)核函數(shù)對(duì)每一個(gè)樣本的貢獻(xiàn)進(jìn)行度量。

? ? ? ?核函數(shù)的定義如下:

? ? ? ?設(shè)Z是輸入空間,H是特征空間,如果存在一個(gè)Z到H的映射: 使得所有 ,函數(shù) 滿足條件: ,則稱 為核函數(shù), 為映射函數(shù)。

? ? ? ?我們?cè)贛ean Shift算法中使用的是高斯核函數(shù),這也是最常用的核函數(shù)之一,高斯核函數(shù)的表達(dá)式為:

? ? ? ?其中,h為帶寬,當(dāng)帶寬一定時(shí),樣本點(diǎn)之間的距離越近,核函數(shù)的值越大;當(dāng)樣本點(diǎn)距離一定時(shí),帶寬越大,核函數(shù)的值越小。

? ? ? ?下面我們使用Python代碼實(shí)現(xiàn)高斯核函數(shù):

            
              import numpy as np
import math

def gs_kernel(dist, h):
    '''
    高斯核函數(shù)
    :param dist: 歐氏距離
    :param h: 帶寬
    :return: 返回高斯核函數(shù)的值
    '''
    m = np.shape(dist)[0]  # 樣本個(gè)數(shù)
    one = 1 / (h * math.sqrt(2 * math.pi))
    two = np.mat(np.zeros((m, 1)))
    for i in range(m):
        two[i, 0] = (-0.5 * dist[i] * dist[i].T) / (h * h)
        two[i, 0] = np.exp(two[i, 0])
    
    gs_val = one * two
    return gs_val
            
          

二、Mean Shift原理

? ? ? ?在Mean Shift中通過(guò)迭代的方式找到最終的聚類中心,即對(duì)每一個(gè)樣本點(diǎn)計(jì)算其漂移均值,以計(jì)算出來(lái)的漂移均值點(diǎn)作為新的起始點(diǎn)重復(fù)上述步驟,直到滿足終止條件,得到的最終的漂移均值點(diǎn)即為最終的聚類中心。

? ? ? ?Mean Shift算法實(shí)現(xiàn)過(guò)程如下:

            
              def mean_shift(points, h=2, MIN_DISTANCE=0.000001):
    '''
    訓(xùn)練Mean Shift模型
    :param points: 特征點(diǎn)
    :param h: 帶寬
    :param MIN_DISTANCE: 最小誤差
    :return: 返回特征點(diǎn)、均值漂移點(diǎn)、類別
    '''
    mean_shift_points = np.mat(points)
    max_min_dist = 1
    iteration = 0  # 迭代的次數(shù)
    m = np.shape(mean_shift_points)[0]  # 樣本的個(gè)數(shù)
    need_shift = [True] * m  # 標(biāo)記是否需要漂移

    # 計(jì)算均值漂移向量
    while max_min_dist > MIN_DISTANCE:
        max_min_dist = 0
        iteration += 1
        print("iteration : " + str(iteration))
        for i in range(0, m):
            if not need_shift[i]:  # 判斷每一個(gè)樣本點(diǎn)是否需要計(jì)算偏移均值
                continue
            point_new = mean_shift_points[i]
            point_new_start = point_new
            point_new  = shift_point(point_new, points, h)  # 對(duì)樣本點(diǎn)進(jìn)行漂移計(jì)算
            dist = distince(point_new, point_new_start)  # 計(jì)算該點(diǎn)與漂移后的點(diǎn)之間的距離
            
            if dist > max_min_dist:
                max_min_dist = dist
            if dist < MIN_DISTANCE:
                need_shift[i] = False
            
            mean_shift_points[i] = point_new
    # 計(jì)算最終的類別
    lb = lb_points(mean_shift_points)  # 計(jì)算所屬的類別
    return np.mat(points), mean_shift_points, lb
            
          

? ? ? ?其中,shift_point()方法目的在于計(jì)算漂移量,lb_points()方法的目的在于計(jì)算最終所屬分類,distance()方法用于計(jì)算歐氏距離,三個(gè)方法的實(shí)現(xiàn)過(guò)程分別如下:

(1)shift_point()方法

            
              def shift_point(point, points, h):
    '''
    計(jì)算漂移向量
    :param point: 需要計(jì)算的點(diǎn)
    :param points: 所有的樣本點(diǎn)
    :param h: 帶寬
    :return: 返回漂移后的點(diǎn)
    '''
    points = np.mat(points)
    m = np.shape(points)[0]  # 樣本的個(gè)數(shù)
    # 計(jì)算距離
    point_dist = np.mat(np.zeros((m, 1)))
    for i in range(m):
        point_dist[i, 0] = distince(point, points[i])

    # 計(jì)算高斯核函數(shù)
    point_weights = gs_kernel(point_dist, h)

    # 計(jì)算分母
    all_sum = 0.0
    for i in range(m):
        all_sum += point_weights[i, 0]

    # 計(jì)算均值偏移
    point_shifted = point_weights.T * points / all_sum
    return point_shifted
            
          

(2)lb_points()

            
              def lb_points(mean_shift_points):
    '''
    計(jì)算所屬類別
    :param mean_shift_points: 漂移向量
    :return: 返回所屬的類別
    '''
    lb_list = []
    m, n = np.shape(mean_shift_points)
    index = 0
    index_dict = {}
    for i in range(m):
        item = []
        for j in range(n):
            item.append(str(("%5.2f" % mean_shift_points[i, j])))

        item_1 = "_".join(item)
        if item_1 not in index_dict:
            index_dict[item_1] = index
            index += 1

    for i in range(m):
        item = []
        for j in range(n):
            item.append(str(("%5.2f" % mean_shift_points[i, j])))

        item_1 = "_".join(item)
        lb_list.append(index_dict[item_1])
    return lb_list
            
          

(3)distince()方法

            
              def distince(pointA, pointB):
    '''
    計(jì)算歐氏距離
    :param pointA: A點(diǎn)坐標(biāo)
    :param pointB: B點(diǎn)坐標(biāo)
    :return: 返回得到的歐氏距離
    '''
    return math.sqrt((pointA - pointB) * (pointA - pointB).T)
            
          

三、Mean Shift算法舉例

1、數(shù)據(jù)集:數(shù)據(jù)集含有兩個(gè)特征,如下圖所示:

Python實(shí)現(xiàn)Mean Shift算法_第1張圖片

2、加載數(shù)據(jù)集

? ? ? ?我們此處使用如下方法加載數(shù)據(jù)集,也可使用其他的方式進(jìn)行加載,此處可以參考我的另外一篇文章《Python兩種方式加載文件內(nèi)容》。加載文件內(nèi)容代碼如下:

            
              def load_data(path, feature_num=2):
    '''
    導(dǎo)入數(shù)據(jù)
    :param path: 路徑
    :param feature_num: 特行總數(shù)
    :return: 返回?cái)?shù)據(jù)特征
    '''
    f = open(path)
    data = []
    for line in f.readlines():
        lines = line.strip().split("\t")
        data_tmp = []
        if len(lines) != feature_num:  # 判斷特征的個(gè)數(shù)是否正確,把不符合特征數(shù)的數(shù)據(jù)去除
            continue
        for i in range(feature_num):
            data_tmp.append(float(lines[i]))
        data.append(data_tmp)
    f.close()
    return data
            
          

3、保存聚類結(jié)果

? ? ? ?通過(guò)Mean Shift聚類后,我們使用一下方法進(jìn)行聚類結(jié)果的保存

            
              def save_result(file_name, data):
    '''
    保存聚類結(jié)果
    :param file_name: 保存的文件名
    :param data: 需要保存的文件
    :return:
    '''
    f = open(file_name, "w")
    m, n = np.shape(data)
    for i in range(m):
        tmp = []
        for j in range(n):
            tmp.append(str(data[i, j]))
        f.write("\t".join(tmp) + "\n")
    f.close()
            
          

4、調(diào)用Mean Shift算法

            
              if __name__ == "__main__":
    data = load_data("F://data", 2)
    points, shift_points, cluster = mean_shift(data, 2)
    save_result("sub", np.mat(cluster))
    save_result("center", shift_points)
            
          

5、結(jié)果展示

? ? ? ?得到的聚類結(jié)果如下所示:

Python實(shí)現(xiàn)Mean Shift算法_第2張圖片

? ? ? ? 你們?cè)诖诉^(guò)程中遇到了什么問(wèn)題,歡迎留言,讓我看看你們都遇到了哪些問(wèn)題。


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號(hào)聯(lián)系: 360901061

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

【本文對(duì)您有幫助就好】

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

發(fā)表我的評(píng)論
最新評(píng)論 總共0條評(píng)論
主站蜘蛛池模板: 国产一级淫片a视频免费观看 | 中文字幕在线观看亚洲日韩 | 亚洲国产综合久久精品 | 四虎b3t77com| 国产精品久久久久久久久久日本 | 亚洲 欧洲 自拍 另类 校园 | 色五月天天 | 久久精品一区二区国产 | 18p爽视频在线观看免费 | 起碰成人免费公开网视频 | 亚洲精品欧洲一区二区三区 | 国产精品成人免费视频 | 免费高清a毛片 | 成人免费午间影院在线观看 | 欧美亚洲另类色国产综合 | 久久夜色tv网站 | 色视频在线播放 | 欧美片欧美日韩国产综合片 | 国产99在线a视频 | 欧美成人26uuu欧美毛片 | 国产亚洲精品久久综合影院 | 久久久久免费精品国产 | 国产女主播在线视频 | 久久久久国产精品免费网站 | 久久99精品久久久久久秒播放器 | 国产成人精品男人免费 | 欧美人成在线 | 一级骚片 | 波多野结衣久久精品免费播放 | 免费黄色在线 | 婷婷在线视频 | 在线免费观看亚洲视频 | 精品亚洲无人区一区二区 | 国产精品久久久一区二区三区 | 色综合综合色综合色综合 | 四虎成人国产精品视频 | 高清波多野结衣一区二区三区 | 青青热久免费精品视频在线观看 | 真实的国产乱xxxx在线播放 | 99精品视频在线观看免费专区 | 农村妇女又色黄一级毛片 |