一、集成学习方法之随机森林
集成学习的基本思想就是将多个分类器组合,从而实现一个预测效果更好的集成分类器。集成算法可以说从一方面验证了中国的一句老话:三个臭皮匠,赛过诸葛亮。集成算法大致可以分为:Bagging,Boosting 和 Stacking 三大类型。
(1)每次有放回地从训练集中取出 n 个训练样本,组成新的训练集;
(2)利用新的训练集,训练得到M个子模型;
(3)对于分类问题,采用投票的方法,得票最多子模型的分类类别为最终的类别;
随机森林就属于集成学习,是通过构建一个包含多个决策树(通常称为基学习器或弱学习器)的森林,每棵树都在不同的数据子集和特征子集上进行训练,最终通过投票或平均预测结果来产生更准确和稳健的预测。这种方法不仅提高了预测精度,也降低了过拟合风险,并且能够处理高维度和大规模数据集
1.1 算法原理
- 样本随机:对于一个总体训练集 T,其中共有 N 个样本,每次有放回地随机选择n个样本,用这 n个样本来训练一个决策树。这种有放回的抽样方式被称为自助采样(Bootstrap Sampling)。
- 特征随机:假设训练集的特征个数为d ,每次仅选择 k(k<d)个特征来构建决策树。这样可以增加决策树之间的差异性,提高模型的泛化能力。
- 森林构建:由于样本和特征的随机性,可以生成多个不同的决策树,这些决策树共同构成随机森林。
- 优点:随机森林可以处理具有高维特征的输入样本,而且不需要降维,同时使用平均或者投票的方式来提高预测精度和控制过拟合。
1.2 Sklearn API
在 sklearn
库中,可以使用 RandomForestClassifier
类来实现随机森林分类器。以下是该类的主要参数:
python
from sklearn.ensemble import RandomForestClassifier# 创建随机森林分类器实例
estimator = RandomForestClassifier(n_estimators=100, # 森林中树木的数量(决策树个数),默认值为 100criterion="gini", # 决策树属性划分算法选择,可选 "gini"(基尼不纯度)或 "entropy"(信息增益),默认值为 "gini"max_depth=None # 树的最大深度,默认值为 None,表示不限制树的深度
)
1.3 示例:泰坦尼克号乘客生存预测
python
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.feature_extraction import DictVectorizer
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import GridSearchCV# 1、获取数据
titanic = pd.read_csv("src/titanic/titanic.csv")
# 筛选特征值和目标值
x = titanic[["pclass", "age", "sex"]]
y = titanic["survived"]# 2、数据处理
# 1)缺失值处理
x["age"].fillna(x["age"].mean(), inplace=True)
# 2) 转换成字典
x = x.to_dict(orient="records")
# 3) 数据集划分
x_train, x_test, y_train, y_test = train_test_split(x, y, random_state=22)
# 4) 字典特征抽取
transfer = DictVectorizer()
x_train = transfer.fit_transform(x_train)
x_test = transfer.transform(x_test)# 3、预估:加网格搜索与交叉验证的代码
estimator = RandomForestClassifier()
# 参数准备
param_dict = {"n_estimators": [120, 200, 300, 500, 800, 1200], # 树的数量"max_depth": [5, 8, 15, 25, 30] # 树的最大深度
}
# 加入网格搜索与交叉验证,cv=3 表示 3 次交叉验证
estimator = GridSearchCV(estimator, param_grid=param_dict, cv=3)
# 训练
estimator.fit(x_train, y_train)# 5)模型评估
# 方法 1:直接比对真实值和预测值
y_predict = estimator.predict(x_test)
print("y_predict:\n", y_predict)
print("直接比对真实值和预测值:\n", y_test == y_predict)# 方法 2:计算准确率
score = estimator.score(x_test, y_test)
print("准确率为:\n", score)# 输出最佳参数、最佳结果、最佳估计器和交叉验证结果
print("最佳参数:\n", estimator.best_params_)
print("最佳结果:\n", estimator.best_score_)
print("最佳估计器:\n", estimator.best_estimator_)
print("交叉验证结果:\n", estimator.cv_results_)
二、线性回归算法
2.1 回归的基本概念
回归的目的是预测数值型的目标值 。最直接的办法是依据输入x 写出一个目标值 y的计算公式,这个公式就是回归方程。
2.2 线性回归
线性回归意味着可以将输入项分别乘以一些常量,再将结果加起来得到输出。线性回归是机器学习中一种有监督学习的算法,主要关注因变量(需要预测的值)和一个或多个数值型的自变量(预测变量)之间的关系。
2.2.1 简单示例:包子价格预测
已知 1 个包子是 2 元,3 个包子是 6 元,预测 5 个包子的价格。设回归方程为y=wx+b ,代入数据可得:
解得w=2 ,b=2,则模型为y=2*x+0 。当 x=5 时,target(y) = 2*5+0=10元。
2.2.2 实际数据中的线性回归
在实际数据中,往往找不到一个完美的方程式来 100% 满足所有的 y 目标,需要找出一个最接近真理的方程式。例如,有一组植物在不同温度下生长高度的数据,我们希望找到一条直线来拟合这些数据点,从而通过环境温度大概判断植物在某个温度下的生长高度。
2.3 损失函数
为了找到最符合数据的直线,需要定义一个损失函数来衡量预测值与真实值之间的误差。常见的损失函数是均方差(Mean Squared Error,MSE),即每个点到线的竖直方向的距离平方求和再平均,当损失函数的值最小时,对应的直线就是最优直线。
假设回归方程为y=wx+b ,对于数据点(x1,y1),(x2,y2),......(xn,yn) ,损失函数为:
为了简化问题,先假设 b=0,通过求损失函数关于w 的导数为 0 时的 w 值,来找到损失函数的最小值。例如,当求得 w=0.795 时损失函数取得最小值,则最终的最优解函数为 y=0.795x+0。
2.4 多参数回归
在实际情况中,影响结果 y 的因素往往不止一个,这时x 就从一个变成了 n 个,即x1,x2,...xn 。多元线性回归的方程为:
其中, 是截距,也可以使用 来表示,只要是个常量就行。则损失函数为:
2.5 最小二乘法(MSE)
最小二乘法是一种求解线性回归参数的常用方法,其目标是使损失函数最小化。设h(x)=w1x1+w2x2+..+wnxn+w0x0 ,则最小二乘法的损失函数为:
其中, X是输入特征矩阵, W是权重向量,y 是目标向量。
为了找到使损失函数最小的W 值,对损失函数求导并令导数为 0:
解得:
2.6 Sklearn API
在 sklearn
库中,可以使用 LinearRegression
类来实现普通最小二乘法线性回归。
python
from sklearn.linear_model import LinearRegression
import numpy as np# 示例数据
data = np.array([[0, 14, 8, 0, 5, -2, 9, -3, 399],[-4, 10, 6, 4, -14, -2, -14, 8, -144],[-1, -6, 5, -12, 3, -3, 2, -2, 30],[5, -2, 3, 10, 5, 11, 4, -8, 126],[-15, -15, -8, -15, 7, -4, -12, 2, -395],[11, -10, -2, 4, 3, -9, -6, 7, -87],[-14, 0, 4, -3, 5, 10, 13, 7, 422],[-3, -7, -2, -8, 0, -6, -5, -9, -309]
])
x = data[:, 0:8]
y = data[:, 8:]# 创建线性回归模型实例
estimator = LinearRegression(fit_intercept=False)
# 训练模型
estimator.fit(x, y)# 输出权重系数和偏置
print("权重系数为:\n", estimator.coef_)
print("偏置为:\n", estimator.intercept_)# 预测新数据
x_new = [[11, 14, 8, 10, 5, 10, 8, 1]]
y_predict = estimator.predict(x_new)
print("预测结果:\n", y_predict)
2.7 梯度下降
2.7.1 梯度下降概念
正规方程求解线性回归参数的缺点是:当损失函数不是凸函数时,设置导数为 0 会得到很多个极值,不能确定唯一解;而且当数据量和特征较多时,矩阵计算量太大。因此,梯度下降算法更常用。
梯度下降是一种通用的优化算法,用于帮助机器学习算法求解最优解。其基本思想是:假设你在一个陌生星球的山地上,想找到一个谷底,需要沿着最陡峭的坡向下行走,每走一步都找到当前位置最陡峭的下坡方向,然后朝着该方向迈进一小步,直到到达谷底(局部或全局最优点)。
在机器学习中,梯度表示损失函数对于模型参数的偏导数。通过计算损失函数对参数的梯度,梯度下降算法能够根据梯度的信息来调整参数,朝着减少损失的方向更新模型,从而逐步优化模型。
2.7.2 梯度下降步骤
- 随机初始化参数:随机生成一组成正态分布的数值w0,w1,w2...wn 作为初始参数。
- 求梯度:计算损失函数对于参数的梯度g ,梯度代表曲线某点上的切线的斜率。
- 更新参数:根据梯度的正负来更新参数,若 g<0,则w 变大;若g>0 ,则 w变小。更新公式为:w=w-a*g,其中a 是学习率。
- 判断收敛:判断是否达到收敛条件,收敛的判断标准是:随着迭代进行查看损失函数 Loss 的值,变化非常微小甚至不再改变,即认为达到收敛。也可以固定迭代次数。
2.7.3 学习率
学习率 a控制着每次参数更新的幅度。如果学习率设置过大,可能会导致参数更新幅度过大,越过最优解,使得损失函数来回震荡;如果学习率设置过小,参数更新速度会很慢,导致迭代次数增加,收敛时间变长。一般会把学习率设置成一个小数,如 0.1、0.01、0.001、0.0001 等,并根据情况进行调整。
2.7.4 自己实现梯度下降
python
import numpy as np
import matplotlib.pyplot as plt# 1. 单个特征的梯度下降示例
# 列损失函数
loss = lambda w_1: (w_1 - 3.5) ** 2 - 4.5 * w_1 + 10
w_1 = np.linspace(0, 11.5, 100)
plt.plot(w_1, loss(w_1))# 求这个损失函数的最小值:梯度下降
def cb():g = lambda w_1: 2 * (w_1 - 3.5) - 4.5 # 导函数t0, t1 = 1, 100alpha = t0 / t1 # 学习率w_1 = np.random.randint(0, 10, size=1)[0] # 随机初始值# 控制更新次数for i in range(1000):alpha = t0 / (i + t1) # 控制学习率逐步变小w_1 = w_1 - alpha * g(w_1) # 梯度下降公式print("更新后的 w_1:", w_1)cb()# 2. 两个特征的梯度下降示例
# 列损失函数
loss = lambda w_1, w_2: (w_1 - 3.5) ** 2 + (w_2 - 2) ** 2 + 2 * w_2 - 4.5 * w_1 + 3 * w_1 * w_2 + 20# 求这个损失函数的最小值:梯度下降
def cb2():t0, t1 = 1, 100alpha = t0 / t1 # 学习率w_1 = 10 # 随机初始值w_2 = 40 # 随机初始值dw_1 = lambda w_1, w_2: 2 * (w_1 - 3.5) + 3 * w_2 - 4.5 # w_1 的导函数dw_2 = lambda w_1, w_2: 3 * w_1 + 2 * w_2 - 2 # w_2 的导函数# 控制更新次数for i in range(100):alpha = t0 / (i + t1) # 控制学习率逐步变小w_1_ = w_1 # 保存起来,防止梯度下降过程中 w_1 和 w_2 的值发生改变w_2_ = w_2w_1 = w_1 - alpha * dw_1(w_1_, w_2_) # 梯度下降公式w_2 = w_2 - alpha * dw_2(w_1_, w_2_)print("更新后的 w_1, w_2:", w_1, w_2)cb2()