机器学习算法 ——XGBoost 的介绍和使用

前言:

最近在工作中遇到一个结构化数据回归预测的问题,用到了很多回归算法(如多元线性回归等)都没有很好的效果,于是使用了XGBoost,自己也冲三个特征参数人为的增加来几个,训练出来的效果还是很不错的,XGBoost还是比较擅长对结构化数据的预测分析。希望对你有帮助

一、XGBoost 的基本介绍

XGBoost(eXtreme Gradient Boosting)是一种基于梯度提升树(GBDT)的高效机器学习算法,由陈天奇等人提出。它在 GBDT 的基础上进行了诸多优化,具有速度快、性能好、泛化能力强等特点,在各类机器学习竞赛和实际工业应用中都有着广泛的应用。

二、XGBoost 的核心原理

(一)梯度提升框架

XGBoost 遵循梯度提升的思想,通过迭代地构建一系列决策树来进行预测。每一棵新的树都是为了纠正前面所有树的预测误差而生成的。具体来说,假设已经有了 t-1 棵树,对于每一个样本,这些树的预测结果之和为(\hat{y}^{(t-1)}_i),那么第 t 棵树的目标就是使得预测误差尽可能减小。

(二)正则化

XGBoost 引入了正则化项来防止过拟合。正则化项包括树的叶子节点数量和叶子节点权重的 L2 范数。其目标函数可以表示为:

(Obj(\theta) = \sum{i=1}^n l(y_i, \hat{y}i) + \sum_{k=1}^K \Omega(f_k))

其中,(l(y_i, \hat{y}i))是损失函数,用于衡量预测值(\hat{y}i)与真实值(y_i)之间的差异;(\Omega(f_k))是正则化项,(f_k)表示第 k 棵树,(K)是树的数量。

(三)树的构建

XGBoost 在构建树的过程中,采用了贪心算法。对于每个特征,它会尝试不同的分割点,计算分割后的增益,选择增益最大的分割点进行分裂。为了提高计算效率,XGBoost 还采用了直方图优化等技术,将连续特征的取值离散化为若干个直方图 bins,从而减少分割点的搜索时间。

三、XGBoost 的核心特性

(一)高效性

  1. 支持并行计算:在树的构建过程中,特征的分裂可以并行处理,大大提高了算法的运行速度。

  2. 直方图优化:如前面所述,通过将连续特征离散化,减少了分割点的搜索时间,提高了计算效率。

(二)灵活性

  1. 支持多种损失函数:可以根据不同的任务(如分类、回归)选择合适的损失函数,如平方损失、逻辑损失等。

  2. 可以处理多种类型的数据:包括数值型数据和类别型数据,对于类别型数据,需要进行适当的编码处理。

(三)鲁棒性

  1. 对缺失值不敏感:XGBoost 可以自动处理缺失值,在训练过程中会学习缺失值的处理方式。

  2. 内置正则化:通过正则化项可以有效防止过拟合,提高模型的泛化能力。

四、XGBoost 的使用步骤

(一)数据准备

  1. 数据收集:获取用于训练和测试的数据集。

  2. 数据清洗:处理数据中的缺失值、异常值等。对于缺失值,可以采用均值填充、中位数填充、众数填充等方法;对于异常值,可以根据实际情况进行删除或修正。

  3. 特征工程:对数据进行特征选择、特征转换等操作,以提高模型的性能。例如,可以进行标准化、归一化处理,或者构建新的特征。

(二)模型训练

  1. 导入 XGBoost 库:在 Python 中,可以使用import xgboost as xgb来导入 XGBoost 库。

  2. 划分训练集和测试集:可以使用train_test_split函数将数据集划分为训练集和测试集,一般按照 7:3 或 8:2 的比例进行划分。

  3. 定义参数:设置 XGBoost 的相关参数,如学习率(learning_rate)、树的数量(n_estimators)、最大深度(max_depth)等。

  4. 训练模型:使用XGBClassifier(分类任务)或XGBRegressor(回归任务)构建模型,并使用fit方法进行训练。

(三)模型评估

  1. 预测:使用训练好的模型对测试集进行预测,得到预测结果。

  2. 评估指标:根据不同的任务选择合适的评估指标。对于分类任务,可以使用准确率、精确率、召回率、F1 值、ROC 曲线等;对于回归任务,可以使用均方误差(MSE)、均方根误差(RMSE)、平均绝对误差(MAE)等。

(四)模型调优

  1. 网格搜索:通过设置不同的参数组合,使用网格搜索来寻找最优的参数。

  2. 随机搜索:与网格搜索类似,但随机选择参数组合进行搜索,在一定程度上可以提高搜索效率。

五、详细示例

(一)分类任务示例(基于鸢尾花数据集)

  1. 数据准备

from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from xgboost import XGBClassifier
from sklearn.metrics import accuracy_score, classification_report
​
# 加载数据集
iris = load_iris()
X = iris.data
y = iris.target
​
# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
  1. 模型训练

# 定义模型
model = XGBClassifier(learning_rate=0.1,n_estimators=100,max_depth=3,objective='multi:softmax',  # 多分类任务num_class=3,  # 类别数量random_state=42
)
​
# 训练模型
model.fit(X_train, y_train)
  1. 模型评估

# 预测
y_pred = model.predict(X_test)
​
# 计算准确率
accuracy = accuracy_score(y_test, y_pred)
print(f"准确率:{accuracy:.2f}")
​
# 详细评估报告
print(classification_report(y_test, y_pred))

运行结果:

准确率:1.00precision    recall  f1-score   support
​0       1.00      1.00      1.00        141       1.00      1.00      1.00        152       1.00      1.00      1.00        11
​accuracy                           1.00        40macro avg       1.00      1.00      1.00        40
weighted avg       1.00      1.00      1.00        40

从结果可以看出,使用 XGBoost 模型在鸢尾花数据集上的分类准确率达到了 100%,效果非常好。

(二)回归任务示例(基于波士顿房价数据集)

  1. 数据准备

from sklearn.datasets import load_boston
from sklearn.model_selection import train_test_split
from xgboost import XGBRegressor
from sklearn.metrics import mean_squared_error, mean_absolute_error
​
# 注意:sklearn 1.2.0版本后移除了boston数据集,这里使用其他方式获取(如从mlxtend库)
# 假设已获取数据
X, y = load_boston(return_X_y=True)
​
# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
  1. 模型训练

# 定义模型
model = XGBRegressor(learning_rate=0.1,n_estimators=100,max_depth=3,objective='reg:squarederror',  # 回归任务,平方误差损失random_state=42
)
​
# 训练模型
model.fit(X_train, y_train)
  1. 模型评估

# 预测
y_pred = model.predict(X_test)
​
# 计算评估指标
mse = mean_squared_error(y_test, y_pred)
rmse = mse **0.5
mae = mean_absolute_error(y_test, y_pred)
​
print(f"均方误差(MSE):{mse:.2f}")
print(f"均方根误差(RMSE):{rmse:.2f}")
print(f"平均绝对误差(MAE):{mae:.2f}")

运行结果(示例):

均方误差(MSE):10.23
均方根误差(RMSE):3.20
平均绝对误差(MAE):2.35

从结果可以看出,模型的预测效果较好,各项误差指标都处于较低水平。

六、XGBoost 与其他算法的对比

(一)与 GBDT 的对比

  1. 相同点:两者都属于梯度提升树算法,都是通过迭代构建决策树来进行预测。

  2. 不同点

  • 正则化:XGBoost 引入了更严格的正则化项,包括树的叶子节点数量和叶子节点权重的 L2 范数,而 GBDT 没有明确的正则化项,容易过拟合。

  • 计算效率:XGBoost 支持并行计算和直方图优化,计算速度比 GBDT 快很多。

  • 对缺失值的处理:XGBoost 可以自动处理缺失值,而 GBDT 需要手动处理。

(二)与随机森林的对比

  1. 相同点:两者都由多棵决策树组成,都可以用于分类和回归任务。

  2. 不同点

  • 构建方式:随机森林是通过 bootstrap 抽样构建多棵决策树,然后进行投票或平均得到结果,树之间是独立的;XGBoost 是迭代地构建树,每一棵新的树都依赖于前面的树。

  • 偏差与方差:随机森林通过集成多棵树来降低方差,XGBoost 通过梯度提升来降低偏差。

  • 性能:在很多任务中,XGBoost 的性能优于随机森林,但随机森林的训练速度可能更快一些。

(三)与支持向量机(SVM)的对比

  1. 相同点:都可以用于分类和回归任务。

  2. 不同点

  • 处理数据规模:SVM 在处理大规模数据时效率较低,而 XGBoost 可以较好地处理大规模数据。

  • 核函数:SVM 需要选择合适的核函数来处理非线性问题,而 XGBoost 通过决策树的组合可以自然地处理非线性问题。

  • 解释性:XGBoost 的模型解释性相对较强,可以通过特征重要性等指标了解特征的影响;SVM 的解释性相对较弱。

七、我的训练脚本(仅供参考)

  • max_depth:树的深度,影响模型复杂度和过拟合风险。

  • learning_rate(或 eta):学习率,控制每次迭代的步长。

  • n_estimators:提升树的数量,即训练的轮数。

代码:

import json
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.model_selection import train_test_split, cross_val_score, KFold
from sklearn.preprocessing import OneHotEncoder, StandardScaler
from sklearn.linear_model import Ridge
from sklearn.ensemble import RandomForestRegressor
from sklearn.metrics import mean_squared_error, r2_score
import xgboost as xgb
from matplotlib.font_manager import FontProperties
import joblib
font_path = r"simhei.ttf"
font = FontProperties(fname=font_path)
with open(r'test.json', 'r', encoding='utf-8') as f:data = json.load(f)
​
#数据处理,将嵌套列表展开为适合建模的表格
rows = []
for item in data:gcbh = item['gcbh']jxtbhj = item['jxtbhj']for debh, sl, dj,dwsl in zip(item['debh'], item['sl'], item['dj'],item['dwsl']):rows.append([gcbh, debh, sl, dj,dwsl, jxtbhj])
df = pd.DataFrame(rows, columns=['gcbh', 'debh', 'sl', 'dj', "dwsl",'jxtbhj'])
​
# 新增特征
df['single_item_total'] = df['sl'] * df['dj'] * df['dwsl']
​
# 在DataFrame创建后,添加更多特征
# 1. 工程级别的统计特征
df['total_by_gcbh'] = df.groupby('gcbh')['single_item_total'].transform('sum')  
df['items_count'] = df.groupby('gcbh')['debh'].transform('count')   
df['avg_price'] = df.groupby('gcbh')['dj'].transform('mean')        
df['price_std'] = df.groupby('gcbh')['dj'].transform('std')       
df['total_quantity'] = df.groupby('gcbh')['sl'].transform('sum')   
​
# 2. 项目级别的统计特征
df['price_ratio'] = df['dj'] / df['avg_price']                      
df['quantity_ratio'] = df['sl'] / df['total_quantity']              
df['value_ratio'] = df['single_item_total'] / df['total_by_gcbh']              
​
# 修改特征列表
cat_features = ['debh'] 
num_features = ['sl', 'dj', 'single_item_total',         # 基础特征'total_by_gcbh', 'items_count','avg_price','price_std','total_quantity', 'price_ratio','quantity_ratio', 'value_ratio'  
]
​
# 3. 处理缺失值
print("处理缺失值前的数据形状:", df.shape)
print("缺失值统计:")
print(df[num_features].isnull().sum())
​
# 处理缺失值 - 使用中位数填充数值特征
for col in num_features:if df[col].isnull().sum() > 0:median_val = df[col].median()df[col].fillna(median_val, inplace=True)print(f"列 {col} 使用中位数 {median_val:.2f} 填充了 {df[col].isnull().sum()} 个缺失值")
​
# 处理分类特征的缺失值
for col in cat_features:if df[col].isnull().sum() > 0:mode_val = df[col].mode()[0]df[col].fillna(mode_val, inplace=True)print(f"列 {col} 使用众数 {mode_val} 填充了 {df[col].isnull().sum()} 个缺失值")
​
print("处理缺失值后的数据形状:", df.shape)
print("缺失值统计:")
print(df[num_features + cat_features].isnull().sum())
​
# 4. 处理异常值
def handle_outliers(df, columns, n_sigmas=3):for col in columns:mean = df[col].mean()std = df[col].std()df[col] = df[col].clip(mean - n_sigmas * std, mean + n_sigmas * std)return df
​
# 处理数值特征的异常值
df = handle_outliers(df, num_features)
​
# 目标值不做对数变换,因为看起来对数变换效果不好
y = df['jxtbhj'].values
​
# 检查目标值是否有缺失值
if np.isnan(y).any():print("警告:目标值包含缺失值,将删除这些行")mask = ~np.isnan(y)df = df[mask]y = y[mask]print(f"删除缺失值后的数据形状: {df.shape}")
​
# 工程编号独热编码
encoder = OneHotEncoder(sparse_output=False, handle_unknown='ignore')
X_cat = encoder.fit_transform(df[cat_features])
X_num = df[num_features].values
​
# 最终检查确保没有NaN值
print("最终数据检查:")
print(f"X_cat 包含 NaN: {np.isnan(X_cat).any()}")
print(f"X_num 包含 NaN: {np.isnan(X_num).any()}")
print(f"y 包含 NaN: {np.isnan(y).any()}")
​
X = np.hstack([X_cat, X_num])
​
# 特征缩放
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
​
# 4. 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X_scaled, y, test_size=0.2, random_state=42)
​
# 在数据处理后,模型训练前添加这段代码
plt.figure(figsize=(12, 4))
​
# 原始值分布
plt.subplot(121)
plt.hist(df['jxtbhj'], bins=50)
plt.title('原始 jxtbhj 分布', fontproperties=font)
​
# 对数变换后的分布
plt.subplot(122)
plt.hist(np.log1p(df['jxtbhj']), bins=50)
plt.title('log(jxtbhj) 分布', fontproperties=font)
​
plt.tight_layout()
plt.show()
​
# 打印一些基本统计信息
print("原始 jxtbhj 统计信息:")
print(df['jxtbhj'].describe())
​
# 5. 建立多种模型
models = {# '岭回归': Ridge(#     alpha=0.5,  # 适中的正则化#     fit_intercept=True# ),# '随机森林': RandomForestRegressor(#     n_estimators=300,  # 增加树的数量#     max_depth=8,       # 控制过拟合#     min_samples_leaf=5,#     max_features='sqrt',#     random_state=42# ),'XGBoost': xgb.XGBRegressor(n_estimators=1500,#900max_depth=8,learning_rate=0.1,  # 降低学习率0.09subsample=0.8,       # 随机采样colsample_bytree=0.8,# 特征采样reg_alpha=0.1,       # L1正则化reg_lambda=1.0,      # L2正则化random_state=42,verbosity=0)
}
results = {}
​
kf = KFold(n_splits=5, shuffle=True, random_state=42)
for name, model in models.items():cv_scores = cross_val_score(model, X_scaled, y, cv=kf, scoring='r2',error_score='raise')print(f"\n模型: {name}")print(f"交叉验证 R² 分数: {cv_scores.mean():.4f} (+/- {cv_scores.std() * 2:.4f})")
​# 在全部数据上训练和评估model.fit(X_train, y_train)y_pred = model.predict(X_test)mse = mean_squared_error(y_test, y_pred)r2 = r2_score(y_test, y_pred)results[name] = {'model': model, 'mse': mse, 'r2': r2, 'y_pred': y_pred}print(f"测试集 MSE: {mse:.2f}")print(f"测试集 R²: {r2:.4f}")
​# 在模型训练后添加def analyze_predictions(y_true, y_pred, name):# 计算预测误差百分比error_percent = np.abs((y_pred - y_true) / y_true) * 100
​print(f"\n{name} 预测分析:")print(f"平均百分比误差: {error_percent.mean():.2f}%")print(f"中位数百分比误差: {np.median(error_percent):.2f}%")print(f"90%预测的误差在 {np.percentile(error_percent, 90):.2f}% 以内")
​# 计算不同误差范围的预测比例for threshold in [10, 20, 30, 50]:accuracy = (error_percent <= threshold).mean() * 100print(f"误差在{threshold}%以内的预测比例: {accuracy:.2f}%")
​analyze_predictions(y_test, y_pred, name)
​
# 6. 选择最佳模型用于解释性分析
best_model_name = max(results, key=lambda k: results[k]['r2'])
best_model = results[best_model_name]['model']
y_pred = results[best_model_name]['y_pred']
print(f"最佳模型: {best_model_name}")
​
# 保存XGBoost模型
if best_model_name == 'XGBoost':best_model.save_model('xgb_model.json')print('XGBoost模型已保存到 xgb_model.json')# 保存encoder和scalerjoblib.dump(encoder, 'encoder.joblib')joblib.dump(scaler, 'scaler.joblib')print('encoder和scaler已保存')
​
# 7. 特征重要性分析
feature_names = list(encoder.get_feature_names_out(cat_features)) + num_features
if hasattr(best_model, 'coef_'):importances = best_model.coef_
elif hasattr(best_model, 'feature_importances_'):importances = best_model.feature_importances_
else:importances = np.zeros(len(feature_names))
​
plt.figure(figsize=(12, 6))
sns.barplot(x=feature_names, y=importances)
plt.title(f'{best_model_name} 特征重要性', fontproperties=font)
plt.xlabel('特征', fontproperties=font)
plt.ylabel('重要性', fontproperties=font)
plt.xticks(rotation=90)
plt.tight_layout()
plt.show()
​
# 8. 预测值与真实值对比图
plt.figure(figsize=(8, 8))
plt.scatter(y_test, y_pred, alpha=0.6)
plt.plot([y_test.min(), y_test.max()], [y_test.min(), y_test.max()], 'r--', lw=2)
plt.title(f'{best_model_name} 真实值 vs 预测值', fontproperties=font)
plt.xlabel('真实值', fontproperties=font)
plt.ylabel('预测值', fontproperties=font)
plt.tight_layout()
plt.show()
​
# 9. 残差分析
residuals = y_test - y_pred
plt.figure(figsize=(8, 5))
sns.histplot(residuals, bins=30, kde=True)
plt.title(f'{best_model_name} 残差分布', fontproperties=font)
plt.xlabel('残差', fontproperties=font)
plt.tight_layout()
plt.show()
​
plt.figure(figsize=(8, 5))
plt.scatter(y_pred, residuals, alpha=0.6)
plt.axhline(0, color='red', linestyle='--')
plt.title(f'{best_model_name} 预测值与残差', fontproperties=font)
plt.xlabel('预测值', fontproperties=font)
plt.ylabel('残差', fontproperties=font)
plt.tight_layout()
plt.show()

八、安装与资源

  • 安装pip install xgboostconda install -c conda-forge xgboost

  • 官方文档:XGBoost Documentation

  • GitHub 仓库:dmlc/xgboost

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.tpcf.cn/news/914636.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux操作系统之信号:保存与处理信号

目录 前言&#xff1a; 前文回顾与补充&#xff1a; 信号的保存 PCB里的信号保存 sigset_t 信号集操作函数 信号的处理 信号捕捉的流程&#xff1a;​编辑 操作系统的运行原理 硬件中断 时钟中断 死循环 软中断 总结&#xff1a; 前言&#xff1a; 在上一篇文…

Spring Boot 设置滚动日志logback

Spring Boot 的 logback 框架 Spring Boot 默认内置了 Logback 作为日志实现框架&#xff0c;只需要在resources文件夹下添加一个logback-spring.xml&#xff0c;springboot会按照你的设置自动开启logback日志功能。 配置 logback-spring.xml 实现每天产生一个日志文件&#xf…

如何定义一个只能在堆上或栈上生成对象的类

在C中&#xff0c;可以通过特定的技术手段来控制对象只能在堆(heap)或栈(stack)上创建。只能在堆上创建对象的类要实现这一点&#xff0c;我们需要阻止用户直接实例化对象&#xff0c;而只能通过new操作符创建。class HeapOnly { public:static HeapOnly* create() {return new…

1.1 前端-vue3项目的创建

构建工具先搭好vue3框架 vue2的vue-cli脚手架基于webpack构建工具创建vue的框架. 而在vue3&#xff0c;可以通过vite构建工具创建vue3项目&#xff0c;性能更优。 两者创建方式的区别&#xff1a;cmd命令基于的构建工具vue2/vue3vue create 项目名称&#xff08;或 vue ui图形化…

PHP password_get_info() 函数

password_get_info() 函数用于返回指定散列&#xff08;hash&#xff09;的相关信息。 PHP 版本要求: PHP 5 > 5.5.0, PHP 7 语法 array password_get_info ( string $hash ) 参数说明&#xff1a; $hash: 一个由 password_hash() 创建的散列值。 返回值 返回三个元素…

mac上的app如何自动分类

使用文件夹进行手动分类在Finder中创建文件夹&#xff0c;将同类应用拖入同一文件夹。右键点击Dock上的应用图标&#xff0c;选择「选项」→「在Finder中显示」&#xff0c;可快速定位应用安装位置。利用Launchpad自动分组打开Launchpad&#xff08;触控板四指捏合或按F4键&…

LLM面试题目 3

LLM面试题目 3 什么是自注意力机制(Self-Attention)?为什么它在LLM中很重要?如何评估LLM的性能?LLM面临的挑战有哪些?Transformer和RNN的区别是什么?LLM如何处理多轮对话? 题目讲解 什么是自注意力机制(Self-Attention)?为什么它在LLM中很重要? 自注意力机制是一种…

linux上的软挂载操作方法

针对linux上的软挂载 可以查看linux已经挂载和存储的磁盘分区 df -hfdisk 命令是检索相同信息的另一种方法&#xff0c;可以看到所有的磁盘分区 sudo fdisk -l 要将磁盘分区 /dev/sda1 挂载到 /home/visionx/EXD1 目录 步骤 1&#xff1a;准备工作 1.创建挂载目录&#xff08;如…

SecretFlow 隐语 (2) --- 隐语架构概览

在前边两篇文章中&#xff0c;介绍了数据要素和可信流通相关的内容&#xff0c;以及基于p2p模式的安装方法 SecretFlow 隐语 (1) --- 快速入门 关于在Linux上部署 SecretFlow --- P2P部署模式 由于安装过程中出现意外报错&#xff0c;现已提交issue等待官方技术人员查阅&#x…

PHP语言基础知识(超详细)第二节

二十七. 数组的遍历 1)通过函数进行遍历:(例:demo07) (此方式不能完全遍历数组,需要借助其他功能辅助)(不推荐,了解即可) key():返回数组中当前指针所在位置的键。 current():返回数组中当前指针所在位置的值。 例如:demo07: <?php/*key():返回数组中…

网络--OSPF实验

目录 OSPF实验报告 一、实验拓扑 二、实验要求 三、实验思路 1.IP地址划分 2. OSPF 部署 3. 其它配置 4. 验证测试 四、实验步骤 1.IP 地址配置 2.OSPF 部署 3.其它配置 4.验证测试 OSPF实验报告 一、实验拓扑 二、实验要求 1、R1-R3为区域0&#xff0c;R3-R4为…

Go语言第一个程序--hello world!

文章目录一、Go 语言程序安装二、运行程序三、go mod tidy 命令四、遇到的问题五、VS Code 调试 go 程序的相关配置说明一、Go 语言程序安装 Go语言下载链接&#xff1a;https://studygolang.com/dl 双击打开下一步下一步即可。 验证安装&#xff1a;go version 二、运行程序 创…

【MCU控制 初级手札】1.1 电阻

作者&#xff1a;电控工程手札 本博文内容著作权归作者所有&#xff0c;转载请务必保留本文链接 目录1. 定义2. 电导3. 电阻率4. 电导率5. 伏安特性6. 开路与短路7. 功率8. 应用元件特性&#xff08;端子特性&#xff09;&#xff1a;元件的两个端子的电路物理量之间的代数函数…

JS中async/await功能介绍和使用演示

JS 中 async/await 功能介绍与使用演示 一、功能介绍基本概念 async&#xff1a;用于声明异步函数&#xff0c;返回一个 Promise 对象。即使函数内没有显式返回 Promise&#xff0c;也会隐式将返回值封装为 Promise.resolve()。await&#xff1a;仅能在 async 函数内部使用&…

系统调用入口机制:多架构对比理解(以 ARM64 为主)

&#x1f4d6; 推荐阅读&#xff1a;《Yocto项目实战教程:高效定制嵌入式Linux系统》 &#x1f3a5; 更多学习视频请关注 B 站&#xff1a;嵌入式Jerry 系统调用入口机制&#xff1a;多架构对比理解&#xff08;以 ARM64 为主&#xff09; 本篇内容聚焦于系统调用的入口实现机…

java MultipartFile初始化

在Java中&#xff0c;MultipartFile 是Spring框架中用于处理文件上传的接口。​开发者通常不会直接初始化MultipartFile对象&#xff0c;而是通过Spring MVC的控制器方法参数接收上传的文件。如果需要在测试或模拟场景中创建其实例&#xff0c;可以使用Spring的MockMultipartFi…

Linux C IO多路复用

在上一节利用管道实现了一个简单的聊天室&#xff0c;但这个聊天室有一个很明显的问题就是&#xff0c;当A处于读阻塞情况下是不能向B发送消息的&#xff0c;只有收到B的消息才能发送。如何实现同时既能接受B的消息&#xff0c;又能向其发送消息&#xff1f;很遗憾&#xff0c;…

day21——特殊文件:XML、Properties、以及日志框架

文章目录一、特殊文件概述二、Properties属性文件2.1 文件特点2.2 Properties类解析2.3 写入属性文件三、XML文件详解3.1 XML核心特性3.2 XML解析&#xff08;Dom4J&#xff09;3.3 XML写入3.4 XML约束&#xff08;了解&#xff09;四、日志技术&#xff08;Logback&#xff09…

经典VB与现代VB(VB.NET)

Visual Basic&#xff08;VB&#xff09;目前其发展状态可以分为经典VB&#xff08;VB6及之前&#xff09;​和现代VB&#xff08;VB.NET&#xff09;​两个阶段。经典VB诞生于1991年&#xff0c;凭借​“快速开发&#xff08;Rapid Application Development, RAD&#xff09;”…

iOS UI视图面试相关

iOS UI视图面试相关 UITableVIew相关 重用机制 cell [tableView dequeueReusableCellWillIdentifier:identifer];其中A2、A3、A4、A5是完全显示在屏幕&#xff0c;A2、A6显示部分&#xff0c;A1和A7不在显示范围内&#xff0c;假如现在是从下滑时的结果&#xff0c;在A1消失时…