当前位置: 首页 > news >正文

GEE+本地XGboot分类

GEE+本地XGboot分类

我想做提取耕地提取,想到了一篇董金玮老师的一篇论文,这个论文是先提取的耕地,再做作物分类,耕地的提取代码是开源的。

但这个代码直接在云端上进行分类,GEE会爆内存,因此我准备把数据下载到本地,使用GPU加速进行XGboot提取耕地。

董老师的代码涉及到了100多个波段特征,我删减到了45个波段,然后分块进行了数据下载:

数据下载代码:

// ========================================
// 1. 初始化与区域选择
// ========================================// 合并训练数据
var trainTable = trainTable_crop.merge(trainTable_other);// 选择第一个区域作为AOI
var aoiFeature = fenqu.first();
var aoi = aoiFeature.geometry();// 可视化AOI(可选)
Map.addLayer(aoi, {color: 'blue'}, 'AOI');// 中心定位到AOI,缩放级别10(可选)
Map.centerObject(aoi, 10);// ========================================
// 2. 划分AOI为16个块
// ========================================// 定义划分块数(4x4网格)
var numCols = 4;
var numRows = 4;// 获取AOI的边界和范围
var aoiBounds = aoi.bounds();
var coords = ee.List(aoiBounds.coordinates().get(0));
var xMin = ee.Number(ee.List(coords.get(0)).get(0));
var yMin = ee.Number(ee.List(coords.get(0)).get(1));
var xMax = ee.Number(ee.List(coords.get(2)).get(0));
var yMax = ee.Number(ee.List(coords.get(2)).get(1));// 计算AOI的宽度和高度
var aoiWidth = xMax.subtract(xMin);
var aoiHeight = yMax.subtract(yMin);// 计算每个块的宽度和高度
var tileWidth = aoiWidth.divide(numCols);
var tileHeight = aoiHeight.divide(numRows);// 要排除的块的ID
var excludeTiles = ee.List(['0_3', '0_2', '3_0']);// 生成4x4网格,但排除特定块
var grid = ee.FeatureCollection(ee.List.sequence(0, numCols - 1).map(function(col) {return ee.List.sequence(0, numRows - 1).map(function(row) {// 将数字转换为整数字符串var colStr = ee.Number(col).int();var rowStr = ee.Number(row).int();var tileId = ee.String(colStr).cat('_').cat(ee.String(rowStr));var xmin = xMin.add(tileWidth.multiply(ee.Number(col)));var ymin = yMin.add(tileHeight.multiply(ee.Number(row)));var xmax = xmin.add(tileWidth);var ymax = ymin.add(tileHeight);var rectangle = ee.Geometry.Rectangle([xmin, ymin, xmax, ymax]);return ee.Feature(rectangle, {'tile': tileId});});}).flatten()
).filter(ee.Filter.inList('tile', excludeTiles).not());// 可视化网格
Map.addLayer(grid, {color: 'red'}, 'Grid');
print('Filtered tile count:', grid.size());// 打印tile ID以验证格式
print('Tile IDs:', grid.aggregate_array('tile'));// ========================================
// 3. 定义数据处理和导出函数
// ========================================function processAndExport(tileFeature) {var tileID = ee.String(tileFeature.get('tile'));print('Processing Tile:', tileID);var region = tileFeature.geometry();// 2. 定义时间范围、波段及区域var year = 2023;var startDate = ee.Date.fromYMD(year, 1, 1);var endDate = ee.Date.fromYMD(year, 12, 31);var bands = ['B2', 'B3', 'B4', 'B8']; // 蓝、绿、红、近红外// 3. 云掩膜函数:基于SCL波段function maskS2clouds(image) {var scl = image.select('SCL');// SCL分类值: 3(云)、8(阴影云)var cloudMask = scl.neq(3).and(scl.neq(8));return image.updateMask(cloudMask).clip(region).copyProperties(image, ["system:time_start"]);}// 4. 添加光谱指数函数function addSpectralIndices(image) {// 计算NDVIvar ndvi = image.normalizedDifference(['B8', 'B4']).rename('NDVI');// 计算EVIvar evi = image.expression('2.5 * ((NIR - RED) / (NIR + 6 * RED - 7.5 * BLUE + 1))', {'NIR': image.select('B8'),'RED': image.select('B4'),'BLUE': image.select('B2')}).rename('EVI');// 计算GNDVIvar gndvi = image.normalizedDifference(['B8', 'B3']).rename('GNDVI');// 计算SAVIvar savi = image.expression('((NIR - RED) / (NIR + RED + 0.5)) * 1.5', {'NIR': image.select('B8'),'RED': image.select('B4')}).rename('SAVI');// 计算MSAVI2var msavi2 = image.expression('0.5 * (2 * NIR + 1 - sqrt((2 * NIR + 1)**2 - 8 * (NIR - RED)))', {'NIR': image.select('B8'),'RED': image.select('B4')}).rename('MSAVI2');// 计算NDWIvar ndwi = image.normalizedDifference(['B3', 'B8']).rename('NDWI');// 计算NDSIvar ndsi = image.normalizedDifference(['B3', 'B11']).rename('NDSI');// 计算NDSVIvar ndsvi = image.normalizedDifference(['B11', 'B4']).rename('NDSVI');// 计算NDTIvar ndti = image.normalizedDifference(['B11', 'B12']).rename('NDTI');// 计算RENDVIvar rendvi = image.normalizedDifference(['B8', 'B5']).rename('RENDVI');// 计算REPvar rep = image.expression('(705 + 35 * ((0.5 * (B6 + B4) - B2) / (B5 - B2))) / 1000', {'B2': image.select('B2'),'B4': image.select('B4'),'B5': image.select('B5'),'B6': image.select('B6'),'B8': image.select('B8')}).rename('REP');// 添加所有计算的波段return image.addBands([ndvi, evi, gndvi, savi, msavi2, ndwi, ndsi, ndsvi, ndti, rendvi, rep]);}// 5. 加载并预处理Sentinel-2 L2A影像集合var sentinel = ee.ImageCollection("COPERNICUS/S2_SR"); // 确保使用正确的Sentinel-2影像集合var s2 = sentinel.filterBounds(region).filterDate(startDate, endDate).filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 20))  // 初步云量过滤.map(maskS2clouds).map(addSpectralIndices).select(['B2', 'B3', 'B4', 'B8', 'NDVI', 'EVI', 'GNDVI', 'SAVI', 'MSAVI2', 'NDWI', 'NDSI', 'NDSVI', 'NDTI', 'RENDVI', 'REP']);// 6. 计算月度NDVI最大值var months = ee.List.sequence(1, 12);var monthlyMaxNDVI = months.map(function(month) {var monthStart = ee.Date.fromYMD(year, month, 1);var monthEnd = monthStart.advance(1, 'month');var monthlyNDVI = s2.filterDate(monthStart, monthEnd).select('NDVI').max();// 使用 ee.String 和 .cat() 正确拼接字符串var bandName = ee.String('NDVI_month_').cat(ee.Number(month).format('%02d'));return monthlyNDVI.rename(bandName);});print(monthlyMaxNDVI,"monthlyMaxNDVI" )// 将所有月份的最大NDVI合并为一个图像var monthlyMaxNDVIImage = ee.Image(monthlyMaxNDVI.get(0));for (var i = 1; i < 12; i++) {monthlyMaxNDVIImage = monthlyMaxNDVIImage.addBands(ee.Image(monthlyMaxNDVI.get(i)));}print(monthlyMaxNDVIImage,"monthlyMaxNDVIImage" )// 7. 提取年度统计特征var Year_Bands = ['B2', 'B3', 'B4', 'B8', 'NDVI', 'EVI', 'GNDVI', 'SAVI', 'MSAVI2', 'NDWI', 'NDSI', 'NDSVI', 'NDTI', 'RENDVI', 'REP'];var annualStats = s2.select(Year_Bands).reduce(ee.Reducer.mean()  .combine(ee.Reducer.max(), null, true).combine(ee.Reducer.stdDev(), null, true));// 重命名年度统计特征的波段var statNames = ['mean', 'max', 'stdDev'];var newBandNames = [];Year_Bands.forEach(function(band) {statNames.forEach(function(stat) {newBandNames.push(band + '_' + stat);});});annualStats = annualStats.rename(newBandNames);// 将月度NDVI最大值和年度统计特征合并annualStats = ee.Image.cat([annualStats, monthlyMaxNDVIImage]);// 9. 合并所有特征var finalImage = annualStats.clip(region);print(finalImage,"finalImage")                // 可视化示例(可选)// Map.addLayer(finalImage.select('NDVI_seasonal'), {min: 0, max: 1, palette: ['white', 'green']}, 'NDVI Seasonal');// 10. 导出数据到Google Drivevar output_name='tile_' + tileID.getInfo()var name2=output_name.replace('.', '').replace('.', '')print(finalImage.toFloat())Export.image.toDrive({image: finalImage.toFloat(),description:  name2,scale: 10,folder: "download_tiles_HENAN_FENQU1",region: region,  maxPixels: 1e13});
}// ========================================
// 4. 应用函数到每个块
// ========================================// 注意:Google Earth Engine 同时只能运行有限的Export任务(通常为3个)。
// 因此,建议分批次运行或手动触发每个块的导出任务。// 将网格转换为特征集合列表
var gridFeatures = grid.toList(grid.size());// 获取总块数
var totalTiles = grid.size().getInfo();// 定义每批次导出的数量(如果需要批量控制,可以在这里调整)
var batchSize = 1;// 处理并导出每个块
// 注意:Google Earth Engine 不支持并行启动大量导出任务,请手动管理导出任务
gridFeatures.evaluate(function(list) {list.forEach(function(feature) {processAndExport(ee.Feature(feature));});
});// 打印总块数和导出说明
print('Total tiles:', totalTiles);
print('导出已启动。请在任务管理器中检查导出状态。');

然后下载完成后,用gdal做一下镶嵌(设置tile为256,LZW压缩),波段太多,导致数据非常大。最好再做一个金字塔

import os
from osgeo import gdal# 输入和输出路径
input_dir = r"几十个波段数据"
output_file = "mosaic_result_gdal.tif"# 获取所有tif文件
tif_files = []
for file in os.listdir(input_dir):if file.endswith('.tif'):tif_files.append(os.path.join(input_dir, file))# 构建VRT
vrt = gdal.BuildVRT("temp.vrt", tif_files)
vrt = None# 转换VRT为GeoTiff
gdal.Translate(output_file,"temp.vrt",format="GTiff",creationOptions=["COMPRESS=LZW","TILED=YES","BLOCKXSIZE=256","BLOCKYSIZE=256","BIGTIFF=YES"]
)

镶嵌完,可以放进GIS软件中查看一下。

数据分类

在此之前,需要先准备点数据,我是准备了两个点数据矢量(耕地矢量和非耕地矢量),字段属性crop为1代表耕地,0代表非耕地。如果你是做多类别,你可以多做几个矢量。

然后开始安装环境:

(1)安装CUDA,用GPU加速运行,也可以CPU,都差不多,xgboot计算量不大;

(2)安装conda,然后使用下面的命令安装环境:

conda create --prefix D:\conda_ENV\xgboot_env python=3.10
conda activate D:\conda_ENV\xgboot_env
conda install -c conda-forge numpy pandas geopandas rasterio scikit-learn tqdm

然后就可以开始分类了,代码如下:

import geopandas as gpd
import rasterio
from rasterio.sample import sample_gen
import numpy as np
import pandas as pd
from sklearn.model_selection import train_test_split
import xgboost as xgb
from sklearn.metrics import accuracy_score, confusion_matrix, classification_report, roc_auc_score
from tqdm import tqdm  # 用于进度指示# 读取矢量数据
CROP_FILE = r"耕地样本点.shp"
OTHERS_FILE = r"非耕地样本点.shp"
TIF_PATH = r"mosaic_result_gdal.tif"cropland = gpd.read_file(CROP_FILE)
non_cropland = gpd.read_file(OTHERS_FILE)
cropland['crop'] = 1
non_cropland['crop'] = 0
samples = pd.concat([cropland, non_cropland], ignore_index=True)with rasterio.open(TIF_PATH) as src:band_count = src.countcoords = [(point.x, point.y) for point in samples.geometry]pixel_values = list(src.sample(coords))pixel_values = np.array(pixel_values)feature_columns = [f'band_{i+1}' for i in range(band_count)]
features = pd.DataFrame(pixel_values, columns=feature_columns)
features['crop'] = samples['crop'].values# 保存特征名称以供预测阶段使用
feature_names = feature_columns.copy()# 数据预处理
features.dropna(inplace=True)
X = features.drop('crop', axis=1)
y = features['crop']
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42, stratify=y
)# 训练模型
dtrain = xgb.DMatrix(X_train, label=y_train, feature_names=feature_names)
dtest = xgb.DMatrix(X_test, label=y_test, feature_names=feature_names)params = {'objective': 'binary:logistic','tree_method': 'hist',         # 修改为 'hist''device': 'gpu',               # 添加 'device' 参数'eval_metric': 'auc','eta': 0.1,'max_depth': 10,'subsample': 0.8,'colsample_bytree': 0.8,'seed': 42
}evallist = [(dtest, 'eval'), (dtrain, 'train')]
num_round = 100print("开始训练模型...")
bst = xgb.train(params, dtrain, num_round, evallist, early_stopping_rounds=10, verbose_eval=True)
print("模型训练完成。\n")# 评估模型
print("开始评估模型...")
y_pred_prob = bst.predict(dtest)
y_pred = (y_pred_prob > 0.5).astype(int)
accuracy = accuracy_score(y_test, y_pred)
auc = roc_auc_score(y_test, y_pred_prob)
conf_matrix = confusion_matrix(y_test, y_pred)
report = classification_report(y_test, y_pred)print(f'Accuracy: {accuracy}')
print(f'AUC: {auc}')
print('Confusion Matrix:')
print(conf_matrix)
print('Classification Report:')
print(report)
print("模型评估完成。\n")# 应用模型进行栅格分类
print("开始进行栅格分类...")
with rasterio.open(TIF_PATH) as src:profile = src.profile.copy()profile.update(dtype=rasterio.uint8,count=1,compress='lzw')# 计算窗口总数用于进度指示windows = list(src.block_windows(1))total_windows = len(windows)with rasterio.open('classified.tif', 'w', **profile) as dst:for ji, window in tqdm(windows, total=total_windows, desc="栅格分类进度"):data = src.read(window=window)# data.shape = (bands, height, width)bands, height, width = data.shapedata = data.reshape(bands, -1).transpose()  # shape: (num_pixels, bands)# 创建 DataFrame 并赋予特征名称df = pd.DataFrame(data, columns=feature_names)# 创建 DMatrixdmatrix = xgb.DMatrix(df, feature_names=feature_names)# 预测predictions = bst.predict(dmatrix)predictions = (predictions > 0.5).astype(np.uint8)# 重塑为原窗口形状out_image = predictions.reshape(height, width)# 写入输出栅格dst.write(out_image, 1, window=window)
print("栅格分类完成。")

训练完成后,就开始分类了,就出结果了:

自此,从数据下载到分类处理完毕。

样本数据多的话,也可以考虑用CNN,但分类速度比不上xgboot。

参考:

You N , Dong J , Huang J ,et al.The 10-m crop type maps in Northeast China during 2017–2019[J].Scientific Data, 2021, 8(1).DOI:10.1038/s41597-021-00827-9.

相关文章:

GEE+本地XGboot分类

GEE本地XGboot分类 我想做提取耕地提取&#xff0c;想到了一篇董金玮老师的一篇论文&#xff0c;这个论文是先提取的耕地&#xff0c;再做作物分类&#xff0c;耕地的提取代码是开源的。 但这个代码直接在云端上进行分类&#xff0c;GEE会爆内存&#xff0c;因此我准备把数据下…...

OpenCV相机标定与3D重建(24)计算两个二维点集之间的最佳仿射变换矩阵(2x3)函数estimateAffine2D()的使用

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 计算两个二维点集之间的最优仿射变换&#xff0c;它计算 [ x y ] [ a 11 a 12 a 21 a 22 ] [ X Y ] [ b 1 b 2 ] \begin{bmatrix} x\\ y\\ \en…...

UIP协议栈 TCP通信客户端 服务端,UDP单播 广播通信 example

文章目录 1. TCP通信 客户端&#xff08;关键配置&#xff09;2. TCP 服务端配置3. UDP 点播通信4. UDP 广播通信5. UIP_UDP_APPCALL 里边的处理example6. TCP数据处理 &#xff0c;UIP_APPCALL调用的函数 UIP_APPCALL TCP的数据都在这个宏定义的函数里进行数据处理的 UDP 数据…...

【NoSQL系列】为什么要使用Redis?

第一次知道Redis是以前准备面试的时候&#xff0c;只知道是用来缓存数据的。随着这几年的工作&#xff0c;对软件的认识从盲人摸象到睁眼看世界。 在常用的软件架构评价模型中&#xff0c;性能、可用性、安全性和可维护性是常见的评价属性&#xff0c;客户总希望系统响应又快有…...

MySQL Explain 分析SQL语句性能

一、EXPLAIN简介 使用EXPLAIN关键字可以模拟优化器执行SQL查询语句&#xff0c;从而知道MySQL是如何处理你的SQL语句的。分析你的查询语句或是表结构的性能瓶颈。 &#xff08;1&#xff09; 通过EXPLAIN&#xff0c;我们可以分析出以下结果&#xff1a; 表的读取顺序数据读取…...

IIS部署程序https是访问出现403或ERR_HTTP2_PROTOCOL_ERROR

一、说明 在windows server 2016中的IIS程序池里部署一套系统&#xff0c;通过https访问站点&#xff0c;同时考虑到安全问题以及防攻击等行为&#xff0c;就用上了WAF云盾功能&#xff0c;能有效的抵挡部分攻击&#xff0c;加强网站的安全性和健壮性。 应用系统一直能够正常…...

学技术学英文:代码中的锁:悲观锁和乐观锁

本文导读&#xff1a; 1. 举例说明加锁的场景&#xff1a; 多线程并发情况下有资源竞争的时候&#xff0c;如果不加锁&#xff0c;会出现数据错误&#xff0c;举例说明&#xff1a; 业务需求&#xff1a;账户余额>取款金额&#xff0c;才能取钱。 时间线 两人共有账户 …...

青少年编程与数学 02-004 Go语言Web编程 02课题、依赖管理

青少年编程与数学 02-004 Go语言Web编程 02课题、依赖管理 课题摘要:一、项目结构各目录说明&#xff1a; 二、依赖项三、依赖管理任务四、依赖管理步骤1. 初始化Go Modules项目2. 添加依赖3. 指定依赖版本4. 更新依赖5. 清理未使用的依赖6. 离线工作7. 模块隔离8. 可重现构建 …...

MyBatis写法汇总

Mybatis写法汇总 1. 批量操作 1.1 批量插入 <insert id"batchInsert" parameterType"java.util.List">INSERT INTO user (username, password, create_time) VALUES<foreach collection"list" item"item" separator"…...

【Linux学习】十五、Linux/CentOS 7 用户和组管理

文章目录 一、组的管理1.组的创建格式&#xff1a;参数&#xff1a; 2.组的删除格式&#xff1a;参数&#xff1a; 3.组的属性修改格式&#xff1a;参数&#xff1a; 4.查看组的信息①cat /etc/group 命令②getent group 命令③仅显示系统中所有组名 二、用户的管理①超级用户&…...

三维无人机航迹算法的目标函数如何确定

一、定义目标函数 在三维无人机航迹算法中,目标函数的确定通常基于具体的任务需求和飞行约束。以下是一个简单的例子,展示了如何为三维无人机航迹规划定义一个目标函数。 例子:最小化飞行时间和避障的三维无人机航迹规划 1.任务描述:无人机需要从起点飞到终点,同时避开一些…...

uniapp v-tabs修改了几项功能,根据自己需求自己改

根据自己的需求都可以改 这里写自定义目录标题 1.数组中的名字过长&#xff0c;导致滑动异常2.change 事件拿不到当前点击的数据&#xff0c;通过index在原数组中查找得到所需要的id 各种字段麻烦3.添加指定下标下新加红点显示样式 1.数组中的名字过长&#xff0c;导致滑动异常…...

用vscode,进行vue开发

使用Visual Studio Code&#xff08;VSCode&#xff09;进行Vue.js开发是一个很好的选择&#xff0c;因为VSCode提供了强大的编辑功能以及丰富的插件生态。以下是使用VSCode进行Vue开发的基本步骤&#xff1a; 1. 安装Node.js和npm 首先&#xff0c;确保你的计算机上安装了No…...

Kafka 磁道寻址过程详解

前言 Apache Kafka 是一款高吞吐、分布式的消息流平台&#xff0c;广泛应用于实时数据处理和事件驱动系统。在 Kafka 中&#xff0c;消息是存储在磁盘上的&#xff0c;这种高效的数据读写性能得益于 Kafka 独特的磁盘存储架构和寻址机制。本文将从 Kafka 的存储结构、磁道寻址…...

基于Spring Boot的社区药房系统

一、系统背景与目的 随着医疗改革的深入和社区医疗服务的不断完善&#xff0c;社区药房在居民健康保障中扮演着越来越重要的角色。然而&#xff0c;传统的药房管理方式存在着库存管理混乱、药品销售不透明、客户信息管理不规范等问题。为了解决这些问题&#xff0c;基于Spring…...

005 QT常用控件Qwidget_上

文章目录 前言控件概述QWidgetenable属性geometry属性windowTitle属性windowlcon属性 小结 前言 本文将会向你介绍常用的Qwidget属性 控件概述 Widget 是 Qt 中的核心概念. 英文原义是 “⼩部件”, 我们此处把它翻译为 “控件” . 控件是构成⼀个图形化界面的基本要素. QWi…...

机器学习之交叉熵

交叉熵&#xff08;Cross-Entropy&#xff09;是机器学习中用于衡量预测分布与真实分布之间差异的一种损失函数&#xff0c;特别是在分类任务中非常常见。它源于信息论&#xff0c;反映了两个概率分布之间的距离。 交叉熵的数学定义 对于分类任务&#xff0c;假设我们有&#…...

数据结构 ——前缀树查词典的实现

数据结构 ——前缀树查词典的实现 一、前缀树的概念 前缀树是一种多叉树结构&#xff0c;主要用于存储字符串。每个节点代表一个字符&#xff0c;路径从根节点到叶节点表示一个完整的字符串。前缀树的关键特征是 共享前缀&#xff0c;也就是说&#xff0c;如果两个字符串有相…...

MySQL 主从复制与高可用架构

一、MySQL 主从复制概述 &#xff08;一&#xff09;定义与作用 MySQL 主从复制是一种允许在多个 MySQL 数据库服务器之间进行数据同步的技术。简单来说&#xff0c;就是可以把数据从一个 MySQL 服务器&#xff08;主服务器、主节点&#xff09;复制到一个或多个从节点&#…...

【Golang】如何读取并解析SQL文件

一、背景 在数据库开发与维护过程中&#xff0c;我们经常需要执行大量的SQL语句。有时&#xff0c;这些SQL语句会被保存在一个文件中&#xff0c;以便于批量执行。为了方便地在Go语言中处理这些SQL文件&#xff0c;我们可以编写一个函数来读取并解析SQL文件中的语句。 二、实…...

5分钟免费制作专业AI翻唱:AICoverGen完整指南

5分钟免费制作专业AI翻唱&#xff1a;AICoverGen完整指南 【免费下载链接】AICoverGen A WebUI to create song covers with any RVC v2 trained AI voice from YouTube videos or audio files. 项目地址: https://gitcode.com/gh_mirrors/ai/AICoverGen 想让AI帮你翻唱…...

手把手教你给STM32MP157开发板接上HDMI显示器(基于Sii9022A芯片与设备树配置)

STM32MP157开发板HDMI显示实战&#xff1a;从硬件连接到设备树配置全解析 引言 当你第一次拿到STM32MP157开发板时&#xff0c;最令人兴奋的莫过于看到图形界面在屏幕上亮起的那一刻。但现实往往很骨感——手头可能没有配套的LCD屏幕&#xff0c;而HDMI显示器却是大多数开发者桌…...

深部空间专属孪生,打造密闭硐室独有不可替代透明体系技术白皮书

深部空间专属孪生&#xff0c;打造密闭硐室独有不可替代透明体系技术白皮书副标题&#xff1a;井下专用暗光算法实现三维实时重建&#xff0c;搭配地下专属无感定位、多盲区跨镜穿透追踪、身体指纹特征识别&#xff0c;场景适配独一无二&#xff0c;行业无同类对标方案前言矿山…...

告别时间混乱:一份超全的Hive日期函数使用手册与常见错误排查

告别时间混乱&#xff1a;一份超全的Hive日期函数使用手册与常见错误排查 在数据开发领域&#xff0c;时间数据处理一直是高频且易错的环节。无论是日志分析、用户行为追踪还是财务报表生成&#xff0c;准确的时间计算都是确保数据质量的基础。Hive作为大数据生态中广泛使用的数…...

DIY蓝牙游戏手柄:基于Bluefruit EZ-Key的免编程硬件制作全攻略

1. 项目概述与设计思路几年前&#xff0c;我还在用有线手柄在电脑上打游戏&#xff0c;那根线总是缠来缠去&#xff0c;桌面也乱糟糟的。后来市面上无线手柄选择多了&#xff0c;但总感觉少了点自己动手的乐趣&#xff0c;功能也千篇一律。直到我开始接触像Adafruit Bluefruit …...

WELearn网课助手完整指南:5大核心功能彻底解放你的英语学习时间

WELearn网课助手完整指南&#xff1a;5大核心功能彻底解放你的英语学习时间 【免费下载链接】WELearnHelper 显示WE Learn随行课堂题目答案&#xff1b;支持班级测试&#xff1b;自动答题&#xff1b;刷时长&#xff1b;基于生成式AI(ChatGPT)的答案生成 项目地址: https://g…...

HTTP客户端设计哲学:从axios到hoomanity的易用性演进

1. 项目概述&#xff1a;一个为人类设计的HTTP客户端在构建现代应用程序时&#xff0c;与外部API或服务进行HTTP通信几乎是每个开发者都会遇到的日常任务。无论是调用一个天气接口、上传文件到云存储&#xff0c;还是与自家的微服务进行数据交换&#xff0c;我们都需要一个可靠…...

基于CircuitPython的Fruit Jam OS:在RP2350上构建复古微型计算机系统

1. 项目概述&#xff1a;当复古计算精神遇见现代微控制器如果你和我一样&#xff0c;对早期个人计算机那种开机即用、一切尽在掌控的纯粹体验抱有怀念&#xff0c;同时又痴迷于现代开源硬件带来的无限可能&#xff0c;那么Fruit Jam OS绝对是一个会让你眼前一亮的项目。它不是一…...

Node.js代理池实战:proxy-agents库核心原理与高级应用

1. 项目概述与核心价值最近在折腾一些需要处理大量网络请求的自动化脚本&#xff0c;比如数据采集、API测试或者模拟用户操作&#xff0c;一个绕不开的痛点就是IP被封。单个IP频繁请求&#xff0c;对方服务器很容易就把你拉黑了。这时候&#xff0c;代理池就成了刚需。市面上成…...

【限时解密】Midjourney未公开的Tea印相冷启动协议:如何绕过默认sampler干扰,直触胶片模拟内核(仅剩37位开发者掌握)

更多请点击&#xff1a; https://intelliparadigm.com 第一章&#xff1a;Midjourney Tea印相冷启动协议的起源与本质 Midjourney Tea印相冷启动协议&#xff08;Tea-Init Protocol&#xff09;并非官方标准&#xff0c;而是由东亚AI艺术协作社区在2023年自发演化出的一套轻量…...