线性回归的集成学习模型之boosting算法与随机森林算法,线性回归总结,分类问题的逻辑回归模型及其实现,分类问题的损失函数,多分类实现方法,决策树分类原理与案例(小汽车质量)
二、集成学习
1. 集成学习
决策树是中庸的模型,集成学习通过构建并合并多个模型来完成学习任务,从而获得比单一学习模型更显著优越的泛化性能,简言之,集成学习就是利用模型的“集体智慧”,提升预测的准确率. 根据单个模型方式,集成学习可以分为两大类:
-
个体模型间存在强依赖关系,必须串行生成的序列化(前面模型结果作为后面模型的输入)方法,其代表为Boosting算法;
-
个体模型之间不存在强依赖关系,可同时生成的并行化方法,代表是Bagging和随机森林算法.
2. Boosting
1)什么是Boosting
Boosting(直译为推进、提升)是一族可以将弱学习器提升为强学习器的算法,其工作原理是:
-
先训练出第一个初始模型;
-
根据第一个模型的表现进行调整参数与权重,使得模型预测错误的数据获得更多的关注,争取再重新训练下一个模型将其预测正确;类似于考试错题集。
-
不断重复第二步,直到模型数量达到预先设定的数目T,最终将这T个模型加权结合.
AdaBoosting是Boosting算法族中最著名的算法,它根据每次训练集之中每个样本的分类是否正确,以及上次的总体分类的准确率,来确定每个样本的权值。将修改过权值的新数据集送给下层分类器进行训练,最后将每次训练得到的分类器最后融合起来,作为最后的决策分类器。
2)实现Boosting
sklearn中,AdaBoosting(正向激励)相关API:
import sklearn.tree as st import sklearn.ensemble as se # model: 决策树模型(单个模型,基学习器) model = st.DecisionTreeRegressor(max_depth=4) # n_estimators:构建400棵不同权重的决策树,训练模型(这个模型里面有很多子模型即400个决策树,每个深度4,前后树串起来的) model = se.AdaBoostRegressor(model, # 单模型 n_estimators=400, # 决策树数量 random_state=7)# 随机种子 # 训练模型 model.fit(train_x, train_y) # 测试模型 pred_test_y = model.predict(test_x)
代码:
# AdaBoosting示例 # 使用AdaBoosting预测波士顿房价 import sklearn.datasets as sd import sklearn.utils as su import sklearn.tree as st import sklearn.ensemble as se import sklearn.metrics as sm boston = sd.load_boston() # 加载boston地区房价数据 print(boston.feature_names) print(boston.data.shape) print(boston.target.shape) random_seed = 7 # 随机种子,计算随机值,相同的随机种子得到的随机值一样 x, y = su.shuffle(boston.data, boston.target, random_state = random_seed) # 计算训练数据的数量 train_size = int(len(x) * 0.8) # 以boston.data中80%的数据作为训练数据 # 构建训练数据、测试数据 train_x = x[:train_size] # 训练输入, x前面80%的数据 test_x = x[train_size:] # 测试输入, x后面20%的数据 train_y = y[:train_size] # 训练输出 test_y = y[train_size:] # 测试输出 model2 = se.AdaBoostRegressor(st.DecisionTreeRegressor(max_depth=4), n_estimators=400, # 决策树数量 random_state=random_seed) # 随机种子 # 训练 model2.fit(train_x, train_y) # 预测 pre_test_y2 = model2.predict(test_x) # 打印预测输出和实际输出的R2值 print(sm.r2_score(test_y, pre_test_y2))
执行结果:
['CRIM' 'ZN' 'INDUS' 'CHAS' 'NOX' 'RM' 'AGE' 'DIS' 'RAD' 'TAX' 'PTRATIO' 'B' 'LSTAT'] (506, 13) (506,) 0.9068598725149652
可以看到,通过AdaBoosting算法,回归模型获得了更高的R2值.
3. 随机森林
1)什么是随机森林
随机森林(Random Forest,简称RF)是专门为决策树设计的一种集成学习方法,是Bagging法的一种拓展,它是指每次构建决策树模型时,不仅随机选择部分样本,而且还随机选择部分特征来构建多棵决策树. 这样不仅规避了强势样本对预测结果的影响,而且也削弱了强势特征的影响,使模型具有更强的泛化能力.
随机森林简单、容易实现、计算开销小,在很多现实任务中展现出强大的性能,被誉为“代表集成学习技术水平的方法”.
2)如何实现随机森林
sklearn中,随机森林相关API:
import sklearn.ensemble as se model = se.RandomForestRegressor( max_depth, # 决策树最大深度 n_estimators, # 决策树数量 min_samples_split)# 子表中最小样本数 若小于这个数字,则不再继续向下拆分
以下是利用随机森林实现波士顿房价预测的代码:
# 使用随机森林预测波士顿房价 import sklearn.datasets as sd import sklearn.utils as su import sklearn.tree as st import sklearn.ensemble as se import sklearn.metrics as sm boston = sd.load_boston() # 加载boston地区房价数据 print(boston.feature_names) print(boston.data.shape) print(boston.target.shape) random_seed = 7 # 随机种子,计算随机值,相同的随机种子得到的随机值一样 x, y = su.shuffle(boston.data, boston.target, random_state=random_seed) # 计算训练数据的数量 train_size = int(len(x) * 0.8) # 以boston.data中80%的数据作为训练数据 # 构建训练数据、测试数据 train_x = x[:train_size] # 训练输入, x前面80%的数据 test_x = x[train_size:] # 测试输入, x后面20%的数据 train_y = y[:train_size] # 训练输出 test_y = y[train_size:] # 测试输出 # 创建随机森林回归器,并进行训练 model = se.RandomForestRegressor(max_depth=10, # 最大深度 n_estimators=1000, # 树数量 min_samples_split=2) # 最小样本数量,小于该数就不再划分子节点 model.fit(train_x, train_y) # 训练 # 基于天统计数据的特征重要性 fi_dy = model.feature_importances_ # print(fi_dy) pre_test_y = model.predict(test_x) print(sm.r2_score(test_y, pre_test_y)) # 打印r2得分
打印输出:
['CRIM' 'ZN' 'INDUS' 'CHAS' 'NOX' 'RM' 'AGE' 'DIS' 'RAD' 'TAX' 'PTRATIO' 'B' 'LSTAT'] (506, 13) (506,) 0.9271955403309159
三、总结
1)什么是决策树:利用样本特征进行决策归类,将具有相同属性的样本划入一个子节点,投票产生分类,平均值产生回归
2)决策树的用途:用作分类器、回归器
3)如何构建决策树:根据信息增益、增益率、基尼系数构建子节点。对应3种不同决策树。
4)什么情况下使用决策树:实用性较广,课用于一般回归、分类问题
5)决策树优化:集成学习、随机森林。 即多个决策树模型共同预测结果
回归问题内容:线性回归,多项式回归,线性回归变种,决策树回归,神经网络回归
一般用于回归的模型都可以用于分类
分类问题:逻辑回归,决策树分类,支持向量机,朴素贝叶斯
四、练习
(1)有一批水果(如下图所示),按照形状进行分类,将长条形、椭圆形各划分到不同子节点中,计算划分后的信息增益.
原始按照颜色信息熵1.522 划分后0,8 * 1+0.2* * 0 = 0.8 信息增益0.722 因此按照形状划分的信息增益比较大,颜色特征更加强烈
(2)一批样本包含A和B两个类别,计算:当A类别比率依次占0%, 10%, 20%, ..., 100%时,这批样本信息熵值,并以占比作为x轴数值、信息熵作为y轴数值绘制图像.
import math import numpy as np import matplotlib.pyplot as mp arr = np.array([[0.0000001, 1.0], [0.1, 0.9], [0.2, 0.8], [0.3, 0.7], [0.4, 0.6], [0.5, 0.5], [0.6, 0.4], [0.7, 0.3], [0.8, 0.2], [0.9, 0.1], [1.0, 0.0000001]]) result = [] for a in arr: # 遍历每种组合,进行计算 v1 = -(a[0] * math.log(a[0])) # p * log(p) v2 = -(a[1] * math.log(a[1])) result.append(v1 + v2) print(result) # 可视化 mp.figure("Entropy") mp.title("Entropy") mp.xlabel("A%") mp.ylabel("entropy") mp.grid(linestyle=":") # 0~1.1(不包含)以0.1为间隔产生均匀数组 x = np.arange(0, 1.1, 0.1) mp.plot(x, result, c="red", label="entropy") mp.legend() mp.show() #结论:对半开熵值最大,系统最混乱,好人与坏人一样多。一九开系统较为纯净,好人比坏人多。
延伸阅读
-
VMware公司使用定制的决策树进行定价优化
VMware(VMW)是一家提供虚拟化技术、终端服务和云处理的公司,它将产品销售给B2B客户。长期以来,VMW公司的产品价格罕有变动。当接收到大订单的时候,销售代表会通过销售人员特别折扣(Sales Person Specific discount,SPF)标识来给出特定折扣。而VMW的定价部门则希望找到一种方法来优化其产品定价。在各个商业领域,市场上都有着对应的解决定价问题的数据挖掘解决方案。解决方案的目标不仅是优化定价,同时还要让客户的利益最大化。 VMW公司的分析和数据科学小组通过分析历史价格和相应的销量变化,来理解折扣百分比与SPF标识的关联性,并以此为依据归纳出所有产品的推荐定价。传统的定价优化会根据数量变化来进行价格变动,但是VMW公司并不会改变价格,而是使用折扣作为替代方法,但是使用折扣需要额外的步骤来确定是否需要给出折扣以及折扣率。 小组使用决策树的方法,基于折扣率和SPF标识的使用情况来对所有订单进行分类。根据业务的需求,以一种特定顺序构建出多分支(非二元)决策树。各种可能订单定价的属性都在决策树构建中被考虑进来。决策树构建过程中,基于均方误差、熵、log-loss、Gini指标等确定了决策树构建过程中分支属性的顺序。相比于使用标准分裂标准,使用的是根据业务需求定制的分裂标准。分裂停止标准是最小化观测对象数目。针对完成的分块,基于分块的属性特性观察其折扣百分比与SPF使用情况的关联性,并完成产品平台级的定价推荐。
一、逻辑回归(分类)
1. 概述
1)什么是逻辑回归
逻辑回归(Logistic Regression) 虽然被称为回归,但其实际上是分类模型,常用于二分类。逻辑回归因其简单、可并行化(多程序同时运行)、可解释强(中间过程清楚)而受到广泛应用。二分类(也称为逻辑分类)是常见的分类方法,是将一批样本或数据划分到两个类别,例如一次考试,根据成绩可以分为及格、不及格两个类别,如下表所示:
姓名 | 成绩 | 分类 |
---|---|---|
Jerry | 86 | 1 |
Tom | 98 | 1 |
Lily | 58 | 0 |
…… | …… | …… |
这就是逻辑分类,将连续值映射到两个类别中。
2)逻辑函数
逻辑回归是一种广义的线性回归,其原理是利用线性模型根据输入计算输出(线性模型输出值为连续),并在逻辑函数作用下,将连续值转换为两个离散值(0或1),其表达式如下:
$$
y = h(w_1x_1 + w_2x_2 + w_3x_3 + ... + w_nx_n + b)
$$
其中,括号中的部分为线性模型,计算结果在函数h()的作用下,做二值化转换,函数h()的定义为:
$$
h= \frac{1}{1+e^{-t}}
$$
该函数称为Sigmoid函数(又称逻辑函数),能将(-\infty, +\infty)的值映射到(0, 1)之间,其图像为:
可以设定一个阈值(例如0.5),当函数的值大于阈值时,分类结果为1;当函数值小于阈值时,分类结果为0. 也可以根据实际情况调整这个阈值.
3)分类问题的损失函数
对于回归问题,可以使用均方差作为损失函数,对于分类问题,如何度量预测值与真实值之间的差异?分类问题采用交叉熵作为损失函数,当只有两个类别时,交叉熵表达式为:
$$
E(y, \hat{y}) = -[y \ log(\hat{y}) + (1-y)log(1-\hat{y})]
$$
其中,y为真实值,\hat{y}为预测值.
-
当y=1时,预测值\hat{y}越接近于1,log(\hat{y})越接近于0,损失函数值越小,表示误差越小,预测的越准确;当预测时\hat{y}接近于0时,log(\hat{y})接近于负无穷大,加上符号后误差越大,表示越不准确;
-
当y=0时,预测值\hat{y}越接近于0,log(1-\hat{y})越接近于0,损失函数值越小,表示误差越小,预测越准确;当预测值\hat{y}接近于1时,log(1-\hat{y})接近于负无穷大,加上符号后误差越大,表示越不准确.
2. 逻辑回归实现
sklearn中,逻辑回归相关API如下:
# 创建模型 # solver参数:逻辑函数中指数的函数关系(liblinear表示线性关系) # C参数:正则强度,越大拟合效果越小,通过调整该参数防止过拟合 model = lm.LogisticRegression(solver='liblinear', C=1) # 训练 model.fit(x, y) # 预测 pred_y = model.predict(x)
以下是使用sklearn库提供的逻辑分类器(LogisticRegression)实现的代码:
# 逻辑分类器示例 import numpy as np import sklearn.linear_model as lm import matplotlib.pyplot as mp x = np.array([[3, 1], [2, 5], [1, 8], [6, 4],#每个样本两个特征值 [5, 2], [3, 5], [4, 7], [4, -1]]) y = np.array([0, 1, 1, 0, 0, 1, 1, 0]) # 创建逻辑分类器对象 model = lm.LogisticRegression() model.fit(x, y) # 训练 # 预测 test_x = np.array([[3, 9], [6, 1]]) test_y = model.predict(test_x) # 预测 print(test_y) # 计算显示坐标的边界 left = x[:, 0].min() - 1 right = x[:, 0].max() + 1 buttom = x[:, 1].min() - 1 top = x[:, 1].max() + 1 # 产生网格化矩阵 grid_x, grid_y = np.meshgrid(np.arange(left, right, 0.01), np.arange(buttom, top, 0.01)) print("grid_x.shape:", grid_x.shape) print("grid_y.shape:", grid_y.shape) # 将x,y坐标合并成两列 mesh_x = np.column_stack((grid_x.ravel(), grid_y.ravel())) print("mesh_x.shape:", mesh_x.shape) # 根据每个点的xy坐标进行预测,并还原成二维形状 mesh_z = model.predict(mesh_x) mesh_z = mesh_z.reshape(grid_x.shape) mp.figure('Logistic Regression', facecolor='lightgray') mp.title('Logistic Regression', fontsize=20) mp.xlabel('x', fontsize=14) mp.ylabel('y', fontsize=14) mp.tick_params(labelsize=10) mp.pcolormesh(grid_x, grid_y, mesh_z, cmap='gray') mp.scatter(x[:, 0], # 样本x坐标 x[:, 1], # 样本y坐标 c=y, cmap='brg', s=80) mp.scatter(test_x[:, 0], test_x[:, 1], c="red", marker='s', s=80) mp.show()
执行结果:
3. 多分类实现
逻辑回归产生两个分类结果,可以通过多个二元分类器实现多元分类(一个多元分类问题转换为多个二元分类问题). 如有以下样本数据:
特征1 | 特征2 | 特征3 | 实际类别 |
---|---|---|---|
x_1 | x_2 | x_3 | A |
x_1 | x_2 | x_3 | B |
x_1 | x_2 | x_3 | C |
进行以下多次分类,得到结果:
第一次:分为A类(值为1)和非A类(值为0)
第二次:分为B类(值为1)和非B类(值为0)
第三次:分为C类(值为1)和非C类(值为0)
……
以此类推.
利用逻辑分类器实现多元分类示例代码如下:
# 多元分类器示例 import numpy as np import sklearn.linear_model as lm import matplotlib.pyplot as mp # 输入 x = np.array([[4, 7], [3.5, 8], [3.1, 6.2], [0.5, 1], [1, 2], [1.2, 1.9], [6, 2], [5.7, 1.5], [5.4, 2.2]]) # 输出(多个类别) y = np.array([0, 0, 0, 1, 1, 1, 2, 2, 2]) # 创建逻辑分类器对象 model = lm.LogisticRegression(C=200) # 调整该值为1看效果 model.fit(x, y) # 训练 # 坐标轴范围 left = x[:, 0].min() - 1 right = x[:, 0].max() + 1 h = 0.005 buttom = x[:, 1].min() - 1 top = x[:, 1].max() + 1 v = 0.005 grid_x, grid_y = np.meshgrid(np.arange(left, right, h), np.arange(buttom, top, v)) mesh_x = np.column_stack((grid_x.ravel(), grid_y.ravel())) mesh_z = model.predict(mesh_x) mesh_z = mesh_z.reshape(grid_x.shape) # 可视化 mp.figure('Logistic Classification', facecolor='lightgray') mp.title('Logistic Classification', fontsize=20) mp.xlabel('x', fontsize=14) mp.ylabel('y', fontsize=14) mp.tick_params(labelsize=10) mp.pcolormesh(grid_x, grid_y, mesh_z, cmap='gray') mp.scatter(x[:, 0], x[:, 1], c=y, cmap='brg', s=80) mp.show()
执行结果:
4. 总结
1)逻辑回归是分类问题,用于实现二分类问题
2)实现方式:利用线性模型计算,在逻辑函数作用下产生分类
3)多分类实现:可以将多分类问题转化为二分类问题实现(多个二分类模型对象多分类)
4)用途:广泛用于各种分类问题
一、决策树分类
1. 决策树分类原理
决策树可以作为分类器使用,从而实现分类问题。使用决策树实现分类时,先根据不同特征将样本划分到不同叶子节点,再根据投票法(少数服从多数)决定预测结果属于哪个类别,预测类别即同一个子节点下数量最多的样本的类别。例如,预测一部电视剧是好剧还是烂剧,可以用以下决策树来实现:
根据以上决策树模型,可以做这样的分类预测:
-
如果是都市题材,导演为张三,好剧的数量较多,预测结果为好剧;
-
如果是古装题材,导演为张三,烂剧的数据量较多,预测结果为烂剧.
2. 决策树分类案例
sklearn中, 提供了以下API实现决策树分类器或随机森林分类器:
sklearn.tree.DecisionTreeClassifier() # 决策树分类器---单个模型 sklearn.ensemble.RandomForestClassifier() # 随机森林分类器 案例采用它---集成模型
该示例中,用离散特征去预测离散值。根据一组小汽车样本数据,该组样本数据统计了小汽车常见特征信息及其分类,特征包括:汽车价格、维修费用、车门数量、载客数、后备箱、安全性,标签为汽车质量。各属性取值如下表所示:
索引-名称 | 取值范围 | 含义说明 |
---|---|---|
1-buying | vhigh, high, med, low | 购买价格 |
2-maint | vhigh, high, med, low | 维护费用 |
3-doors | 2, 3, 4, 5more | 车门数量 |
4-persons | 2, 4, more | 载客数 |
5-lug_boot | small, med, big | 后备箱大小 |
6-safety | low, med, high | 安全性 |
标签 | unacc, acc, good, vgood | 汽车质量 |
以下是使用决策树进行分类的示例代码。需要对数据集用标签编码成数字。字符串不好处理。
# 决策树分类示例 import numpy as np import sklearn.preprocessing as sp import sklearn.ensemble as se import sklearn.model_selection as ms raw_samples = [] # 保存一行样本数据 with open("../data/car.txt", "r") as f: for line in f.readlines(): raw_samples.append(line.replace("\n", "").split(",")) data = np.array(raw_samples).T # 转置 encoders = [] # 记录标签编码器 train_x = [] # 编码后的x # 对样本数据进行标签编码 for row in range(len(data)): encoder = sp.LabelEncoder() # 创建标签编码器 encoders.append(encoder) if row < len(data) - 1: # 不是最后一行,为样本特征 lbl_code = encoder.fit_transform(data[row]) # 编码 train_x.append(lbl_code) else: # 最后一行,为样本输出 train_y = encoder.fit_transform(data[row]) train_x = np.array(train_x).T # 转置回来,变为编码后的数组 print(train_x) # 创建随机森林分类器 model = se.RandomForestClassifier(max_depth=8, # 最大树高 n_estimators=150, # 评估系数 random_state=7) # 随机种子 # 训练 model.fit(train_x, train_y) print("accuracy:", model.score(train_x, train_y)) # 打印平均精度,看测试准确度如何 # 预测 ## 待预测数据 data = [['high', 'med', '5more', '4', 'big', 'low'], ['high', 'high', '4', '4', 'med', 'med'], ['low', 'low', '2', '2', 'small', 'high'], ['low', 'med', '3', '4', 'med', 'high']] data = np.array(data).T test_x = [] for row in range(len(data)): encoder = encoders[row] # 取得每列对应的标签编码器 test_x.append(encoder.transform(data[row])) # 待预测数据编码 test_x = np.array(test_x).T # 转置回来 pred_test_y = model.predict(test_x) # 执行预测 pred_test_y = encoders[-1].inverse_transform(pred_test_y) # 预测结果反向编码 print("pred_test_y:", pred_test_y) # 预测结果
执行结果:
accuracy: 0.9704861111111112 pred_test_y: ['unacc' 'acc' 'unacc' 'vgood']