- Линейная регрессия для машинного обучения
- Логистическая регрессия и реализация машинного обучения на Python
- Борьба с проектами машинного обучения Обнаружение аномалий данных транзакций
- Дерево решений для машинного обучения
- Реализация дерева решений машинного обучения (Decision Tree) на Python
- PCA (анализ основных компонентов) для машинного обучения
- разработка функций машинного обучения
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from math import log
Мы используем набор данных из арбузной книги для построения нашего дерева решений.
data = pd.read_csv("decision_tree_data3.txt",names=['编号','色泽','根蒂','敲声','纹理','脐部','触感','密度','含糖率','好瓜' ])
data.head()
Нумерация | цвет | корень | стучать | текстура | пупок | трогать | плотность | содержание сахара | хорошая дыня | |
---|---|---|---|---|---|---|---|---|---|---|
0 | 1 | зеленый | свернуться | мутный звук | чистый | Провисание | жесткая горка | 0.697 | 0.460 | да |
1 | 2 | угольно-черный | свернуться | тупой | чистый | Провисание | жесткая горка | 0.774 | 0.376 | да |
2 | 3 | угольно-черный | свернуться | мутный звук | чистый | Провисание | жесткая горка | 0.634 | 0.264 | да |
3 | 4 | зеленый | свернуться | тупой | чистый | Провисание | жесткая горка | 0.608 | 0.318 | да |
4 | 5 | светло-белый | свернуться | мутный звук | чистый | Провисание | жесткая горка | 0.556 | 0.215 | да |
Во-первых, нам нужно обработать набор данных, чтобы преобразовать соответствующий текст в дискретные данные.
# def initdata_feature(data):
# len_columns = data.shape[1]
# data_columns = data.columns
# for i in range(len_columns):
# if(i>0 and i<len_columns-3):
# str_values = data.iloc[:,i].unique()
# for j in range(len(str_values)):
# data.loc[data[data_columns[i]]==str_values[j],data_columns[i]] = j
def initdata_y(data):
data.loc[data.好瓜 == '是 ','好瓜'] = 1
data.loc[data.好瓜 == '否 ','好瓜'] = 0
проверить это
# initdata_feature(data)
initdata_y(data)
data
Нумерация | цвет | корень | стучать | текстура | пупок | трогать | плотность | содержание сахара | хорошая дыня | |
---|---|---|---|---|---|---|---|---|---|---|
0 | 1 | зеленый | свернуться | мутный звук | чистый | Провисание | жесткая горка | 0.697 | 0.460 | 1 |
1 | 2 | угольно-черный | свернуться | тупой | чистый | Провисание | жесткая горка | 0.774 | 0.376 | 1 |
2 | 3 | угольно-черный | свернуться | мутный звук | чистый | Провисание | жесткая горка | 0.634 | 0.264 | 1 |
3 | 4 | зеленый | свернуться | тупой | чистый | Провисание | жесткая горка | 0.608 | 0.318 | 1 |
4 | 5 | светло-белый | свернуться | мутный звук | чистый | Провисание | жесткая горка | 0.556 | 0.215 | 1 |
5 | 6 | зеленый | свернуться | мутный звук | чистый | слегка вогнутый | мягкая палочка | 0.403 | 0.237 | 1 |
6 | 7 | угольно-черный | свернуться | мутный звук | слегка мягкий | слегка вогнутый | мягкая палочка | 0.481 | 0.149 | 1 |
7 | 8 | угольно-черный | свернуться | мутный звук | чистый | слегка вогнутый | жесткая горка | 0.437 | 0.211 | 1 |
8 | 9 | угольно-черный | свернуться | тупой | слегка мягкий | слегка вогнутый | жесткая горка | 0.666 | 0.091 | 0 |
9 | 10 | зеленый | жесткий | хрустящий | чистый | плоский | мягкая палочка | 0.243 | 0.267 | 0 |
10 | 11 | светло-белый | жесткий | хрустящий | Нечеткий | плоский | жесткая горка | 0.245 | 0.057 | 0 |
11 | 12 | светло-белый | свернуться | мутный звук | Нечеткий | плоский | мягкая палочка | 0.343 | 0.099 | 0 |
12 | 13 | зеленый | свернуться | мутный звук | слегка мягкий | Провисание | жесткая горка | 0.639 | 0.161 | 0 |
13 | 14 | светло-белый | свернуться | тупой | слегка мягкий | Провисание | жесткая горка | 0.657 | 0.198 | 0 |
14 | 15 | угольно-черный | свернуться | мутный звук | чистый | слегка вогнутый | мягкая палочка | 0.360 | 0.370 | 0 |
15 | 16 | светло-белый | свернуться | мутный звук | Нечеткий | плоский | жесткая горка | 0.593 | 0.042 | 0 |
16 | 17 | зеленый | свернуться | тупой | слегка мягкий | слегка вогнутый | жесткая горка | 0.719 | 0.103 | 0 |
Сначала удалите бесполезную функцию нумерации
data = data.drop('编号', axis = 1)
data
цвет | корень | стучать | текстура | пупок | трогать | плотность | содержание сахара | хорошая дыня | |
---|---|---|---|---|---|---|---|---|---|
0 | зеленый | свернуться | мутный звук | чистый | Провисание | жесткая горка | 0.697 | 0.460 | 1 |
1 | угольно-черный | свернуться | тупой | чистый | Провисание | жесткая горка | 0.774 | 0.376 | 1 |
2 | угольно-черный | свернуться | мутный звук | чистый | Провисание | жесткая горка | 0.634 | 0.264 | 1 |
3 | зеленый | свернуться | тупой | чистый | Провисание | жесткая горка | 0.608 | 0.318 | 1 |
4 | светло-белый | свернуться | мутный звук | чистый | Провисание | жесткая горка | 0.556 | 0.215 | 1 |
5 | зеленый | свернуться | мутный звук | чистый | слегка вогнутый | мягкая палочка | 0.403 | 0.237 | 1 |
6 | угольно-черный | свернуться | мутный звук | слегка мягкий | слегка вогнутый | мягкая палочка | 0.481 | 0.149 | 1 |
7 | угольно-черный | свернуться | мутный звук | чистый | слегка вогнутый | жесткая горка | 0.437 | 0.211 | 1 |
8 | угольно-черный | свернуться | тупой | слегка мягкий | слегка вогнутый | жесткая горка | 0.666 | 0.091 | 0 |
9 | зеленый | жесткий | хрустящий | чистый | плоский | мягкая палочка | 0.243 | 0.267 | 0 |
10 | светло-белый | жесткий | хрустящий | Нечеткий | плоский | жесткая горка | 0.245 | 0.057 | 0 |
11 | светло-белый | свернуться | мутный звук | Нечеткий | плоский | мягкая палочка | 0.343 | 0.099 | 0 |
12 | зеленый | свернуться | мутный звук | слегка мягкий | Провисание | жесткая горка | 0.639 | 0.161 | 0 |
13 | светло-белый | свернуться | тупой | слегка мягкий | Провисание | жесткая горка | 0.657 | 0.198 | 0 |
14 | угольно-черный | свернуться | мутный звук | чистый | слегка вогнутый | мягкая палочка | 0.360 | 0.370 | 0 |
15 | светло-белый | свернуться | мутный звук | Нечеткий | плоский | жесткая горка | 0.593 | 0.042 | 0 |
16 | зеленый | свернуться | тупой | слегка мягкий | слегка вогнутый | жесткая горка | 0.719 | 0.103 | 0 |
Давайте начнем реализовывать алгоритм дерева решений. В прошлой статье уже известно, что дерево решений необходимо построить в соответствии с набором образцов. Конкретный процесс алгоритма выглядит следующим образом:
Давайте реализуем это в модулях.
Во-первых, давайте посмотрим на решение информационной энтропии для заданного набора данных.
#求对应数据集的信息熵
def getInfoEntropy(data):
#print('################################')
#print(data)
count_class = pd.value_counts(data.iloc[:,-1], sort=True) #根据输出值,统计不同样本个数
#print(count_class)
data_count = len(data.iloc[:,-1])
#print(data_count)
Entropy = 0.0
for i in range(len(count_class)):
p = count_class.iloc[i]/data_count
Entropy = Entropy + (-p * log(p,2))
#print('当前数据集的信息熵为:',Entropy)
return Entropy
Взгляните на тест и найдите информационную энтропию всей выборки
getInfoEntropy(data)
0.9975025463691153
Далее реализуем его, и разделим данные по соответствующим характеристикам. Требуются две ситуации
- Дискретные функции, непосредственно разделенные по дискретным соответствующим категориям
- Для непрерывных данных необходимо обратиться к дискретизации данных, чтобы выбрать оптимальное значение деления. Конкретные принципы см. в предыдущей статье о непрерывной обработке объектов.
Давайте посмотрим на конкретную реализацию кода
#离散型数据划分
def split_data(data, column):
splt_datas = pd.Series() #将划分的多个数据集保存在Series中
str_values = data.iloc[:,column].unique() #获取当前数据集中,对应特征的所有类别
for i in range(len(str_values)): #遍历对应类别,找出类别所对应的数据集
df = data.loc[data.iloc[:,column] == str_values[i]]
# print(df)
splt_datas[str(i)] = df
return splt_datas
#连续型数据划分
#返回划分后的左右两个数据集以及所对应的最优划分点,还有以此划分点进行划分数据后,对应的信息熵
def split_continuous(data,column):
splt_datas = pd.Series()
series_data_sort = data.iloc[:,column].sort_values() #对应对应连续型特征的在当前数据集中的所有值,进行从小到大排序
split_values = [] #创建一个list,用于存储所有的划分点
# print(series_data_sort)
for i in range(len(series_data_sort)-1): #求得所有划分点
split_values.append((series_data_sort.iloc[i] + series_data_sort.iloc[i+1])/2) # 注意,这块不能用series_data_sort[i]
best_split_value = 0. #所要找出的最佳划分点
minInfoGain = 100.
# print(split_values)
for i in range(len(split_values)): #遍历所有划分点
# print('split_values[i]==',split_values[i])
#根据对应划分点,将数据集划分为左右两个数据集(即二分)
left_data = data.loc[data.iloc[:,column]<=split_values[i]]
right_data = data.loc[data.iloc[:,column]>split_values[i]]
#求得对应信息熵
InfoGain = len(left_data)/len(data) * getInfoEntropy(left_data) + len(right_data)/len(data) * getInfoEntropy(right_data)
#print('InfoGain====',InfoGain)
if(InfoGain < minInfoGain): #找出最小的信息熵
minInfoGain = InfoGain
best_split_value = split_values[i]
left_data = data.loc[data.iloc[:,column]<=best_split_value]
right_data = data.loc[data.iloc[:,column]>best_split_value]
series = pd.Series()
series['0'] = left_data
series['1'] = right_data
return series,best_split_value,minInfoGain
проверить это
seris = split_data(data,0)
for i in range(len(seris)):
print (seris.iloc[i])
色泽 根蒂 敲声 纹理 脐部 触感 密度 含糖率 好瓜
0 青绿 蜷缩 浊响 清晰 凹陷 硬滑 0.697 0.460 1
3 青绿 蜷缩 沉闷 清晰 凹陷 硬滑 0.608 0.318 1
5 青绿 稍蜷 浊响 清晰 稍凹 软粘 0.403 0.237 1
9 青绿 硬挺 清脆 清晰 平坦 软粘 0.243 0.267 0
12 青绿 稍蜷 浊响 稍糊 凹陷 硬滑 0.639 0.161 0
16 青绿 蜷缩 沉闷 稍糊 稍凹 硬滑 0.719 0.103 0
色泽 根蒂 敲声 纹理 脐部 触感 密度 含糖率 好瓜
1 乌黑 蜷缩 沉闷 清晰 凹陷 硬滑 0.774 0.376 1
2 乌黑 蜷缩 浊响 清晰 凹陷 硬滑 0.634 0.264 1
6 乌黑 稍蜷 浊响 稍糊 稍凹 软粘 0.481 0.149 1
7 乌黑 稍蜷 浊响 清晰 稍凹 硬滑 0.437 0.211 1
8 乌黑 稍蜷 沉闷 稍糊 稍凹 硬滑 0.666 0.091 0
14 乌黑 稍蜷 浊响 清晰 稍凹 软粘 0.360 0.370 0
色泽 根蒂 敲声 纹理 脐部 触感 密度 含糖率 好瓜
4 浅白 蜷缩 浊响 清晰 凹陷 硬滑 0.556 0.215 1
10 浅白 硬挺 清脆 模糊 平坦 硬滑 0.245 0.057 0
11 浅白 蜷缩 浊响 模糊 平坦 软粘 0.343 0.099 0
13 浅白 稍蜷 沉闷 稍糊 凹陷 硬滑 0.657 0.198 0
15 浅白 蜷缩 浊响 模糊 平坦 硬滑 0.593 0.042 0
series,best_split_value,minInfoGain = split_continuous(data,6)
for i in range(len(series)):
print (series.iloc[i])
色泽 根蒂 敲声 纹理 脐部 触感 密度 含糖率 好瓜
9 青绿 硬挺 清脆 清晰 平坦 软粘 0.243 0.267 0
10 浅白 硬挺 清脆 模糊 平坦 硬滑 0.245 0.057 0
11 浅白 蜷缩 浊响 模糊 平坦 软粘 0.343 0.099 0
14 乌黑 稍蜷 浊响 清晰 稍凹 软粘 0.360 0.370 0
色泽 根蒂 敲声 纹理 脐部 触感 密度 含糖率 好瓜
0 青绿 蜷缩 浊响 清晰 凹陷 硬滑 0.697 0.460 1
1 乌黑 蜷缩 沉闷 清晰 凹陷 硬滑 0.774 0.376 1
2 乌黑 蜷缩 浊响 清晰 凹陷 硬滑 0.634 0.264 1
3 青绿 蜷缩 沉闷 清晰 凹陷 硬滑 0.608 0.318 1
4 浅白 蜷缩 浊响 清晰 凹陷 硬滑 0.556 0.215 1
5 青绿 稍蜷 浊响 清晰 稍凹 软粘 0.403 0.237 1
6 乌黑 稍蜷 浊响 稍糊 稍凹 软粘 0.481 0.149 1
7 乌黑 稍蜷 浊响 清晰 稍凹 硬滑 0.437 0.211 1
8 乌黑 稍蜷 沉闷 稍糊 稍凹 硬滑 0.666 0.091 0
12 青绿 稍蜷 浊响 稍糊 凹陷 硬滑 0.639 0.161 0
13 浅白 稍蜷 沉闷 稍糊 凹陷 硬滑 0.657 0.198 0
15 浅白 蜷缩 浊响 模糊 平坦 硬滑 0.593 0.042 0
16 青绿 蜷缩 沉闷 稍糊 稍凹 硬滑 0.719 0.103 0
Далее, что нам нужно сделать, это, учитывая набор данных, нам нужно найти оптимальные функции деления, давайте сначала посмотрим на реализацию кода
# 查找当前数据集data 的 最优划分特征。返回对应最优特征在数据集data中的索引
def find_best_feature(data):
best_feature_index = 0 #用来保存最优划分特征的索引
minInfoGain = 100. #保存信息增益
samplenumber = len(data) #当前数据集的个数
best_split_value_return = 0. #如果最优划分特征是个连续类型的,则还需要保存对应的连续特征的最优划分点
best_split_value = 0.
best_Series = pd.Series()
for i in range(data.shape[1]-1): #遍历数据集的所有特征
InfoGain = 0.
series = pd.Series()
if(i < data.shape[1]-3): #离散型属性
series = split_data(data, i) #根据特征划分数据,将划分的多个数据集(DataFrame)保存在一个Series中返回
for j in range(len(series)):
df = series[j]
InfoGain = InfoGain +len(df)/samplenumber *(getInfoEntropy(df))
# print('InfoGain==',InfoGain,'----i=',i)
else: #连续型属性
series,best_split_value, InfoGain = split_continuous(data,i)
# print('InfoGain==',InfoGain,'----i=',i)
if(InfoGain < minInfoGain):
minInfoGain = InfoGain
InfoGain = 0.0
best_feature_index = i
best_Series = series
if(i >= data.shape[1]-3):
best_split_value_return = best_split_value
return data.columns[best_feature_index],best_Series,best_split_value_return
проверить это
find_best_feature(data)
('纹理', 0 色泽 根蒂 敲声 纹理 脐部 触感 密度 含糖率 好瓜
0...
1 色泽 根蒂 敲声 纹理 脐部 触感 密度 含糖率 好瓜
6...
2 色泽 根蒂 敲声 纹理 脐部 触感 密度 含糖率 好瓜
1...
dtype: object, 0.0)
Следующим шагом является реализация построения дерева решений.
#创建树模型
def creat_Tree(data):
y_values = data.iloc[:,-1].unique() #得到当前数据集的y的类别
if(len(y_values) == 1): #如果只剩下一个类别,说明已经是纯净的数据,不需要再分,直接返回
return y_values[0]
flag = 0
for i in range(data.shape[1]-1): #当前节点中的所有样本在当前所剩属性集中取值相同,则直接返回当前数据集中类别样本多的那个类别
if(len(data.iloc[:,i].unique()) != 1):
flag = 1
break
if(flag == 0):
value_count = pd.value_counts(data.iloc[:,-1])
return value_count.index[0]
best_feature, best_Series,best_split_value = find_best_feature(data) #寻找最优特征,返回最优特征,划分后的数据集,已经如果是连续型特征,还需要划分点
Tree = {best_feature:{}} #用字典来模拟树
for j in range(len(best_Series)): #遍历划分后的数据集
split_data = best_Series.iloc[j]
value = ''
if(best_split_value == 0.0): #说明是离散型特征
value = split_data.loc[:,best_feature].unique()[0] #获取对应划分的特征中,对应的特征类别
split_data = split_data.drop(best_feature, axis = 1) #离散型型特征,用完后需要删除
else: #否则,说明是连续型特征
if(j == 0):
value = '<='+str(best_split_value)
else:
value = '>'+str(best_split_value)
Tree[best_feature][value] = creat_Tree(split_data) #采用递归思想,继续构建
return Tree
Tree = creat_Tree(data)
Tree
{'纹理': {'模糊': 0,
'清晰': {'密度': {'<=0.38149999999999995': 0, '>0.38149999999999995': 1}},
'稍糊': {'触感': {'硬滑': 0, '软粘': 1}}}}
Далее для реализации используйте обученное дерево решений для классификации новых данных
#预测一个样本
def classification_one(Tree, data):
print(Tree)
first_key = list(Tree.keys())[0] #获取根节点的key
first_value = Tree[first_key] #获取根节点对应的value
result = -1 #初始化,用来保存当前节点的结果
if('<' in list(first_value.keys())[0]): #连续型特征
#解释下下面两行代码,里面的 list(first_value.keys())[0] 获取来的就是‘<=0.38...’这种格式,需要从这个里面解析出0.38...这个分割点
left_key = list(first_value.keys())[0] #'<=分割点'
right_key = list(first_value.keys())[1] #'>分割点'
split_poit = float(''.join(list(left_key)[2:])) # '分割点'
if(data[first_key] <= split_poit): #如果属于左分支
if(isinstance(first_value[left_key], dict)): #判断是否是叶子节点,如果对应的value还是一个dict字典,则说明是个非叶子节点,继续递归
result = classification_one(first_value[left_key],data)
else: #如果是叶子节点,返回结果值
result = first_value[left_key]
else: #如果属于左分支
if(isinstance(first_value[right_key], dict)):
result = classification_one(first_value[right_key],data)
else:
result = first_value[right_key]
else: #离散型特征
if(isinstance(first_value[data[first_key]], dict)):
result = classification_one(first_value[data[first_key]],data)
else:
result = first_value[data[first_key]]
return result
#预测多个样本
def classification_more(Tree, data):
result_list = []
for i in range(data.shape[0]):
result = classification_one(Tree, data.iloc[i])
result_list.append(result)
return result_list
classification_more(Tree,data)
{'纹理': {'清晰': {'密度': {'<=0.38149999999999995': 0, '>0.38149999999999995': 1}}, '稍糊': {'触感': {'软粘': 1, '硬滑': 0}}, '模糊': 0}}
{'密度': {'<=0.38149999999999995': 0, '>0.38149999999999995': 1}}
{'纹理': {'清晰': {'密度': {'<=0.38149999999999995': 0, '>0.38149999999999995': 1}}, '稍糊': {'触感': {'软粘': 1, '硬滑': 0}}, '模糊': 0}}
{'密度': {'<=0.38149999999999995': 0, '>0.38149999999999995': 1}}
{'纹理': {'清晰': {'密度': {'<=0.38149999999999995': 0, '>0.38149999999999995': 1}}, '稍糊': {'触感': {'软粘': 1, '硬滑': 0}}, '模糊': 0}}
{'密度': {'<=0.38149999999999995': 0, '>0.38149999999999995': 1}}
{'纹理': {'清晰': {'密度': {'<=0.38149999999999995': 0, '>0.38149999999999995': 1}}, '稍糊': {'触感': {'软粘': 1, '硬滑': 0}}, '模糊': 0}}
{'密度': {'<=0.38149999999999995': 0, '>0.38149999999999995': 1}}
{'纹理': {'清晰': {'密度': {'<=0.38149999999999995': 0, '>0.38149999999999995': 1}}, '稍糊': {'触感': {'软粘': 1, '硬滑': 0}}, '模糊': 0}}
{'密度': {'<=0.38149999999999995': 0, '>0.38149999999999995': 1}}
{'纹理': {'清晰': {'密度': {'<=0.38149999999999995': 0, '>0.38149999999999995': 1}}, '稍糊': {'触感': {'软粘': 1, '硬滑': 0}}, '模糊': 0}}
{'密度': {'<=0.38149999999999995': 0, '>0.38149999999999995': 1}}
{'纹理': {'清晰': {'密度': {'<=0.38149999999999995': 0, '>0.38149999999999995': 1}}, '稍糊': {'触感': {'软粘': 1, '硬滑': 0}}, '模糊': 0}}
{'触感': {'软粘': 1, '硬滑': 0}}
{'纹理': {'清晰': {'密度': {'<=0.38149999999999995': 0, '>0.38149999999999995': 1}}, '稍糊': {'触感': {'软粘': 1, '硬滑': 0}}, '模糊': 0}}
{'密度': {'<=0.38149999999999995': 0, '>0.38149999999999995': 1}}
{'纹理': {'清晰': {'密度': {'<=0.38149999999999995': 0, '>0.38149999999999995': 1}}, '稍糊': {'触感': {'软粘': 1, '硬滑': 0}}, '模糊': 0}}
{'触感': {'软粘': 1, '硬滑': 0}}
{'纹理': {'清晰': {'密度': {'<=0.38149999999999995': 0, '>0.38149999999999995': 1}}, '稍糊': {'触感': {'软粘': 1, '硬滑': 0}}, '模糊': 0}}
{'密度': {'<=0.38149999999999995': 0, '>0.38149999999999995': 1}}
{'纹理': {'清晰': {'密度': {'<=0.38149999999999995': 0, '>0.38149999999999995': 1}}, '稍糊': {'触感': {'软粘': 1, '硬滑': 0}}, '模糊': 0}}
{'纹理': {'清晰': {'密度': {'<=0.38149999999999995': 0, '>0.38149999999999995': 1}}, '稍糊': {'触感': {'软粘': 1, '硬滑': 0}}, '模糊': 0}}
{'纹理': {'清晰': {'密度': {'<=0.38149999999999995': 0, '>0.38149999999999995': 1}}, '稍糊': {'触感': {'软粘': 1, '硬滑': 0}}, '模糊': 0}}
{'触感': {'软粘': 1, '硬滑': 0}}
{'纹理': {'清晰': {'密度': {'<=0.38149999999999995': 0, '>0.38149999999999995': 1}}, '稍糊': {'触感': {'软粘': 1, '硬滑': 0}}, '模糊': 0}}
{'触感': {'软粘': 1, '硬滑': 0}}
{'纹理': {'清晰': {'密度': {'<=0.38149999999999995': 0, '>0.38149999999999995': 1}}, '稍糊': {'触感': {'软粘': 1, '硬滑': 0}}, '模糊': 0}}
{'密度': {'<=0.38149999999999995': 0, '>0.38149999999999995': 1}}
{'纹理': {'清晰': {'密度': {'<=0.38149999999999995': 0, '>0.38149999999999995': 1}}, '稍糊': {'触感': {'软粘': 1, '硬滑': 0}}, '模糊': 0}}
{'纹理': {'清晰': {'密度': {'<=0.38149999999999995': 0, '>0.38149999999999995': 1}}, '稍糊': {'触感': {'软粘': 1, '硬滑': 0}}, '模糊': 0}}
{'触感': {'软粘': 1, '硬滑': 0}}
[1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0]
Мы все еще используем приведенный выше набор данных для проверки.Как вы можете видеть, обучающий набор был полностью подобран,
Но действительно ли это хорошо? Как упоминалось в предыдущей статье, если дерево решений не обрезать, оно определенно будет продолжать делиться в конце, пока разделенные наборы данных не станут полностью чистыми, поэтому очень легко привести к переоснащению. Поэтому операция обрезки также требуется. Конкретный код не демонстрируется, пока вы освоите принцип построения всего дерева решений, реализовать его очень просто.
Вышеприведенное демонстрирует только соответствующую реализацию алгоритма ID3, а также других алгоритмов принятия решений, таких как алгоритм дерева решений C4.5, Основное отличие состоит в том, что критерии выбора оптимальных признаков разбиения различны. Процесс в основном такой же.
Добро пожаловать, чтобы обратить внимание на мою личную общедоступную учетную запись AI Computer Vision Workshop. Эта общедоступная учетная запись будет время от времени публиковать статьи о машинном обучении, глубоком обучении, компьютерном зрении и другие связанные статьи. Приглашаю всех учиться и общаться со мной.