PointNet数据预处理+网络训练

news2024/12/29 11:11:09

PointNet数据预处理+网络训练

    • 数据预处理
    • 分类网络的训练
    • 分割网络训练
    • 分类和分割的结果

数据预处理

数据预处理,这里仅介绍一个shapenetdataset;

class ShapeNetDataset(data.Dataset):
    def __init__(self,
                 root,
                 npoints=2500,
                 classification=False,
                 class_choice=None,
                 split='train',
                 data_augmentation=True):
        self.npoints = npoints  # 单个数据集的点数
        self.root = root
        self.catfile = os.path.join(self.root,'synsetoffset2category.txt') #各个类别的数据对应的文件夹的路径
        self.cat = {}
        self.data_augmentation = data_augmentation # 是否进行数据增强
        self.classification = classification       # 数据的种类
        self.seg_classes = {}

        with open(self.catfile,'r') as f:
            for line in f:
                ls = line.strip().split()
                self.cat[ls[0]] = ls[1]

        if not class_choice is None:
            self.cat = {k: v for k,v in self.cat.items() if k in class_choice}

        self.id2cat = {v:k for k,v in self.cat.items()}

        self.meta = {}

        # 读取已经分类好的数据的地址
        splitfile = os.path.join(self.root,'train_test_split','shuffled_{}_file_list.json'.format(split))

        filelist = json.load(open(splitfile,'r'))
        for item in self.cat:
            self.meta[item] = []

        # 数据存储地址的转换
        for file in filelist:
            _,category,uuid = file.split('/')
            if category in self.cat.values():
                self.meta[self.id2cat[category]].append((os.path.join(self.root,category,'points',uuid+'.pts'),
                                                         os.path.join(self.root, category, 'points_label', uuid+'.seg')))

        #按类别存储数据路径
        self.datapath = []
        for item in self.cat:
            for fn in self.meta[item]:
                self.datapath.append((item,fn[0],fn[1]))

        self.classes = dict(zip(sorted(self.cat),range(len(self.cat))))

        print(self.classes)
        with open(os.path.join(os.path.dirname(os.path.realpath(__file__)),'../misc/num_seg_classes.txt'),'r') as f:
            for line in f:
                ls = line.strip().split()
                self.seg_classes[ls[0]] = int(ls[1])
        self.num_seg_classes = self.seg_classes[list(self.cat.keys())[0]]
        print(self.seg_classes,self.num_seg_classes)

    #__getitem__ 方法通常用于定制类的实例对象的索引访问行为,使得类的实例可以像序列(如列表、元组)或映射(如字典)一样进行索引操作。
    # 在你的代码片段中,这个方法的定义可能是为了支持类实例的索引访问,比如 instance[index] 的操作。
    def __getitem__(self, index):
        fn = self.datapath[index]
        cls = self.classes[self.datapath[index][0]]
        point_set = np.loadtxt(fn[1]).astype(np.float32)
        seg = np.loadtxt((fn[2])).astype(np.int64)

        choice = np.random.choice(len(seg),self.npoints,replace=True)
        #resample
        point_set = point_set[choice,:]
        #去中心化
        point_set = point_set - np.expand_dims(np.mean(point_set,axis=0),0)
        #单位化
        dist = np.max(np.sqrt(np.sum(point_set ** 2,axis = 1)),0)
        point_set = point_set / dist

        # 采用随机旋转和随机高斯抖动对数据进行数据增强
        if self.data_augmentation:
            theta = np.random.uniform(0,np.pi*2)
            rotation_matrix = np.array([[np.cos(theta),-np.sin(theta)],[np.sin(theta),np.cos(theta)]])
            point_set[:,[0,2]] = point_set[:,[0,2]].dot(rotation_matrix) # 随机旋转
            point_set += np.random.normal(0,0.02,size=point_set.shape) # 生成的随机数服从均值为 0,标准差为 0.02 的正态分布

        seg = seg[choice]
        point_set = torch.from_numpy(point_set)
        seg = torch.from_numpy(seg)
        cls = torch.from_numpy(np.array([cls]).astype(np.int64))

        if self.classification:
            return point_set,cls
        else:
            return  point_set,seg

    def __len__(self):
        return len(self.datapath)

分类网络的训练

from __future__ import print_function
import argparse
import os
import random
import torch
import torch.nn.parallel
import torch.optim as optim
import torch.utils.data
import matplotlib.pyplot as plt

from pointnet.my_dataset import ShapeNetDataset
from pointnet.my_model import PointNetCls,feature_transform_regularizer
import torch.nn.functional as F
from tqdm import tqdm

# 初始化记录变量
train_losses = []
test_losses = []
train_accuracies = []
test_accuracies = []
learning_rates = []

# 创建绘图函数
def plot_metrics(train_losses, test_losses, train_accuracies, test_accuracies, learning_rates):
    epochs = range(len(train_losses))

    plt.figure(figsize=(12, 6))

    # 绘制损失函数曲线
    plt.subplot(2, 2, 1)
    plt.plot(epochs, train_losses, label='Training Loss')
    plt.plot(epochs, test_losses, label='Test Loss')
    plt.xlabel('Epoch')
    plt.ylabel('Loss')
    plt.legend()
    plt.title('Loss Curve')

    # 绘制准确率曲线
    plt.subplot(2, 2, 2)
    plt.plot(epochs, train_accuracies, label='Training Accuracy')
    plt.plot(epochs, test_accuracies, label='Test Accuracy')
    plt.xlabel('Epoch')
    plt.ylabel('Accuracy')
    plt.legend()
    plt.title('Accuracy Curve')

    # 绘制学习率曲线
    plt.subplot(2, 2, 3)
    plt.plot(epochs, learning_rates, label='Learning Rate')
    plt.xlabel('Epoch')
    plt.ylabel('Learning Rate')
    plt.legend()
    plt.title('Learning Rate Curve')

    plt.tight_layout()
    # 保存图表
    plt.savefig("result.png")
    plt.close()

# 设置输入参数
parser = argparse.ArgumentParser()
parser.add_argument(
    '--batchSize', type=int, default=32, help='input batch size')
parser.add_argument(
    '--num_points', type=int, default=2500, help='input batch size')
parser.add_argument(
    '--workers', type=int, help='number of data loading workers', default=4)
parser.add_argument(
    '--nepoch', type=int, default=250, help='number of epochs to train for')
parser.add_argument('--outf', type=str, default='cls', help='output folder')
parser.add_argument('--model', type=str, default='', help='model path')
parser.add_argument('--dataset', type=str, required=True, help="dataset path")
parser.add_argument('--dataset_type', type=str, default='shapenet', help="dataset type shapenet|modelnet40")
parser.add_argument('--feature_transform', action='store_true', help="use feature transform")

opt = parser.parse_args()
print(opt)

blue = lambda x: '\033[94m' + x + '\033[0m'

opt.manualSeed = random.randint(1,10000)
print("Random Seed: ",opt.manualSeed)
random.seed(opt.manualSeed)
torch.manual_seed(opt.manualSeed)

# 设置数据类型,目前只写ShapeNet这一个数据集
if opt.dataset_type == 'shapenet':
    dataset = ShapeNetDataset(
        root = opt.dataset,
        classification=True,
        npoints=opt.num_points
    )

    test_dataset = ShapeNetDataset(
        root = opt.dataset,
        classification=True,
        split='test',
        npoints=opt.num_points,
        data_augmentation=False
    )
else:
    exit("wrong dataset type!!!")

dataloader = torch.utils.data.DataLoader(
    dataset,
    batch_size=opt.batchSize,
shuffle=True,
    num_workers=int(opt.workers))

testdataloader = torch.utils.data.DataLoader(
        test_dataset,
        batch_size=opt.batchSize,
        shuffle=True,
        num_workers=int(opt.workers))

print(len(dataset), len(test_dataset))
num_classes = len(dataset.classes)
print('classes', num_classes)

try:
    os.makedirs(opt.outf)
except OSError:
    pass

# 加载模型
classifier = PointNetCls(k=num_classes,feature_transform=opt.feature_transform)

#可以加载预训练模型
if opt.model != '':
    classifier.load_state_dict(torch.load(opt.model))
#设置损失函数
optimizer = optim.Adam(classifier.parameters(),lr=0.001,betas=(0.9,0.999))
#设置激活函数
scheduler = optim.lr_scheduler.StepLR(optimizer,step_size=20,gamma=0.5)
classifier.cuda()
num_batch = len(dataset) / opt.batchSize
#按照轮次进行训练
for epoch in range(opt.nepoch):
    scheduler.step()
    epoch_train_loss = 0
    epoch_train_correct = 0
    num_batch = len(dataloader)
    for i,data in enumerate(dataloader,0):
        # 获取输入数据和标签
        points,target = data
        target = target[:,0]
        # 数据预处理
        points = points.transpose(2,1)
        points,target = points.cuda(),target.cuda()
        optimizer.zero_grad() # 梯度清零
        classifier = classifier.train() # 设置分类器为训练模式
        pred ,trans,trans_feat = classifier(points) # 前向传播 pred:[batchsize,classify]
        # 计算损失函数
        loss = F.nll_loss(pred,target.squeeze())
        if opt.feature_transform:
            loss += feature_transform_regularizer(trans_feat) * 0.001
        # 反向传播和参数更新
        loss.backward()
        optimizer.step()
        # 记录损失和准确率
        epoch_train_loss += loss.item()
        pred_choice = pred.data.max(1)[1]
        correct = pred_choice.eq(target.data).cpu().sum()
        epoch_train_correct += correct.item()
        # 打印训练信息
        print('[%d: %d/%d] train loss: %f accuracy: %f' % (
        epoch, i, num_batch, loss.item(), correct.item() / float(opt.batchSize)))

        # 每隔一定步数进行测试
        if i % 10 == 0:
            j, data = next(enumerate(testdataloader, 0))
            points, target = data
            target = target[:, 0]
            points = points.transpose(2, 1)
            points, target = points.cuda(), target.cuda()
            classifier = classifier.eval()
            pred, _, _ = classifier(points)
            loss = F.nll_loss(pred, target)
            pred_choice = pred.data.max(1)[1]
            correct = pred_choice.eq(target.data).cpu().sum()
            print('[%d: %d/%d] %s loss: %f accuracy: %f' % (epoch, i, num_batch, blue('test'), loss.item(), correct.item()/float(opt.batchSize)))

    # 记录每个epoch的平均损失和准确率
    train_losses.append(epoch_train_loss / num_batch)
    train_accuracies.append(epoch_train_correct / (num_batch * opt.batchSize))
    learning_rates.append(optimizer.param_groups[0]['lr'])

    # 计算整个测试集的损失和准确率
    classifier = classifier.eval()
    epoch_test_loss = 0
    epoch_test_correct = 0
    with torch.no_grad():
        for data in testdataloader:
            points, target = data
            target = target[:, 0]
            points = points.transpose(2, 1)
            points, target = points.cuda(), target.cuda()
            pred, _, _ = classifier(points)
            loss = F.nll_loss(pred, target)
            epoch_test_loss += loss.item()
            pred_choice = pred.data.max(1)[1]
            correct = pred_choice.eq(target.data).cpu().sum()
            epoch_test_correct += correct.item()
    test_losses.append(epoch_test_loss / len(testdataloader))
    test_accuracies.append(epoch_test_correct / (len(testdataloader) * opt.batchSize))

    torch.save(classifier.state_dict(), '%s/cls_model_%d.pth' % (opt.outf, epoch))

# 绘制训练过程中的指标变化曲线
plot_metrics(train_losses, test_losses, train_accuracies, test_accuracies, learning_rates)

total_correct = 0
total_testset = 0

for i,data in tqdm(enumerate(testdataloader, 0)):
    points, target = data
    target = target[:, 0]
    points = points.transpose(2, 1)
    points, target = points.cuda(), target.cuda()
    classifier = classifier.eval()
    pred, _, _ = classifier(points)
    pred_choice = pred.data.max(1)[1]
    correct = pred_choice.eq(target.data).cpu().sum()
    total_correct += correct.item()
    total_testset += points.size()[0]

print("final accuracy {}".format(total_correct / float(total_testset)))

分割网络训练

from __future__ import print_function
import argparse
import os
import random
import torch.optim as optim
import torch.utils.data
import matplotlib.pyplot as plt
from pointnet.my_dataset import ShapeNetDataset
from pointnet.my_model import PointNetDenseCls,feature_transform_regularizer
import torch.nn.functional as F
from tqdm import tqdm
import numpy as np

def plot_metrics(train_losses, test_losses, train_accuracies, test_accuracies, mIOUs):
    epochs = range(len(train_losses))
    plt.figure(figsize=(16,12))
    # 绘制损失函数曲线
    plt.subplot(2, 2, 1)
    plt.plot(epochs, train_losses, label='Training Loss')
    plt.plot(epochs, test_losses, label='Test Loss')
    plt.xlabel('Epoch')
    plt.ylabel('Loss')
    plt.legend()
    plt.title('Loss Curve')
    # 绘制准确率曲线
    plt.subplot(2, 2, 2)
    plt.plot(epochs, train_accuracies, label='Training Accuracy')
    plt.plot(epochs, test_accuracies, label='Test Accuracy')
    plt.xlabel('Epoch')
    plt.ylabel('Accuracy')
    plt.legend()
    plt.title('Accuracy Curve')

    # 绘制mIOU曲线
    plt.subplot(2, 2, 3)
    plt.plot(epochs, mIOUs, label='mIOUs')
    plt.xlabel('Epoch')
    plt.ylabel('mIOU')
    plt.legend()
    plt.title('mIOUs')

    # 标注mIOU的最大值和最小值
    max_mIOU = np.max(mIOUs)
    plt.annotate(f'Max mIOU: {max_mIOU:.2f}', xy=(np.argmax(mIOUs), max_mIOU), xytext=(10, -20),
                 textcoords='offset points', arrowprops=dict(arrowstyle='->', color='blue'), fontsize=10)
    plt.tight_layout()
    # 保存图表
    plt.savefig("seg_result.png")
    plt.close()
parser = argparse.ArgumentParser()
parser.add_argument(
    '--batchSize', type=int, default=32, help='input batch size')
parser.add_argument(
    '--workers', type=int, help='number of data loading workers', default=4)
parser.add_argument(
    '--nepoch', type=int, default=25, help='number of epochs to train for')
parser.add_argument('--outf', type=str, default='seg', help='output folder')
parser.add_argument('--model', type=str, default='', help='model path')
parser.add_argument('--dataset', type=str, required=True, help="dataset path")
parser.add_argument('--class_choice', type=str, default='Chair', help="class_choice")
parser.add_argument('--feature_transform', action='store_true', help="use feature transform")

opt = parser.parse_args()
print(opt)

opt.manualSeed = random.randint(1,10000)
print("Random Seed: ",opt.manualSeed)
random.seed(opt.manualSeed)
torch.manual_seed(opt.manualSeed)

dataset = ShapeNetDataset(
    root=opt.dataset,
    classification=False,
    class_choice=[opt.class_choice]
)
dataloader = torch.utils.data.DataLoader(
    dataset,
    batch_size=opt.batchSize,
    shuffle=True,
    num_workers=int(opt.workers)
)

testset = ShapeNetDataset(
    root=opt.dataset,
    classification=False,
    class_choice=[opt.class_choice],
    split='test',
    data_augmentation=False
)
testdataloader = torch.utils.data.DataLoader(
    testset,
    batch_size=opt.batchSize,
    shuffle=True,
    num_workers=int(opt.workers)
)
print(len(dataset), len(testset))
num_classes = dataset.num_seg_classes
print('classes', num_classes)
try:
    os.makedirs(opt.outf)
except OSError:
    pass
blue = lambda x: '\033[94m' + x + '\033[0m'
classifier = PointNetDenseCls(k=num_classes,feature_transform=opt.feature_transform)
if opt.model != '':
    classifier.load_state_dict(torch.load(opt.model))
optimizer = optim.Adam(classifier.parameters(),lr=0.001,betas=(0.9,0.999))
scheduler = optim.lr_scheduler.StepLR(optimizer, step_size=20, gamma=0.5)
classifier.cuda()

num_batch = len(dataset) / opt.batchSize

# Lists to store data for plotting
train_losses = []
train_accuracies = []
test_losses = []
test_accuracies = []
mious = []

for epoch in range(opt.nepoch):
    scheduler.step()
    epoch_train_loss = 0
    epoch_train_correct = 0
    for i, data in enumerate(dataloader, 0):
        points, target = data
        points = points.transpose(2, 1)
        points, target = points.cuda(), target.cuda()
        optimizer.zero_grad()
        classifier = classifier.train()
        pred, trans, trans_feat = classifier(points)
        pred = pred.view(-1, num_classes)
        target = target.view(-1, 1)[:, 0] - 1
        #print(pred.size(), target.size())
        loss = F.nll_loss(pred, target)
        if opt.feature_transform:
            loss += feature_transform_regularizer(trans_feat) * 0.001
        loss.backward()
        optimizer.step()
        pred_choice = pred.data.max(1)[1]
        correct = pred_choice.eq(target.data).cpu().sum()
        print('[%d: %d/%d] train loss: %f accuracy: %f' % (epoch, i, num_batch, loss.item(), correct.item()/float(opt.batchSize * 2500)))
        # Append training loss and accuracy for plotting
        epoch_train_loss += loss.item()
        epoch_train_correct += correct.item()

    # 计算整个测试集的损失和准确率
    epoch_test_loss = 0
    epoch_test_correct = 0
    with torch.no_grad():
        for data in testdataloader:
            points,target = data
            points = points.transpose(2, 1)
            points, target = points.cuda(), target.cuda()
            classifier = classifier.eval()
            pred, _, _ = classifier(points)
            pred = pred.view(-1, num_classes)
            target = target.view(-1, 1)[:, 0] - 1
            loss = F.nll_loss(pred, target)
            pred_choice = pred.data.max(1)[1]
            correct = pred_choice.eq(target.data).cpu().sum()
            epoch_test_correct += correct.item()
            epoch_test_loss += loss.item()
    test_losses.append(epoch_test_loss / len(testdataloader))
    test_accuracies.append(epoch_test_correct / (len(testdataloader) * opt.batchSize * 2500))
    # 记录每个epoch的平均损失和准确率
    train_losses.append(epoch_train_loss / num_batch)
    train_accuracies.append(epoch_train_correct / (num_batch * opt.batchSize * 2500))
    print('[%d] %s loss: %f accuracy: %f' % (
        epoch, blue('test'), epoch_test_loss / len(testdataloader), epoch_test_correct / (len(testdataloader) * opt.batchSize * 2500)))
    torch.save(classifier.state_dict(), '%s/seg_model_%s_%d.pth' % (opt.outf, opt.class_choice, epoch))
    ## benchmark mIOU
    shape_ious = []
    for i,data in tqdm(enumerate(testdataloader, 0)):
        points, target = data
        points = points.transpose(2, 1)
        points, target = points.cuda(), target.cuda()
        classifier = classifier.eval()
        pred, _, _ = classifier(points)
        pred_choice = pred.data.max(2)[1]

        pred_np = pred_choice.cpu().data.numpy()
        target_np = target.cpu().data.numpy() - 1

        for shape_idx in range(target_np.shape[0]):
            parts = range(num_classes)#np.unique(target_np[shape_idx])
            part_ious = []
            for part in parts:
                I = np.sum(np.logical_and(pred_np[shape_idx] == part, target_np[shape_idx] == part))
                U = np.sum(np.logical_or(pred_np[shape_idx] == part, target_np[shape_idx] == part))
                if U == 0:
                    iou = 1 #If the union of groundtruth and prediction points is empty, then count part IoU as 1
                else:
                    iou = I / float(U)
                part_ious.append(iou)
            shape_ious.append(np.mean(part_ious))
    mious.append(np.mean(shape_ious))
    print("mIOU for class {}: {}".format(opt.class_choice, np.mean(shape_ious)))

# Save the data to a txt file
with open('plot_data.txt', 'w') as f:
    f.write('Train Losses:\n')
    f.write(','.join(map(str, train_losses)) + '\n')
    f.write('Train Accuracies:\n')
    f.write(','.join(map(str, train_accuracies)) + '\n')
    f.write('Test Losses:\n')
    f.write(','.join(map(str, test_losses)) + '\n')
    f.write('Test Accuracies:\n')
    f.write(','.join(map(str, test_accuracies)) + '\n')
    f.write('mIOUs:\n')
    f.write(','.join(map(str, mious)) + '\n')
f.close()
plot_metrics(train_losses,test_losses,train_accuracies,test_accuracies,mious)

分类和分割的结果

shapenet分割结果
在这里插入图片描述shapenet分类结果
在这里插入图片描述

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

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

相关文章

没有手机怎么办呐!高考成绩出来了:请不要吹灭别人的灯——早读(逆天打工人爬取热门微信文章解读)

结婚的时候红包随礼随多少呢 引言Python 代码第一篇 洞见 高考成绩出来了:请不要吹灭别人的灯第二篇结尾 为什么是这个标题呢? 是因为摸鱼看足球直播 主播好兄弟结婚 他老婆问他要红包 引言 今天早上停电了 大概是在3点多的时候 我本身一直都没有开空调…

SAP-SD-修改字段描述

在销售订单中,想修改某字段名的描述,以客户组12为例,如下图 现在想把这个字段修改为客户组1,选择-F1 双击“数据元素” 双击 域 转到-翻译

移动硬盘删除的文件能恢复吗?一文揭晓答案!

“我很喜欢把重要的文件都存储到移动硬盘中,但今天在操作时误删了比较重要的一些文件。大家有什么方法可以帮我恢复里面的重要数据吗?” 在数字世界的浩瀚宇宙中,我们的每一份文件、每一张照片、每一个视频,都是一段珍贵的记忆&am…

修改 Linux 终端提示符的色彩与字体

1、引言 Linux 终端是许多开发者和系统管理员每天工作的主要工具之一。但你是否曾留意过那个位于命令行开头的提示符?是不是觉得它有点单调?别担心,本文将介绍如何通过修改提示符的颜色和字体,为你的 Linux 终端增添一抹独特的色…

昇思25天学习打卡营第二天|张量 Tensor

背景 华为组织了昇思25天学习学习营,提供免费算力,算力支持是昇腾Ascend 910芯片96G内存,很给力。 第一天的学习内容可以阅读文章: 昇思25天学习打卡营第一天|快速入门 学习内容 今天的学习内容是张量。如果线性代数学的好的同…

python - 运算符 / 条件语句 / 数字类型

一.运算符 >>> 5<3 False >>> 5<3 False >>> 5>3 True >>> 5>3 True >>> 53 False >>> 5!3 True 与操作and&#xff1a; >>> 5<3 and 2<4 False >>> 5>3 and 2<4 True 二…

解锁高效办公:ONLYOFFICE版本8.1新功能揭秘与个人使用体验

文章目录 &#x1f4af;ONLYOFFICE 桌面编辑器 8.1 ✍1 新增功能介绍✍2 轻松编辑器PDF文件&#x1f353;2.1 PDF新增编辑器操作&#x1f353;2.2 PDF新增表单操作 ✍3 用幻灯片版式快速修改幻灯片✍4 无缝切换文档编辑、审阅和查看模式✍5 改进从右至左语言的支持 & 新的本…

景联文科技构建高质量多轮对话数据库,赋能AI交互新飞跃

近年来&#xff0c;大语言模型的发展极大推动了自然语言处理领域的进步&#xff0c;大语言模型正引领智能对话领域进入一个全新时代&#xff0c;不仅提升了对话体验的自然度和效率&#xff0c;也为探索更加人性化、智能化的交互方式开辟了道路。 景联文科技作为大语言模型数据服…

【PB案例学习笔记】-24创建一个窗口图形菜单

写在前面 这是PB案例学习笔记系列文章的第24篇&#xff0c;该系列文章适合具有一定PB基础的读者。 通过一个个由浅入深的编程实战案例学习&#xff0c;提高编程技巧&#xff0c;以保证小伙伴们能应付公司的各种开发需求。 文章中设计到的源码&#xff0c;小凡都上传到了gite…

【面试干货】Java中new与clone操作对象的比较

【面试干货】Java中new与clone操作对象的比较 1、new操作符创建对象的过程2、clone方法创建对象的过程3、总结 &#x1f496;The Begin&#x1f496;点点关注&#xff0c;收藏不迷路&#x1f496; 1、new操作符创建对象的过程 new操作符在Java中用于创建对象&#xff0c;并执行…

MySQL索引优化解决方案--索引优化(4)

排序优化 尽量避免使用Using FileSort方式排序。order by语句使用索引最左前列或使用where子句与order by子句条件组合满足索引最左前列。where子句中如果出现索引范围查询会导致order by索引失效。 优化案例 联表查询优化 分组查询优化 慢查询日志

简约的服务器监控工具Ward

什么是 Ward &#xff1f; Ward 是一个简单简约的服务器监控工具。 Ward 支持自适应设计系统。此外&#xff0c;它还支持深色主题。它仅显示主要信息&#xff0c;如果您想查看漂亮的仪表板而不是查看一堆数字和图表&#xff0c;则可以使用它。 Ward 在所有流行的操作系统上都能…

SiLM585x系列SiLM5851NHCG-DG一款具有分离的管脚输出 单通道隔离驱动器 拥有强劲的驱动能力

SiLM585x系列SiLM5851NHCG-DG是一款单通道隔离驱动器&#xff0c;具有分离的管脚输出&#xff0c;提供3.0A源电流和6.0A灌电流。主动保护功能包括退饱和过流检测、UVLO、隔离故障报警和 2.5A 米勒钳位。输入侧电源的工作电压为3V至5.5V&#xff0c;输出侧电源的工作电压范围为1…

深度学习项目实例(一)—— 实时AI换脸项目

一、前言 人工智能&#xff08;AI&#xff09;技术的快速发展为各个领域带来了革命性的变化&#xff0c;其中之一就是人脸识别与图像处理技术。在这之中&#xff0c;AI换脸技术尤其引人注目。这种技术不仅在娱乐行业中得到广泛应用&#xff0c;如电影制作、视频特效等&#xf…

想要用tween实现相机的移动,three.js渲染的canvas画布上相机位置一点没动,如何解决??

&#x1f3c6;本文收录于「Bug调优」专栏&#xff0c;主要记录项目实战过程中的Bug之前因后果及提供真实有效的解决方案&#xff0c;希望能够助你一臂之力&#xff0c;帮你早日登顶实现财富自由&#x1f680;&#xff1b;同时&#xff0c;欢迎大家关注&&收藏&&…

Linux入门攻坚——27、httpd2.4配置使用、lamp基础

CentOS 7上&#xff0c;httpd已经到了2.4版本&#xff0c;新增了很多新特性&#xff1a; &#xff08;1&#xff09;MPM支持运行DSO机制&#xff1b;以模块形式按需加载 &#xff08;2&#xff09;支持event MPM&#xff1b; &#xff08;3&#xff09;支持异步读写&#xff1…

微服务+云原生:打造高效、灵活的分布式系统

&#x1f407;明明跟你说过&#xff1a;个人主页 &#x1f3c5;个人专栏&#xff1a;《未来已来&#xff1a;云原生之旅》&#x1f3c5; &#x1f516;行路有良友&#xff0c;便是天堂&#x1f516; 目录 一、引言 1、云原生概述 2、微服务概述 二、微服务架构基础 1、…

ADS SIPro使用技巧之数据分坐标轴显示

在SIPro data display页面中显示数据时&#xff0c;逐个显示数据非常地麻烦&#xff0c;可读性也较差&#xff1b; 常规的做法&#xff0c;是将数据拖入到一个显示窗口中进行显示&#xff0c;但是&#xff0c;当数据量较多或者各数据之间的数值差异较大时&#xff0c;可视化效果…

大模型管理平台:one-api使用指南

大模型相关目录 大模型&#xff0c;包括部署微调prompt/Agent应用开发、知识库增强、数据库增强、知识图谱增强、自然语言处理、多模态等大模型应用开发内容 从0起步&#xff0c;扬帆起航。 大模型应用向开发路径&#xff1a;AI代理工作流大模型应用开发实用开源项目汇总大模…

想让梦想照进现实?六西格玛绿带培训为你架起桥梁

六西格玛&#xff0c;这个源自摩托罗拉的质量管理方法论&#xff0c;如今已成为全球众多企业追求卓越的秘诀。它强调以数据为基础&#xff0c;通过减少变异和浪费&#xff0c;提高流程效率和质量&#xff0c;进而提升企业整体绩效。而六西格玛绿带培训&#xff0c;则是这个强大…