旋转随机森林算法

  当输入数据中存在非线性关系的时候,基于线性回归的模型就会失效,而基于树的算法则不受数据中非线性关系的影响,基于树的方法最大的一个困扰时为了避免过拟合而对树进行剪枝的难度,对于潜在数据中的噪声,大型的树倾向于受影响,导致低偏差(过度拟合)或高方差(极度不拟合)。不过如果我们生成大量的树,最终的预测值采用集成所有树产生的输出的平均值,就可以避免方差的问题。


1. 随机森林:集成技术,采用大量的树来建模,但这里我们要保证树之间没有相互关联,不能选择所有属性,而是随机选择一个属性的子集给某个树。虽然我们再随机森林中构建最大深度的树,这样它们可以很好适应自举的样本,得到的偏差较低,后果是引入了高方差,但通过构建大量树,使用平均法则作为最后的预测值,可以解决方差问题。

2. 超随机树:比随机森林引入更多随机化,可以更高效地解决方差问题,它的运算复杂度也略有降低。随机森林是自举部分实例来给每棵树,但超随机树是使用完整的训练集数据,另外关于给定K作为给定节点随机选择的属性数量,它随机选择割点,不考虑目标变量,不像随机森林那样基于基尼不纯度或熵标准。这种更多随机化带来的架构可以更好的降低方差。而且由于划分节点不需要相关标准,因此不需要花费时间来鉴定最适合用来划分数据集的属性

3. 旋转森林:前两种需要集成大量的树才能获得好效果,而旋转森林可以用较小的树来获取相同甚至更好的效果。算法场景是投票场景属性被划分为大小相等的K个不重叠的子集,然后结合PCA、旋转矩阵来完成模型的构建。

下面是代码:

  1 # -*- coding: utf-8 -*-
  2 """
  3 Created on Wed Apr 11 17:01:22 2018
  4 @author: Alvin AI
  5 """
  6 
  7 from sklearn.datasets import make_classification
  8 from sklearn.metrics import classification_report
  9 from sklearn.cross_validation import train_test_split
 10 from sklearn.decomposition import PCA
 11 from sklearn.tree import DecisionTreeClassifier
 12 import numpy as np
 13 
 14 
 15 # 加载数据
 16 def get_data():
 17     no_features = 50
 18     redundant_features = int(0.1 * no_features)
 19     informative_features = int(0.6 * no_features)
 20     repeated_features = int(0.1 * no_features)
 21     x, y = make_classification(n_samples=500, n_features=no_features, 
 22                                flip_y=0.03, n_informative=informative_features, 
 23                                n_redundant=redundant_features, 
 24                                n_repeated=repeated_features, random_state=7)
 25     return x, y
 26 
 27 
 28 # 得到随机子集
 29 def get_random_subset(iterable, k):
 30     subsets = []
 31     iteration = 0
 32     np.random.shuffle(iterable)  # 打乱特征索引
 33     subset = 0
 34     limit = len(iterable) / k
 35     while iteration < limit:
 36         if k <= len(iterable):
 37             subset = k
 38         else:
 39             subset = len(iterable)
 40         subsets.append(iterable[-subset:])
 41         del iterable[-subset:]
 42         iteration += 1
 43     return subsets
 44 
 45 
 46 # 建立旋转森林模型
 47 def build_rotationtree_model(x_train, y_train, d, k):
 48     models = []  # 决策树
 49     r_matrices = []  # 与树相关的旋转矩阵
 50     feature_subsets = []  # 迭代中用到的特征子集
 51     for i in range(d):
 52         x, _, _, _ = train_test_split(x_train, y_train, test_size=0.3, random_state=7)
 53         # 特征的索引
 54         feature_index = range(x.shape[1])
 55         # 获取特征的子集
 56         # 10个子集,每个子集包含5个索引
 57         random_k_subset = get_random_subset(feature_index, k)  # 10个子集
 58         feature_subsets.append(random_k_subset)  # 25个树,每个树10个子集
 59         R_matrix = np.zeros((x.shape[1], x.shape[1]), dtype=float)  # 旋转矩阵
 60         for each_subset in random_k_subset:
 61             pca = PCA()
 62             x_subset = x[:, each_subset]  # 提取出子集内索引对应的x值
 63             pca.fit(x_subset)  # 主成分分析
 64             for ii in range(0, len(pca.components_)):
 65                 for jj in range(0, len(pca.components_)):
 66                     R_matrix[each_subset[ii], each_subset[jj]] = 
 67                         pca.components_[ii, jj]
 68         x_transformed = x_train.dot(R_matrix)
 69 
 70         model = DecisionTreeClassifier()
 71         model.fit(x_transformed, y_train)
 72         models.append(model)
 73         r_matrices.append(R_matrix)
 74     return models, r_matrices, feature_subsets
 75 
 76 
 77 def model_worth(models, r_matrices, x, y):
 78     predicted_ys = []
 79     for i, model in enumerate(models):
 80         x_mod = x.dot(r_matrices[i])
 81         predicted_y = model.predict(x_mod)
 82         predicted_ys.append(predicted_y)
 83 
 84         predicted_matrix = np.asmatrix(predicted_ys)  # 转化为矩阵 25*350
 85 
 86         final_prediction = []
 87         for i in range(len(y)):
 88             pred_from_all_models = np.ravel(predicted_matrix[:, i])  # 将多维数组降为一维
 89             non_zero_pred = np.nonzero(pred_from_all_models)[0]  # nonzeros(a)返回数组a中值不为零的元素的下标
 90             is_one = len(non_zero_pred) > len(models) / 2  # 如果非0预测大于模型内树的总数的一半则为1
 91             final_prediction.append(is_one)
 92         print classification_report(y, final_prediction)
 93     return predicted_matrix
 94 
 95 
 96 # 主函数
 97 if __name__ == "__main__":
 98     x, y = get_data()
 99     # 数据集划分
100     x_train, x_test_all, y_train, y_test_all = train_test_split(x, y, 
101                                                                 test_size=0.3, random_state=9)
102     x_dev, x_test, y_dev, y_test = train_test_split(x_test_all, y_test_all, 
103                                                     test_size=0.3, random_state=9)
104     models, r_matrices, features = build_rotationtree_model(x_train, y_train, 25, 5)  # 输的数量25,要用的特征子集5
105     predicted_matrix1 = model_worth(models, r_matrices, x_train, y_train)
106     predicted_matrix2 = model_worth(models, r_matrices, x_dev, y_dev)

详情参见https://blog.csdn.net/qq_33704653/article/details/80090175

原文地址:https://www.cnblogs.com/babyfei/p/9606582.html