优化随机森林算法,正确率提高1%~5%(已经有90%+的正确率,再调高会导致过拟合)
论文当然是参考的,毕竟出现早的算法都被人研究烂了,什么优化基本都做过。而人类最高明之处就是懂得利用前人总结的经验和制造的工具(说了这么多就是为偷懒找借口。hhhh)
优化思路
1. 计算传统模型准确率
2. 计算设定树木颗数时最佳树深度,以最佳深度重新生成随机森林
3. 计算新生成森林中每棵树的AUC,选取AUC靠前的一定百分比的树
4. 通过计算各个树的数据相似度,排除相似度超过设定值且AUC较小的树
5. 计算最终的准确率
主要代码粘贴如下(注释比较详细,就不介绍代码了)
#-*- coding: utf-8 -*-
import time
from csv import reader
from random import randint
from random import seed
import numpy as np
from numpy import mat
from group_11 import caculateAUC_1, plotTree
# 建立一棵CART树
'''试探分枝'''
def data_split(index, value, dataset):
left, right = list(), list()
for row in dataset:
if row[index] < value:
left.append(row)
else:
right.append(row)
return left, right
'''计算基尼指数'''
def calc_gini(groups, class_values):
gini = 0.0
total_size = 0
for group in groups:
total_size += len(group)
for group in groups:
size = len(group)
if size == 0:
continue
for class_value in class_values:
proportion = [row[-1] for row in group].count(class_value) / float(size)
gini += (size / float(total_size)) * (proportion * (1.0 - proportion))# 二分类执行两次,相当于*2
return gini
'''找最佳分叉点'''
def get_split(dataset, n_features):
class_values = list(set(row[-1] for row in dataset))# 类别标签集合
b_index, b_value, b_score, b_groups = 999, 999, 999, None
# 随机选取特征子集,包含n_features个特征
features = list()
while len(features) < n_features:
# 随机选取特征
# 特征索引
index = randint(0, len(dataset[0]) - 2) # 往features添加n_features个特征(n_feature等于特征数的根号),特征索引从dataset中随机取
if index not in features:
features.append(index)
for index in features: # 对每一个特征
# 计算Gini指数
for row in dataset: # 按照每个记录的该特征的取值划分成两个子集,计算对于的Gini(D,A),取最小的
groups = data_split(index, row[index], dataset)
gini = calc_gini(groups, class_values)
if gini < b_score:
b_index, b_value, b_score, b_groups = index, row[index], gini, groups
return {'index': b_index, 'value': b_value, 'groups': b_groups} # 每个节点由字典组成
'''多数表决'''
def to_terminal(group):
outcomes = [row[-1] for row in group]
return max(set(outcomes), key=outcomes.count)
'''分枝'''
def split(node, max_depth, min_size, n_features, depth):
left, right = node['groups'] # 自动分包/切片
del (node['groups'])
if not left or not right: # left或者right为空时
node['left'] = node['right'] = to_terminal(left + right) # 叶节点不好理解
return
if depth >= max_depth:
node['left'], node['right'] = to_terminal(left), to_terminal(right)
return
# 左子树
if len(left) <= min_size:
node['left'] = to_terminal(left)
else:
node['left'] = get_split(left, n_features)
split(node['left'], max_depth, min_size, n_features, depth + 1)
# 右子树
if len(right) <= min_size: # min_size最小的的分枝样本数
node['right'] = to_terminal(ri