模糊C均值聚類算法及python實現


目錄

模糊理論

Fuzzy C-Means算法原理

算法步驟

python實現


本文采用數據集為iris,將iris.txt放在程序的同一文件夾下。請先自行下載好。

模糊理論

模糊控制是自動化控制領域的一項經典方法。其原理則是模糊數學、模糊邏輯。1965,L. A. Zadeh發表模糊集合“Fuzzy Sets”的論文, 首次引入隸屬度函數的概念,打破了經典數學“非0即 1”的局限性,用[0,1]之間的實數來描述中間狀態。

很多經典的集合(即:論域U內的某個元素是否屬於集合A,可以用一個數值來表示。在經典集合中,要么0,要么1)不能描述很多事物的屬性,需要用模糊性詞語來判斷。比如天氣冷熱程度、人的胖瘦程度等等。模糊數學和模糊邏輯把只取1或0二值(屬於/不屬於)的普通集合概念推廣0~1區間內的多個取值,即隸屬度。用“隸屬度”來描述元素和集合之間的關系。

如圖所示,對於冷熱程度,我們采取三個模糊子集:冷、暖、熱。對於某一個溫度,可能同時屬於兩個子集。要進一步具體判斷,我們就需要提供一個描述“程度”的函數,即隸屬度。

例如,身高可以分為“高”、“中等”、“矮”三個子集。取論域U(即人的身高范圍)為[1.0,3.0],單位m。在U上定義三個隸屬度函數來確定身高與三個模糊子集的關系:

模糊規則的設定

(1)專家的經驗和知識

– 藉由詢問經驗豐富的專家,在獲得系統的知 識后,將知識改為IF....THEN ....的型式。

(2)操作員的操作模式

– 記錄熟練的操作員的操作模式,並將其整理為IF....THEN ....的型式。

(3)自學習

– 設定的模糊規則可能存在偏差,模糊控制器能依設定的目標,增加或修改模糊控制規則

Fuzzy C-Means算法原理

模糊c均值聚類融合了模糊理論的精髓。相較於k-means的硬聚類,模糊c提供了更加靈活的聚類結果。因為大部分情況下,數據集中的對象不能划分成為明顯分離的簇,指派一個對象到一個特定的簇有些生硬,也可能會出錯。故,對每個對象和每個簇賦予一個權值,指明對象屬於該簇的程度。當然,基於概率的方法也可以給出這樣的權值,但是有時候我們很難確定一個合適的統計模型,因此使用具有自然地、非概率特性的模糊c均值就是一個比較好的選擇。

簡單地說,就是要最小化目標函數Jm:(在一些資料中也定義為SSE即誤差的平方和)

其中m是聚類的簇數;i,j是類標號;u_i_j表示樣本x_i屬於j類的隸屬度。i表示第i個樣本,x是具有d維特征的一個樣本。c_j是j簇的中心,也具有d維度。||*||可以是任意表示距離的度量。》。

模糊c是一個不斷迭代計算隸屬度u_i_j和簇中心c_j的過程,直到他們達到最優。

注:對於單個樣本x_i,它對於每個簇的隸屬度之和為1。

迭代的終止條件為:

其中k是迭代步數,\varepsilon是誤差閾值。上式含義是,繼續迭代下去,隸屬程度也不會發生較大的變化。即認為隸屬度不變了,已經達到比較優(局部最優或全局最優)狀態了。該過程收斂於目標Jm的局部最小值或鞍點

拋開復雜的算式,這個算法的意思就是:給每個樣本賦予屬於每個簇的隸屬度函數。通過隸屬度值大小來將樣本歸類。

算法步驟

1、初始化

通常采用隨機初始化。即權值隨機地選取。簇數需要人為選定。

2、計算質心

FCM中的質心有別於傳統質心的地方在於,它是以隸屬度為權重做一個加權平均。

3、更新模糊偽划分

即更新權重(隸屬度)。簡單地說,如果x越靠近質心c,則隸屬度越高,反之越低。

python實現

這段代碼是以iris數據集為例的,雛形源於網絡,在錯誤的地方做了一些修正。是專門針對iris寫的:

如果要使用你自己的數據集,請看第二段代碼。


   
   
  
  
          
  1. #!/usr/bin/env python3
  2. # -*- coding: utf-8 -*-
  3. """
  4. Created on Wed Mar 27 10:51:45 2019
  5. @author: youxinlin
  6. """
  7. import copy
  8. import math
  9. import random
  10. import time
  11. global MAX # 用於初始化隸屬度矩陣U
  12. MAX = 10000.0
  13. global Epsilon # 結束條件
  14. Epsilon = 0.0000001
  15. def import_data_format_iris(file):
  16. """
  17. file這里是輸入文件的路徑,如iris.txt.
  18. 格式化數據,前四列為data,最后一列為類標號(有0,1,2三類)
  19. 如果是你自己的data,就不需要執行此段函數了。
  20. """
  21. data = []
  22. cluster_location =[]
  23. with open(str(file), 'r') as f:
  24. for line in f:
  25. current = line.strip().split( ",") #對每一行以逗號為分割,返回一個list
  26. current_dummy = []
  27. for j in range( 0, len(current) -1):
  28. current_dummy.append(float(current[j])) #current_dummy存放data
  29. #下面注這段話提供了一個范例:若類標號不是0,1,2之類數字時該怎么給數據集
  30. j += 1
  31. if current[j] == "Iris-setosa\n":
  32. cluster_location.append( 0)
  33. elif current[j] == "Iris-versicolor\n":
  34. cluster_location.append( 1)
  35. else:
  36. cluster_location.append( 2)
  37. data.append(current_dummy)
  38. print( "加載數據完畢")
  39. return data
  40. # return data , cluster_location
  41. def randomize_data(data):
  42. """
  43. 該功能將數據隨機化,並保持隨機化順序的記錄
  44. """
  45. order = list(range( 0, len(data)))
  46. random.shuffle(order)
  47. new_data = [[] for i in range( 0, len(data))]
  48. for index in range( 0, len(order)):
  49. new_data[index] = data[order[index]]
  50. return new_data, order
  51. def de_randomise_data(data, order):
  52. """
  53. 此函數將返回數據的原始順序,將randomise_data()返回的order列表作為參數
  54. """
  55. new_data = [[] for i in range( 0, len(data))]
  56. for index in range(len(order)):
  57. new_data[order[index]] = data[index]
  58. return new_data
  59. def print_matrix(list):
  60. """
  61. 以可重復的方式打印矩陣
  62. """
  63. for i in range( 0, len(list)):
  64. print (list[i])
  65. def initialize_U(data, cluster_number):
  66. """
  67. 這個函數是隸屬度矩陣U的每行加起來都為1. 此處需要一個全局變量MAX.
  68. """
  69. global MAX
  70. U = []
  71. for i in range( 0, len(data)):
  72. current = []
  73. rand_sum = 0.0
  74. for j in range( 0, cluster_number):
  75. dummy = random.randint( 1,int(MAX))
  76. current.append(dummy)
  77. rand_sum += dummy
  78. for j in range( 0, cluster_number):
  79. current[j] = current[j] / rand_sum
  80. U.append(current)
  81. return U
  82. def distance(point, center):
  83. """
  84. 該函數計算2點之間的距離(作為列表)。我們指歐幾里德距離。閔可夫斯基距離
  85. """
  86. if len(point) != len(center):
  87. return -1
  88. dummy = 0.0
  89. for i in range( 0, len(point)):
  90. dummy += abs(point[i] - center[i]) ** 2
  91. return math.sqrt(dummy)
  92. def end_conditon(U, U_old):
  93. """
  94. 結束條件。當U矩陣隨着連續迭代停止變化時,觸發結束
  95. """
  96. global Epsilon
  97. for i in range( 0, len(U)):
  98. for j in range( 0, len(U[ 0])):
  99. if abs(U[i][j] - U_old[i][j]) > Epsilon :
  100. return False
  101. return True
  102. def normalise_U(U):
  103. """
  104. 在聚類結束時使U模糊化。每個樣本的隸屬度最大的為1,其余為0
  105. """
  106. for i in range( 0, len(U)):
  107. maximum = max(U[i])
  108. for j in range( 0, len(U[ 0])):
  109. if U[i][j] != maximum:
  110. U[i][j] = 0
  111. else:
  112. U[i][j] = 1
  113. return U
  114. # m的最佳取值范圍為[1.5,2.5]
  115. def fuzzy(data, cluster_number, m):
  116. """
  117. 這是主函數,它將計算所需的聚類中心,並返回最終的歸一化隸屬矩陣U.
  118. 參數是:簇數(cluster_number)和隸屬度的因子(m)
  119. """
  120. # 初始化隸屬度矩陣U
  121. U = initialize_U(data, cluster_number)
  122. # print_matrix(U)
  123. # 循環更新U
  124. while ( True):
  125. # 創建它的副本,以檢查結束條件
  126. U_old = copy.deepcopy(U)
  127. # 計算聚類中心
  128. C = []
  129. for j in range( 0, cluster_number):
  130. current_cluster_center = []
  131. for i in range( 0, len(data[ 0])):
  132. dummy_sum_num = 0.0
  133. dummy_sum_dum = 0.0
  134. for k in range( 0, len(data)):
  135. # 分子
  136. dummy_sum_num += (U[k][j] ** m) * data[k][i]
  137. # 分母
  138. dummy_sum_dum += (U[k][j] ** m)
  139. # 第i列的聚類中心
  140. current_cluster_center.append(dummy_sum_num/dummy_sum_dum)
  141. # 第j簇的所有聚類中心
  142. C.append(current_cluster_center)
  143. # 創建一個距離向量, 用於計算U矩陣。
  144. distance_matrix =[]
  145. for i in range( 0, len(data)):
  146. current = []
  147. for j in range( 0, cluster_number):
  148. current.append(distance(data[i], C[j]))
  149. distance_matrix.append(current)
  150. # 更新U
  151. for j in range( 0, cluster_number):
  152. for i in range( 0, len(data)):
  153. dummy = 0.0
  154. for k in range( 0, cluster_number):
  155. # 分母
  156. dummy += (distance_matrix[i][j ] / distance_matrix[i][k]) ** ( 2/(m -1))
  157. U[i][j] = 1 / dummy
  158. if end_conditon(U, U_old):
  159. print ( "結束聚類")
  160. break
  161. print ( "標准化 U")
  162. U = normalise_U(U)
  163. return U
  164. def checker_iris(final_location):
  165. """
  166. 和真實的聚類結果進行校驗比對
  167. """
  168. right = 0.0
  169. for k in range( 0, 3):
  170. checker =[ 0, 0, 0]
  171. for i in range( 0, 50):
  172. for j in range( 0, len(final_location[ 0])):
  173. if final_location[i + ( 50*k)][j] == 1: #i+(50*k)表示 j表示第j類
  174. checker[j] += 1 #checker分別統計每一類分類正確的個數
  175. right += max(checker) #累加分類正確的個數
  176. print ( '分類正確的個數是:',right)
  177. answer = right / 150 * 100
  178. return "准確率:" + str(answer) + "%"
  179. if __name__ == '__main__':
  180. # 加載數據
  181. data = import_data_format_iris( "iris.txt")
  182. # print_matrix(data)
  183. # 隨機化數據
  184. data , order = randomize_data(data)
  185. # print_matrix(data)
  186. start = time.time()
  187. # 現在我們有一個名為data的列表,它只是數字
  188. # 我們還有另一個名為cluster_location的列表,它給出了正確的聚類結果位置
  189. # 調用模糊C均值函數
  190. final_location = fuzzy(data , 3 , 2)
  191. # 還原數據
  192. final_location = de_randomise_data(final_location, order)
  193. # print_matrix(final_location)
  194. # 准確度分析
  195. print (checker_iris(final_location))
  196. print ( "用時:{0}".format(time.time() - start))

如果要用你自己的數據集做聚類:替換下面代碼的data為你自己的數據集;自己寫一個准確率的判斷方法。


   
   
  
  
          
  1. #!/usr/bin/env python3
  2. # -*- coding: utf-8 -*-
  3. """
  4. Created on Wed Mar 27 10:51:45 2019
  5. 模糊c聚類:https://blog.csdn.net/lyxleft/article/details/88964494
  6. @author: youxinlin
  7. """
  8. import copy
  9. import math
  10. import random
  11. import time
  12. global MAX # 用於初始化隸屬度矩陣U
  13. MAX = 10000.0
  14. global Epsilon # 結束條件
  15. Epsilon = 0.0000001
  16. def print_matrix(list):
  17. """
  18. 以可重復的方式打印矩陣
  19. """
  20. for i in range( 0, len(list)):
  21. print (list[i])
  22. def initialize_U(data, cluster_number):
  23. """
  24. 這個函數是隸屬度矩陣U的每行加起來都為1. 此處需要一個全局變量MAX.
  25. """
  26. global MAX
  27. U = []
  28. for i in range( 0, len(data)):
  29. current = []
  30. rand_sum = 0.0
  31. for j in range( 0, cluster_number):
  32. dummy = random.randint( 1,int(MAX))
  33. current.append(dummy)
  34. rand_sum += dummy
  35. for j in range( 0, cluster_number):
  36. current[j] = current[j] / rand_sum
  37. U.append(current)
  38. return U
  39. def distance(point, center):
  40. """
  41. 該函數計算2點之間的距離(作為列表)。我們指歐幾里德距離。閔可夫斯基距離
  42. """
  43. if len(point) != len(center):
  44. return -1
  45. dummy = 0.0
  46. for i in range( 0, len(point)):
  47. dummy += abs(point[i] - center[i]) ** 2
  48. return math.sqrt(dummy)
  49. def end_conditon(U, U_old):
  50. """
  51. 結束條件。當U矩陣隨着連續迭代停止變化時,觸發結束
  52. """
  53. global Epsilon
  54. for i in range( 0, len(U)):
  55. for j in range( 0, len(U[ 0])):
  56. if abs(U[i][j] - U_old[i][j]) > Epsilon :
  57. return False
  58. return True
  59. def normalise_U(U):
  60. """
  61. 在聚類結束時使U模糊化。每個樣本的隸屬度最大的為1,其余為0
  62. """
  63. for i in range( 0, len(U)):
  64. maximum = max(U[i])
  65. for j in range( 0, len(U[ 0])):
  66. if U[i][j] != maximum:
  67. U[i][j] = 0
  68. else:
  69. U[i][j] = 1
  70. return U
  71. def fuzzy(data, cluster_number, m):
  72. """
  73. 這是主函數,它將計算所需的聚類中心,並返回最終的歸一化隸屬矩陣U.
  74. 輸入參數:簇數(cluster_number)、隸屬度的因子(m)的最佳取值范圍為[1.5,2.5]
  75. """
  76. # 初始化隸屬度矩陣U
  77. U = initialize_U(data, cluster_number)
  78. # print_matrix(U)
  79. # 循環更新U
  80. while ( True):
  81. # 創建它的副本,以檢查結束條件
  82. U_old = copy.deepcopy(U)
  83. # 計算聚類中心
  84. C = []
  85. for j in range( 0, cluster_number):
  86. current_cluster_center = []
  87. for i in range( 0, len(data[ 0])):
  88. dummy_sum_num = 0.0
  89. dummy_sum_dum = 0.0
  90. for k in range( 0, len(data)):
  91. # 分子
  92. dummy_sum_num += (U[k][j] ** m) * data[k][i]
  93. # 分母
  94. dummy_sum_dum += (U[k][j] ** m)
  95. # 第i列的聚類中心
  96. current_cluster_center.append(dummy_sum_num/dummy_sum_dum)
  97. # 第j簇的所有聚類中心
  98. C.append(current_cluster_center)
  99. # 創建一個距離向量, 用於計算U矩陣。
  100. distance_matrix =[]
  101. for i in range( 0, len(data)):
  102. current = []
  103. for j in range( 0, cluster_number):
  104. current.append(distance(data[i], C[j]))
  105. distance_matrix.append(current)
  106. # 更新U
  107. for j in range( 0, cluster_number):
  108. for i in range( 0, len(data)):
  109. dummy = 0.0
  110. for k in range( 0, cluster_number):
  111. # 分母
  112. dummy += (distance_matrix[i][j ] / distance_matrix[i][k]) ** ( 2/(m -1))
  113. U[i][j] = 1 / dummy
  114. if end_conditon(U, U_old):
  115. print ( "已完成聚類")
  116. break
  117. U = normalise_U(U)
  118. return U
  119. if __name__ == '__main__':
  120. data= [[ 6.1, 2.8, 4.7, 1.2], [ 5.1, 3.4, 1.5, 0.2], [ 6.0, 3.4, 4.5, 1.6], [ 4.6, 3.1, 1.5, 0.2], [ 6.7, 3.3, 5.7, 2.1], [ 7.2, 3.0, 5.8, 1.6], [ 6.7, 3.1, 4.4, 1.4], [ 6.4, 2.7, 5.3, 1.9], [ 4.8, 3.0, 1.4, 0.3], [ 7.9, 3.8, 6.4, 2.0], [ 5.2, 3.5, 1.5, 0.2], [ 5.9, 3.0, 5.1, 1.8], [ 5.7, 2.8, 4.1, 1.3], [ 6.8, 3.2, 5.9, 2.3], [ 5.4, 3.4, 1.5, 0.4], [ 5.4, 3.7, 1.5, 0.2], [ 6.6, 3.0, 4.4, 1.4], [ 5.1, 3.5, 1.4, 0.2], [ 6.0, 2.2, 4.0, 1.0], [ 7.7, 2.8, 6.7, 2.0], [ 6.3, 2.8, 5.1, 1.5], [ 7.4, 2.8, 6.1, 1.9], [ 5.5, 4.2, 1.4, 0.2], [ 5.7, 3.0, 4.2, 1.2], [ 5.5, 2.6, 4.4, 1.2], [ 5.2, 3.4, 1.4, 0.2], [ 4.9, 3.1, 1.5, 0.1], [ 4.6, 3.6, 1.0, 0.2], [ 4.6, 3.2, 1.4, 0.2], [ 5.8, 2.7, 3.9, 1.2], [ 5.0, 3.4, 1.5, 0.2], [ 6.1, 3.0, 4.6, 1.4], [ 4.7, 3.2, 1.6, 0.2], [ 6.7, 3.3, 5.7, 2.5], [ 6.5, 3.0, 5.8, 2.2], [ 5.4, 3.4, 1.7, 0.2], [ 5.8, 2.7, 5.1, 1.9], [ 5.4, 3.9, 1.3, 0.4], [ 5.3, 3.7, 1.5, 0.2], [ 6.1, 3.0, 4.9, 1.8], [ 7.2, 3.2, 6.0, 1.8], [ 5.5, 2.3, 4.0, 1.3], [ 5.7, 2.8, 4.5, 1.3], [ 4.9, 2.4, 3.3, 1.0], [ 5.4, 3.0, 4.5, 1.5], [ 5.0, 3.5, 1.6, 0.6], [ 5.2, 4.1, 1.5, 0.1], [ 5.8, 4.0, 1.2, 0.2], [ 5.4, 3.9, 1.7, 0.4], [ 6.5, 3.2, 5.1, 2.0], [ 5.5, 2.4, 3.7, 1.0], [ 5.0, 3.5, 1.3, 0.3], [ 6.3, 2.5, 5.0, 1.9], [ 6.9, 3.1, 4.9, 1.5], [ 6.2, 2.2, 4.5, 1.5], [ 6.3, 3.3, 4.7, 1.6], [ 6.4, 3.2, 4.5, 1.5], [ 4.7, 3.2, 1.3, 0.2], [ 5.5, 2.4, 3.8, 1.1], [ 5.0, 2.0, 3.5, 1.0], [ 4.4, 2.9, 1.4, 0.2], [ 4.8, 3.4, 1.9, 0.2], [ 6.3, 3.4, 5.6, 2.4], [ 5.5, 2.5, 4.0, 1.3], [ 5.7, 2.5, 5.0, 2.0], [ 6.5, 3.0, 5.2, 2.0], [ 6.7, 3.0, 5.0, 1.7], [ 5.2, 2.7, 3.9, 1.4], [ 6.9, 3.1, 5.1, 2.3], [ 7.2, 3.6, 6.1, 2.5], [ 4.8, 3.0, 1.4, 0.1], [ 6.3, 2.9, 5.6, 1.8], [ 5.1, 3.5, 1.4, 0.3], [ 6.9, 3.1, 5.4, 2.1], [ 5.6, 3.0, 4.1, 1.3], [ 7.7, 2.6, 6.9, 2.3], [ 6.4, 2.9, 4.3, 1.3], [ 5.8, 2.7, 4.1, 1.0], [ 6.1, 2.9, 4.7, 1.4], [ 5.7, 2.9, 4.2, 1.3], [ 6.2, 2.8, 4.8, 1.8], [ 4.8, 3.4, 1.6, 0.2], [ 5.6, 2.9, 3.6, 1.3], [ 6.7, 2.5, 5.8, 1.8], [ 5.0, 3.4, 1.6, 0.4], [ 6.3, 3.3, 6.0, 2.5], [ 5.1, 3.8, 1.9, 0.4], [ 6.6, 2.9, 4.6, 1.3], [ 5.1, 3.3, 1.7, 0.5], [ 6.3, 2.5, 4.9, 1.5], [ 6.4, 3.1, 5.5, 1.8], [ 6.2, 3.4, 5.4, 2.3], [ 6.7, 3.1, 5.6, 2.4], [ 4.6, 3.4, 1.4, 0.3], [ 5.5, 3.5, 1.3, 0.2], [ 5.6, 2.7, 4.2, 1.3], [ 5.6, 2.8, 4.9, 2.0], [ 6.2, 2.9, 4.3, 1.3], [ 7.0, 3.2, 4.7, 1.4], [ 5.0, 3.2, 1.2, 0.2], [ 4.3, 3.0, 1.1, 0.1], [ 7.7, 3.8, 6.7, 2.2], [ 5.6, 3.0, 4.5, 1.5], [ 5.8, 2.7, 5.1, 1.9], [ 5.8, 2.8, 5.1, 2.4], [ 4.9, 3.1, 1.5, 0.1], [ 5.7, 3.8, 1.7, 0.3], [ 7.1, 3.0, 5.9, 2.1], [ 5.1, 3.7, 1.5, 0.4], [ 6.3, 2.7, 4.9, 1.8], [ 6.7, 3.0, 5.2, 2.3], [ 5.1, 2.5, 3.0, 1.1], [ 7.6, 3.0, 6.6, 2.1], [ 4.5, 2.3, 1.3, 0.3], [ 4.9, 3.0, 1.4, 0.2], [ 6.5, 2.8, 4.6, 1.5], [ 5.7, 4.4, 1.5, 0.4], [ 6.8, 3.0, 5.5, 2.1], [ 4.9, 2.5, 4.5, 1.7], [ 5.1, 3.8, 1.5, 0.3], [ 6.5, 3.0, 5.5, 1.8], [ 5.7, 2.6, 3.5, 1.0], [ 5.1, 3.8, 1.6, 0.2], [ 5.9, 3.0, 4.2, 1.5], [ 6.4, 3.2, 5.3, 2.3], [ 4.4, 3.0, 1.3, 0.2], [ 6.1, 2.8, 4.0, 1.3], [ 6.3, 2.3, 4.4, 1.3], [ 5.0, 2.3, 3.3, 1.0], [ 5.0, 3.6, 1.4, 0.2], [ 5.9, 3.2, 4.8, 1.8], [ 6.4, 2.8, 5.6, 2.2], [ 6.1, 2.6, 5.6, 1.4], [ 5.6, 2.5, 3.9, 1.1], [ 6.0, 2.7, 5.1, 1.6], [ 6.0, 3.0, 4.8, 1.8], [ 6.4, 2.8, 5.6, 2.1], [ 6.0, 2.9, 4.5, 1.5], [ 5.8, 2.6, 4.0, 1.2], [ 7.7, 3.0, 6.1, 2.3], [ 5.0, 3.3, 1.4, 0.2], [ 6.9, 3.2, 5.7, 2.3], [ 6.8, 2.8, 4.8, 1.4], [ 4.8, 3.1, 1.6, 0.2], [ 6.7, 3.1, 4.7, 1.5], [ 4.9, 3.1, 1.5, 0.1], [ 7.3, 2.9, 6.3, 1.8], [ 4.4, 3.2, 1.3, 0.2], [ 6.0, 2.2, 5.0, 1.5], [ 5.0, 3.0, 1.6, 0.2]]
  121. start = time.time()
  122. # 調用模糊C均值函數
  123. res_U = fuzzy(data , 3 , 2)
  124. # 計算准確率
  125. print ( "用時:{0}".format(time.time() - start))

https://blog.csdn.net/zwqhehe/article/details/75174918

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM