• 统计学习算法实现(01)——决策数


    目录

    1.数据集的创建

    2.将上述表中文字转为数字编号 ,并转为numpy格式

    3.熵与条件熵的计算

    4.计算信息增益与信息增益比

    5.特征选择

    6.完整程序:

    7. ID3算法:

    7.1 代码 

    7.1.1 决策树的生成算法: 

    8.决策树的剪枝


    1.数据集的创建

    1. import numpy as np
    2. import pandas as pd
    3. #数据集的创建
    4. def create_data():
    5. datasets = [['青年', '否', '否', '一般', '否'],
    6. ['青年', '否', '否', '好', '否'],
    7. ['青年', '是', '否', '好', '是'],
    8. ['青年', '是', '是', '一般', '是'],
    9. ['青年', '否', '否', '一般', '否'],
    10. ['中年', '否', '否', '一般', '否'],
    11. ['中年', '否', '否', '好', '否'],
    12. ['中年', '是', '是', '好', '是'],
    13. ['中年', '否', '是', '非常好', '是'],
    14. ['中年', '否', '是', '非常好', '是'],
    15. ['老年', '否', '是', '非常好', '是'],
    16. ['老年', '否', '是', '好', '是'],
    17. ['老年', '是', '否', '好', '是'],
    18. ['老年', '是', '否', '非常好', '是'],
    19. ['老年', '否', '否', '一般', '否'],
    20. ]
    21. labels = [u'年龄', u'有工作', u'有自己的房子', u'信贷情况', u'类别'] #前缀u表示该字符串是unicode编码,防止因为编码问题,导致中文出现乱码
    22. # 返回数据集和每个维度的名称
    23. return datasets, labels
    24. datasets, labels = create_data() #调用数据集创建函数
    25. train_data = pd.DataFrame(datasets, columns=labels) # 创建DataFrame表
    26. print(train_data)

    输出:

     

    注意:datasets对应的应该就是数据集,而通过pandas的DataFrame创建得就是一个表。 

    2.将上述表中文字转为数字编号 ,并转为numpy格式

    1. d = {'青年':1, '中年':2, '老年':3, '一般':1, '好':2, '非常好':3, '是':0, '否':1}
    2. data = [] #定义空表用以存放编号后的数据表
    3. for i in range(15): #表中一共有15组数据
    4. tmp = []
    5. t = datasets[i] #依次打印表中的各组数据,如:t=datasets[1] ---> ['青年', '否', '否', '好', '否']
    6. for tt in t: #此处tt读取的分别是键:'青年', '否', '否', '好', '否'
    7. tmp.append(d[tt]) # 此步接如上,依次为上行代码的键按 d{} 中规则配对
    8. data.append(tmp) # 注意:上步中的tmp中只存了一组编码后的数据。而data中依次存入各组数据构成数据表
    9. data = np.array(data) #将表转为numpy的格式
    10. print(data)
    11. print(data.shape) #查看数据形状

     输出:

    3.熵与条件熵的计算

    理论:

     

    1. # 熵的计算
    2. def entropy(y):
    3. N = len(y)
    4. count = []
    5. for value in set(y):
    6. count.append(len(y[y == value]))
    7. count = np.array(count)
    8. entro = -np.sum((count / N) * (np.log2(count / N)))
    9. return entro
    10. # 条件熵的计算
    11. def cond_entropy(X, y, cond):
    12. N = len(y)
    13. cond_X = X[:, cond]
    14. tmp_entro = []
    15. for val in set(cond_X):
    16. tmp_y = y[np.where(cond_X == val)]
    17. tmp_entro.append(len(tmp_y)/N * entropy(tmp_y))
    18. cond_entro = sum(tmp_entro)
    19. return cond_entro
    20. #准备好计算熵与条件熵的数据
    21. #data[:,:-1] 依次取每一组数据中除最后一位以外的数
    22. #data[:, -1] 依次取每一组数据中的最后一位
    23. X, y = data[:,:-1], data[:, -1]
    24. Entropy = entropy(y) #计算熵
    25. Cond_entropy = cond_entropy(X, y, 0) #计算条件熵
    26. print("熵:",Entropy)
    27. print("条件熵:",Cond_entropy)

    4.计算信息增益与信息增益比

    1. # 信息增益
    2. def info_gain(X, y, cond):
    3. return entropy(y) - cond_entropy(X, y, cond)
    4. # 信息增益比
    5. def info_gain_ratio(X, y, cond):
    6. return (entropy(y) - cond_entropy(X, y, cond))/cond_entropy(X, y, cond)
    7. # A1, A2, A3, A4 =》年龄 工作 房子 信贷
    8. # 信息增益
    9. gain_a1 = info_gain(X, y, 0)
    10. print("年龄信息增益:",gain_a1)
    11. gain_a2 = info_gain(X, y, 1)
    12. gain_a3 = info_gain(X, y, 2)
    13. gain_a4 = info_gain(X, y, 3)
    14. print("工作信息增益:",gain_a2)
    15. print("房子信息增益:",gain_a3)
    16. print("信贷信息增益:",gain_a4)

    5.特征选择

    1. def best_split(X, y, method='info_gain'):
    2. """根据method指定的方法使用信息增益或信息增益比来计算各个维度的最大信息增益(比),返回特征的axis"""
    3. _, M = X.shape
    4. info_gains = []
    5. if method == 'info_gain':
    6. split = info_gain
    7. elif method == 'info_gain_ratio':
    8. split = info_gain_ratio
    9. else:
    10. print('No such method')
    11. return
    12. for i in range(M):
    13. tmp_gain = split(X, y, i)
    14. info_gains.append(tmp_gain)
    15. best_feature = np.argmax(info_gains)
    16. return best_feature
    17. print(best_split(X,y)) #result--> 2
    18. def majorityCnt(y):
    19. """当特征使用完时,返回类别数最多的类别"""
    20. unique, counts = np.unique(y, return_counts=True)
    21. max_idx = np.argmax(counts)
    22. return unique[max_idx]
    23. print(majorityCnt(y))

    输出:0.

    6.完整程序:

    1. import numpy as np
    2. import pandas as pd
    3. # import matplotlib.pyplot as plt
    4. # #matplotlib inline
    5. #
    6. # from sklearn.datasets import load_iris
    7. # from sklearn.model_selection import train_test_split
    8. #
    9. # from collections import Counter
    10. # import math
    11. # from math import log
    12. #
    13. # import pprint
    14. #数据集的创建
    15. def create_data():
    16. datasets = [['青年', '否', '否', '一般', '否'],
    17. ['青年', '否', '否', '好', '否'],
    18. ['青年', '是', '否', '好', '是'],
    19. ['青年', '是', '是', '一般', '是'],
    20. ['青年', '否', '否', '一般', '否'],
    21. ['中年', '否', '否', '一般', '否'],
    22. ['中年', '否', '否', '好', '否'],
    23. ['中年', '是', '是', '好', '是'],
    24. ['中年', '否', '是', '非常好', '是'],
    25. ['中年', '否', '是', '非常好', '是'],
    26. ['老年', '否', '是', '非常好', '是'],
    27. ['老年', '否', '是', '好', '是'],
    28. ['老年', '是', '否', '好', '是'],
    29. ['老年', '是', '否', '非常好', '是'],
    30. ['老年', '否', '否', '一般', '否'],
    31. ]
    32. labels = [u'年龄', u'有工作', u'有自己的房子', u'信贷情况', u'类别'] #前缀u表示该字符串是unicode编码,防止因为编码问题,导致中文出现乱码
    33. # 返回数据集和每个维度的名称
    34. return datasets, labels
    35. # 熵的计算
    36. def entropy(y):
    37. N = len(y)
    38. count = []
    39. for value in set(y):
    40. count.append(len(y[y == value]))
    41. count = np.array(count)
    42. entro = -np.sum((count / N) * (np.log2(count / N)))
    43. return entro
    44. # 条件熵的计算
    45. def cond_entropy(X, y, cond):
    46. N = len(y)
    47. cond_X = X[:, cond]
    48. tmp_entro = []
    49. for val in set(cond_X):
    50. tmp_y = y[np.where(cond_X == val)]
    51. tmp_entro.append(len(tmp_y)/N * entropy(tmp_y))
    52. cond_entro = sum(tmp_entro)
    53. return cond_entro
    54. datasets, labels = create_data() #调用数据集创建函数
    55. train_data = pd.DataFrame(datasets, columns=labels) # 创建DataFrame表
    56. print(train_data)
    57. print("-----------------如下将上述表中文字转为数字编号----------------")
    58. """
    59. 测试:
    60. t = datasets[1]
    61. d = {'青年':1, '中年':2, '老年':3, '一般':1, '好':2, '非常好':3, '是':0, '否':1}
    62. print(t)
    63. ['青年', '否', '否', '好', '否']
    64. print(d['青年'])
    65. 1
    66. """
    67. d = {'青年':1, '中年':2, '老年':3, '一般':1, '好':2, '非常好':3, '是':0, '否':1}
    68. data = [] #定义空表用以存放编号后的数据表
    69. for i in range(15): #表中一共有15组数据
    70. tmp = []
    71. t = datasets[i] #依次打印表中的各组数据,如:t=datasets[1] ---> ['青年', '否', '否', '好', '否']
    72. for tt in t: #此处tt读取的分别是键:'青年', '否', '否', '好', '否'
    73. tmp.append(d[tt]) # 此步接如上,依次为上行代码的键按 d{} 中规则配对
    74. data.append(tmp) # 注意:上步中的tmp中只存了一组编码后的数据。而data中依次存入各组数据构成数据表
    75. data = np.array(data) #将表转为numpy的格式
    76. print(data)
    77. print(data.shape) #查看数据形状
    78. #准备好计算熵与条件熵的数据
    79. #data[:,:-1] 依次取每一组数据中除最后一位以外的数
    80. #data[:, -1] 依次取每一组数据中的最后一位
    81. X, y = data[:,:-1], data[:, -1]
    82. Entropy = entropy(y) #计算熵
    83. Cond_entropy = cond_entropy(X, y, 0) #计算条件熵
    84. print("熵:",Entropy)
    85. print("条件熵:",Cond_entropy)
    86. # 信息增益
    87. def info_gain(X, y, cond):
    88. return entropy(y) - cond_entropy(X, y, cond)
    89. # 信息增益比
    90. def info_gain_ratio(X, y, cond):
    91. return (entropy(y) - cond_entropy(X, y, cond))/cond_entropy(X, y, cond)
    92. # A1, A2, A3, A4 =》年龄 工作 房子 信贷
    93. # 信息增益
    94. gain_a1 = info_gain(X, y, 0)
    95. print("年龄信息增益:",gain_a1)
    96. gain_a2 = info_gain(X, y, 1)
    97. gain_a3 = info_gain(X, y, 2)
    98. gain_a4 = info_gain(X, y, 3)
    99. print("工作信息增益:",gain_a2)
    100. print("房子信息增益:",gain_a3)
    101. print("信贷信息增益:",gain_a4)
    102. def best_split(X, y, method='info_gain'):
    103. """根据method指定的方法使用信息增益或信息增益比来计算各个维度的最大信息增益(比),返回特征的axis"""
    104. _, M = X.shape
    105. info_gains = []
    106. if method == 'info_gain':
    107. split = info_gain
    108. elif method == 'info_gain_ratio':
    109. split = info_gain_ratio
    110. else:
    111. print('No such method')
    112. return
    113. for i in range(M):
    114. tmp_gain = split(X, y, i)
    115. info_gains.append(tmp_gain)
    116. best_feature = np.argmax(info_gains)
    117. return best_feature
    118. print(best_split(X,y)) #result--> 2
    119. def majorityCnt(y):
    120. """当特征使用完时,返回类别数最多的类别"""
    121. unique, counts = np.unique(y, return_counts=True)
    122. max_idx = np.argmax(counts)
    123. return unique[max_idx]
    124. print(majorityCnt(y))

    7. ID3算法:

     

     

     

     

     

    7.1 代码 

    7.1.1 决策树的生成算法: 

    1. class DecisionTreeClassifer:
    2. """
    3. 决策树生成算法,
    4. method指定ID3或C4.5,两方法唯一不同在于特征选择方法不同
    5. info_gain: 信息增益即ID3
    6. info_gain_ratio: 信息增益比即C4.5
    7. """
    8. def __init__(self, threshold, method='info_gain'):
    9. self.threshold = threshold
    10. self.method = method
    11. def fit(self, X, y, labels):
    12. labels = labels.copy()
    13. M, N = X.shape
    14. if len(np.unique(y)) == 1:
    15. return y[0]
    16. if N == 1:
    17. return majorityCnt(y)
    18. bestSplit = best_split(X, y, method=self.method)
    19. bestFeaLable = labels[bestSplit]
    20. Tree = {bestFeaLable: {}}
    21. del (labels[bestSplit])
    22. feaVals = np.unique(X[:, bestSplit])
    23. for val in feaVals:
    24. idx = np.where(X[:, bestSplit] == val)
    25. sub_X = X[idx]
    26. sub_y = y[idx]
    27. sub_labels = labels
    28. Tree[bestFeaLable][val] = self.fit(sub_X, sub_y, sub_labels)
    29. return Tree
    30. My_Tree = DecisionTreeClassifer(threshold=0.1)
    31. print("tree:",My_Tree.fit(X, y, labels))

    8.决策树的剪枝

    (待补充....)

    (学习笔记,侵删。欢迎讨论呢) 

  • 相关阅读:
    谷粒商城实战(044集群学习-redis集群)
    第二章第二节:字符串 索引和切片
    Java 内置包装类——System类详解
    Css 3 动画
    idea配置Idea类注释模板和方法注释模板(亲测有效)
    CSDN算法技能树评测
    【C++入门系列】——命名空间和输入输出
    如何才能设计出“好的”测试用例?
    机器视觉:实现精准农业的关键技术
    obj解析为集合
  • 原文地址:https://blog.csdn.net/m0_55196097/article/details/126850361