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