精准识别花生豆:基于EfficientNetB0的深度学习检测与分类项目
精准检测花生豆:基于EfficientNet的深度学习分类项目
在现代农业生产中,作物的质量检测和分类是确保产品质量的重要环节。针对花生豆的检测与分类需求,我们开发了一套基于深度学习的解决方案,利用EfficientNetB0模型实现高效、准确的花生豆分类。本博客将详细介绍该项目的背景、数据处理、模型架构、训练过程、评估方法及预测应用。
目录
- 项目背景
- 项目概述
- 数据处理
- 数据集结构
- 数据增强与规范化
- 模型架构
- 训练过程
- 训练脚本 (
train.py)
- 训练脚本 (
- 模型评估
- 评估脚本 (
evaluate.py)
- 评估脚本 (
- 预测与应用
- 预测脚本 (
predict.py)
- 预测脚本 (
- 项目成果
- 结论与未来工作
项目背景
花生豆作为一种重要的经济作物,其品质直接影响到市场价值和消费者满意度。传统的人工检测方法不仅耗时耗力,而且易受主观因素影响,难以实现大规模、精准的分类。因此,开发一种高效、准确的自动化检测系统显得尤为重要。
项目概述
本项目旨在利用深度学习技术,构建一个能够自动检测和分类花生豆的系统。通过收集和处理大量花生豆图像数据,训练一个高性能的卷积神经网络模型,实现对不同类别花生豆的精准分类。项目主要包括以下几个部分:
- 数据处理:图像数据的加载、预处理与增强。
- 模型架构:基于EfficientNetB0的分类模型设计。
- 训练过程:模型的训练与优化,包括断点续训与学习率调度。
- 模型评估:在测试集上的性能评估。
- 预测应用:对新图像进行花生豆分类与标注。
数据处理
数据集结构
项目使用的数据集分为训练集、验证集和测试集,具体结构如下:
./data/dataset/
├── train/
│ ├── baiban/
│ ├── bandian/
│ ├── famei/
│ ├── faya/
│ ├── hongpi/
│ ├── qipao/
│ ├── youwu/
│ └── zhengchang/
├── validation/
│ ├── baiban/
│ ├── bandian/
│ ├── famei/
│ ├── faya/
│ ├── hongpi/
│ ├── qipao/
│ ├── youwu/
│ └── zhengchang/
└── test/├── baiban/├── bandian/├── famei/├── faya/├── hongpi/├── qipao/├── youwu/└── zhengchang/
每个子文件夹对应一种花生豆类别,包含相应的图像数据。
数据增强与规范化
为了提高模型的泛化能力,训练过程中对图像数据进行了多种数据增强操作,如随机裁剪、水平翻转、旋转和颜色抖动。同时,使用ImageNet的均值和标准差对图像进行了归一化处理,与预训练模型的输入要求保持一致。
# utils/dataLoader.pytrain_transform = transforms.Compose([transforms.Resize((image_size, image_size)),transforms.RandomResizedCrop(image_size, scale=(0.8, 1.0)),transforms.RandomHorizontalFlip(),transforms.RandomRotation(15),transforms.ColorJitter(brightness=0.2, contrast=0.2, saturation=0.2, hue=0.1),transforms.ToTensor(),transforms.Normalize(*stats)
])validation_transform = transforms.Compose([transforms.Resize((image_size, image_size)),transforms.CenterCrop(image_size),transforms.ToTensor(),transforms.Normalize(*stats)
])test_transform = transforms.Compose([transforms.Resize((image_size, image_size)),transforms.CenterCrop(image_size),transforms.ToTensor(),transforms.Normalize(*stats)
])
模型架构
本项目采用了EfficientNetB0作为基础模型。EfficientNet系列通过系统性地平衡网络的宽度、深度和分辨率,在模型性能和计算效率之间取得了优异的平衡。具体来说:
- 预训练权重:使用在ImageNet上预训练的权重,帮助模型在较小的数据集上快速收敛。
- 冻结特征提取部分:根据需要,可以选择冻结模型的特征提取层,仅训练最后的分类器,适用于数据量较小的情况。
- 分类器设计:在原有分类器前添加了Dropout层,减少过拟合风险。
# utils/model.pyclass EfficientNetB0(nn.Module):def __init__(self, num_classes, pretrained=True, freeze_features=False):super(EfficientNetB0, self).__init__()if pretrained:self.model = models.efficientnet_b0(weights=models.EfficientNet_B0_Weights.IMAGENET1K_V1)else:self.model = models.efficientnet_b0(weights=None)if freeze_features:for param in self.model.features.parameters():param.requires_grad = Falsein_features = self.model.classifier[1].in_featuresself.model.classifier = nn.Sequential(nn.Dropout(p=0.4, inplace=True),nn.Linear(in_features, num_classes))def forward(self, x):return self.model(x)
训练过程
训练脚本 (train.py)
训练脚本负责模型的训练与验证,包括数据加载、模型初始化、训练循环、学习率调度、模型保存和训练曲线绘制等功能。
关键功能包括:
- 训练与验证循环:每个epoch包括训练阶段和验证阶段,记录损失与准确率。
- 优化与调度:使用Adam优化器和
ReduceLROnPlateau学习率调度器,根据验证损失动态调整学习率。 - 模型保存:保存验证集准确率最高的模型,并定期自动保存模型检查点。
- 断点续训:支持从保存的检查点继续训练,避免重复计算。
- 训练曲线绘制:训练结束后,生成并保存训练与验证的准确率和损失曲线。
# train.pyimport torch
import torch.nn as nn
from utils.dataLoader import load_data
from utils.model import EfficientNetB0
from tqdm import tqdm
import time
import matplotlib.pyplot as plt
import osdef accuracy(predictions, labels):pred = torch.argmax(predictions, dim=1)correct = (pred == labels).sum().item()return correctdef train(net, start_epoch, epochs, train_loader, validation_loader, device, criterion, optimizer, scheduler, model_path, auto_save):# 初始化train_acc_list, validation_acc_list = [], []train_loss_list, validation_loss_list = [], []best_validation_acc = 0net = net.to(device)if start_epoch > 0:print(f"从 epoch {start_epoch} 开始训练。")for epoch in range(start_epoch, epochs):# 训练阶段net.train()train_correct, train_loss, total = 0, 0, 0with tqdm(train_loader, ncols=100, colour='green', desc=f"Train Epoch {epoch+1}/{epochs}") as pbar:for images, labels in pbar:images, labels = images.to(device), labels.to(device)optimizer.zero_grad()outputs = net(images)loss = criterion(outputs, labels)loss.backward()optimizer.step()train_loss += loss.item() * images.size(0)train_correct += accuracy(outputs, labels)total += labels.size(0)pbar.set_postfix({'loss': f"{train_loss / total:.4f}", 'acc': f"{train_correct / total:.4f}"})train_acc = train_correct / totaltrain_loss = train_loss / totaltrain_acc_list.append(train_acc)train_loss_list.append(train_loss)# 验证阶段net.eval()validation_correct, validation_loss, total_validation = 0, 0, 0with torch.no_grad():with tqdm(validation_loader, ncols=100, colour='blue', desc=f"Validation Epoch {epoch+1}/{epochs}") as pbar:for images, labels in pbar:images, labels = images.to(device), labels.to(device)outputs = net(images)loss = criterion(outputs, labels)validation_loss += loss.item() * images.size(0)validation_correct += accuracy(outputs, labels)total_validation += labels.size(0)pbar.set_postfix({'loss': f"{validation_loss / total_validation:.4f}", 'acc': f"{validation_correct / total_validation:.4f}"})validation_acc = validation_correct / total_validationvalidation_loss = validation_loss / total_validationvalidation_acc_list.append(validation_acc)validation_loss_list.append(validation_loss)# 更新学习率scheduler.step(validation_loss)# 保存最佳模型if validation_acc > best_validation_acc:best_validation_acc = validation_acccheckpoint = {'epoch': epoch,'model_state_dict': net.state_dict(),'optimizer_state_dict': optimizer.state_dict(),'scheduler_state_dict': scheduler.state_dict(),'validation_acc': best_validation_acc}torch.save(checkpoint, model_path)print(f"保存最佳模型,验证准确率: {best_validation_acc:.4f}")# 自动保存模型if (epoch + 1) % auto_save == 0:save_path = model_path.replace('.pth', f'_epoch{epoch+1}.pth')checkpoint = {'epoch': epoch,'model_state_dict': net.state_dict(),'optimizer_state_dict': optimizer.state_dict(),'scheduler_state_dict': scheduler.state_dict(),'validation_acc': best_validation_acc}torch.save(checkpoint, save_path)print(f"自动保存模型到 {save_path}")# 绘制训练曲线def plot_training_curves(train_acc_list, validation_acc_list, train_loss_list, validation_loss_list, epochs):plt.figure(figsize=(12, 5))plt.subplot(1, 2, 1)plt.plot(range(1, epochs+1), train_acc_list, 'bo-', label="训练准确率")plt.plot(range(1, epochs+1), validation_acc_list, 'ro-', label="验证准确率")plt.title("训练准确率 vs 验证准确率")plt.xlabel("轮次")plt.ylabel("准确率")plt.legend()plt.subplot(1, 2, 2)plt.plot(range(1, epochs+1), train_loss_list, 'bo-', label="训练损失")plt.plot(range(1, epochs+1), validation_loss_list, 'ro-', label="验证损失")plt.title("训练损失 vs 验证损失")plt.xlabel("轮次")plt.ylabel("损失")plt.legend()os.makedirs('logs', exist_ok=True)plt.savefig('logs/training_curve.png')plt.show()plot_training_curves(train_acc_list, validation_acc_list, train_loss_list, validation_loss_list, epochs)if __name__ == '__main__':batch_size = 64image_size = 224classes_num = 8num_epochs = 100auto_save = 10lr = 1e-4weight_decay = 1e-4device = 'cuda' if torch.cuda.is_available() else 'cpu'classify = {'baiban': 0, 'bandian': 1, 'famei': 2, 'faya': 3, 'hongpi': 4, 'qipao': 5, 'youwu': 6, 'zhengchang': 7}train_loader, validation_loader, test_loader = load_data(batch_size, image_size, classify)net = EfficientNetB0(classes_num, pretrained=True, freeze_features=False)model_path = 'model_weights/EfficientNetB0.pth'os.makedirs('model_weights', exist_ok=True)criterion = nn.CrossEntropyLoss()optimizer = torch.optim.Adam(net.parameters(), lr=lr, weight_decay=weight_decay)scheduler = torch.optim.lr_scheduler.ReduceLROnPlateau(optimizer, mode='min', factor=0.1, patience=10, verbose=True)# 检查点续训start_epoch = 0best_validation_acc = 0if os.path.exists(model_path):try:checkpoint = torch.load(model_path, map_location=device)required_keys = ['model_state_dict', 'optimizer_state_dict', 'scheduler_state_dict', 'epoch', 'validation_acc']if all(key in checkpoint for key in required_keys):net.load_state_dict(checkpoint['model_state_dict'])optimizer.load_state_dict(checkpoint['optimizer_state_dict'])scheduler.load_state_dict(checkpoint['scheduler_state_dict'])start_epoch = checkpoint['epoch'] + 1best_validation_acc = checkpoint['validation_acc']print(f"从 epoch {checkpoint['epoch']} 继续训练,最佳验证准确率: {best_validation_acc:.4f}")else:print(f"检查点文件缺少必要的键,开始从头训练。")except Exception as e:print(f"加载检查点时发生错误: {e}")print("开始从头训练。")print("训练开始")time_start = time.time()train(net, start_epoch, num_epochs, train_loader, validation_loader, device=device, criterion=criterion, optimizer=optimizer, scheduler=scheduler, model_path=model_path, auto_save=auto_save)time_end = time.time()seconds = time_end - time_startm, s = divmod(seconds, 60)h, m = divmod(m, 60)print("训练结束")print("本次训练时长为:%02d:%02d:%02d" % (h, m, s))
主要特点:
- 进度条可视化:使用
tqdm库实时展示训练和验证进度。 - 断点续训:支持从上一次中断的epoch继续训练,确保训练过程的连续性。
- 自动保存:定期保存模型检查点,防止意外中断导致的训练损失。
- 训练曲线:生成并保存训练与验证的准确率和损失曲线,便于后续分析与调优。
模型评估
评估脚本 (evaluate.py)
评估脚本用于在测试集上评估训练好的模型性能,计算准确率和损失,并将结果保存到文件中。
# evaluate.pyimport torch
import torch.nn as nn
from utils.dataLoader import load_data
from utils.model import EfficientNetB0
from tqdm import tqdm
import osdef accuracy(predictions, labels):pred = torch.argmax(predictions, dim=1)correct = (pred == labels).sum().item()return correctdef evaluate(net, test_loader, device, criterion, output_path):net.eval()test_correct, test_loss, total_test = 0, 0, 0with torch.no_grad():with tqdm(test_loader, ncols=100, colour='blue', desc=f"Evaluating on Test Set") as pbar:for images, labels in pbar:images, labels = images.to(device), labels.to(device)outputs = net(images)loss = criterion(outputs, labels)test_loss += loss.item() * images.size(0)test_correct += accuracy(outputs, labels)total_test += labels.size(0)pbar.set_postfix({'loss': f"{test_loss / total_test:.4f}", 'acc': f"{test_correct / total_test:.4f}"})test_acc = test_correct / total_testtest_loss = test_loss / total_testresult = f"测试集准确率: {test_acc:.4f}, 测试集损失: {test_loss:.4f}"print(result)# 保存结果到文件os.makedirs(os.path.dirname(output_path), exist_ok=True)with open(output_path, 'a') as f:f.write(result + '\n')if __name__ == '__main__':batch_size = 64image_size = 224classes_num = 8device = 'cuda' if torch.cuda.is_available() else 'cpu'classify = {'baiban': 0, 'bandian': 1, 'famei': 2, 'faya': 3, 'hongpi': 4, 'qipao': 5, 'youwu': 6, 'zhengchang': 7}_, _, test_loader = load_data(batch_size, image_size, classify)net = EfficientNetB0(classes_num, pretrained=False)model_path = 'model_weights/EfficientNetB0.pth'if not os.path.exists(model_path):print(f"模型权重文件 {model_path} 不存在,请先训练模型。")exit()net.load_state_dict(torch.load(model_path, map_location=device))net.to(device)criterion = nn.CrossEntropyLoss()evaluation_output_path = 'outputs/evaluation_results.txt'# 清空之前的评估结果if os.path.exists(evaluation_output_path):os.remove(evaluation_output_path)print("评估开始")evaluate(net, test_loader, device=device, criterion=criterion, output_path=evaluation_output_path)print("评估结束")
评估流程:
- 加载模型:从保存的权重文件中加载训练好的模型。
- 模型评估:在测试集上计算模型的准确率和损失。
- 结果保存:将评估结果保存到指定的输出文件中,便于后续查看与分析。
预测与应用
预测脚本 (predict.py)
预测脚本用于对新图像进行花生豆分类,并在图像上标注分类结果和边框。
# predict.pyimport os
import cv2
import numpy as np
import torch
from PIL import Image
from utils.model import EfficientNetB0
from torchvision import transformsdef delet_contours(contours, delete_list):delta = 0for i in range(len(delete_list)):del contours[delete_list[i] - delta]delta += 1return contoursdef main():input_path = 'data/pic'output_dir = 'outputs/predicted_images'os.makedirs(output_dir, exist_ok=True)image_files = os.listdir(input_path)classify = {0: 'baiban', 1: 'bandian', 2: 'famei', 3: 'faya', 4: 'hongpi', 5: 'qipao', 6: 'youwu', 7: 'zhengchang'}# 与训练时相同的预处理transform = transforms.Compose([transforms.Resize((224, 224)),transforms.ToTensor(),transforms.Normalize(mean=(0.485, 0.456, 0.406), # ImageNet均值std=(0.229, 0.224, 0.225)) # ImageNet标准差])device = 'cuda' if torch.cuda.is_available() else 'cpu'net = EfficientNetB0(8, pretrained=False)model_path = 'model_weights/EfficientNetB0.pth'if not os.path.exists(model_path):print(f"模型权重文件 {model_path} 不存在,请先训练模型。")returnnet.load_state_dict(torch.load(model_path, map_location=device))net.to(device)net.eval()min_size = 30max_size = 400for img_name in image_files:img_path = os.path.join(input_path, img_name)img = cv2.imread(img_path)if img is None:print(f"无法读取图像: {img_path}")continuehsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) # 转换到HSV颜色空间# 根据HSV颜色范围进行掩膜操作(根据实际情况调整颜色范围)lower_blue = np.array([100, 100, 8])upper_blue = np.array([255, 255, 255])mask = cv2.inRange(hsv, lower_blue, upper_blue) # 创建掩膜result = cv2.bitwise_and(img, img, mask=mask) # 应用掩膜result = result.astype(np.uint8)# 转换为灰度图并二值化gray = cv2.cvtColor(result, cv2.COLOR_BGR2GRAY)_, binary_image = cv2.threshold(gray, 1, 255, cv2.THRESH_BINARY)# 查找轮廓contours, _ = cv2.findContours(binary_image, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)contours = list(contours)# 过滤轮廓delete_list = []for idx, contour in enumerate(contours):perimeter = cv2.arcLength(contour, True)if perimeter < min_size or perimeter > max_size:delete_list.append(idx)contours = delet_contours(contours, delete_list)# 对每个轮廓进行分类for contour in contours:x, y, w, h = cv2.boundingRect(contour)crop = img[y:y+h, x:x+w]if crop.size == 0:continuecrop_pil = Image.fromarray(cv2.cvtColor(crop, cv2.COLOR_BGR2RGB))crop_tensor = transform(crop_pil).unsqueeze(0).to(device)with torch.no_grad():output = net(crop_tensor)pred = torch.argmax(output, dim=1).item()label = classify[pred]# 标注图像cv2.putText(img, label, (x, y-10), cv2.FONT_HERSHEY_SIMPLEX, 0.9, (36,255,12), 2)cv2.rectangle(img, (x, y), (x + w, y + h), (0, 0, 255), 2)# 保存结果图像到outputs/predicted_images/output_image_path = os.path.join(output_dir, f"{os.path.splitext(img_name)[0]}_predicted.jpg")cv2.imwrite(output_image_path, img)print(f"保存预测结果到 {output_image_path}")print("所有图像的预测和标注已完成并保存到 ./outputs/predicted_images/")if __name__ == '__main__':main()
预测流程:
- 图像预处理:将输入图像转换到HSV颜色空间,应用颜色掩膜提取花生豆区域。
- 轮廓检测与过滤:查找并过滤不符合大小要求的轮廓,确保只处理有效的花生豆区域。
- 分类与标注:对每个有效轮廓进行裁剪、预处理,并使用训练好的模型进行分类。在图像上标注分类结果和边框。
- 结果保存:将标注后的图像保存到指定的输出目录。
预测结果






项目成果
通过本项目,我们成功构建了一个能够高效、准确地检测和分类花生豆的深度学习模型。主要成果包括:
- 高准确率:模型在测试集上达到了令人满意的分类准确率。
- 自动化检测:实现了对新图像的自动检测与分类,大大提高了检测效率。
- 可视化结果:通过图像标注,直观展示了分类结果,便于用户理解和应用。
训练与验证的准确率和损失曲线示例

开源的程序及数据集
git clone https://gitee.com/songaoxiangsoar/peanut-bean-testing.git
结论与未来工作
本项目展示了基于深度学习的花生豆检测与分类的可行性与有效性。通过采用预训练的EfficientNetB0模型,并结合数据增强与优化策略,模型在花生豆分类任务中表现出色。
未来的工作方向包括:
- 模型优化:尝试更深更复杂的模型,如EfficientNetB7,以进一步提升分类性能。
- 数据扩展:收集更多多样化的花生豆图像,增强模型的泛化能力。
- 实时检测:优化模型推理速度,实现实时花生豆检测与分类。
- 部署应用:将模型集成到移动设备或嵌入式系统,便于现场检测与应用。
通过持续的优化与扩展,我们相信这一系统将在农业生产中发挥更大的价值,助力智能农业的发展。
感谢阅读本博客!如果您对本项目有任何疑问或建议,欢迎在下方留言交流。
相关文章:
精准识别花生豆:基于EfficientNetB0的深度学习检测与分类项目
精准检测花生豆:基于EfficientNet的深度学习分类项目 在现代农业生产中,作物的质量检测和分类是确保产品质量的重要环节。针对花生豆的检测与分类需求,我们开发了一套基于深度学习的解决方案,利用EfficientNetB0模型实现高效、准…...
【UE5 C++课程系列笔记】13——GameInstanceSubsystem的简单使用
目录 概念 基本使用案例 效果 步骤 概念 UGameInstanceSubsystem 类继承自 USubsystem,它与 GameInstance 紧密关联,旨在为游戏提供一种模块化、可方便扩展和管理的功能单元机制。在整个游戏运行期间,一个 GameInstance 可以包含多个 UGa…...
实用工具推荐----Doxygen使用方法
目录 目录 1 软件介绍 2 Doxygen软件下载方法 3 Doxygen软件配置方法 4 标准注释描述 4.1 块注释 和 特殊描述字符 4.1.1 函数描述示例 4.1.2结构体数组变量示例 特别注意: 4.2单行注释 4.2.1 单个变量注释示例 特别注意: 4.2.2对于枚举变量…...
js垃圾回收机制详细讲解
JavaScript 垃圾回收机制(Garbage Collection, GC)负责自动管理内存的分配和释放,确保程序在运行时不会因为内存泄漏而崩溃。它的主要任务是回收不再使用的内存空间,防止内存泄漏。JavaScript 的垃圾回收通常由引擎自动完成&#…...
【Linux/踩坑】Linux中启动eclipse或HDFS因JAVA_HOME设置报错
Linux中启动eclipse或hadoop因JAVA_HOME设置报错 eclipseHadoop eclipse 错误提示: A Java Runtime Environment (JRE) or Java Development Kit (JDK) must be available in order to run Eclipse. No Java virtual machine was found after searching the follo…...
百度千帆平台构建AI APP的基础概念梳理
百度千帆平台构建AI APP的基础概念梳理 如果想制作大语言模型(LLM)相关的APP, 将利用百度的千帆平台在国内可能是最便捷的途径,因为百度开发了成熟的工作流,前些年还有些不稳定,现在固定下来了,…...
Unity3D Huatuo技术原理剖析详解
前言 在游戏开发领域,Unity3D凭借其强大的跨平台能力和丰富的功能,成为了众多开发者的首选工具。而在Unity3D的生态系统中,Huatuo作为一款重要的插件,为游戏开发带来了极大的便利。本文将深入剖析Huatuo的技术原理,并…...
记Fastjson2的一个报ConcurrentModificationException的bug
错误背景:fastjson2的parseObject方法,在spring webflux项目中被调用,有时会报java.util.ConcurrentModificationException错误。报错处的代码如下图: 改了半天与并发安全相关的代码,还是会报此错误。后来改变思路搜…...
使用TimesFM 对车辆销售进行预测
代码功能概述 导入相关包与设置环境变量: 首先导入了如 os、numpy、pandas 等常用的 Python 库,同时设置了一些与特定库(如 XLA_PYTHON_CLIENT_PREALLOCATE 和 JAX_PM AP_USE_TENSORSTORE)相关的环境变量,用于优化计算…...
OpenEuler 22.03 不依赖zookeeper安装 kafka 3.3.2集群
零:规划 本次计划安装三台OpenEuler 22.03 版本操作系统的服务器,用于搭建 kafka和flink 集群。因为从kafka 2.8 版本以后开始不依赖 zookeeper ,同时考虑到需要找一个发布时间早于 flink 1.17 的kafka 版本且应尽量稳定,综合考虑…...
ubuntu 将python3.8 升级为python3.10并进行版本切换
ubuntu 将python3.8 升级为python3.10并进行版本切换 前言将python3.8 升级为3.10安装pippython版本切换 前言 有一个功能包编译环境需要为python3.10 ,但是当前环境为python3.8 ,所以需要进行版本升级,编译完还需要把环境切换回来。 将pyt…...
3. Kafka入门—安装与基本命令
Kafka基础操作 一. 章节简介二. kafka简介三. Kafka安装1. 准备工作2. Zookeeper安装2.1 配置文件2.2 启动相关命令3. Kafka安装3.1 配置文件3.2 启动相关命令-------------------------------------------------------------------------------------------------------------…...
如何使用 python创建图片格式转换器
在本篇博客中,我们将通过一个简单的实例来展示如何使用 wxPython 创建一个图形用户界面(GUI)应用程序,用于将图片从一种格式转换为另一种格式。我们将通过以下几个步骤实现这一目标: C:\pythoncode\new\imageconvertty…...
命令行之巅:Linux Shell编程的至高艺术(上)
文章一览 前言一、shell概述1.1 shell的特点和类型1.1.1 **shell的特点:**1.1.2 常用shell类型 1.2 shell脚本的建立和执行1.2.1 建立shell脚本1.2.2 执行shell脚本的方式1.2.3 shell程序实例 二、shell变量与算数运算2.1 简单shell变量2.1.1 简单变量定义和赋值2.1…...
【gulp】gulp 的基本使用
gulp 是一个基于node的自动化打包构建工具,前端开发者可以使用它来处理常见任务: 创建项目 进入项目 npm init -ynpm i gulp -g (使用命令 gulp)npm i gulp -D # 开发依赖(前端工具都是开发依赖 本地安装 代…...
Linux 下处理 ^M 字符的最佳实践
Linux 下处理 ^M 字符的最佳实践 一、快速解决方案 按照优先级排序的三种解决方案: 1. 使用 dos2unix(推荐) # 安装 sudo apt-get install dos2unix # Ubuntu/Debian sudo yum install dos2unix # CentOS# 使用 dos2unix 文件名2. 使用 sed sed...
【优选算法】—复写零(双指针算法)
云边有个稻草人-CSDN博客 每天至少一道算法题,接着干,以额现在的实力想完成那个目标确实难。算法题确实烧脑,挺煎熬的,但脑子烧多了是不是就该好些了?。。。 记得那句话,必须有为成功付出代价的决心&#x…...
2024国赛A问题三和四
问题三 最小螺距单目标优化模型的建立 问题二考虑了在螺距固定的条件下计算舞龙队盘入的终止时间,问题三在第二问的基础提出了改变螺距的要求,即求解在螺距最小为多少时,龙头前把手能够沿着相应的螺线盘入到调头空间的边界。故可将其转换为…...
asp.net 高校学生勤工俭学系统设计与实现
博主介绍:专注于Java(springboot ssm 等开发框架) vue .net php python(flask Django) 小程序 等诸多技术领域和毕业项目实战、企业信息化系统建设,从业十五余年开发设计教学工作 ☆☆☆ 精彩专栏推荐订阅☆☆☆☆☆不然下次找…...
《计算机组成及汇编语言原理》阅读笔记:p116-p120
《计算机组成及汇编语言原理》学习第 7 天,p116-p120 总结,总计 5 页。 一、技术总结 1.CPU优化 (1)increase overall performance number 例如:16位电脑提升到32位电脑。 (2)multiprocessing One way to make computers more useful i…...
Python|GIF 解析与构建(5):手搓截屏和帧率控制
目录 Python|GIF 解析与构建(5):手搓截屏和帧率控制 一、引言 二、技术实现:手搓截屏模块 2.1 核心原理 2.2 代码解析:ScreenshotData类 2.2.1 截图函数:capture_screen 三、技术实现&…...
第19节 Node.js Express 框架
Express 是一个为Node.js设计的web开发框架,它基于nodejs平台。 Express 简介 Express是一个简洁而灵活的node.js Web应用框架, 提供了一系列强大特性帮助你创建各种Web应用,和丰富的HTTP工具。 使用Express可以快速地搭建一个完整功能的网站。 Expre…...
TDengine 快速体验(Docker 镜像方式)
简介 TDengine 可以通过安装包、Docker 镜像 及云服务快速体验 TDengine 的功能,本节首先介绍如何通过 Docker 快速体验 TDengine,然后介绍如何在 Docker 环境下体验 TDengine 的写入和查询功能。如果你不熟悉 Docker,请使用 安装包的方式快…...
el-switch文字内置
el-switch文字内置 效果 vue <div style"color:#ffffff;font-size:14px;float:left;margin-bottom:5px;margin-right:5px;">自动加载</div> <el-switch v-model"value" active-color"#3E99FB" inactive-color"#DCDFE6"…...
大模型多显卡多服务器并行计算方法与实践指南
一、分布式训练概述 大规模语言模型的训练通常需要分布式计算技术,以解决单机资源不足的问题。分布式训练主要分为两种模式: 数据并行:将数据分片到不同设备,每个设备拥有完整的模型副本 模型并行:将模型分割到不同设备,每个设备处理部分模型计算 现代大模型训练通常结合…...
JDK 17 新特性
#JDK 17 新特性 /**************** 文本块 *****************/ python/scala中早就支持,不稀奇 String json “”" { “name”: “Java”, “version”: 17 } “”"; /**************** Switch 语句 -> 表达式 *****************/ 挺好的ÿ…...
华为云Flexus+DeepSeek征文|DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建
华为云FlexusDeepSeek征文|DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建 前言 如今大模型其性能出色,华为云 ModelArts Studio_MaaS大模型即服务平台华为云内置了大模型,能助力我们轻松驾驭 DeepSeek-V3/R1,本文中将分享如何…...
Pinocchio 库详解及其在足式机器人上的应用
Pinocchio 库详解及其在足式机器人上的应用 Pinocchio (Pinocchio is not only a nose) 是一个开源的 C 库,专门用于快速计算机器人模型的正向运动学、逆向运动学、雅可比矩阵、动力学和动力学导数。它主要关注效率和准确性,并提供了一个通用的框架&…...
Redis的发布订阅模式与专业的 MQ(如 Kafka, RabbitMQ)相比,优缺点是什么?适用于哪些场景?
Redis 的发布订阅(Pub/Sub)模式与专业的 MQ(Message Queue)如 Kafka、RabbitMQ 进行比较,核心的权衡点在于:简单与速度 vs. 可靠与功能。 下面我们详细展开对比。 Redis Pub/Sub 的核心特点 它是一个发后…...
算法:模拟
1.替换所有的问号 1576. 替换所有的问号 - 力扣(LeetCode) 遍历字符串:通过外层循环逐一检查每个字符。遇到 ? 时处理: 内层循环遍历小写字母(a 到 z)。对每个字母检查是否满足: 与…...
