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

从零起步的Kaggle竞赛 - BirdCLEF2025

一个优秀的coder,先从CV工程开始......

首先复制了 LB 0.804- EfficientNet B0 Pytorch Pipeline | Kaggle 这个notebook并尝试提交,ok,0.804

下载了大佬的代码试图在本地修改模型结构并训练。

以下是大佬的notebook中的代码,可以直接提交。

由于其中只含有加载模型推理的代码,我把它命名为test.py。这样后续我就可以从test.py调用模型结构进行训练,无需重复定义模型,而且也只需修改一次模型结构。

import os
import gc
import warnings
import logging
import time
import math
import cv2
from pathlib import Pathimport numpy as np
import pandas as pd
import librosa
import torch
import torch.nn as nn
import torch.nn.functional as F
import timm
from tqdm.auto import tqdm# Suppress warnings and limit logging output
warnings.filterwarnings("ignore")
logging.basicConfig(level=logging.ERROR)class CFG:"""Configuration class holding all paths and parameters required for the inference pipeline."""test_soundscapes = '/kaggle/input/birdclef-2025/test_soundscapes'submission_csv = '/kaggle/input/birdclef-2025/sample_submission.csv'taxonomy_csv = '/kaggle/input/birdclef-2025/taxonomy.csv'model_path = '/kaggle/input/birdclef-2025-efficientnet-b0' # 从这里上传?# Audio parametersFS = 32000WINDOW_SIZE = 5# Mel spectrogram parametersN_FFT = 1034HOP_LENGTH = 64N_MELS = 136FMIN = 20FMAX = 16000TARGET_SHAPE = (256, 256)model_name = 'efficientnet_b0'in_channels = 1device = 'cpu'# Inference parametersbatch_size = 16use_tta = Falsetta_count = 3threshold = 0.7use_specific_folds = False  # If False, use all found modelsfolds = [0, 1]  # Used only if use_specific_folds is Truedebug = Falsedebug_count = 3class BirdCLEFModel(nn.Module):"""Custom neural network model for BirdCLEF-2025 that uses a timm backbone."""def __init__(self, cfg, num_classes):"""Initialize the BirdCLEFModel.:param cfg: Configuration parameters.:param num_classes: Number of output classes."""super().__init__()self.cfg = cfg# Create backbone using timm with specified parameters.self.backbone = timm.create_model(cfg.model_name,pretrained=False,in_chans=cfg.in_channels,drop_rate=0.0,drop_path_rate=0.0)# Adjust final layers based on model typeif 'efficientnet' in cfg.model_name:backbone_out = self.backbone.classifier.in_featuresself.backbone.classifier = nn.Identity()elif 'resnet' in cfg.model_name:backbone_out = self.backbone.fc.in_featuresself.backbone.fc = nn.Identity()else:backbone_out = self.backbone.get_classifier().in_featuresself.backbone.reset_classifier(0, '')self.pooling = nn.AdaptiveAvgPool2d(1)self.feat_dim = backbone_outself.classifier = nn.Linear(backbone_out, num_classes)def forward(self, x):"""Forward pass through the network.:param x: Input tensor.:return: Logits for each class."""features = self.backbone(x)if isinstance(features, dict):features = features['features']# If features are 4D, apply global average pooling.if len(features.shape) == 4:features = self.pooling(features)features = features.view(features.size(0), -1)logits = self.classifier(features)return logitsclass BirdCLEF2025Pipeline:"""Pipeline for the BirdCLEF-2025 inference task.This class organizes the complete inference process:- Loading taxonomy data.- Loading and preparing the trained models.- Processing audio files into mel spectrograms.- Making predictions on each audio segment.- Creating the submission file.- Post-processing the submission to smooth predictions."""def __init__(self, cfg):"""Initialize the inference pipeline with the given configuration.:param cfg: Configuration object with paths and parameters."""self.cfg = cfgself.taxonomy_df = Noneself.species_ids = []self.models = []self._load_taxonomy()def _load_taxonomy(self):"""Load taxonomy data from CSV and extract species identifiers."""print("Loading taxonomy data...")self.taxonomy_df = pd.read_csv(self.cfg.taxonomy_csv)self.species_ids = self.taxonomy_df['primary_label'].tolist()print(f"Number of classes: {len(self.species_ids)}")def audio2melspec(self, audio_data):"""Convert raw audio data to a normalized mel spectrogram.:param audio_data: 1D numpy array of audio samples.:return: Normalized mel spectrogram."""if np.isnan(audio_data).any():mean_signal = np.nanmean(audio_data)audio_data = np.nan_to_num(audio_data, nan=mean_signal)mel_spec = librosa.feature.melspectrogram(y=audio_data,sr=self.cfg.FS,n_fft=self.cfg.N_FFT,hop_length=self.cfg.HOP_LENGTH,n_mels=self.cfg.N_MELS,fmin=self.cfg.FMIN,fmax=self.cfg.FMAX,power=2.0)mel_spec_db = librosa.power_to_db(mel_spec, ref=np.max)mel_spec_norm = (mel_spec_db - mel_spec_db.min()) / (mel_spec_db.max() - mel_spec_db.min() + 1e-8)return mel_spec_normdef process_audio_segment(self, audio_data):"""Process an audio segment to obtain a mel spectrogram with the target shape.:param audio_data: 1D numpy array of audio samples.:return: Processed mel spectrogram as a float32 numpy array."""# Pad audio if it is shorter than the required window size.if len(audio_data) < self.cfg.FS * self.cfg.WINDOW_SIZE:audio_data = np.pad(audio_data,(0, self.cfg.FS * self.cfg.WINDOW_SIZE - len(audio_data)),mode='constant')mel_spec = self.audio2melspec(audio_data)# Resize spectrogram to the target shape if necessary.if mel_spec.shape != self.cfg.TARGET_SHAPE:mel_spec = cv2.resize(mel_spec, self.cfg.TARGET_SHAPE, interpolation=cv2.INTER_LINEAR)return mel_spec.astype(np.float32)def find_model_files(self):"""Find all .pth model files in the specified model directory.:return: List of model file paths."""model_files = []model_dir = Path(self.cfg.model_path)for path in model_dir.glob('**/*.pth'):model_files.append(str(path))return model_filesdef load_models(self):"""Load all found model files and prepare them for ensemble inference.:return: List of loaded PyTorch models."""self.models = []model_files = self.find_model_files()if not model_files:print(f"Warning: No model files found under {self.cfg.model_path}!")return self.modelsprint(f"Found a total of {len(model_files)} model files.")# If specific folds are required, filter the model files.if self.cfg.use_specific_folds:filtered_files = []for fold in self.cfg.folds:fold_files = [f for f in model_files if f"fold{fold}" in f]filtered_files.extend(fold_files)model_files = filtered_filesprint(f"Using {len(model_files)} model files for the specified folds ({self.cfg.folds}).")# Load each model file.for model_path in model_files:try:print(f"Loading model: {model_path}")checkpoint = torch.load(model_path, map_location=torch.device(self.cfg.device))model = BirdCLEFModel(self.cfg, len(self.species_ids))model.load_state_dict(checkpoint['model_state_dict'])model = model.to(self.cfg.device)model.eval()self.models.append(model)except Exception as e:print(f"Error loading model {model_path}: {e}")return self.modelsdef apply_tta(self, spec, tta_idx):"""Apply test-time augmentation (TTA) to the spectrogram.:param spec: Input mel spectrogram.:param tta_idx: Index indicating which TTA to apply.:return: Augmented spectrogram."""if tta_idx == 0:# No augmentation.return specelif tta_idx == 1:# Time shift (horizontal flip).return np.flip(spec, axis=1)elif tta_idx == 2:# Frequency shift (vertical flip).return np.flip(spec, axis=0)else:return specdef predict_on_spectrogram(self, audio_path):"""Process a single audio file and predict species presence for each 5-second segment.:param audio_path: Path to the audio file.:return: Tuple (row_ids, predictions) for each segment."""predictions = []row_ids = []soundscape_id = Path(audio_path).stemtry:print(f"Processing {soundscape_id}")audio_data, _ = librosa.load(audio_path, sr=self.cfg.FS)total_segments = int(len(audio_data) / (self.cfg.FS * self.cfg.WINDOW_SIZE))for segment_idx in range(total_segments):start_sample = segment_idx * self.cfg.FS * self.cfg.WINDOW_SIZEend_sample = start_sample + self.cfg.FS * self.cfg.WINDOW_SIZEsegment_audio = audio_data[start_sample:end_sample]end_time_sec = (segment_idx + 1) * self.cfg.WINDOW_SIZErow_id = f"{soundscape_id}_{end_time_sec}"row_ids.append(row_id)if self.cfg.use_tta:all_preds = []for tta_idx in range(self.cfg.tta_count):mel_spec = self.process_audio_segment(segment_audio)mel_spec = self.apply_tta(mel_spec, tta_idx)mel_spec_tensor = torch.tensor(mel_spec, dtype=torch.float32).unsqueeze(0).unsqueeze(0)mel_spec_tensor = mel_spec_tensor.to(self.cfg.device)if len(self.models) == 1:with torch.no_grad():outputs = self.models[0](mel_spec_tensor)probs = torch.sigmoid(outputs).cpu().numpy().squeeze()all_preds.append(probs)else:segment_preds = []for model in self.models:with torch.no_grad():outputs = model(mel_spec_tensor)probs = torch.sigmoid(outputs).cpu().numpy().squeeze()segment_preds.append(probs)avg_preds = np.mean(segment_preds, axis=0)all_preds.append(avg_preds)final_preds = np.mean(all_preds, axis=0)else:mel_spec = self.process_audio_segment(segment_audio)mel_spec_tensor = torch.tensor(mel_spec, dtype=torch.float32).unsqueeze(0).unsqueeze(0)mel_spec_tensor = mel_spec_tensor.to(self.cfg.device)if len(self.models) == 1:with torch.no_grad():outputs = self.models[0](mel_spec_tensor)final_preds = torch.sigmoid(outputs).cpu().numpy().squeeze()else:segment_preds = []for model in self.models:with torch.no_grad():outputs = model(mel_spec_tensor)probs = torch.sigmoid(outputs).cpu().numpy().squeeze()segment_preds.append(probs)final_preds = np.mean(segment_preds, axis=0)predictions.append(final_preds)except Exception as e:print(f"Error processing {audio_path}: {e}")return row_ids, predictionsdef run_inference(self):"""Run inference on all test soundscape audio files.:return: Tuple (all_row_ids, all_predictions) aggregated from all files."""test_files = list(Path(self.cfg.test_soundscapes).glob('*.ogg'))if self.cfg.debug:print(f"Debug mode enabled, using only {self.cfg.debug_count} files")test_files = test_files[:self.cfg.debug_count]print(f"Found {len(test_files)} test soundscapes")all_row_ids = []all_predictions = []for audio_path in tqdm(test_files):row_ids, predictions = self.predict_on_spectrogram(str(audio_path))all_row_ids.extend(row_ids)all_predictions.extend(predictions)return all_row_ids, all_predictionsdef create_submission(self, row_ids, predictions):"""Create the submission dataframe based on predictions.:param row_ids: List of row identifiers for each segment.:param predictions: List of prediction arrays.:return: A pandas DataFrame formatted for submission."""print("Creating submission dataframe...")submission_dict = {'row_id': row_ids}for i, species in enumerate(self.species_ids):submission_dict[species] = [pred[i] for pred in predictions]submission_df = pd.DataFrame(submission_dict)submission_df.set_index('row_id', inplace=True)sample_sub = pd.read_csv(self.cfg.submission_csv, index_col='row_id')missing_cols = set(sample_sub.columns) - set(submission_df.columns)if missing_cols:print(f"Warning: Missing {len(missing_cols)} species columns in submission")for col in missing_cols:submission_df[col] = 0.0submission_df = submission_df[sample_sub.columns]submission_df = submission_df.reset_index()return submission_dfdef smooth_submission(self, submission_path):"""Post-process the submission CSV by smoothing predictions to enforce temporal consistency.For each soundscape (grouped by the file name part of 'row_id'), each row's predictionsare averaged with those of its neighbors using defined weights.:param submission_path: Path to the submission CSV file."""print("Smoothing submission predictions...")sub = pd.read_csv(submission_path)cols = sub.columns[1:]# Extract group names by splitting row_id on the last underscoregroups = sub['row_id'].str.rsplit('_', n=1).str[0].valuesunique_groups = np.unique(groups)for group in unique_groups:# Get indices for the current groupidx = np.where(groups == group)[0]sub_group = sub.iloc[idx].copy()predictions = sub_group[cols].valuesnew_predictions = predictions.copy()if predictions.shape[0] > 1:# Smooth the predictions using neighboring segmentsnew_predictions[0] = (predictions[0] * 0.8) + (predictions[1] * 0.2)new_predictions[-1] = (predictions[-1] * 0.8) + (predictions[-2] * 0.2)for i in range(1, predictions.shape[0] - 1):new_predictions[i] = (predictions[i - 1] * 0.2) + (predictions[i] * 0.6) + (predictions[i + 1] * 0.2)# Replace the smoothed values in the submission dataframesub.iloc[idx, 1:] = new_predictionssub.to_csv(submission_path, index=False)print(f"Smoothed submission saved to {submission_path}")def run(self):"""Main method to execute the complete inference pipeline.This method:- Loads the pre-trained models.- Processes test audio files and runs predictions.- Creates the submission CSV.- Applies smoothing to the predictions."""start_time = time.time()print("Starting BirdCLEF-2025 inference...")print(f"TTA enabled: {self.cfg.use_tta} (variations: {self.cfg.tta_count if self.cfg.use_tta else 0})")self.load_models()if not self.models:print("No models found! Please check model paths.")returnprint(f"Model usage: {'Single model' if len(self.models) == 1 else f'Ensemble of {len(self.models)} models'}")row_ids, predictions = self.run_inference()submission_df = self.create_submission(row_ids, predictions)submission_path = 'submission.csv'submission_df.to_csv(submission_path, index=False)print(f"Initial submission saved to {submission_path}")# Apply smoothing on the submission predictions.self.smooth_submission(submission_path)end_time = time.time()print(f"Inference completed in {(end_time - start_time) / 60:.2f} minutes")# Run the BirdCLEF2025 Pipeline:
if __name__ == "__main__":cfg = CFG()print(f"Using device: {cfg.device}")pipeline = BirdCLEF2025Pipeline(cfg)pipeline.run()

 

由于想要自己训练一个模型,所以另外写了一个train.py
注意其中的

    train_audio_dir = '/root/autodl-tmp/BirdCLEF2025/train_audio' train_csv = '/root/autodl-tmp/BirdCLEF2025/train.csv'taxonomy_csv = '/root/autodl-tmp/BirdCLEF2025/taxonomy.csv' output_dir = "

需要修改为你实际存放数据的位置。

以下是完整的train.py

# train.py
import os
import pandas as pd
import numpy as np
import librosa
import cv2
import torch
from torch.utils.data import Dataset, DataLoader
from sklearn.model_selection import StratifiedKFold
from tqdm.auto import tqdm# 继承test.py中的原始组件
from test import CFG, BirdCLEFModelimport warnings  # 必须放在最顶部
warnings.filterwarnings("ignore")  # 忽略所有警告# ---------------------- 扩展训练配置 ----------------------
class TrainCFG(CFG):"""新增训练专用参数"""# 数据路径需要覆盖父类配置train_audio_dir = '/root/autodl-tmp/BirdCLEF2025/train_audio' # "./data/birdclef-2025/train_audio"train_csv = '/root/autodl-tmp/BirdCLEF2025/train.csv'  # "./data/birdclef-2025/train.csv"taxonomy_csv = '/root/autodl-tmp/BirdCLEF2025/taxonomy.csv' # './data/birdclef-2025/taxonomy.csv'output_dir = "./checkpoints"# 训练参数device = "cuda" # if torch.cuda.is_available() else "cpu"num_epochs = 20lr = 1e-4batch_size = 256num_workers = 4num_folds = 5seed = 42# 标签平滑参数label_smoothing = 0.05# 混合精度训练use_amp = True# ---------------------- 核心数据处理器 ----------------------
class BirdDataset(Dataset):def __init__(self, cfg, df, audio_dir, is_train=True):"""保持与test.py中spectrogram生成逻辑一致:param df: 从train.csv加载的DataFrame"""self.cfg = cfgself.df = df.reset_index(drop=True)self.audio_dir = audio_dirself.is_train = is_train# 从taxonomy获取标签映射taxonomy = pd.read_csv(cfg.taxonomy_csv)self.label_mapping = {row['primary_label']: idxfor idx, row in taxonomy.iterrows()}print(f"Total classes: {len(self.label_mapping)}")def __len__(self):return len(self.df)def _load_audio(self, filename):"""严格保持与test.py相同的音频加载逻辑"""audio_path = os.path.join(self.audio_dir, filename)# 异常处理与test.py一致try:audio, _ = librosa.load(audio_path, sr=self.cfg.FS)if np.isnan(audio).any():audio = np.nan_to_num(audio, nan=np.mean(audio))except Exception as e:print(f"Error loading {audio_path}: {e}")audio = np.zeros(self.cfg.FS * 5)return audiodef _process_segment(self, audio):"""严格复制test.py中的频谱生成代码"""# 填充逻辑需要完全相同if len(audio) < self.cfg.FS * self.cfg.WINDOW_SIZE:audio = np.pad(audio,(0, self.cfg.FS * self.cfg.WINDOW_SIZE - len(audio)),mode='constant')# Mel频谱生成参数完全一致mel_spec = librosa.feature.melspectrogram(y=audio,sr=self.cfg.FS,n_fft=self.cfg.N_FFT,hop_length=self.cfg.HOP_LENGTH,n_mels=self.cfg.N_MELS,fmin=self.cfg.FMIN,fmax=self.cfg.FMAX,power=2.0)mel_spec_db = librosa.power_to_db(mel_spec, ref=np.max)mel_spec_norm = (mel_spec_db - mel_spec_db.min()) / (mel_spec_db.max() - mel_spec_db.min() + 1e-8)# 调整尺寸方式与test.py完全一致return cv2.resize(mel_spec_norm, self.cfg.TARGET_SHAPE, interpolation=cv2.INTER_LINEAR)def __getitem__(self, idx):row = self.df.iloc[idx]# 1.音频加载与预处理audio = self._load_audio(row['filename'])# 2.保持数据增强与test.py的兼容性# (注意:训练时需要自定义增广,但推理时不应启用)if self.is_train:# 随机时间裁剪(保持核心逻辑但扩展为训练模式)if len(audio) > self.cfg.FS * self.cfg.WINDOW_SIZE:start = np.random.randint(0, len(audio) - self.cfg.FS * self.cfg.WINDOW_SIZE)audio = audio[start: start + self.cfg.FS * self.cfg.WINDOW_SIZE]# 3.严格使用test.py频谱生成方法spec = self._process_segment(audio)  # shape (256,256)# 4.目标生成(保持与模型输出的206类一致)target = torch.zeros(len(self.label_mapping), dtype=torch.float32)primary_idx = self.label_mapping.get(row['primary_label'], -1)if primary_idx != -1:target[primary_idx] = 1.0 - self.cfg.label_smoothingtarget += self.cfg.label_smoothing / len(target)return {'spec': torch.tensor(spec).unsqueeze(0),  # shape [1,256,256]'target': target  # shape [206]}# ---------------------- 训练循环 ----------------------
def train_fn(cfg, model, train_loader, optimizer, criterion):model.train()total_loss = 0.0progress = tqdm(train_loader, desc="Training", leave=False)scaler = torch.cuda.amp.GradScaler(enabled=cfg.use_amp)for batch in progress:specs = batch['spec'].to(cfg.device)  # shape [B,1,256,256]targets = batch['target'].to(cfg.device)  # shape [B,206]optimizer.zero_grad()with torch.cuda.amp.autocast(enabled=cfg.use_amp):outputs = model(specs)  # 完全保留test.py的forward逻辑loss = criterion(outputs, targets)scaler.scale(loss).backward()scaler.step(optimizer)scaler.update()total_loss += loss.item()progress.set_postfix(loss=loss.item())return total_loss / len(train_loader)def validate_fn(cfg, model, val_loader, criterion):model.eval()total_loss = 0.0progress = tqdm(val_loader, desc="Validating", leave=False)with torch.no_grad():for batch in progress:specs = batch['spec'].to(cfg.device)targets = batch['target'].to(cfg.device)outputs = model(specs)loss = criterion(outputs, targets)total_loss += loss.item()return total_loss / len(val_loader)# ---------------------- 主流程 ----------------------
def main():cfg = TrainCFG()os.makedirs(cfg.output_dir, exist_ok=True)# 确保不同来源的配置同步cfg.TARGET_SHAPE = (256, 256)  # 与test.py完全一致torch.manual_seed(cfg.seed)# 加载数据train_df = pd.read_csv(cfg.train_csv)taxonomy = pd.read_csv(cfg.taxonomy_csv)assert len(taxonomy) == 206, "Taxonomy类数应与模型输出一致"# Cross-validation训练循环skf = StratifiedKFold(n_splits=cfg.num_folds)for fold, (train_idx, val_idx) in enumerate(skf.split(train_df, train_df['primary_label'])):print(f"\n{'=' * 25} Fold {fold + 1}/{cfg.num_folds} {'=' * 25}")# 数据加载器print('loading dataset...')train_ds = BirdDataset(cfg, train_df.iloc[train_idx], cfg.train_audio_dir)val_ds = BirdDataset(cfg, train_df.iloc[val_idx], cfg.train_audio_dir, is_train=False)train_loader = DataLoader(train_ds,batch_size=cfg.batch_size,shuffle=True,num_workers=0,#cfg.num_workers,pin_memory=True)val_loader = DataLoader(val_ds,batch_size=cfg.batch_size * 2,shuffle=False,num_workers=0,#cfg.num_workers,)# 初始化与test.py完全一致的模型结构print('constructing MODEL...')model = BirdCLEFModel(cfg, num_classes=len(taxonomy)).to(cfg.device)optimizer = torch.optim.AdamW(model.parameters(), lr=cfg.lr)criterion = torch.nn.BCEWithLogitsLoss()  # 使用与sigmoid推理一致的目标函数# 训练循环best_val_loss = float('inf')for epoch in range(1, cfg.num_epochs + 1):print(f"Epoch {epoch}/{cfg.num_epochs}")train_loss = train_fn(cfg, model, train_loader, optimizer, criterion)val_loss = validate_fn(cfg, model, val_loader, criterion)# 保存最佳模型(与test.py加载格式完全兼容)if val_loss < best_val_loss:best_val_loss = val_lossckpt_path = os.path.join(cfg.output_dir, f"best_fold{fold}.pth")torch.save({'model_state_dict': model.state_dict(),'config': vars(cfg)}, ckpt_path)print(f"Fold {fold} New best model saved (val_loss={val_loss:.4f})")print(f"Fold {fold} completed. Best val loss: {best_val_loss:.4f}")if __name__ == "__main__":main()

在代码中学:

num_folds(折数)通常指交叉验证中的子集划分数量,用于评估模型的泛化性能。以下是详细解释:


一、核心作用

  1. 数据利用率优化
    将数据集划分为K个子集(K=num_folds),进行K次训练/验证,每次用 K-1个子集训练1个子集验证,充分利用有限数据。

  2. 评估稳定性增强
    通过多个不同验证集的平均结果,减少因数据划分随机性带来的评估偏差。


二、常用场景

场景应用方式
交叉验证训练num_folds=5, 运行5次训练后平均结果
集成学习每折训练一个子模型,最终预测为多模型投票或平均
超参数调优在每折中搜索最佳参数,选择平均性能最优的配置
小数据集验证数据量少时提高验证可靠性(常用num_folds=5/10

三、工作流程示例(5折交叉验证)

数据集划分:
原始数据 ➜ 划分为5等份(F1~F5)

训练轮次训练集验证集评估模型
第1折F2+F3+F4+F5F1Model_1
第2折F1+F3+F4+F5F2Model_2
第3折F1+F2+F4+F5F3Model_3
第4折F1+F2+F3+F5F4Model_4
第5折F1+F2+F3+F4F5Model_5

最终性能:
取5次验证结果的均值(如准确率、F1分数等)

相关文章:

从零起步的Kaggle竞赛 - BirdCLEF2025

一个优秀的coder&#xff0c;先从CV工程开始...... 首先复制了 LB 0.804- EfficientNet B0 Pytorch Pipeline | Kaggle 这个notebook并尝试提交&#xff0c;ok&#xff0c;0.804 下载了大佬的代码试图在本地修改模型结构并训练。 以下是大佬的notebook中的代码&#xff0c;可…...

基于CNN+ViT的蔬果图像分类实验

本文只是做一个简单融合的实验&#xff0c;没有任何新颖&#xff0c;大家看看就行了。 1.数据集 本文所采用的数据集为Fruit-360 果蔬图像数据集&#xff0c;该数据集由 Horea Mureșan 等人整理并发布于 GitHub&#xff08;项目地址&#xff1a;Horea94/Fruit-Images-Datase…...

MySQL SQL 执行顺序(理论顺序)

示例 SQL&#xff1a; SELECT name, COUNT(*) FROM users WHERE age > 18 GROUP BY name HAVING COUNT(*) > 1 ORDER BY name ASC LIMIT 10;虽然语句是从 SELECT 写起的&#xff0c;但执行顺序其实是这样的&#xff1a; 执行顺序SQL 子句作用说明①FROM确定查询的…...

用Allan Deviation的方式估计长时间频率偏差

在电路设计中&#xff0c;若需要评估OSC长时间的偏差(秒级别)&#xff0c;观测的时间越多&#xff0c;低频噪声1/f上载的越厉害,如何通过PhaseNoise去有效估计长时间的偏差呢?...

无人机避障与目标识别技术分析!

一、无人机避障技术 1. 技术实现方式 传感器融合&#xff1a; 视觉传感&#xff08;RGB/双目/红外相机&#xff09;&#xff1a;基于SLAM&#xff08;同步定位与地图构建&#xff09;实现环境建模&#xff0c;但依赖光照条件。 激光雷达&#xff08;LiDAR&#xff09;&…...

2025年渗透测试面试题总结-拷打题库01(题目+回答)

网络安全领域各种资源&#xff0c;学习文档&#xff0c;以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各种好玩的项目及好用的工具&#xff0c;欢迎关注。 目录 2025年渗透测试面试题总结-拷打题库01 1. PHP爆绝对路径方法&#xff1f; 2. 渗透工具及最常用工具 3…...

大厂面试:六大排序

前言 本篇博客集中了冒泡&#xff0c;选择&#xff0c;二分插入&#xff0c;快排&#xff0c;归并&#xff0c;堆排&#xff0c;六大排序算法 如果觉得对你有帮助&#xff0c;可以点点关注&#xff0c;点点赞&#xff0c;谢谢你&#xff01; 1.冒泡排序 //冒泡排序&#xff…...

Python爬虫第15节-2025今日头条街拍美图抓取实战

目录 一、项目背景与概述 二、环境准备与工具配置 2.1 开发环境要求 2.2 辅助工具配置 三、详细抓取流程解析 3.1 页面加载机制分析 3.2 关键请求识别技巧 3.3 参数规律深度分析 四、爬虫代码实现 五、实现关键 六、法律与道德规范 一、项目概述 在当今互联网时代&a…...

std::map gdb调试ok ,直接运行会crash

在使用 std::map 并且在调试模式下没有问题&#xff0c;但在直接运行时出现崩溃&#xff08;crash&#xff09;的情况&#xff0c;通常是由于以下几个原因引起的&#xff1a; 未初始化的变量使用&#xff1a;在调试模式下&#xff0c;某些变量可能因为调试工具&#xff08;如 G…...

【2025年泰迪杯数据挖掘挑战赛】A题 数据分析+问题建模与求解+Python代码直接分享

目录 2025年泰迪杯数据挖掘挑战赛A题完整论文&#xff1a;建模与求解Python代码1问题一的思路与求解1.1 问题一的思路1.1.1对统计数据进行必要说明&#xff1a;1.1.2统计流程&#xff1a;1.1.3特殊情况的考虑&#xff1a; 1.2 问题一的求解1.2.1代码实现1.2.2 问题一结果代码分…...

git在分支上会退到某个指定的commit

1、在idea上先备份好分支&#xff08;基于现有分支new branch&#xff09; 2、在gitlab管理端删除现有分支 3、在idea中大卡terminal&#xff0c;执行 git log 查看commit log ,找到要会退到的commit唯一码&#xff0c;然后执行git reset 唯一码 4、查看本地代码状态 git st…...

Cursor入门教程-JetBrains过度向

Cursor使用笔记 **前置&#xff1a;**之前博主使用的是JetBrains的IDE&#xff0c;VSCode使用比较少&#xff0c;所以会尽量朝着JetBrains的使用习惯及样式去调整。 一、设置语言为中文 如果刚上手Cursor&#xff0c;那么肯定对Cursor中的众多选项配置项不熟悉&#xff0c;这…...

MySQL之text字段详细分类说明

在 MySQL 中&#xff0c;TEXT 是用来存储大量文本数据的数据类型。TEXT 类型可以存储非常长的字符串&#xff0c;比 VARCHAR 类型更适合存储大块的文本数据。TEXT 数据类型分为以下几个子类型&#xff0c;每个子类型用于存储不同大小范围的文本数据&#xff1a; TINYTEXT: 可以…...

为什么 Transformer 要使用多头注意力机制?

简而言之&#xff0c;多头注意力机制可以让模型从不同的在空间中并行地捕捉到不同的特征关系&#xff0c;从而更全面&#xff0c;更灵活地理解序列中的信息。 举个例子&#xff0c;如果要看一幅画&#xff0c;就不能简单地只关注例如颜色&#xff0c;还要关注到结构&#xff0…...

Python项目--基于Python的自然语言处理文本摘要系统

1. 项目概述 自然语言处理(NLP)是人工智能领域中一个重要的研究方向&#xff0c;而文本摘要作为NLP的一个重要应用&#xff0c;在信息爆炸的时代具有重要意义。本项目旨在开发一个基于Python的文本摘要系统&#xff0c;能够自动从长文本中提取关键信息&#xff0c;生成简洁而全…...

【Web APIs】JavaScript 操作多个元素 ③ ( 鼠标经过高亮显示 | onmouseover 事件设置 | onmouseout 事件设置 )

文章目录 一、核心要点解析 - 鼠标经过高亮显示1、案例需求2、获取高亮显示的 列表行3、鼠标经过 onmouseover 事件设置4、鼠标离开 onmouseout 事件设置5、设置高亮方式 二、完整代码示例1、完整代码示例2、执行结果 一、核心要点解析 - 鼠标经过高亮显示 1、案例需求 案例需求…...

金融的未来

1. DeFi的爆发式增长与核心使命 DeFi&#xff08;去中心化金融&#xff09;的使命是重构传统金融基础设施&#xff0c;通过区块链技术实现更高的透明度、可访问性、效率、便利性和互操作性。其增长数据印证了这一趋势&#xff1a; TVL&#xff08;总锁定价值&#xff09;爆炸…...

[ElasticSearch]Suggest查询建议(自动补全纠错)

概述 搜索一般都会要求具有“搜索推荐”或者叫“搜索补全”的功能&#xff0c;即在用户输入搜索的过程中&#xff0c;进行自动补全或者纠错。以此来提高搜索文档的匹配精准度&#xff0c;进而提升用户的搜索体验&#xff0c;这就是Suggest。 四种Suggester 1 Term Suggester…...

GPT-4.1 提示词使用指南

GPT-4.1 提示词使用指南 参考&#xff1a;https://cookbook.openai.com/examples/gpt4-1_prompting_guide 为什么要关注 GPT-4.1 提示词使用指南&#xff1f; GPT-4.1 比其前代模型 GPT-4o 更倾向于严格跟随指令&#xff0c;而不是像 GPT-4o 那样更自由地推断用户和系统提示…...

es6面试常见问题╮(╯▽╰)╭

ES6(ECMAScript 2015)的一些常见面试问题,涵盖了变量声明、箭头函数、模板字符串、解构赋值、模块化、类、Promise、生成器等关键特性。有些面试就是问问,对老程序员面试其实不问这么多╮(╯▽╰)╭ 文章目录 **1. 变量声明****1.1 `let` 和 `const` 与 `var` 的区别是什么…...

Xenomai 如何实现 <10μs 级抖动控制

1. 抖动&#xff08;Jitter&#xff09;的定义与重要性 1.1 什么是抖动&#xff1f; 在实时控制系统中&#xff0c;抖动&#xff08;Jitter&#xff09;指任务实际执行时间与预期周期时间的偏差。例如&#xff1a; • 设定一个任务每 100μs 运行一次&#xff0c;但实际运行时间…...

前端基础常见的算法

你整理的这些前端常见算法知识点挺实用的&#xff0c;适合复习或面试准备。下面我帮你稍微整理美化一下格式&#xff0c;并补充一点细节&#xff0c;让内容更清晰易读&#xff1a; 1. 排序算法 冒泡排序&#xff08;Bubble Sort&#xff09; 原理&#xff1a;通过重复比较相邻元…...

RPA机器人技术原理初探

RPA&#xff08;Robotic Process Automation&#xff0c;机器人流程自动化&#xff09;通过模拟人类操作界面元素来实现自动化任务&#xff0c;其技术原理可分为以下核心模块&#xff1a; 一、基础技术架构 界面元素识别技术 选择器&#xff08;Selector&#xff09;引擎&#…...

AWS CloudFront加速S3配置跨域

1、点击分配 源我们就选择S3–>选择我们要加速的S3存储桶 2、创建OAC访问方式 在我们的来源访问处–>来源访问控制设置(推荐)–>选择创建新的OAC(Create new OAC)–>自定义名字按默认选项保存–>选择刚刚新创建的OAC 3、选择查看器的配置 根据具体情况&#x…...

58.最后一个单词的长度

目录 一、问题描述 二、解题思路 三、代码 四、复杂度分析 一、问题描述 给你一个字符串 s&#xff0c;由若干单词组成&#xff0c;单词前后用一些空格字符隔开。返回字符串中 最后一个 单词的长度。单词 是指仅由字母组成、不包含任何空格字符的最大子字符串。 二、解题思…...

leetcode_344.反转字符串_java

344. 反转字符串 1、题目 编写一个函数&#xff0c;其作用是将输入的字符串反转过来。输入字符串以字符数组 s 的形式给出。 不要给另外的数组分配额外的空间&#xff0c;你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。 示例 1&#xff1a; 输入&#xff1a…...

Android --- FrameWork 入门:极速上手AOSP

文章目录 一、硬件要求二、虚拟机安装三、开发环境搭建四、下载编译源码 一、硬件要求 CPU不低于6核心,建议8核及以上 内存不低于32G,建议64G 存储空间不低于500G,建议 1TB SSD 二、虚拟机安装 1.下载ubuntu&#xff0c;官网网址如下&#xff1a; releases.ubuntu.com/focal…...

“大湾区珠宝艺境花园”璀璨绽放第五届消博会

2025年4月13日&#xff0c;第五届中国国际消费品博览会&#xff08;以下简称"消博会"&#xff09;重要主题活动——《大湾区珠宝艺境花园》启动仪式在海南国际会展中心2号馆隆重举行。由广东省金银珠宝玉器业厂商会组织带领粤港澳大湾区优秀珠宝品牌&#xff0c;以“…...

Spring Boot系列之使用Arthas Tunnel Server 进行远程调试实践

Spring Boot系列之使用Arthas Tunnel Server 进行远程调试实践 前言 在开发和运维 Java 应用的过程中&#xff0c;远程诊断和调试是一个不可或缺的需求。尤其是当生产环境出现问题时&#xff0c;能够快速定位并解决这些问题至关重要。Arthas 是阿里巴巴开源的一款强大的 Java…...

ILGPU的核心功能使用详解

什么是ILGPU? ILGPU 是一种用于高性能 GPU 程序的新型 JIT&#xff08;即时&#xff09;编译器 &#xff08;也称为 kernels&#xff09;编写的 .基于 Net 的语言。ILGPU 完全 用 C# 编写&#xff0c;没有任何原生依赖项&#xff0c;允许您编写 GPU 真正可移植的程序。…...

Ubuntu服务器日志满audit:backlog limit exceeded了会报错解决方案-Linux 审计系统 (auditd) 工具

auditd 是 Linux 系统中的审计守护进程&#xff0c;负责收集、记录和监控系统安全相关事件。以下是相关工具及其功能&#xff1a; 核心组件 auditd - 审计守护进程 系统的审计服务主程序 收集系统调用信息并写入日志文件 通常存储在 /var/log/audit/audit.log auditctl - 审计控…...

数据加载与保存

通用方式‌ SparkSQL提供了通用的数据加载方式&#xff0c;使用spark.read.loa方法&#xff0c;并可通过format指定数据类型&#xff08;如csv、jdbc、json、orc、parquet、textFile&#xff09;。 load方法后需传入数据路径&#xff08;针对csv、jdbc、json、orc、parquet、…...

TODO!! IM项目2

感觉似乎部署好了 真不容易 mysql、redis、 rocketmq&#xff08;nameserver、broker&#xff09;、nginx 看代码里是mybatisplus、netty->protobuf协议 现在还发不出去消息 每个密码都要改对 现在可以发消息了但不能at 房间成员也没有 broker内存不够&#xff1f; 从…...

Android ImageView 使用详解

文章目录 一、基本使用1. XML 中声明 ImageView2. Java/Kotlin 中设置图片 二、图片缩放类型 (scaleType)三、加载网络图片1. 使用 Glide (推荐)2. 使用 Picasso 四、高级功能1. 圆形图片2. 圆角图片3. 图片点击缩放动画 五、性能优化六、常见问题解决 ImageView 是 Android 中…...

工资管理系统的主要功能有哪些

工资管理系统通过自动化薪资计算、税务处理、员工数据管理、报表生成等功能&#xff0c;极大地提升了薪资发放的效率和准确性。在传统的人工薪资管理中&#xff0c;HR人员需要手动计算每位员工的薪资&#xff0c;并确保符合税务要求&#xff0c;极易出错且耗时。而现代工资管理…...

WordPiece 详解与示例

WordPiece详解 1. 定义与背景 WordPiece 是一种子词分词算法,由谷歌于2012年提出,最初用于语音搜索系统,后广泛应用于机器翻译和BERT等预训练模型。其核心思想是将单词拆分为更小的子词单元(如词根、前缀/后缀),从而解决传统分词方法面临的词汇表过大和未知词(OOV)处…...

【LeetCode基础算法】滑动窗口与双指针

定长滑动窗口 总结&#xff1a;入-更新-出。 入&#xff1a;下标为 i 的元素进入窗口&#xff0c;更新相关统计量。如果 i<k−1 则重复第一步。 更新&#xff1a;更新答案。一般是更新最大值/最小值。 出&#xff1a;下标为 i−k1 的元素离开窗口&#xff0c;更新相关统计量…...

日本Shopify 3月数据:家居品类销售额激增120%!

2024年第一季度末&#xff0c;电商平台运营商Shopify发布了3月份的最新销售数据&#xff0c;引发业界高度关注。据最新数据显示&#xff0c;日本市场家居品类销售在3月份实现了惊人的增长&#xff0c;同比激增120%&#xff0c;成为该区域增速最快的类目。这一变化不仅映射出日本…...

C语言多进程素数计算

题目描述&#xff1a; 以下代码实现了一个多进程素数计算程序&#xff0c;通过fork()函数创建子进程来并行计算指定范围内的素数。请仔细阅读代码并回答以下问题。 #include "stdio.h" #include "unistd.h" #include <sys/types.h> #include "…...

链表知识回顾

类型&#xff1a;单链表&#xff0c;双链表、循环链表 存储&#xff1a;在内存中不是连续存储 删除操作&#xff1a;即让c的指针指向e即可&#xff0c;无需释放d&#xff0c;因为java中又内存回收机制 添加节点&#xff1a; 链表的构造函数 public class ListNode {// 结点…...

数据库勒索病毒威胁升级:企业数据安全防线如何用安当RDM组件重构

摘要&#xff1a;2025年Q1全球数据库勒索攻击量同比激增101.8%&#xff0c;Cl0p、Akira等团伙通过边缘设备漏洞渗透企业核心系统&#xff0c;制造业、金融业等关键领域面临数据加密与业务停摆双重危机。本文深度解析勒索病毒对数据库的五大毁灭性影响&#xff0c;结合安当RDM防…...

50%时效提升!中巴新航线如何重构ebay跨境电商物流成本?

50%时效提升&#xff01;中巴新航线如何重构eBay跨境电商物流成本&#xff1f; 近年&#xff0c;拉美市场逐步升温&#xff0c;特别是巴西&#xff0c;已成为中国跨境卖家争相布局的新蓝海市场。而随着eBay大力拓展拉美板块&#xff0c;更多卖家开始将目光投向这个人口超2亿、…...

自建 eSIM RSP 服务指南

一、 自建 eSIM RSP 服务的必要性评估 在决定是否自建 RSP&#xff08;远程 SIM 配置&#xff09;服务时&#xff0c;企业需要全面了解其带来的利弊。以下是核心要点&#xff1a; 1. GSMA 安全认证 (SAS-SM) 的重要性 目的: 确保 RSP 服务符合全球移动网络运营商 (MNO) 对安…...

TensorRT模型部署剪枝

TensorRT模型部署剪枝 本文属于学习笔记&#xff0c;在重点章节或代码位置加入个人理解&#xff0c;欢迎批评指正&#xff01; 参考&#xff1a; CUDA与TensorRT部署部署实战第四章 一. Pruning 学习目标 理解什么是模型剪枝模型剪枝的分类&#xff0c;以及各类剪枝的利弊都…...

Servlet 线程安全与并发编程深度解析

Servlet 线程安全与并发编程深度解析 一、Servlet 线程安全机制与风险场景 1.1 Servlet 容器工作原理 单实例多线程模型&#xff1a;每个Servlet在容器中只有一个实例&#xff0c;通过线程池处理并发请求请求处理流程&#xff1a; 接收HTTP请求创建HttpServletRequest和HttpS…...

C++学习:六个月从基础到就业——面向对象编程:封装、继承与多态

C学习&#xff1a;六个月从基础到就业——面向对象编程&#xff1a;封装、继承与多态 本文是我C学习之旅系列的第九篇技术文章&#xff0c;主要讨论C中面向对象编程的三大核心特性&#xff1a;封装、继承与多态。这些概念是理解和应用面向对象设计的关键。查看完整系列目录了解…...

光谱相机的成像方式

光谱相机的成像方式决定了其如何获取物体的空间与光谱信息&#xff0c;核心在于分光技术与扫描模式的结合。以下是主要成像方式的分类解析&#xff1a; ‌一、滤光片切换型‌ ‌1. 滤光片轮&#xff08;Filter Wheel&#xff09;‌ ‌原理‌&#xff1a;通过旋转装有多个窄带…...

Excel 中让表格内容自适应列宽和行高

Excel 中让表格内容自适应列宽和行高 目录 Excel 中让表格内容自适应列宽和行高自适应列宽自适应行高在Excel中让表格内容自适应列宽和行高,可参考以下操作: 自适应列宽 方法一:手动调整 选中需要调整列宽的列(如果是整个表格,可点击表格左上角行号和列号交叉处的三角形全…...

android rtsp 拉流h264 h265,解码nv12转码nv21耗时卡顿问题及ffmpeg优化

一、 背景介绍及问题概述 项目需求需要在rk3568开发板上面&#xff0c;通过rtsp协议拉流的形式获取摄像头预览&#xff0c;然后进行人脸识别 姿态识别等后续其它操作。由于rtsp协议一般使用h.264 h265视频编码格式&#xff08;也叫 AVC 和 HEVC&#xff09;是不能直接用于后续处…...

Day(21)--网络编程

网络编程 在网络通信协议下&#xff0c;不同计算机上运行的程序&#xff0c;进行的数据传输 应用场景&#xff1a;即使通信、网友对战、金融证券等等&#xff0c;不管是什么场景&#xff0c;都是计算机和计算机之间通过网络进行的数据传输 java.net 常见的软件架构 C/S&am…...