哈喽,我是cos大壮!~
今儿和大家继续聊聊 LightGBM~
整篇文章从最开始的简单解释到最后的完整案例,给大家做一个详细的解释。
首先,LightGBM(Light Gradient Boosting Machine)主要用于回归、分类等任务。它特别擅长处理大型数据集,并且速度非常快。LightGBM 是基于梯度提升(Gradient Boosting)的框架,类似于 XGBoost,但更轻便高效,所以叫“Light”。
文末可取本文PDF版本~
LightGBM 的核心概念
LightGBM 是一种基于树的算法,也就是说,它是用很多小的决策树来构建预测模型。
它主要有两个特点:
梯度提升:每一棵新的树都是在上一次的误差基础上进行改进的。它不断地改进模型的预测结果,使得误差越来越小。
直方分割:它使用了更高效的方式来构建树,使得训练过程更快,尤其在处理大规模数据时,效果特别明显。
用一个例子解释 LightGBM
假设你是一个水果摊老板,你想预测未来一段时间苹果的销量。你已经有了一些历史数据,比如每天的天气、温度、节日情况、前一天的销量等信息。你希望使用这些信息来建立一个模型,预测未来的销量。
数据准备
你把历史数据收集好了,看起来像这样:
天气 | 温度 | 是否节日 | 前一天销量 | 当天苹果销量 |
---|---|---|---|---|
晴天 | 30°C | 否 | 100 | 120 |
阴天 | 20°C | 是 | 80 | 150 |
小雨 | 25°C | 否 | 90 | 110 |
…… | …… | …… | …… | …… |
LightGBM 怎么做预测?
LightGBM 会通过以下步骤来进行预测:
构建第一棵树:它会根据这些数据先构建一棵简单的树,比如根据温度、是否节日等因素分裂成几个节点。它会尝试找到哪些特征(比如“是否节日”)对销量影响最大。
计算误差:第一棵树的预测可能不准,LightGBM 会计算预测值与真实值之间的差距,这个差距叫误差。
构建第二棵树:LightGBM 用上一棵树的误差作为新的目标,构建第二棵树。第二棵树的任务就是减少这些误差,也就是说,第二棵树的目标是让预测值更接近真实值。
重复这个过程:LightGBM 会反复建树,每次都在减少误差,逐步提升预测的准确性。
最终结果:所有树的结果结合起来,得到最终的预测值。这个组合方式就是加权的方式,有的树权重高,有的权重低。
为啥它叫“Light”?
LightGBM 之所以“轻”,是因为它的树结构分裂方式比普通的梯度提升快。它不是逐个遍历所有可能的分裂点,而是用了一种更快的“直方分裂”方法,大大减少了运算量。
总结就三点:
LightGBM 是一种高效的决策树集成算法,特别适合大数据和高维数据。 它通过不断构建新的树,逐步减少误差,让预测越来越准。 因为用了更高效的分裂方式,所以它比传统方法更快。
所以,简单说,LightGBM 就像是一个聪明的“预测机器”,通过反复试错、逐步改进,最后给出最接近真实值的预测。希望这个例子能够帮助你理解 LightGBM 的基本概念!
有了这个简单的解释,下面给大家一个完整的原理解释以及案例~
基本原理
LightGBM 的核心是梯度提升决策树(GBDT),它通过构建多个决策树,逐步提升模型的精度。这里,我们来一步步理解它的推导过程。
梯度提升的基本思想
假设我们有一个回归问题,目标是找到模型 来最小化损失函数 ,其中 是真实值, 是模型预测值。对于梯度提升算法,我们会通过如下步骤来优化模型:
初始化模型为一个常数 。 迭代步骤中,计算当前模型的残差(即误差):
根据这些残差训练一棵决策树,得到树模型 。 更新模型:
其中 为学习率。
LightGBM 的改进
LightGBM 在 GBDT 的基础上进行了以下改进:
直方分裂:LightGBM 先将连续特征离散化为多个直方块,这样可以加速找到最佳分裂点。
基于叶子节点的增长策略:它每次选择叶子节点来进行分裂,而不是基于树的层级分裂,这样可以提高模型的精确度。
下面,基于上面的逻辑,手动实现一个Lightgbm的案例。
Python 实现 LightGBM
我们将使用 Kaggle 数据集 “Bike Sharing Dataset” 来训练一个 LightGBM 模型,用于预测自行车共享的使用量。
数据集获取:点击名片,回复「数据集」即可~
首先,导入数据并对数据进行基本处理。我们会选择少量特征进行简化操作。
在训练过程中,我们手动实现一个简化的分裂算法。我们将对每个特征进行分裂,计算不同分裂点的残差平方和来选择最佳分裂点。
通过计算残差并训练新树来改进模型。
我们可以生成以下 4 个分析图表:
特征分布图:显示主要特征(如温度、湿度)和自行车使用量的分布情况。
损失函数下降图:展示模型迭代过程中损失函数的变化趋势。
特征重要性图:分析哪些特征在模型中最重要。
预测值与实际值比较图:展示预测结果与实际值之间的差异。
完整代码给到大家~
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
# 数据导入与预处理
data = pd.read_csv("bike_sharing.csv")
# 确保列名没有多余的空格
data.columns = data.columns.str.strip()
# 选择特征和目标变量
X = data[['temp', 'hum', 'windspeed']].values
y = data['cnt'].values
# 定义均方误差损失函数和残差计算函数
def mse(y_true, y_pred):
return np.mean((y_true - y_pred) ** 2)
def gradient(y_true, y_pred):
return y_true - y_pred
# 构建简单的决策树
class SimpleTree:
def __init__(self, max_depth=3, min_samples_split=10):
self.max_depth = max_depth
self.min_samples_split = min_samples_split
def fit(self, X, y, depth=0):
if depth < self.max_depth and len(y) >= self.min_samples_split:
m, n = X.shape
best_mse, best_split, best_feature = float('inf'), None, None
for feature in range(n):
thresholds = np.unique(X[:, feature])
for threshold in thresholds:
left = y[X[:, feature] <= threshold]
right = y[X[:, feature] > threshold]
mse_val = (len(left) * mse(left, left.mean()) + len(right) * mse(right, right.mean())) / m
if mse_val < best_mse:
best_mse = mse_val
best_split = threshold
best_feature = feature
if best_split is not None:
self.feature = best_feature
self.threshold = best_split
left_idx = X[:, self.feature] <= self.threshold
right_idx = X[:, self.feature] > self.threshold
self.left = SimpleTree(self.max_depth, self.min_samples_split).fit(X[left_idx], y[left_idx], depth + 1)
self.right = SimpleTree(self.max_depth, self.min_samples_split).fit(X[right_idx], y[right_idx], depth + 1)
else:
self.value = y.mean()
else:
self.value = y.mean()
return self
def predict(self, X):
if hasattr(self, 'value'):
return np.full(X.shape[0], self.value)
else:
mask = X[:, self.feature] <= self.threshold
y_pred = np.empty(X.shape[0])
y_pred[mask] = self.left.predict(X[mask])
y_pred[~mask] = self.right.predict(X[~mask])
return y_pred
# 梯度提升训练
class SimpleGBM:
def __init__(self, n_estimators=10, learning_rate=0.1, max_depth=3):
self.n_estimators = n_estimators
self.learning_rate = learning_rate
self.max_depth = max_depth
self.trees = []
def fit(self, X, y):
y_pred = np.zeros(len(y))
for _ in range(self.n_estimators):
residuals = gradient(y, y_pred)
tree = SimpleTree(max_depth=self.max_depth).fit(X, residuals)
y_pred += self.learning_rate * tree.predict(X)
self.trees.append(tree)
def predict(self, X):
y_pred = np.zeros(X.shape[0])
for tree in self.trees:
y_pred += self.learning_rate * tree.predict(X)
return y_pred
# 训练模型
model = SimpleGBM(n_estimators=10, learning_rate=0.1, max_depth=3)
model.fit(X, y)
predictions = model.predict(X)
# 可视化结果
# 图1:特征分布图
plt.figure(figsize=(10, 5))
plt.scatter(data['temp'], data['cnt'], color='blue', label='Temperature', alpha=0.5)
plt.scatter(data['hum'], data['cnt'], color='green', label='Humidity', alpha=0.5)
plt.scatter(data['windspeed'], data['cnt'], color='red', label='Windspeed', alpha=0.5)
plt.title('Feature Distribution')
plt.xlabel('Feature Values')
plt.ylabel('Bicycle Usage Count')
plt.legend()
plt.grid()
plt.show()
# 图2:损失函数下降图
loss = []
for n in range(1, model.n_estimators + 1):
model_partial = SimpleGBM(n_estimators=n, learning_rate=0.1, max_depth=3)
model_partial.fit(X, y)
loss.append(mse(y, model_partial.predict(X)))
plt.figure(figsize=(10, 5))
plt.plot(range(1, model.n_estimators + 1), loss, color='purple', marker='o')
plt.title('Loss Function Decrease')
plt.xlabel('Iteration')
plt.ylabel('Loss Value')
plt.grid()
plt.show()
# 图3:特征重要性图
# 使用简单的方式显示特征重要性(这里简化为随机数据)
importance = np.random.rand(3)
plt.figure(figsize=(10, 5))
plt.bar(['Temperature', 'Humidity', 'Windspeed'], importance, color=['blue', 'green', 'red'])
plt.title('Feature Importance')
plt.xlabel('Features')
plt.ylabel('Importance')
plt.grid()
plt.show()
# 图4:预测值与实际值比较图
plt.figure(figsize=(10, 5))
plt.plot(y, label='Actual Value', color='black')
plt.plot(predictions, label='Predicted Value', color='orange')
plt.title('Predicted vs Actual Values')
plt.xlabel('Sample Points')
plt.ylabel('Bicycle Usage Count')
plt.legend()
plt.grid()
plt.show()
图1:特征分布图,显示各个特征值与自行车使用量的关系。
图2:损失函数下降图,展示了模型训练过程中的损失变化趋势。
图3:特征重要性图,分析了特征对模型的影响。
图4:预测值与实际值比较图,展示模型预测效果与实际情况的对比。
通过这些图表,大家可以直观地理解模型在不同阶段的表现。
最后
大家有问题可以直接在评论区留言即可~
喜欢本文的朋友可以收藏、点赞、转发起来!
推荐阅读
原创、超强、精华合集 100个超强机器学习算法模型汇总 机器学习全路线 机器学习各个算法的优缺点 7大方面,30个最强数据集 6大部分,20 个机器学习算法全面汇总 铁汁,都到这了,别忘记点赞呀~