基於信息熵的數據離散化


1、准備數據

  基於信息熵的數據離散化算法是由監督學習算法,在使用該方法對數據進行離散化時,需要數據有對應的標簽。
  下面是一份用戶最近點擊的20個商品的價格與是否加入購物車對應關系:

        價格 標簽 價格 標簽 價格 標簽 價格 標簽
        56 1 641 1 10 1 2398 1
        87 1 63 0 9 0 592 1
        129 0 2764 1 88 1 561 1
        23 0 2323 0 222 0 764 0
        342 1 453 1 97 0 121 1

對該份數據進行離散化:新建DiscreteByEntropy類,然后初始化相關函數,並加載數據。對應如下基於信息熵的數據離散化--新建類並加載數據:

import numpy as np                                                                                                                                                                                                                                                          
import math                                                                                                                                                                                                                                                          
                                                                                                                                                                                                                                                      
class DiscreteByEntropy:                                                                                                                                                                                         
      def __init__(self,group,threshold):
          self.maxGroup = group	#最大分組數
          self.minInfoThreshold = threshold		#停止划分的最小熵
          self.result = dict()		#保存划分結果
    
      #准備數據
      def loadData(self):
          data = np.array(
              [
                  [56,1],[87,1],[129,0],[23,0],[342,1],
                  [641,1],[63,0],[2764,1],[2323,0],[453,1],
                  [10,1],[9,0],[88,1],[222,0],[97,0],
              ]
          )
          return data

2、計算數據的信息熵
該步驟是計算數據的信息熵,是為下一步分割數據集做准備。對應如下基於信息熵的數據離散化--計算數據的信息熵

 #計算按照數據指定數據分組后的香農熵
 def calEntropy(self,data):
      numData = len(data)
      labelCounts = {}
      for feature in data:
          #獲得標簽
          oneLabel = feature[-1]
          #如果標簽步驟新定義的字典里則創建該標簽
          labelCounts.setdefault(oneLabel,0)
          #該類標簽下含有數據的個數
          labelCounts[oneLabel] += 1
      shannonEnt = 0.0
      for key in labelCounts:
          #同類標簽出現的概率
          prob = float(labelCounts[key]) / numData
          #以2為底求對數
          shannonEnt -= prob * math.log(prob,2)
      return shannonEnt

3、分割數據集
尋找一組數據最佳分割點的方法是:遍歷所有屬性值,數據按照該屬性分割,使得平均熵最小。對應基於信息熵的數據離散化--分割數據集:

按照調和信息熵最小化原則分割數據集

def split(self,data):
    #inf為正無窮大
    minEntropy = np.inf
    #記錄最終分割索引
    index = -1
    #按照第一列對數據進行排序
    sortData = data[np.argsort(data[:,0])]
    #初始化最終分割數據后的熵
    lastE1,lastE2 = -1,-1
    #返回的數據結構,包含數據和對應的熵
    S1 = dict()
    S2 = dict()
    for i in range(len(sortData)):
        #分割數據集
        splitData1,splitData2 = sortData[: i + 1],sortData[i + 1 :]
        entropy1,entropy2 = (
            self.calEntropy(splitData1),
            self.calEntropy(splitData2),
        ) #計算信息熵
        entropy = entropy1 * len(splitData1) / len(sortData) + \
                entropy2 * len(splitData2) / len(sortData)
        #如果調和平均熵小於最小值
        if entropy < minEntropy:
            minEntropy = entropy
            index = i
            lastE1 = entropy1
            lastE2 = entropy2
s1["entropy"] = lastE1
s1["data"] = sortData[: index + 1]
s1["entropy"] = lastE2
s2["data"] = sortData[index + 1 :]
return S1,S2,minEntropy

4、數據離散化
按照上面基於信息熵分組的內容,對數據做離散化處理。對應基於信息熵的數據離散化--數據離散化:

#對數據進行分組
def train(self,data):
    #需要遍歷的key
    needSplitKey = [0]
    #將整個數據作為一組
    self.result.setdefault(0,{})
    self.result[0]["entropy"] = np.inf
    self.result[0]["data"] = data
    group = 1
    for key in needSplitKey:
        S1,S2,entropy = self.split(self.result[key]["data"])
        #如果滿足條件
        if entropy > self.minInfoThreshold and group < self.maxGroup:
            self.result[key] = S1
            newKey = max(self.result.keys()) + 1
            self.result[newKey] = S2
            needSplitKey.extend([key])
            needSplitKey.extend([newKey])
            group += 1
        else:
            break
if __name__ == "__main__":
    dbe = DiscreteByEntropy(group=6,threshold=0.5)
    data = dbe.loadData()
    dbe.train(data)
print("result is {}".format(dbe.result))

運行結果如下:

可見這里將商品價格分為了3份,分別為{9,10,23,56,63,87,88}、{342,453,641,2323,2764}、{97,129,222}


免責聲明!

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



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