久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

模糊聚類算法(FCM)和硬聚類算法(HCM)的VB6.0實(shí)現(xiàn)及其應(yīng)用

 kaichun 2006-11-09

程序?qū)崿F(xiàn):

    上面的公式看似復(fù)雜,其實(shí)我們關(guān)心的就是最后的5個(gè)計(jì)算步驟,,這里說(shuō)明一下,,有的書上以隸屬度矩陣的某一范數(shù)小于一定值作為收斂的條件,這也可,,不過計(jì)算量稍微要大一點(diǎn)了。

        程序采用VB6.0編制,,完全按照以上的步驟進(jìn)行,。

    

‘程序?qū)崿F(xiàn)功能:模糊聚類和硬聚類
‘作    者: laviewpbt
‘聯(lián)系方式:
[email protected]
‘QQ:33184777
‘版本:Version 2.3.1
‘說(shuō)明:復(fù)制請(qǐng)保留源作者信息,轉(zhuǎn)載請(qǐng)說(shuō)明,,歡迎大家提出意見和建議


Private Declare Function GetTickCount Lib "kernel32" () As Long

Private Enum IniCenterMethod    ‘初始中心的方法
    CreateRandom                ‘隨機(jī)的中心點(diǎn)
    CreateByHcm                 ‘由HCM創(chuàng)建的中心點(diǎn)
    CreateByRandomZadeh         ‘先隨機(jī)創(chuàng)建隸屬矩陣,,然后計(jì)算得到的中心點(diǎn)

    CreateByHand                ‘手工確定初始中心點(diǎn)

End Enum


Private Enum AntiFuzzyMethod    ‘反模糊的方法
    Max                         ‘最大隸屬度法
    Middle                      ‘中位數(shù)法
    Mean                        ‘加權(quán)均值法
End Enum


Private Type FcmInfo
     Center() As Double         ‘聚類中心
     Degree() As Double         ‘隸屬度,為Double類型
     Class() As Byte            ‘記錄數(shù)據(jù)屬于那一類
     TimeUse As Long            ‘所用時(shí)間
     Iterations  As Long        ‘迭帶次數(shù)
     ErrMsg As String           ‘錯(cuò)誤信息
End Type


Private Type HcmInfo
    Center() As Double          ‘聚類中心
    Class() As Byte             ‘記錄數(shù)據(jù)屬于那一類
    TimeUse As Long             ‘所用時(shí)間
    Iterations  As Long         ‘迭帶次數(shù)
    ErrMsg As String            ‘錯(cuò)誤信息
End Type

‘*************************************************************************************
‘*    作    者 :    laviewpbt
‘*    函 數(shù) 名 :    Fcm
‘*    參    數(shù) :    Data     -   待分類的樣本,,第一維的大小表示樣本的個(gè)數(shù),,
‘*                                第二維的大小表示樣本的維數(shù)
‘*                   Cluster  -   分類數(shù)
‘*                   CreateIniCenter - 初始聚類中心的創(chuàng)建方法
‘*                   AntiFuzzy -  反模糊化的方法
‘*                   Exponent  -  一個(gè)控制聚類效果的參數(shù),一般取2
‘*                   Maxiterations  - 最大的迭代次數(shù)
‘*                   MinImprovement - 最小的改進(jìn)參數(shù)(兩次迭代間聚類中心的距離)
‘*    返回值 :      FcmInfo結(jié)構(gòu),,記錄了相關(guān)的參數(shù)
‘*    功能描述 :    利用模糊理論的聚類方法把數(shù)據(jù)分類
‘*    日    期 :    2004-10-27 10.25.32
‘*    修 改 人 :    laviewpbt
‘*    日    期 :    2006-11-7 19.25.31
‘*    版    本 :    Version 2.3.1
‘**************************************************************************************



Private Function Fcm(ByRef Data() As Double, ByVal Cluster As Long, Optional ByVal CreateIniCenter As IniCenterMethod = IniCenterMethod.CreateByHcm, Optional AntiFuzzy As AntiFuzzyMethod = Max, Optional Exponent As Byte = 2, Optional Maxiterations As Long = 400, Optional MinImprovement As Double = 0.01, Optional ByRef CenterByHandle As Variant) As FcmInfo
    If ArrayRange(Data) <> 2 Then
        Fcm.ErrMsg = "數(shù)據(jù)只能為二維數(shù)組"
        Exit Function
    End If
    Dim i As Long, j As Long, k As Long, l As Long, m As Long
    Dim DataNumber As Long, DataSize As Long
    Dim Temp As Double, Sum1 As Double, Sum2 As Double, Sum3 As Double, Index As Integer
    Dim OldCenter() As Double
    Fcm.TimeUse = GetTickCount
    DataNumber = UBound(Data, 1): DataSize = UBound(Data, 2)
    ReDim Fcm.center(1 To Cluster, 1 To DataSize) As Double
    ReDim Fcm.Degree(1 To Cluster, 1 To DataNumber) As Double
    ReDim Fcm.Class(1 To DataNumber) As Byte
    ReDim OldCenter(1 To Cluster, 1 To DataSize) As Double
    On Error GoTo ErrHandle:
    Randomize
    If CreateIniCenter = CreateRandom Then
        For i = 1 To Cluster
            For j = 1 To DataSize
                OldCenter(i, j) = Data(Rnd * DataNumber, j)    ‘產(chǎn)生隨機(jī)初始中心點(diǎn)
            Next
        Next
    ElseIf CreateIniCenter = CreateByHcm Then
        Dim HcmCenter As HcmInfo
        HcmCenter = Hcm(Data, Cluster)
        For i = 1 To Cluster
            For j = 1 To DataSize
                OldCenter(i, j) = HcmCenter.center(i, j)   ‘產(chǎn)生HCM初始中心點(diǎn)
            Next
        Next
    ElseIf CreateIniCenter = CreateByRandomZadeh Then
        ReDim RndDegree(1 To Cluster, 1 To DataNumber) As Double
        Dim RndSum As Double
        For i = 1 To Cluster
            For j = 1 To DataNumber
                RndDegree(i, j) = Rnd           ‘創(chuàng)建隨機(jī)的隸屬度
            Next
        Next
        For j = 1 To DataNumber
            RndSum = 0
            For i = 1 To Cluster
                RndSum = RndSum + RndDegree(i, j)
            Next
            For i = 1 To Cluster
                RndDegree(i, j) = RndDegree(i, j) / RndSum   ‘隸屬度矩陣每列之后必須為1
            Next
        Next
       
        For i = 1 To Cluster
            For j = 1 To DataSize
                Sum1 = 0: Sum2 = 0
                For k = 1 To DataNumber
                    Temp = Exp(Log(RndDegree(i, k)) * Exponent)  ‘其實(shí)就是RndDegree(i, k)^Exponent
                    Sum1 = Sum1 + Temp * Data(k, j)           ‘隸屬度的平方乘以數(shù)值
                    Sum2 = Sum2 + Temp                        ‘隸屬度的和
                Next
                OldCenter(i, j) = Sum1 / Sum2                 ‘得到聚類中心
            Next
        Next
    ElseIf CreateIniCenter = CreateByHand Then
        If IsMissing(CenterByHandle) Then
            Fcm.ErrMsg = "請(qǐng)?zhí)峁┏跏季垲愔行摹?"
            Exit Function
        ElseIf UBound(CenterByHandle, 1) <> Cluster Or UBound(CenterByHandle, 2) <> DataSize Then
            Fcm.ErrMsg = "手工提供的初始聚類中心維數(shù)有錯(cuò)誤."
            Exit Function
        End If
        For i = 1 To Cluster
            For j = 1 To DataSize
                OldCenter(i, j) = CenterByHandle(i, j)
            Next
        Next
    End If

    
    Do
        Fcm.Iterations = Fcm.Iterations + 1
        For i = 1 To Cluster
            For j = 1 To DataNumber
                Sum1 = 0: Sum3 = 1
                For k = 1 To DataSize
                    Temp = Data(j, k) - OldCenter(i, k)
                    Sum1 = Sum1 + Temp * Temp             ‘計(jì)算第j點(diǎn)到第i個(gè)聚類中心的距離
                Next
                If Sum1 = 0 Then
                    Fcm.Degree(i, j) = 1                      ‘如果j點(diǎn)與第i個(gè)聚類中心重合,,則完全屬于該類
                Else
                    For k = 1 To Cluster
                        Sum2 = 0
                        If k <> i Then
                            For l = 1 To DataSize
                                Temp = Data(j, l) - OldCenter(k, l)
                                Sum2 = Sum2 + Temp * Temp  ‘計(jì)算第j點(diǎn)到其他聚類中心的距離
                            Next
                            Sum3 = Sum3 + Exp(Log(Sum1 / Sum2) * (2 / (Exponent - 1)))      ‘計(jì)算累加值,
                        End If
                    Next
                    Fcm.Degree(i, j) = 1 / Sum3    ‘計(jì)算新的隸屬度
                End If
            Next
        Next
       
        For i = 1 To Cluster
            For j = 1 To DataSize
                Sum1 = 0: Sum2 = 0
                For k = 1 To DataNumber
                    Temp = Exp(Log(Fcm.Degree(i, k)) * Exponent)
                    Sum1 = Sum1 + Temp * Data(k, j)           ‘隸屬度的平方乘以數(shù)值
                    Sum2 = Sum2 + Temp                        ‘隸屬度的和
                Next
                Fcm.Center(i, j) = Sum1 / Sum2                    ‘得到新的聚類中心
            Next
        Next
       
        Temp = 0
        For i = 1 To Cluster
            For j = 1 To DataSize
                Temp = Temp + (OldCenter(i, j) - Fcm.Center(i, j)) ^ 2      ‘ 計(jì)算兩次迭代之間的聚類中心的距離
                OldCenter(i, j) = Fcm.Center(i, j)                          ‘ 保留上一次的聚類中心
            Next
        Next

    Loop While Fcm.Iterations < Maxiterations And Temp > MinImprovement
   
    If AntiFuzzy = Max Then
        For i = 1 To DataNumber
            Temp = -1
            For k = 1 To Cluster
                If Temp < Fcm.Degree(k, i) Then    ‘得到列方向的最大值
                    Temp = Fcm.Degree(k, i)
                    Index = k
                End If
            Next
            Fcm.Class(i) = Index                  ‘Index記錄了列方向最大隸屬度的類
        Next
    ElseIf AntiFuzzy = Mean Then
         For i = 1 To DataNumber
             Temp = 0
             For j = 1 To Cluster
                Temp = Temp + Fcm.Degree(j, i) * j   ‘去隸書乘以對(duì)應(yīng)的類別數(shù)之和
             Next
             Fcm.Class(i) = CInt(Temp)
      Next
    ElseIf AntiFuzzy = Middle Then
        For i = 1 To DataNumber
            Temp = 0
            For j = 1 To Cluster
                If Temp <= 0.5 And Temp + Fcm.Degree(j, i) >= 0.5 Then
                    Index = j
                    Exit For
                Else
                    Temp = Temp + Fcm.Degree(j, i)   ‘取面積的一半處
                End If
            Next
            Fcm.Class(i) = Index
        Next
    End If
    Fcm.TimeUse = GetTickCount - Fcm.TimeUse
    Exit Function
ErrHandle:
    Fcm.ErrMsg = Err.Description
    Fcm.TimeUse = GetTickCount - Fcm.TimeUse
End Function


‘*************************************************************************************
‘*    作    者 :    laviewpbt
‘*    函 數(shù) 名 :    Hcm
‘*    參    數(shù) :    Data     -   待分類的樣本,第一維的大小表示樣本的個(gè)數(shù),,
‘*                                第二維的大小表示樣本的維數(shù)
‘*                   Cluster  -   分類數(shù)
‘*                   Maxiterations  - 最大的迭代次數(shù)
‘                    MinImprovement - 最小的改進(jìn)參數(shù)(兩次迭代間聚類中心的距離)
‘*    返回值 :      HcmInfo結(jié)構(gòu),,記錄了相關(guān)的參數(shù)
‘*    功能描述 :    直接利用硬聚類方法把數(shù)據(jù)分類
‘*    日    期 :    2004-10-24 20.10.56
‘*    修 改 人 :    laviewpbt
‘*    日    期 :    2006-11-7 20.11.23
‘*    版    本 :    Version 2.3.1
‘**************************************************************************************


Private Function Hcm(ByRef Data() As Double, ByVal Cluster As Byte, Optional Maxiterations As Long = 400, Optional MinImprovement As Double = 0.01) As HcmInfo
    If ArrayRange(Data) <> 2 Then
        Hcm.ErrMsg = "數(shù)據(jù)只能為二維數(shù)組"
        Exit Function
    End If
    Dim i As Long, j As Long, k As Long, l As Long, m As Long
    Dim DataNumber As Long, DataSize As Long
    Dim Temp As Double, DX As Double, DY As Double, SumValue() As Double, SumNumber() As Long
    Dim OldCenter() As Double, Distance As Double, Dist As Double, Index As Long
    On Error GoTo ErrHandle:
    Hcm.TimeUse = GetTickCount
    DataNumber = UBound(Data, 1): DataSize = UBound(Data, 2)
    ReDim Hcm.Center(1 To Cluster, 1 To DataSize) As Double
    ReDim Hcm.Class(1 To DataNumber) As Byte
    ReDim OldCenter(1 To Cluster, 1 To DataSize) As Double
    For i = 1 To Cluster
        For j = 1 To DataSize
            OldCenter(i, j) = Data(i * DataNumber / Cluster, j) ‘產(chǎn)生初始中心點(diǎn)
        Next
    Next
    Do
        Hcm.Iterations = Hcm.Iterations + 1
        ReDim SumNumber(Cluster) As Long
        ReDim SumValue(Cluster, DataSize) As Double
        For i = 1 To DataNumber
            Distance = 40000000000#
            For j = 1 To Cluster
                Dist = 0
                For k = 1 To DataSize
                    Temp = Data(i, k) - OldCenter(j, k)
                    Dist = Dist + Temp * Temp             ‘計(jì)算第j點(diǎn)到第i個(gè)聚類中心的距離
                Next
                If Distance > Dist Then
                    Distance = Dist
                    Index = j                         ‘把i點(diǎn)歸于距離該點(diǎn)最近的中心點(diǎn)所在的類
                End If
            Next
            Hcm.Class(i) = Index
            For j = 1 To DataSize
                SumValue(Index, j) = SumValue(Index, j) + Data(i, j)
            Next
            SumNumber(Index) = SumNumber(Index) + 1
        Next
       
        For i = 1 To Cluster
            For k = 1 To DataSize
                If SumNumber(i) = 0 Then
                    Hcm.Center(i, k) = Data(Rnd * DataNumber, k)
                Else
                    Hcm.Center(i, k) = SumValue(i, k) / SumNumber(i)         ‘求新的中心
                End If
            Next
        Next
        Temp = 0
        For i = 1 To Cluster
            For j = 1 To DataSize
                Temp = Temp + (OldCenter(i, j) - Hcm.Center(i, j)) ^ 2      ‘ 計(jì)算兩次迭代之間的聚類中心的距離
                OldCenter(i, j) = Hcm.Center(i, j)                          ‘ 保留上一次的聚類中心
            Next
        Next
    Loop While Hcm.Iterations < Maxiterations And Temp > MinImprovement
    Hcm.TimeUse = GetTickCount - Hcm.TimeUse
    Exit Function
ErrHandle:
    Hcm.ErrMsg = Err.Description
    Hcm.TimeUse = GetTickCount - Hcm.TimeUse
    End Function

 

‘*************************************************************************************
‘*    作    者 :    網(wǎng)絡(luò)
‘*    函 數(shù) 名 :    ArrayRange
‘*    參    數(shù) :    Data     -   待測(cè)試的數(shù)據(jù)
‘*    返回值 :      返回?cái)?shù)組的維數(shù)
‘*    日    期 :    2006-7-10 13.20.40
‘*    修 改 人 :    laviewpbt
‘*    日    期 :    2006-11-7 10。10,。45
‘*    版    本 :    Version 1.2.1
‘**************************************************************************************
Public Function ArrayRange(Data() As Double) As Integer
    Dim i As Integer, ret As Integer
    Dim ErrF As Boolean
    ErrF = False
    On Error GoTo ErrHandle
    For i = 1 To 60               ‘VB中數(shù)組最大為60
        ret = UBound(mArray, i)   ‘用UBound函數(shù)判斷某一維的上界,,如果大數(shù)組的實(shí)際維數(shù)時(shí)產(chǎn)生超出范圍錯(cuò)誤,此時(shí)我們通過Resume Next 來(lái)捕捉錯(cuò)這個(gè)錯(cuò)誤
        ret = ret + 1
        If ErrF Then Exit For
    Next
    ArrayRange = ret
    Exit Function
ErrHandle:
    ret = i
    ErrF = True
    Resume Next
End Function

 

 

 

 測(cè)試情況:

1,、簡(jiǎn)單數(shù)據(jù)的聚類

原始數(shù)據(jù)為:
1    2   
2    3   
1.5    2.5   
1.5    2   
5.1    1   
4.1    1   
5    3   
6    2   
聚類中心為:
1.500    2.374   
5.062    1.750   
隸屬矩陣為:
1.00 1.00 1.00 1.00 0.00 0.03 0.02 0.00
0.00 0.00 0.00 0.00 1.00 0.97 0.98 1.00
迭代次數(shù)為:2

以下是一組氣候的統(tǒng)計(jì)數(shù)據(jù),,根據(jù)要求我們把氣候分為三類:

原始數(shù)據(jù)為:
1    3.5    1    0   
2    2.5    2    2   
2    3.5    1    1   
3    3    3    1   
3    3    1    1   
5    .5    5    2   
6    1.5    4    0   
6    1.5    4    1   
5    3    2    2   
4    3    1    2   
聚類中心為:
4.434    2.992    1.600    1.948   
5.740    1.251    4.250    0.931   
1.902    3.280    1.204    0.845   
隸屬矩陣為:
0.09 0.26 0.02 0.40 0.26 0.12 0.08 0.02 0.92 0.88
0.04 0.08 0.00 0.16 0.04 0.82 0.89 0.97 0.04 0.03
0.87 0.67 0.98 0.44 0.70 0.06 0.04 0.01 0.03 0.09
迭代次數(shù)為:4
每個(gè)樣本的類別為:
3 3 3 3 3 2 2 2 1 1

這個(gè)分析的結(jié)果是可以接受的。

2 ,、二維數(shù)據(jù)的聚類

隨機(jī)生成二維的數(shù)據(jù),,然后比較分類結(jié)果

 

 上圖中第一排第二個(gè)式HCM的結(jié)果,,其他的圖是不同的參數(shù)相結(jié)合的FCM的結(jié)果,,至于結(jié)果的好壞對(duì)于這些點(diǎn)群不好說(shuō)。

  這副圖選擇的聚類類別為4,,中間那4個(gè)點(diǎn)被聚集到左上角的一類,F(xiàn)CM和HCM的結(jié)果是一樣的,。

      上面這副圖的聚類類別為4,,但他顯示出無(wú)論HCM還是FCM都沒有給出合理的分類,,產(chǎn)生這一現(xiàn)象的原因與其說(shuō)是算法的問題,,不如說(shuō)是對(duì)距離的定義,在FCM/HCM中我們使用的是歐式距離,,這使得中間那一部分到左側(cè)的距離要近一些,,因此被聚集到這個(gè)類中,。通過適當(dāng)改變對(duì)距離的定義,我們也可以得到合理的結(jié)果,。

3 ,、 圖像分割中的應(yīng)用,。

圖像分割也是數(shù)據(jù)聚類的過程,我們選擇圖像的原始象素矩陣為聚類樣本,。效果如下:

 

        第一行第二列是HCM的結(jié)果,,其他是不同參數(shù)FCM的結(jié)果,,其中第四副是采用加權(quán)平均反模糊化的,看到這副效果是比較差的,,邊緣有很多毛刺,,這是因?yàn)榧訖?quán)平均的過程有個(gè)取整的操作所造成的,。

      這副圖片是在工業(yè)現(xiàn)場(chǎng)拍攝的一副火焰圖像,我以前做一個(gè)項(xiàng)目用到的,,分割后的圖片根據(jù)一定的原理可以得到一定溫度 ,,并且能大概的不同燃料和其他物份的分布狀況,。

    在常用的二值化及其vb.net實(shí)現(xiàn)一文中,,我曾提到用模糊聚類的方法二值化圖像,應(yīng)該說(shuō)這種方法有其合理之處,,他不同于其他的閥值分割,,二帶有一定模糊信息,,并且能方便實(shí)現(xiàn)彩色二值分割(即樣本的維數(shù)為3)。

 

       如上圖,,程序完美的把天空綠草和樹木分開,。

      當(dāng)然FCM在其他方面也有著廣泛的應(yīng)用,。

      以上是最基本的模糊聚類算法,,針對(duì)FCM的計(jì)算速度慢的特點(diǎn),人們提出了快速FCM的步驟,,不過那玩意我沒看懂是什么意思,。 

      前面我說(shuō)過遺傳算法,遺傳算法在優(yōu)化方面有很大的優(yōu)勢(shì),,而FCM算法實(shí)際上就是找到目標(biāo)函數(shù)的最小值,因此可以把兩者結(jié)合起來(lái)從而獲得更好的效果,。

 

最后談一點(diǎn)速度優(yōu)化方面的問題:

1,、FCM算法的計(jì)算量是比較大的,在算法模型不變的情況下我們可以通過以下方法減小計(jì)算量.   a.如果對(duì)某一個(gè)特定的問題,,我們知道聚類中心的大概位置,,則通過程序提供的CreateByHand方法運(yùn)行。 b,、在不確定聚類中心的情況下,,選擇聚類中心由HCM產(chǎn)生,HCM算法的速度是相當(dāng)塊的,。  c.針對(duì)不同對(duì)象選擇不同數(shù)據(jù)類型,,這點(diǎn)在下面要講到。

2,、如果處理對(duì)象是圖像,,則數(shù)據(jù)量一般很大,速度就是關(guān)鍵了,??紤]到圖像數(shù)據(jù)是byte類型的,則可以把FCM算法的Data()參數(shù)數(shù)據(jù)類型改為byte,我們知道浮點(diǎn)數(shù)的運(yùn)算總是很慢的,。并且考慮到象素值沒有小數(shù)部分,,程序中有些/可以改為\,整除總比一般除法塊,,還有既然確定了樣本的第二維,,則把程序中所有的 DataSize改為3,并且對(duì)于所有的有關(guān)DataSize的小循環(huán),,全部改為手寫。

3,、實(shí)踐證明,RndDegree(i, k)^Exponent 的計(jì)算速度比 Exp(Log(RndDegree(i, k)) * Exponent)要慢,。X^2 比X*X要慢,,我是指大數(shù)據(jù)量的。

 

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式,、誘導(dǎo)購(gòu)買等信息,,謹(jǐn)防詐騙,。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào),。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多