Skynet

          ---------- ---------- 我的新 blog : liukaiyi.cublog.cn ---------- ----------

            BlogJava :: 首頁(yè) :: 聯(lián)系 :: 聚合  :: 管理
            112 Posts :: 1 Stories :: 49 Comments :: 0 Trackbacks

          轉(zhuǎn):http://www.daniweb.com/forums/thread31449.html
          什么都不說(shuō)了,直接看代碼吧。
          注解 應(yīng)該寫的比較詳細(xì)


          # liukaiyi 
          # 注 k-means ,維度類型 - 數(shù)值形式 ( 199 或 23.13 

          import sys, math, random

          # -- 類化 '數(shù)據(jù)' 
          #
           在 n-維度空間
          class Point:
              
          def __init__(self, coords, reference=None):
                  self.coords 
          = coords
                  self.n 
          = len(coords)
                  self.reference 
          = reference
              
          def __repr__(self):
                  
          return str(self.coords)

          # -- 類化 '聚集點(diǎn) / 聚類平均距離 點(diǎn) ' 
          #
           -- 在 n-維度空間
          #
           -- k-means 核心類
          #
           -- 每次 聚集各點(diǎn) 圍繞她 進(jìn)行聚集 
          #
           -- 并提供方法 求-聚集后的計(jì)算中心點(diǎn),同時(shí)記入 此次 中心點(diǎn)(聚集各點(diǎn)平均距離),為下一次聚集提供中心點(diǎn).
          class Cluster:
              
          def __init__(self, points):
                  
          if len(points) == 0: raise Exception("ILLEGAL: EMPTY CLUSTER")
                  self.points 
          = points
                  self.n 
          = points[0].n
              
          for p in points:
                      
          if p.n != self.n: raise Exception("ILLEGAL: MULTISPACE CLUSTER")
                  
          # 求 聚集各點(diǎn)后 平均點(diǎn)
              self.centroid = self.calculateCentroid()
              
          def __repr__(self):
                  
          return str(self.points)
              
              
          # 更新 中心點(diǎn),并返回 原中心點(diǎn) 與 現(xiàn)中心點(diǎn)(聚集各點(diǎn)平均距離)距離  
              def update(self, points):
                  old_centroid 
          = self.centroid
                  self.points 
          = points
                  self.centroid 
          = self.calculateCentroid()
                  
          return getDistance(old_centroid, self.centroid)
              
              
          # 計(jì)算平均點(diǎn) (聚集/收集各點(diǎn)(離本類的中心點(diǎn))最近數(shù)據(jù),后生成新的 中心點(diǎn) )
              def calculateCentroid(self):
                  centroid_coords 
          = []
                  
          #  維度 迭代
              for i in range(self.n):
                      centroid_coords.append(
          0.0)
                      
          # 收集各點(diǎn) 迭代 
                  for p in self.points:
                          centroid_coords[i] 
          = centroid_coords[i]+p.coords[i]
                      centroid_coords[i] 
          = centroid_coords[i]/len(self.points)
                  
          return Point(centroid_coords)

          # -- 返回根據(jù) k-means 聚集形成的 數(shù)據(jù)集 
          def kmeans(points, k, cutoff):
              
          # Randomly sample k Points from the points list, build Clusters around them
              initial = random.sample(points, k)
              clusters 
          = []
              
          for p in initial: clusters.append(Cluster([p]))
              
          # 迭代 k-means 直到 每次迭代 各收集點(diǎn) 別的 最多 不超過(guò) 0.5 
              while True:
                  
          #  k 個(gè)收集 數(shù)組
                  lists = []
                  
          for c in clusters: lists.append([])
              
          # 迭代 每個(gè) 數(shù)據(jù)點(diǎn) ,并計(jì)算與每個(gè)中心點(diǎn)距離
              # 并把數(shù)據(jù)點(diǎn)添加入相應(yīng)最短的中心點(diǎn)收集數(shù)組中
              # 在迭代中 smallest_distance 為每個(gè)點(diǎn)與各中心點(diǎn)最短距離 參數(shù),請(qǐng)注意看
                  for p in points:
                      smallest_distance 
          = getDistance(p, clusters[0].centroid)
                      index 
          = 0
                      
          for i in range(len(clusters[1:])):
                          distance 
          = getDistance(p, clusters[i+1].centroid)
                          
          if distance < smallest_distance:
                              smallest_distance 
          = distance
                              index 
          = i+1
                      
          # 添加到 離最短中心距離的 數(shù)組中
                  lists[index].append(p)
              
                  
          # 聚集完,計(jì)算新 中心點(diǎn)
              # 并 cluster.centroid 屬性記入下 新中心點(diǎn)(下一次 聚集的中心點(diǎn) )
              # 并 計(jì)算與上一次 中心點(diǎn) 距離 ,如果 差值在 cutoff 0.5 以下 ,跳出迭代 (結(jié)束,返回最后一次 聚集集合)
              biggest_shift = 0.0
                  
          for i in range(len(clusters)):
                      shift 
          = clusters[i].update(lists[i])
                      biggest_shift 
          = max(biggest_shift, shift)
                  
          if biggest_shift < cutoff: break
              
          return clusters


          # -- 得到歐幾里德距離兩點(diǎn)之間 
          def getDistance(a, b):
              
          # Forbid measurements between Points in different spaces
              if a.n != b.n: raise Exception("ILLEGAL: NON-COMPARABLE POINTS")
              
          # Euclidean distance between a and b is sqrt(sum((a[i]-b[i])^2) for all i)
              ret = 0.0
              
          for i in range(a.n):
                  ret 
          = ret+pow((a.coords[i]-b.coords[i]), 2)
              
          return math.sqrt(ret)

          # -- 在 n-維度 空間中創(chuàng)建 隨機(jī)點(diǎn)
          #
           -- 隨機(jī)生成 測(cè)試數(shù)據(jù)
          def makeRandomPoint(n, lower, upper):
              coords 
          = []
              
          for i in range(n): coords.append(random.uniform(lower, upper))
              
          return Point(coords)

          # main 
          def main(args):
              
          # 參數(shù)說(shuō)明
              # num_points,    n,    k,      cutoff,         lower,        upper 
              # 隨機(jī)數(shù)據(jù)數(shù)量 , 維度, 聚集數(shù), 跳出迭代最小距離 ,   維度數(shù)最大值,維度數(shù)最小值
              num_points, n, k, cutoff, lower, upper = 10230.5-200200

              
          # 在 n-維度空間里 , 創(chuàng)建 num_points 隨機(jī)點(diǎn)
              # 測(cè)試數(shù)據(jù)生成 
              points = []
              
          for i in range(num_points): points.append(makeRandomPoint(n, lower, upper))

              
          # 使用 k-means 算法,來(lái) 聚集數(shù)據(jù)點(diǎn) (算法入口點(diǎn))
              clusters = kmeans(points, k, cutoff)

              
          print "\nPOINTS:"
              
          for p in points: print "P:", p
              
          print "\nCLUSTERS:"
              
          for c in clusters: print "C:", c
          if __name__ == "__main__": main(sys.argv)



          整理 www.aygfsteel.com/Good-Game
          posted on 2009-08-07 16:20 劉凱毅 閱讀(2065) 評(píng)論(0)  編輯  收藏 所屬分類: python算法/函數(shù)
          主站蜘蛛池模板: 阳城县| 鲁甸县| 巴青县| 韶关市| 鄂伦春自治旗| 新疆| 商城县| 岫岩| 台北市| 南开区| 滁州市| 商丘市| 吴川市| 三门县| 裕民县| 蓬安县| 安溪县| 温宿县| 荥阳市| 开原市| 琼海市| 灵丘县| 永春县| 洪雅县| 荃湾区| 泰兴市| 钦州市| 大关县| 环江| 舟山市| 自贡市| 武定县| 靖边县| 渭南市| 民乐县| 大足县| 临朐县| 南昌市| 馆陶县| 达州市| 遂昌县|