學習記錄 6 pointnet復現

一、復現代碼

然后去找相關的2d的聲吶圖像分類的算法

融合可以搞的,雖然有文獻但是不多,感覺也是可以的

"""
Author: Benny
Date: Nov 2019
"""import os
import sys
import torch
import numpy as npimport datetime
import logging
import provider
import importlib
import shutil
import argparsefrom pathlib import Path
from tqdm import tqdm
from data_utils.ModelNetDataLoader import ModelNetDataLoaderBASE_DIR = os.path.dirname(os.path.abspath(__file__))
ROOT_DIR = BASE_DIR
sys.path.append(os.path.join(ROOT_DIR, 'models'))
#隨機種子 seed
#測試驗證的時候,只跑一次結果,還是【投票跑3次取平均】
#點云分類有兩個指標,一個是總體的分類準確率,另一個是類平均準確率
#是選擇最好的作為結果還是【用自己的保存的最好的模型的函數(沒聽懂)】
def parse_args():'''PARAMETERS'''parser = argparse.ArgumentParser('training')parser.add_argument('--use_cpu', action='store_true', default=False, help='use cpu mode')parser.add_argument('--gpu', type=str, default='0', help='specify gpu device')parser.add_argument('--batch_size', type=int, default=24, help='batch size in training')parser.add_argument('--model', default='pointnet_cls', help='model name [default: pointnet_cls]')parser.add_argument('--num_category', default=40, type=int, choices=[10, 40],  help='training on ModelNet10/40')parser.add_argument('--epoch', default=200, type=int, help='number of epoch in training')parser.add_argument('--learning_rate', default=0.001, type=float, help='learning rate in training')parser.add_argument('--num_point', type=int, default=1024, help='Point Number')parser.add_argument('--optimizer', type=str, default='Adam', help='optimizer for training')parser.add_argument('--log_dir', type=str, default=None, help='experiment root')parser.add_argument('--decay_rate', type=float, default=1e-4, help='decay rate')parser.add_argument('--use_normals', action='store_true', default=False, help='use normals')parser.add_argument('--process_data', action='store_true', default=False, help='save data offline')parser.add_argument('--use_uniform_sample', action='store_true', default=False, help='use uniform sampiling')return parser.parse_args()def inplace_relu(m):classname = m.__class__.__name__if classname.find('ReLU') != -1:m.inplace=Truedef test(model, loader, num_class=40):mean_correct = []class_acc = np.zeros((num_class, 3))classifier = model.eval()for j, (points, target) in tqdm(enumerate(loader), total=len(loader)):if not args.use_cpu:points, target = points.cuda(), target.cuda()points = points.transpose(2, 1)pred, _ = classifier(points)pred_choice = pred.data.max(1)[1]for cat in np.unique(target.cpu()):classacc = pred_choice[target == cat].eq(target[target == cat].long().data).cpu().sum()class_acc[cat, 0] += classacc.item() / float(points[target == cat].size()[0])class_acc[cat, 1] += 1correct = pred_choice.eq(target.long().data).cpu().sum()mean_correct.append(correct.item() / float(points.size()[0]))class_acc[:, 2] = class_acc[:, 0] / class_acc[:, 1]class_acc = np.mean(class_acc[:, 2])instance_acc = np.mean(mean_correct)return instance_acc, class_accdef main(args):def log_string(str):logger.info(str)print(str)'''HYPER PARAMETER'''os.environ["CUDA_VISIBLE_DEVICES"] = args.gpu'''CREATE DIR'''timestr = str(datetime.datetime.now().strftime('%Y-%m-%d_%H-%M'))exp_dir = Path('./log/')exp_dir.mkdir(exist_ok=True)exp_dir = exp_dir.joinpath('classification')exp_dir.mkdir(exist_ok=True)if args.log_dir is None:exp_dir = exp_dir.joinpath(timestr)else:exp_dir = exp_dir.joinpath(args.log_dir)exp_dir.mkdir(exist_ok=True)checkpoints_dir = exp_dir.joinpath('checkpoints/')checkpoints_dir.mkdir(exist_ok=True)log_dir = exp_dir.joinpath('logs/')log_dir.mkdir(exist_ok=True)'''LOG'''args = parse_args()logger = logging.getLogger("Model")logger.setLevel(logging.INFO)formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')file_handler = logging.FileHandler('%s/%s.txt' % (log_dir, args.model))file_handler.setLevel(logging.INFO)file_handler.setFormatter(formatter)logger.addHandler(file_handler)log_string('PARAMETER ...')log_string(args)'''DATA LOADING'''log_string('Load dataset ...')data_path = 'data/modelnet40_normal_resampled/'train_dataset = ModelNetDataLoader(root=data_path, args=args, split='train', process_data=args.process_data)test_dataset = ModelNetDataLoader(root=data_path, args=args, split='test', process_data=args.process_data)trainDataLoader = torch.utils.data.DataLoader(train_dataset, batch_size=args.batch_size, shuffle=True, num_workers=10, drop_last=True)testDataLoader = torch.utils.data.DataLoader(test_dataset, batch_size=args.batch_size, shuffle=False, num_workers=10)'''MODEL LOADING'''num_class = args.num_categorymodel = importlib.import_module(args.model)shutil.copy('./models/%s.py' % args.model, str(exp_dir))shutil.copy('models/pointnet2_utils.py', str(exp_dir))shutil.copy('./train_classification.py', str(exp_dir))classifier = model.get_model(num_class, normal_channel=args.use_normals)criterion = model.get_loss()classifier.apply(inplace_relu)if not args.use_cpu:classifier = classifier.cuda()criterion = criterion.cuda()try:checkpoint = torch.load(str(exp_dir) + '/checkpoints/best_model.pth')start_epoch = checkpoint['epoch']classifier.load_state_dict(checkpoint['model_state_dict'])log_string('Use pretrain model')except:log_string('No existing model, starting training from scratch...')start_epoch = 0if args.optimizer == 'Adam':optimizer = torch.optim.Adam(classifier.parameters(),lr=args.learning_rate,betas=(0.9, 0.999),eps=1e-08,weight_decay=args.decay_rate)else:optimizer = torch.optim.SGD(classifier.parameters(), lr=0.01, momentum=0.9)scheduler = torch.optim.lr_scheduler.StepLR(optimizer, step_size=20, gamma=0.7)global_epoch = 0global_step = 0best_instance_acc = 0.0best_class_acc = 0.0'''TRANING'''logger.info('Start training...')for epoch in range(start_epoch, args.epoch):log_string('Epoch %d (%d/%s):' % (global_epoch + 1, epoch + 1, args.epoch))mean_correct = []classifier = classifier.train()scheduler.step()for batch_id, (points, target) in tqdm(enumerate(trainDataLoader, 0), total=len(trainDataLoader), smoothing=0.9):optimizer.zero_grad()points = points.data.numpy()points = provider.random_point_dropout(points)points[:, :, 0:3] = provider.random_scale_point_cloud(points[:, :, 0:3])points[:, :, 0:3] = provider.shift_point_cloud(points[:, :, 0:3])points = torch.Tensor(points)points = points.transpose(2, 1)if not args.use_cpu:points, target = points.cuda(), target.cuda()pred, trans_feat = classifier(points)loss = criterion(pred, target.long(), trans_feat)pred_choice = pred.data.max(1)[1]correct = pred_choice.eq(target.long().data).cpu().sum()mean_correct.append(correct.item() / float(points.size()[0]))loss.backward()optimizer.step()global_step += 1train_instance_acc = np.mean(mean_correct)log_string('Train Instance Accuracy: %f' % train_instance_acc)with torch.no_grad():instance_acc, class_acc = test(classifier.eval(), testDataLoader, num_class=num_class)if (instance_acc >= best_instance_acc):best_instance_acc = instance_accbest_epoch = epoch + 1if (class_acc >= best_class_acc):best_class_acc = class_acclog_string('Test Instance Accuracy: %f, Class Accuracy: %f' % (instance_acc, class_acc))log_string('Best Instance Accuracy: %f, Class Accuracy: %f' % (best_instance_acc, best_class_acc))if (instance_acc >= best_instance_acc):logger.info('Save model...')savepath = str(checkpoints_dir) + '/best_model.pth'log_string('Saving at %s' % savepath)state = {'epoch': best_epoch,'instance_acc': instance_acc,'class_acc': class_acc,'model_state_dict': classifier.state_dict(),'optimizer_state_dict': optimizer.state_dict(),}torch.save(state, savepath)global_epoch += 1logger.info('End of training...')if __name__ == '__main__':args = parse_args()main(args)

?具體進程:

1、虛擬環境

anaconda prompt :

---conda create -n pointnet python=3.7

---conda install pytorch==1.6.0 cudatoolkit=10.1 -c pytorch

2、pycharm

設置環境

3、數據

在pointnet文件夾下新建data文件,將40數據放到data文件夾下

4、代碼

修改代碼參數運行

5、運行結果

訓練

C:\Users\229\anaconda3\envs\pointnet\python.exe D:\pycharm\Pointnet_Pointnet2_pytorch-master\train_classification.py 
PARAMETER ...
Namespace(batch_size=8, decay_rate=0.0001, epoch=1, gpu='0', learning_rate=0.001, log_dir='pointnet2_cls_ssg', model='pointnet2_cls_ssg', num_category=40, num_point=1024, optimizer='Adam', process_data=False, use_cpu=False, use_normals=False, use_uniform_sample=False)
Load dataset ...
The size of train data is 9843
The size of test data is 2468
No existing model, starting training from scratch...
Epoch 1 (1/1):
100%|██████████| 1230/1230 [09:21<00:00,  2.19it/s]
Train Instance Accuracy: 0.448069
100%|██████████| 309/309 [02:12<00:00,  2.34it/s]
Test Instance Accuracy: 0.652508, Class Accuracy: 0.532580
Best Instance Accuracy: 0.652508, Class Accuracy: 0.532580
Saving at log\classification\pointnet2_cls_ssg\checkpoints/best_model.pth

測試

PARAMETER ...
Namespace(batch_size=24, gpu='0', log_dir='pointnet2_cls_ssg', num_category=40, num_point=1024, num_votes=3, use_cpu=False, use_normals=False, use_uniform_sample=False)
Load dataset ...
The size of test data is 2468
100%|██████████| 103/103 [02:39<00:00,  1.55s/it]
Test Instance Accuracy: 0.650485, Class Accuracy: 0.527661

?

二、論文

基于深度學習的點云配準的最新進展改進了泛化,但大多數方法仍然需要針對每個新環境進行重新訓練或手動參數調整。

在實踐中,大多數現有方法仍然要求用戶在未知數據集環境的情況下提供最佳參數->所以要針對不同的場景(室內和室外)進行泛化

限制泛化的三個關鍵因素:

(a) 依賴于特定于環境的體素大小和搜索半徑

(b)基于學習的關鍵點檢測器在域外情況的魯棒性較差

(c) 原始坐標使用

目標:估計兩個無序的三維點云 P 和 Q 之間的相對三維旋轉矩陣 R和平移向量 t

BUFFER-X方法

(a) 自適應地確定體素大小和搜索半徑

1)基于球形度的體素化——v

h(P,Q)根據點的數量選擇較大點云

g(P,δ) 是一個從點云 P 中隨機采樣 δ% 點的函數

C是 g(h(P,Q),δv) 的協方差矩陣,δv是定義的采樣率

然后使用PCA計算三個特征值和對應的特征向量:Cva?=λa?va?

假設λ1?≥λ2?≥λ3,則球形度為λ3/λ1

通常來講雷達的球形度低于rgb-d相機的

所以有:

其中s 表示點云沿最小特征值 v3? 對應的特征向量方向的分布范圍

2)基于密度感知的半徑估計

搜索半徑在local、中間和全局三個尺度上分別進行估計,以捕捉不同尺度下的特征信息

設 N(pq?,P,r) 為點 pq? 在點云 P 中,以 r 為半徑的鄰域內的點集,定義為:

半徑的計算,τξ? 是用戶定義的閾值,表示期望的鄰域密度(即鄰域點相對于總點數的平均比例)

?

?

τl? ≤ τm ?≤ τg?,相應地,rl? ≤ rm ?≤ rg?(半徑和期望密度的關系

(b) 多尺度

1)最遠點采樣

我們在每個尺度上使用最遠點采樣(FPS)從 P 中采樣 Pξ?(分別從 Q 中采樣 Qξ?),以避免使用基于學習的關鍵點檢測器。需要注意的是,我們為每個尺度獨立采樣不同的點,這是因為不同區域可能需要不同的尺度來進行最佳特征提取

2)基于Mini-SpinNet的描述符生成

我們通過除以 rξ 將每個塊中的點的尺度歸一化到有界范圍 [?1,1]來確保尺度的一致性,然后

將塊的大小固定為 Npatch?,將這些歸一化的塊作為輸入,Mini-SpinNet輸出一個超集 SPξ??,包含 D 維特征向量 FPξ?? 和圓柱形特征圖 CPξ??,對應于 Pξ?(分別地,SQξ?? 包含 FQξ?? 和 CQξ?? 來自 Qξ?)

BUFFER使用學習到的參考軸來提取圓柱坐標,我們的方法通過將PCA應用于塊內點的協方差來定義每個塊的參考軸,將 z 方向設置為 v3?(協方差對應的特征向量)

(c) 分層內點搜索

1)在 FPξ?? 和 FQξ?? 之間進行基于最近鄰的雙向匹配,得到每個尺度上的匹配對應關系 Aξ?

2)成對變換估計

計算R和t

3)使用所有尺度上的每對 (R,t) 估計值,選擇具有最大基數的3D點對,確保跨尺度一致性,通過共識最大化問題來選擇最終的內點對應關系

4)最終,將 I 作為輸入,使用求解器(如 RANSAC)估計最終的相對旋轉 R^ 和平移 t^?







三、

正則化層——加快神經網絡的訓練速度

線性層——

torch.reshape是什么東西捏,感覺只能理解一個大概

神經網絡搭建:

from torch import nn
from torch.nn import Conv2d, MaxPool2d, Flatten, Linearclass Tudui(nn.Module):def __init__(self):super(Tudui, self).__init__()self.conv1 = Conv2d(in_channels=3, out_channels=32, kernel_size=5, stride=1, padding=2)self.maxpool1 = MaxPool2d(kernel_size=2)self.conv2 = Conv2d(in_channels=32, out_channels=32, kernel_size=5, stride=1, padding=2)self.maxpool2 = MaxPool2d(kernel_size=2)self.conv3 = Conv2d(in_channels=32, out_channels=64, kernel_size=5, stride=1, padding=2)self.maxpool3 = MaxPool2d(kernel_size=2)self.flatten = Flatten()self.linear1 = Linear(in_features=1024, out_features=64)self.linear2 = Linear(in_features=64, out_features=10)def forward(self, x):x = self.conv1(x)x = self.maxpool1(x)x = self.conv2(x)x = self.maxpool2(x)x = self.conv3(x)x = self.maxpool3(x)x = self.flatten(x)x = self.linear1(x)x = self.linear2(x)return xtudui = Tudui()
print(tudui)

損失函數loss function

現有網絡模型的使用與修改:

要多看官方文檔)

import torchvision
from torch import nn# train_data = torchvision.datasets.ImageNet("./data_image_net",spilt='train', download=Ture, transform=trocvision.transforms.ToTensor())
vgg16_false = torchvision.models.vgg16(pretrained=False)vgg16_true = torchvision.models.vgg16(pretrained=True)print(vgg16_true)train_data = torchvision.datasets.CIFAR10(root='./data', train=True, download=True, transform=torchvision.transforms.ToTensor())
#數據集是CIFAR10,然后通過vgg16的模型
#但是vgg16的輸出是1000層,所以還要進一步搞成10層的才符合原數據集的分類要求
vgg16_true.add_module('add_linear',nn.Linear(1000,10))print(vgg16_true)

輸出結果:

VGG(
? (features): Sequential(
? ? (0): Conv2d(3, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
? ? (1): ReLU(inplace=True)
? ? (2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
? ? (3): ReLU(inplace=True)
? ? (4): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
? ? (5): Conv2d(64, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
? ? (6): ReLU(inplace=True)
? ? (7): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
? ? (8): ReLU(inplace=True)
? ? (9): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
? ? (10): Conv2d(128, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
? ? (11): ReLU(inplace=True)
? ? (12): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
? ? (13): ReLU(inplace=True)
? ? (14): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
? ? (15): ReLU(inplace=True)
? ? (16): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
? ? (17): Conv2d(256, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
? ? (18): ReLU(inplace=True)
? ? (19): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
? ? (20): ReLU(inplace=True)
? ? (21): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
? ? (22): ReLU(inplace=True)
? ? (23): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
? ? (24): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
? ? (25): ReLU(inplace=True)
? ? (26): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
? ? (27): ReLU(inplace=True)
? ? (28): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
? ? (29): ReLU(inplace=True)
? ? (30): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
? )
? (avgpool): AdaptiveAvgPool2d(output_size=(7, 7))
? (classifier): Sequential(
? ? (0): Linear(in_features=25088, out_features=4096, bias=True)
? ? (1): ReLU(inplace=True)
? ? (2): Dropout(p=0.5, inplace=False)
? ? (3): Linear(in_features=4096, out_features=4096, bias=True)
? ? (4): ReLU(inplace=True)
? ? (5): Dropout(p=0.5, inplace=False)
? ? (6): Linear(in_features=4096, out_features=1000, bias=True)
? )
? (add_linear): Linear(in_features=1000, out_features=10, bias=True)
)

vgg16_true.classifier.add_module('add_linear',nn.Linear(1000,10))

通過這個classifier的操作可以把這一步添加到classifier層中而不是單獨放出來

直接修改最后一個線性層:

vgg16_false.classifier[6] = nn.Linear(1000,10)
print(vgg16_false)

結果:

? (classifier): Sequential(
? ? (0): Linear(in_features=25088, out_features=4096, bias=True)
? ? (1): ReLU(inplace=True)
? ? (2): Dropout(p=0.5, inplace=False)
? ? (3): Linear(in_features=4096, out_features=4096, bias=True)
? ? (4): ReLU(inplace=True)
? ? (5): Dropout(p=0.5, inplace=False)
? ? (6): Linear(in_features=1000, out_features=10, bias=True)
? )
)

模型的保存

模型的加載

準確率:

import torchoutputs = torch.tensor([[0.1,0.2],[0.3,0.4]])#argmax(1)是橫向比較一行,argmax(0)是縱向比較一列
print(outputs.argmax(1))
preds = outputs.argmax(1)
targets = torch.tensor([0, 1])
print(preds == targets)
print((preds == targets).sum())

GPU訓練

完整的模型驗證套路-》利用已經訓練好的模型,然后給他提供輸入

注意這里可能的報錯,如果記錄的是用gpu訓練過的,那么在運行的時候要加入cuda的相關內容,

import torch
import torchvision
from PIL import Image
from torch import nnimage_path= "images/dog.png"
image = Image.open(image_path)
print(image)
image = image.convert('RGB')transform = torchvision.transforms.Compose([torchvision.transforms.Resize((32,32)),torchvision.transforms.ToTensor()])
image = transform(image)
print(image.shape)class Tudui(nn.Module):def __init__(self):super(Tudui, self).__init__()self.model = nn.Sequential(nn.Conv2d(in_channels=3, out_channels=32, kernel_size=5, stride=1, padding=2),nn.MaxPool2d(2),nn.Conv2d(in_channels=32, out_channels=32, kernel_size=5, stride=1, padding=2),nn.MaxPool2d(2),nn.Conv2d(in_channels=32, out_channels=64, kernel_size=5, stride=1, padding=2),nn.MaxPool2d(2),nn.Flatten(),nn.Linear(in_features=64*4*4, out_features=64),nn.Linear(in_features=64, out_features=10))def forward(self, x):x = self.model(x)return xmodel = torch.load("tudui_9.pth",weights_only=False)
print(model)image = torch.reshape(image,(1,3,32,32))
model.eval()
with torch.no_grad():output = model(image)
print(output)

也算是學完了,最后開源代碼的部分也看一下把

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/72789.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/72789.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/72789.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Linux 文件操作-標準IO函數3- fread讀取、fwrite寫入、 fprintf向文件寫入格式化數據、fscanf逐行讀取格式化數據的驗證

目錄 1. fread 從文件中讀取數據 1.1 讀取次數 每次讀取字節數 < 原內容字節數 1.2 讀取次數 每次讀取字節數 > 原內容字節數 2.fwrite 向文件中寫入數據 2.1寫入字符串驗證 2.2寫入結構體驗證 3. fprintf 將數據寫入到指定文件 4. fscanf 從文件中逐行讀取內容…

Python 中下劃線 “_” 的多面性:從變量到約定

# Python中下劃線“_”的多面性&#xff1a;從變量到約定 在Python的語法體系里&#xff0c;下劃線“_”看似毫不起眼&#xff0c;實則扮演著極為重要且多樣化的角色。它不僅能作為普通變量參與編程&#xff0c;更在多個特殊場景下有著獨特的用途與約定。深入理解下劃線的各種…

深入 Linux 聲卡驅動開發:核心問題與實戰解析

1. 字符設備驅動如何為聲卡提供操作接口&#xff1f; 問題背景 在 Linux 系統中&#xff0c;聲卡被抽象為字符設備。如何通過代碼讓應用程序能夠訪問聲卡的錄音和播放功能&#xff1f; 核心答案 1.1 字符設備驅動的核心結構 Linux 字符設備驅動通過 file_operations 結構體定…

基于Spring Boot的圖書管理系統的設計與實現(LW+源碼+講解)

專注于大學生項目實戰開發,講解,畢業答疑輔導&#xff0c;歡迎高校老師/同行前輩交流合作?。 技術范圍&#xff1a;SpringBoot、Vue、SSM、HLMT、小程序、Jsp、PHP、Nodejs、Python、爬蟲、數據可視化、安卓app、大數據、物聯網、機器學習等設計與開發。 主要內容&#xff1a;…

記錄 macOS 上使用 Homebrew 安裝的軟件

Homebrew 是 macOS 上最受歡迎的軟件包管理器之一&#xff0c;能夠輕松安裝各種命令行工具和 GUI 應用。本文記錄了我通過 Homebrew 安裝的各種軟件&#xff0c;并對它們的用途和基本使用方法進行介紹。 &#x1f37a; Homebrew 介紹 Homebrew 是一個開源的包管理器&#xff…

個人AI助手的未來:Yi AI開源系統助力快速搭建

摘要 Yi AI推出了一站式個人AI助手平臺解決方案&#xff0c;助力用戶快速搭建專屬AI助手。該平臺采用全套開源系統&#xff0c;涵蓋前端應用、后臺管理及小程序功能&#xff0c;并基于MIT協議開放使用。同時&#xff0c;平臺集成了本地RAG方案&#xff0c;利用Milvus與Weaviate…

dpkg-architecture命令詳解

dpkg-architecture 是 Debian 系系統中用于處理軟件包架構相關操作的工具&#xff0c;尤其在軟件包構建和交叉編譯環境中至關重要。以下是其核心功能及用法的詳細說明&#xff1a; ?一、核心功能? ?架構查詢與驗證? 顯示或驗證當前系統&#xff08;DEB_HOST_ARCH&#xff…

STM32HAL庫,解決串口UART中斷接收到的第一個字節數據丟失

1.問題描述&#xff1a; 只有上電后第一次接收到的第一字節數據會丟失&#xff0c;往后再接收也不會存在問題了。 2.先貼出來重寫UART中斷回調函數 我在接收到第一字節數據后開啟定時器中斷的&#xff0c;做一個超時處理&#xff0c;每次接收到數據會對定時器計數值清零&…

解決 vxe-table 固定列對不齊,滾動后錯位、展開行遮擋的問題,解決渲染空白、邊框丟失問題

解決 vxe-table 固定列對不齊&#xff0c;滾動后錯位、展開行遮擋的問題&#xff0c;解決渲染空白、邊框丟失問題。 解決方法&#xff0c;更新到最新版本就完美解決了&#xff1b;v4 版本更新到 v4.12&#xff0c;v3版本更新到 v3.14 查看官網&#xff1a;https://vxetable.cn…

React相關面試題

以下是150道React面試題及其詳細回答&#xff0c;涵蓋了React的基礎知識、組件、狀態管理、路由、性能優化等多個方面&#xff0c;每道題目都盡量詳細且簡單易懂&#xff1a; React基礎概念類 1. 什么是React&#xff1f; React是一個用于構建用戶界面的JavaScript庫&#xff…

設備健康管理系統是什么,設備健康管理系統多少錢?

想象一下&#xff0c;你的汽車在儀表盤報警前 3 天&#xff0c;手機就收到 “發動機軸承剩余壽命 1500 公里” 的提醒 —— 這就是 ** 設備健康管理系統&#xff08;EHM&#xff09;** 的日常。在制造業&#xff0c;設備故障每年造成全球 3.4 萬億美元損失&#xff0c;而 80% 的…

Redis項目:秒殺業務

/*** 搶購秒殺券** param voucherId* return*/TransactionalOverridepublic Result seckillVoucher(Long voucherId) {// 1、查詢秒殺券SeckillVoucher voucher seckillVoucherService.getById(voucherId);// 2、判斷秒殺券是否合法if (voucher.getBeginTime().isAfter(LocalD…

區塊鏈(Blockchain)

區塊鏈&#xff08;Blockchain&#xff09;是一種去中心化、分布式的賬本技術&#xff0c;它通過密碼學保證數據的安全性和不可篡改性。它的核心特點包括去中心化、不可篡改性、可追溯性、智能合約等。 區塊鏈的關鍵概念 區塊&#xff08;Block&#xff09;&#xff1a;每個區…

和鯨科技受邀赴中國氣象局氣象干部培訓學院湖南分院開展 DeepSeek 趨勢下的人工智能技術應用專題培訓

為深入貫徹落實國家關于人工智能與氣象業務深度融合的戰略部署&#xff0c;提升在實際業務中應用人工智能技術解決問題的能力&#xff0c;推動氣象現代化高質量發展&#xff0c;中國氣象局氣象干部培訓學院湖南分院于 2025 年 3 月 14 日組織開展 “DeepSeek 等人工智能技術在氣…

Ubuntu 24 常用命令方法

文章目錄 環境說明1、賬號管理1.1、啟用 root 2、包管理工具 apt & dpkg2.1、apt 簡介 & 阿里源配置2.2、dpkg 簡介2.3、apt 和 dpkg 兩者之間的關系2.4、常用命令 3、啟用 ssh 服務4、防火墻5、開啟遠程登錄6、關閉交換分區7、build-essential&#xff08;編譯和開發軟…

OpenCV計算攝影學(22)將輸入的彩色圖像轉換為兩種風格的鉛筆素描效果函數pencilSketch()

操作系統&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 編程語言&#xff1a;C11 算法描述 鉛筆風格非寫實線描圖。 該函數通過圖像處理技術將輸入的彩色圖像轉換為兩種風格的鉛筆素描效果&#xff1a; dst1&#xff1a;炭筆效果的灰度圖…

hackmyvm-Smol

信息收集 ┌──(root?kali)-[/home/kali] └─# arp-scan -I eth1 192.168.56.0/24 Interface: eth1, type: EN10MB, MAC: 00:0c:29:34:da:f5, IPv4: 192.168.56.103 WARNING: Cannot open MAC/Vendor file ieee-oui.txt: Permission denied WARNING: Cannot open MAC/Vendo…

使用DeepSeek和墨刀AI,寫PRD文檔、畫原型圖的思路、過程及方法

使用DeepSeek和墨刀AI&#xff0c;寫PRD文檔、畫原型圖的思路、過程及方法 現在PRD文檔要如何寫更高效、更清晰、更完整&#xff1f; 還是按以前的思路寫PRD&#xff0c;就還是以前的樣子。 現在AI這么強大&#xff0c;產品經理如何使用DeepSeek寫PRD文檔&#xff0c;產品經…

SpringData Redis緩存:自定義序列化與過期策略

文章目錄 引言一、Spring Cache與Redis集成基礎二、Redis緩存配置基礎三、自定義序列化策略四、實現自定義序列化器五、多級緩存配置六、自定義過期策略七、緩存注解的高級應用八、實現緩存預熱與更新策略九、緩存監控與統計總結 引言 在現代高并發分布式系統中&#xff0c;緩…

HOVER:人形機器人的多功能神經網絡全身控制器

編輯&#xff1a;陳萍萍的公主一點人工一點智能 HOVER&#xff1a;人形機器人的多功能神經網絡全身控制器HOVER通過策略蒸餾和統一命令空間設計&#xff0c;為人形機器人提供了通用、高效的全身控制框架。https://mp.weixin.qq.com/s/R1cw47I4BOi2UfF_m-KzWg 01 介紹 1.1 摘…