Эта статья участвовала в "Проект «Звезда раскопок»”, чтобы выиграть творческий подарочный пакет и бросить вызов творческим поощрительным деньгам.
Мало знаний, большой вызов! Эта статья участвует в "Необходимые знания для программистов«Творческая деятельность.
1. Введение
Одноуровневое дерево решений (пень решения), также известное как пень решения, представляет собой простое дерево решений. Во втором выпуске мы уже говорили о соответствующих принципах деревьев решений, теперь давайте построим однослойное дерево решений, которое принимает решения на основе только одного признака. Поскольку это дерево имеет только один раскол, оно фактически представляет собой пень.
2. Создайте простой набор данных
Давайте начнем с создания простого набора данных, чтобы убедиться, что написанная нами функция будет работать правильно.
import numpy as np
import pandas as pd
#获得特征矩阵和标签矩阵
def get_Mat(path):
dataSet = pd.read_table(path,header = None)
xMat = np.mat(dataSet.iloc[:,:-1].values)
yMat = np.mat(dataSet.iloc[:,-1].values).T
return xMat,yMat
xMat,yMat = get_Mat('simpdata.txt')
xMat
yMat
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif']=['simhei']#显示中文
%matplotlib inline
#数据集可视化函数
def showPlot(xMat,yMat):
x=np.array(xMat[:,0])
y=np.array(xMat[:,1])
label = np.array(yMat)
plt.scatter(x,y,c=label)
plt.title('单层决策树测试数据')
plt.show()
showPlot(xMat,yMat)
3. Постройте одноуровневое дерево решений
Мы создадим две функции для реализации нашего одноуровневого дерева решений: первая функция проверяет, меньше или больше значение порогового значения, которое мы тестируем. Вторая функция немного сложнее, она перебирает взвешенный набор данных и находит одноуровневое дерево решений с наименьшей частотой ошибок. Псевдокод выглядит следующим образом:
- Установите минимальную частоту ошибок minE на +∞
- Для каждого объекта в наборе данных (цикл слоя 1):
- Для каждого шага (петля слоя 2):
- Для каждого знака неравенства (петля слоя 3):
- Построить одноуровневое дерево решений и спрогнозировать его с помощью взвешенного набора данных.
- Если частота ошибок ниже, чем minE, установите текущее одноуровневое дерево решений как лучшее одноуровневое дерево решений.
- Возвращает лучшее одноуровневое дерево решений
def Classify0(xMat,i,Q,S):
re = np.ones((xMat.shape[0],1)) #初始化re为1
if S == 'lt':
re[xMat[:,i] <= Q] = -1 #如果小于阈值,则赋值为-1
else:
re[xMat[:,i] > Q] = -1 #如果大于阈值,则赋值为-1
return re
def get_Stump(xMat,yMat,D):
m,n = xMat.shape #m为样本个数,n为特征数
Steps = 10 #初始化一个步数
bestStump = {} #用字典形式来储存树桩信息
bestClas = np.mat(np.zeros((m,1))) #初始化分类结果为1
minE = np.inf #最小误差初始化为正无穷大
for i in range(n): #遍历所有特征
Min = xMat[:,i].min() #找到特征中最小值
Max = xMat[:,i].max() #找到特征中最大值
stepSize = (Max - Min) / Steps #计算步长
for j in range(-1, int(Steps)+1):
for S in ['lt', 'gt']: #大于和小于的情况,均遍历。lt:less than,gt:greater than
Q = (Min + j * stepSize) #计算阈值
re = Classify0(xMat, i, Q, S) #计算分类结果
err = np.mat(np.ones((m,1))) #初始化误差矩阵
err[re == yMat] = 0 #分类正确的,赋值为0
eca = D.T * err #计算误差
#print(f'切分特征: {i}, 阈值:{np.round(Q,2)}, 标志:{S}, 权重误差:{np.round(eca,3)}')
if eca < minE: #找到误差最小的分类方式
minE = eca
bestClas = re.copy()
bestStump['特征列'] = i
bestStump['阈值'] = Q
bestStump['标志'] = S
return bestStump,minE,bestClas
m=xMat.shape[0]
D = np.mat(np.ones((m, 1)) / m) #初始化样本权重(每个样本权重相等)
get_Stump(xMat,yMat,D)