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

U-Net 与深度学习的完美结合:图像分割的高效解决方案

1. 引言:U-Net背景及应用

1.1 U-Net的起源与发展

U-Net 是由 Olaf Ronneberger 和他的团队于2015年提出的卷积神经网络(CNN)架构。最初的设计目的是解决医学图像分割中的挑战,尤其是在有限的训练数据下如何实现准确的分割。

在医学图像分割中,许多重要任务(例如肿瘤、器官分割等)往往需要大量标注数据进行训练。然而,医学图像的标注是一个繁琐且昂贵的过程,通常只能获得少量的标注样本。因此,U-Net的设计旨在通过利用少量的训练数据来进行有效的图像分割。

U-Net 的名字源于其网络结构的形状,它的架构像字母“U”一样对称——即包含一个编码器部分和一个解码器部分。这个结构帮助网络在进行图像分割时,既能提取高层次特征,又能恢复图像的空间细节。
在这里插入图片描述

1.2 U-Net的主要特点

U-Net 的主要创新之一就是它的 跳跃连接(Skip Connections)。跳跃连接直接将编码器层的特征图传递给解码器层。这种设计避免了在下采样过程中丢失图像的细节信息,从而使得网络在解码时能够利用低层次的特征恢复更多的空间信息。

通过这些创新,U-Net 在医学图像分割任务中取得了极大的成功,尤其是在处理小数据集时,U-Net 展现了强大的能力。


1.2 U-Net的应用领域

1.2.1 医学图像分割

U-Net 在医学图像分割中扮演着重要角色。它被广泛应用于自动化的医学图像分析任务,如肿瘤分割、器官分割、血管提取等。利用 U-Net,可以大大减少医学图像分析中的人工标注工作量,并提高分割的准确性。

举个例子,U-Net 被广泛应用于 CT 图像MRI 扫描图像,帮助医生自动分割病变区域,从而更快、更准确地做出诊断。

1.2.2 遥感图像处理

U-Net 不仅仅局限于医学图像领域,它也在遥感图像处理中取得了显著成绩。在遥感领域,U-Net 常用于分割卫星图像,提取地物信息(如城市建筑、森林、农田等)。这种技术对于环境监测、城市规划等任务至关重要。

通过 U-Net,遥感图像的处理效率得到了显著提升,为快速响应环境变化提供了强有力的支持。

1.2.3 自动驾驶

在自动驾驶领域,U-Net 被用于图像分割任务,以帮助自动驾驶系统更好地理解周围环境。例如,U-Net 可以分割出道路、行人、车辆、交通标志等信息,帮助自动驾驶系统做出决策。

U-Net 的高效分割能力使得它能够在实际应用中提供及时且准确的环境感知,为自动驾驶的发展提供了可靠的支持。


2. U-Net 的工作原理

2.1 网络结构概述

U-Net 的结构可以分为两个主要部分:编码器(下采样部分)和 解码器(上采样部分)。在这个网络中,输入图像会先通过编码器进行下采样,然后通过解码器恢复分辨率,最终输出与输入图像大小相同的分割图。

2.1.1 编码器部分

编码器部分由多个卷积层和池化层组成,每一层的卷积操作用于提取图像的特征,池化操作则用来减小图像的尺寸,同时保留最重要的信息。通过逐步下采样,网络能够逐渐学习到更高阶的图像特征。

2.1.2 解码器部分

解码器的目标是将编码器中提取的特征恢复到原始图像的尺寸。解码器通常由上采样层和卷积层组成,最终输出与原始图像大小相同的分割图。解码器通过逐步恢复图像的空间分辨率,并结合跳跃连接的信息,能够实现高精度的图像分割。

2.1.3 跳跃连接的作用

U-Net 最具创新性的设计之一就是其 跳跃连接。跳跃连接将编码器中每个卷积层的输出与解码器中相应层的输入进行连接。这样,在上采样过程中,低层次的细节信息得以保留,避免了在下采样过程中丢失重要的空间信息。

图示:U-Net 跳跃连接示意图

通过这种设计,U-Net 在图像分割时能够捕捉到更加细腻的局部特征,特别是在图像边缘和细节部分,分割效果显著提升。


2.2 数学原理与公式

2.2.1 卷积操作

卷积操作是 U-Net 中的核心操作之一,用于提取图像的特征。在卷积神经网络中,卷积操作通常定义为:

y ( x , y ) = ( f ∗ g ) ( x , y ) = ∑ m ∑ n f ( m , n ) g ( x − m , y − n ) y(x, y) = (f * g)(x, y) = \sum_m \sum_n f(m, n) g(x - m, y - n) y(x,y)=(fg)(x,y)=mnf(m,n)g(xm,yn)

其中,( f ) 是输入图像,( g ) 是卷积核,(*) 表示卷积操作。

卷积操作的本质是对图像进行加权求和,使得网络能够提取到局部特征(如边缘、纹理等)。

2.2.2 池化与上采样
  • 池化(Pooling):池化操作是 U-Net 中常用的下采样操作。池化层通常采用最大池化(Max Pooling),它通过从每个子区域中选取最大值来减少图像的空间分辨率,从而提取最显著的特征。

MaxPool ( x ) = max ⁡ ( x 1 , x 2 , . . . , x k ) \text{MaxPool}(x) = \max(x_1, x_2, ..., x_k) MaxPool(x)=max(x1,x2,...,xk)

  • 上采样(Upsampling):上采样操作用于恢复图像的分辨率。在 U-Net 中,常用的上采样方法有转置卷积(Deconvolution)或双线性插值(Bilinear Interpolation)。这些方法通过插值方式逐步恢复图像的尺寸,使得输出图像与原始图像相同。
2.2.3 损失函数

U-Net 通常使用 交叉熵损失函数Dice 系数损失函数 作为训练过程中优化的目标。
Dice 系数是一种衡量分割结果与真实标签之间重叠度的指标,公式如下:

Dice = 2 ∣ A ∩ B ∣ ∣ A ∣ + ∣ B ∣ \text{Dice} = \frac{2|A \cap B|}{|A| + |B|} Dice=A+B2∣AB

其中,| A | 和 | B | 分别表示预测图和真实标签的像素集合。


3. 数学原理与公式

3.1 卷积操作

卷积操作是神经网络,尤其是卷积神经网络(CNN)中的核心操作之一。在 U-Net 网络中,卷积层用于从输入图像中提取特征。卷积操作本质上是通过一个滤波器(即卷积核)对输入图像进行滑动窗口式的局部加权求和。

具体的卷积操作可以用以下公式表示:

y ( x , y ) = ( f ∗ g ) ( x , y ) = ∑ m ∑ n f ( m , n ) g ( x − m , y − n ) y(x, y) = (f * g)(x, y) = \sum_m \sum_n f(m, n) g(x - m, y - n) y(x,y)=(fg)(x,y)=mnf(m,n)g(xm,yn)

其中:

  • ( f(m, n) ) 是输入图像,表示图像中像素点的位置。
  • ( g(x - m, y - n) ) 是卷积核(或滤波器),它决定了卷积操作的计算方式。

卷积操作的目的是提取图像中的特征,如边缘、角点、纹理等。这些特征在后续的层中会被组合和加强,帮助网络逐步学习图像中的高层次信息。


3.2 池化与上采样

3.2.1 池化(Pooling)

池化是 U-Net 中另一个重要的操作。池化层主要用于降低特征图的空间维度,减少计算量,同时保留图像的最重要特征。在 U-Net 中,常用的池化方法是 最大池化(Max Pooling),其操作通过从每个子区域(例如 (2 \times 2))中选取最大值来进行降维。

最大池化的数学公式为:

MaxPool ( x ) = max ⁡ ( x 1 , x 2 , . . . , x k ) \text{MaxPool}(x) = \max(x_1, x_2, ..., x_k) MaxPool(x)=max(x1,x2,...,xk)

其中 ( x_1, x_2, …, x_k ) 是池化窗口中的像素值,( \max ) 表示选取窗口中的最大值。池化操作能够提取出图像的显著特征,减少空间维度,并提高模型的鲁棒性。

3.2.2 上采样(Upsampling)

上采样操作用于恢复图像的空间分辨率。在解码器部分,U-Net 通过上采样层将特征图的尺寸逐步恢复到原始图像的大小。常见的上采样方法包括:

  • 转置卷积(Deconvolution):通过学习卷积核进行反卷积操作,逐步恢复图像的分辨率。

  • 双线性插值(Bilinear Interpolation):通过插值方法计算新像素值,适用于对图像进行平滑上采样。

转置卷积的数学表达式为:

y ( x , y ) = ∑ m ∑ n f ( m , n ) g ( x + m , y + n ) y(x, y) = \sum_m \sum_n f(m, n) g(x + m, y + n) y(x,y)=mnf(m,n)g(x+m,y+n)

其中 ( f(m, n) ) 是输入的特征图,( g(x + m, y + n) ) 是转置卷积核。


3.3 损失函数

在训练 U-Net 时,选择合适的损失函数对于模型的优化至关重要。U-Net 通常使用 交叉熵损失函数Dice 系数损失函数 来评估模型的分割精度。

3.3.1 交叉熵损失函数

交叉熵损失函数用于计算预测结果与真实标签之间的差距。在二分类任务中,交叉熵损失函数的表达式为:

L CE = − ( y log ⁡ ( p ) + ( 1 − y ) log ⁡ ( 1 − p ) ) L_{\text{CE}} = - \left( y \log(p) + (1 - y) \log(1 - p) \right) LCE=(ylog(p)+(1y)log(1p))

其中,( y ) 是真实标签,( p ) 是模型预测的概率值。对于多分类问题,交叉熵损失函数可以通过扩展为每个类的概率分布来进行修改。

3.3.2 Dice 系数损失函数

Dice 系数是衡量两个样本相似度的一种方式,在图像分割中,Dice 系数用来衡量预测结果与真实标签的重叠度。其数学公式为:

Dice = 2 ∣ A ∩ B ∣ ∣ A ∣ + ∣ B ∣ \text{Dice} = \frac{2|A \cap B|}{|A| + |B|} Dice=A+B2∣AB

其中 ( A ) 和 ( B ) 分别表示预测分割区域和真实标签区域。Dice 系数的值介于 0 到 1 之间,值越大表示预测结果与真实标签越相似。Dice 系数损失函数通常定义为:

L Dice = 1 − 2 ∣ A ∩ B ∣ ∣ A ∣ + ∣ B ∣ L_{\text{Dice}} = 1 - \frac{2|A \cap B|}{|A| + |B|} LDice=1A+B2∣AB

这是一个适用于图像分割任务的常用损失函数,尤其在医学图像分割中,能够帮助模型在不均衡数据的情况下取得较好的效果。


4. U-Net 的变种与改进

尽管 U-Net 本身已成为图像分割任务中的经典架构,但随着实际应用需求的变化,许多改进和变种版本应运而生。这些改进主要是为了提升 U-Net 在不同领域的适应性和精度。

4.1 U-Net++

U-Net++: 论文
U-Net++: 代码

U-Net++(U-Net++: A Nested U-Net Architecture for Medical Image Segmentation)是 U-Net 的一个变种,旨在通过更加密集的跳跃连接(dense skip pathways)来增强信息流动。U-Net++ 在每个跳跃连接中引入了额外的卷积层,从而使网络能够捕获更多的信息。这个结构能够有效避免传统 U-Net 中信息流动的瓶颈问题,提升分割精度。

U-Net++ 的关键创新是其使用了 嵌套的跳跃连接,这些跳跃连接提供了更丰富的特征信息流,使得网络能够在不同层次上聚合信息,从而获得更好的分割效果。
在这里插入图片描述

4.2 Attention U-Net

Attention U-Net: 论文
Attention U-Net: 代码

Attention U-Net 引入了 注意力机制,能够自动学习哪些区域对分割任务更加重要,从而重点关注这些区域。通过在跳跃连接处添加注意力模块,网络能够自适应地调整关注的区域,这对于复杂场景的分割尤其有效。
在这里插入图片描述

Attention U-Net 通过 注意力卷积 层来计算权重,并动态调整卷积核的响应,使得网络能够在分割时“集中注意力”在重要区域上,减少无关背景对分割结果的干扰。
在这里插入图片描述

4.3 3D U-Net

3D U-Net: 论文
3D U-Net: 代码

3D U-Net 是 U-Net 在三维图像分割任务中的扩展,尤其适用于医学图像(如 CT 扫描、MRI 扫描)。与传统的 2D U-Net 不同,3D U-Net 使用三维卷积和池化操作,可以直接处理三维数据。通过对三维图像进行分割,3D U-Net 能够保留图像的空间信息,从而提升三维医学图像的分割效果。

3D U-Net 的工作原理与 2D U-Net 类似,区别在于其在各个层中使用三维卷积核,以便在三维空间内提取特征。
在这里插入图片描述


5. U-Net 的应用领域

U-Net 的成功不仅仅局限于医学图像分割,还广泛应用于许多其他领域。以下是一些典型的应用场景:

5.1 医学图像分割

U-Net 被广泛用于肿瘤、血管、器官等医学图像的自动分割,减少了人工标注的工作量,并提高了分割的准确度。通过 U-Net,医生能够更快速地获取高质量的图像分割结果,为诊断和治疗提供重要支持。
在这里插入图片描述

5.2 遥感图像处理

U-Net 也在遥感图像处理中取得了显著成果。例如,U-Net 可用于从卫星图像中提取地物信息(如城市建筑、森林、农田等),这对于环境监测、城市规划等领域至关重要。
在这里插入图片描述

5.3 自动驾驶

自动驾驶领域需要准确的环境感知能力,而 U-Net 在图像分割中的应用可以帮助自动驾驶系统识别道路、行人、交通标志等。通过 U-Net,自动驾驶系统能够更好地理解周围的环境,为安全行驶提供支持。
在这里插入图片描述


6. U-Net 的挑战与未来发展方向

虽然 U-Net 在许多领域取得了巨大成功,但仍然面临一些挑战:

6.1 训练难度

U-Net 在大规模数据集上的训练非常依赖强大的计算资源。尤其是在医学图像和遥感图像中,标注数据往往较为稀缺,且训练过程计算复杂,可能需要较长时间。

6.2 模型优化

在分割复杂场景时,U-Net 仍然面临过拟合和泛化能力不足的问题。因此,如何优化 U-Net 模型,提升其对未知数据的适应能力,仍然是当前的一个重要挑战。

6.3 跨领域应用

随着 U-Net 在医学图像分割中的成功,它的应用范围逐渐拓展到其他领域,如遥感图像分析、自动驾驶、机器人视觉等。在这些领域,U-Net 的模型设计需要根据具体任务进行调整和优化。如何有效地迁移 U-Net 到这些新领域,特别是在数据分布差异较大的情况下,仍然是一个研究热点。

6.4 未来的发展方向

未来,U-Net 的研究方向可能包括以下几个方面:

  1. 多模态数据融合:结合来自不同传感器或数据源的信息(例如,CT 和 MRI 图像融合)进行更精确的分割。

  2. 增强学习(Reinforcement Learning)与自监督学习:通过增强学习来优化模型训练策略,或利用自监督学习从未标注的数据中学习特征,减少对大量标注数据的依赖。

  3. 可解释性:虽然深度学习模型(包括 U-Net)在图像分割任务中取得了显著的成果,但它们通常被视为“黑箱”模型。未来的研究可以致力于提升 U-Net 模型的可解释性,使其输出的分割结果更加透明,方便医生或其他领域专家进行决策。

  4. 边缘计算:随着硬件技术的发展,边缘计算开始成为重要趋势。如何将 U-Net 模型优化到能够在边缘设备(如智能手机、无人驾驶汽车、医疗设备等)上运行,将是未来的一个重要研究方向。


7. U-Net 在 PyTorch 中的实现

7.1 U-Net 模型结构

首先,我们从 U-Net 的模型结构开始,代码会使用 PyTorch 定义每一层,并进行注释说明。

import torch
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import DataLoader, Dataset
import torchvision.transforms as transforms
import numpy as np
import os
from PIL import Image# U-Net 模型定义
class UNet(nn.Module):def __init__(self, in_channels=3, out_channels=1):super(UNet, self).__init__()# Contracting path (Encoder)self.enc1 = self.conv_block(in_channels, 64)  # 输入图像经过第一层卷积self.enc2 = self.conv_block(64, 128)           # 第二层卷积,通道数增多self.enc3 = self.conv_block(128, 256)          # 第三层卷积self.enc4 = self.conv_block(256, 512)          # 第四层卷积# Bottleneckself.bottleneck = self.conv_block(512, 1024)   # 最深层卷积# Expansive path (Decoder)self.upconv4 = self.upconv_block(1024, 512)    # 上采样,将分辨率恢复self.upconv3 = self.upconv_block(512, 256)     # 第二层上采样self.upconv2 = self.upconv_block(256, 128)     # 第三层上采样self.upconv1 = self.upconv_block(128, 64)      # 最后层上采样# Output layerself.out_conv = nn.Conv2d(64, out_channels, kernel_size=1)  # 输出层,将通道数调整为所需数量def conv_block(self, in_channels, out_channels):"""创建一个包含两个卷积层和一个ReLU激活函数的卷积模块"""block = nn.Sequential(nn.Conv2d(in_channels, out_channels, kernel_size=3, padding=1),nn.ReLU(inplace=True),nn.Conv2d(out_channels, out_channels, kernel_size=3, padding=1),nn.ReLU(inplace=True))return blockdef upconv_block(self, in_channels, out_channels):"""创建上采样模块,包含转置卷积和卷积"""block = nn.Sequential(nn.ConvTranspose2d(in_channels, out_channels, kernel_size=2, stride=2),  # 转置卷积(上采样)nn.ReLU(inplace=True),)return blockdef forward(self, x):# Contracting pathenc1 = self.enc1(x)enc2 = self.enc2(enc1)enc3 = self.enc3(enc2)enc4 = self.enc4(enc3)# Bottleneckbottleneck = self.bottleneck(enc4)# Expansive pathdec4 = self.upconv4(bottleneck)dec3 = self.upconv3(dec4 + enc4)  # 跳跃连接(skip connection)dec2 = self.upconv2(dec3 + enc3)dec1 = self.upconv1(dec2 + enc2)# Output layeroutput = self.out_conv(dec1)return output
7.1.1 代码解释
  • conv_block:定义了两个卷积层和一个 ReLU 激活函数的结构。每个卷积操作后都有一个 ReLU 激活,使网络能够捕捉到非线性特征。
  • upconv_block:用于上采样的转置卷积操作,将特征图尺寸扩大。ConvTranspose2d 用于图像的上采样处理。
  • 跳跃连接(Skip Connections):通过将编码器中的输出直接连接到解码器中的相应层,保持图像的空间信息。这样可以恢复更高分辨率的图像细节。

7.2 训练手册

7.2.1 数据预处理

数据预处理通常包括读取图像、标准化和数据增强。以下是如何使用 PyTorch 中的 Dataset 类来加载图像。

# 自定义数据集类,用于加载图像和标签
class ImageDataset(Dataset):def __init__(self, image_dir, mask_dir, transform=None):self.image_dir = image_dir  # 输入图像文件夹路径self.mask_dir = mask_dir    # 掩膜文件夹路径self.transform = transform  # 数据增强或标准化# 获取所有图像文件的路径self.image_paths = [os.path.join(image_dir, f) for f in os.listdir(image_dir)]self.mask_paths = [os.path.join(mask_dir, f) for f in os.listdir(mask_dir)]def __len__(self):return len(self.image_paths)  # 返回数据集的长度def __getitem__(self, idx):# 读取图像和标签image = Image.open(self.image_paths[idx]).convert('RGB')mask = Image.open(self.mask_paths[idx]).convert('L')  # 假设掩膜是灰度图像if self.transform:image = self.transform(image)  # 应用图像预处理(如归一化)mask = self.transform(mask)  # 应用标签预处理return image, mask
7.2.2 数据加载和训练准备

我们将使用 DataLoader 来批量加载训练数据,进行模型训练。

# 数据增强和标准化
transform = transforms.Compose([transforms.Resize((128, 128)),transforms.ToTensor(),transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),  # 归一化
])# 初始化数据集和数据加载器
train_dataset = ImageDataset(image_dir='train/images', mask_dir='train/masks', transform=transform)
train_loader = DataLoader(train_dataset, batch_size=16, shuffle=True)val_dataset = ImageDataset(image_dir='val/images', mask_dir='val/masks', transform=transform)
val_loader = DataLoader(val_dataset, batch_size=16, shuffle=False)
7.2.3 损失函数与优化器

对于二元图像分割任务,我们使用 二元交叉熵损失BCELoss)作为损失函数,并使用 Adam优化器

# 使用二元交叉熵损失函数
criterion = nn.BCEWithLogitsLoss()  # 用于处理 sigmoid 输出
optimizer = optim.Adam(model.parameters(), lr=0.001)  # Adam优化器
7.2.4 模型训练过程
# 训练 U-Net 模型
num_epochs = 20
for epoch in range(num_epochs):model.train()  # 设置为训练模式running_loss = 0.0for images, masks in train_loader:# 将图像和掩膜移动到GPU(如果可用)images, masks = images.cuda(), masks.cuda()optimizer.zero_grad()  # 清除梯度# 前向传播outputs = model(images)# 计算损失loss = criterion(outputs, masks.unsqueeze(1).float())  # masks.unsqueeze(1) 将标签变为1通道# 反向传播loss.backward()optimizer.step()running_loss += loss.item()# 每个 epoch 打印训练损失print(f"Epoch [{epoch+1}/{num_epochs}], Loss: {running_loss/len(train_loader)}")
7.2.5 模型评估与保存
# 保存训练好的模型
torch.save(model.state_dict(), 'unet_model.pth')# 评估模型(在验证集上)
model.eval()  # 设置为评估模式
with torch.no_grad():correct = 0total = 0for images, masks in val_loader:images, masks = images.cuda(), masks.cuda()outputs = model(images)preds = (outputs > 0.5).float()  # 进行阈值处理,得到预测结果correct += (preds == masks.unsqueeze(1).float()).sum().item()total += masks.numel()accuracy = correct / totalprint(f'Validation Accuracy: {accuracy * 100:.2f}%')

8. 总结

U-Net 自 2015 年问世以来,凭借其独特的网络结构和出色的分割能力,成为了图像分割领域的重要工具。其在医学图像处理中的应用尤其成功,推动了智能医疗的发展。除了传统的医学图像分割,U-Net 还在遥感图像处理、自动驾驶等领域展现出了强大的适应性。

虽然 U-Net 在许多实际应用中已经取得了显著成果,但在面对复杂场景和跨领域任务时,仍然存在一些挑战,如模型的训练难度、过拟合问题以及对大规模标注数据的需求。因此,U-Net 的优化和改进仍是未来研究的一个重要方向。

随着技术的发展,我们可以期待 U-Net 能够在更多领域中发挥其潜力,推动人工智能在各行各业的深入应用。

相关文章:

U-Net 与深度学习的完美结合:图像分割的高效解决方案

1. 引言:U-Net背景及应用 1.1 U-Net的起源与发展 U-Net 是由 Olaf Ronneberger 和他的团队于2015年提出的卷积神经网络(CNN)架构。最初的设计目的是解决医学图像分割中的挑战,尤其是在有限的训练数据下如何实现准确的分割。 在…...

nginx ngx_http_module(9) 指令详解

nginx ngx_http_module(9) 指令详解 nginx 模块目录 nginx 全指令目录 一、目录 1.1 模块简介 ngx_http_uwsgi_module:uWSGI支持模块,允许Nginx与uWSGI服务器进行通信。uWSGI是一种应用服务器协议,广泛用于Python Web应用的部署。通过该…...

【从0做项目】Java搜索引擎(4)——性能优化~烧脑~~~

本篇文章将对项目搜索引擎(1)~(3)进行性能优化,包括测试,优化思路,优化前后对比 目录 一:文件读取 二:实现多线程制作索引 1:代码分析 2:代码…...

【HarmonyOS Next】鸿蒙应用进程和线程详解

【HarmonyOS Next】鸿蒙应用进程和线程详解 一、前言 进程的定义: 进程是系统进行资源分配的基本单位,是操作系统结构的基础。 在鸿蒙系统中,一个应用下会有三类进程: (1) 主进程, (2) ExtensionAbility进程&#xff…...

【前端ES】ECMAScript 2023 (ES14) 引入了多个新特性,简单介绍几个不为人知但却好用的方法

Array.prototype.toSorted() 返回一个新的已排序数组副本,不改变原数组。 let arr [5, 4, 2, 3, 1]; console.log(arr.toSorted()); // [1, 2, 3, 4, 5]Array.prototype.with() 允许根据索引修改数组中的单个元素,并返回新数组。 const arr ["…...

【EndNote】WPS 导入EndNote 21

写在前面:有没有人有激活码,跪求! EndNote,在文献管理和文献引用方面很好用。写文章的时候,使用EndNote引入需要的文献会很方便。我目前用的WPS,想把EndNote的CWYW(Cite While You Write&#…...

网上购物|基于SprinBoot+vue的网上购物系统(源码+数据库+文档)

网上购物系统目录 基于SprinBootvue的网上购物 一、前言 二、系统设计 三、系统功能设计 5.1 管理员功能实现 5.1.1 论坛管理 5.1.2 商品管理 5.1.3 商品评价管理 5.1.4 商品订单管理 5.2 用户功能实现 5.2.1 商品信息 5.2.2 确认下单 5.2.3 商品订单 5.2.4 购物…...

AI 语言模型发展史:统计方法、RNN 与 Transformer 的技术演进

引言 自然语言处理(NLP)是 AI 领域的重要分支,而语言模型(Language Model, LM)是 NLP 的核心技术。语言模型经历了从 统计方法 到 RNN(循环神经网络),再到 Transformer 的演进&…...

Pycharm中查找与替换

1、Edit -> Find -> Find 在当前文件中查找 2、Edit -> Find -> Find in Files 在所有文件中查找 3、Edit -> Find -> Replace 在当前文件中执行替换 4、Edit -> Find -> Replace in Files 在所有文件中执行替换...

有向图的强连通分量: Kosaraju算法和Tarjan算法详解

在上一篇文章中, 我们了解了图的最小生成树算法. 本节我们来学习 图的强连通分量(Strongly Connected Component, SCC) 算法. 什么是强连通分量? 在 有向图 中, 若一组节点内的任意两个节点都能通过路径互相到达(例如 A → B A \rightarrow B A→B 且 B → A B \rightarro…...

mac相关命令

显示和隐藏usr等隐藏文件文件 terminal输入: defaults write com.apple.Finder AppleShowAllFiles YESdefaults write com.apple.Finder AppleShowAllFiles NO让.bashrc每次启动shell自动生效 编辑vim ~/.bash_profile 文件, 加上 if [ -f ~/.bashrc ]; then. ~/.bashrc fi注…...

代码随想录算法训练营第六天| 242.有效的字母异位词 、349. 两个数组的交集、202. 快乐数 、1. 两数之和

242.有效的字母异位词 题目链接:242.有效的字母异位词 文档讲解:代码随想录有效的字母异位词 视频讲解:LeetCode:有效的字母异位词 状态:学会了 思路: 数组其实是简单哈希表。 哈希表用来快速判断元素是否在…...

dify实现分析-rag-关键词索引的实现

概述 在dify中有两种构建索引的方式,一种是经济型,另一种是高质量索引(通过向量数据库来实现)。其中经济型就是关键词索引,通过构建关键词索引来定位查询的文本块,而关键词索引的构建是通过Jieba这个库来完…...

【小白学HTML5】一文讲清常用单位(px、em、rem、%、vw、vh)

html5中,常用的单位有px、em、rem、%、vw、vh(不常用)、cm、m等,这里主要讲解px、em、rem、%、vw。 学习了解:主流浏览器默认的字号:font-size:16px,无论用什么单位,浏览器最终计算…...

Fastgpt学习(5)- FastGPT 私有化部署问题解决

1.☺ 问题描述: Windows系统,本地私有化部署,postgresql数据库镜像日志持续报错" data directory “/var/lib/postgresql/data” has invalid permissions ",“ DETAIL: Permissions should be urwx (0700) or urwx,gr…...

ubuntu下安装TFTP服务器

在 Ubuntu 系统下安装和配置 TFTP(Trivial File Transfer Protocol)服务器可以按照以下步骤进行: 1. 安装 TFTP 服务器软件包 TFTP 服务器通常使用 tftpd-hpa 软件包,你可以使用以下命令进行安装: sudo apt update …...

深入解析 iText 7:从 PDF 文档中提取文本和图像

在现代开发中,PDF 文件的操作是不可避免的一部分。无论是生成报告、解析文档,还是从文件中提取信息,我们常常需要处理 PDF 文件。iText 是一个非常强大的库,广泛应用于 PDF 文件的创建、修改和解析。自 iText 7 发布以来&#xff…...

Rust编程语言入门教程 (六)变量与可变性

Rust 系列 🎀Rust编程语言入门教程(一)安装Rust🚪 🎀Rust编程语言入门教程(二)hello_world🚪 🎀Rust编程语言入门教程(三) Hello Cargo&#x1f…...

事务--实操演示

目录 一、准备工作 二、在MySQL中操作事务(重点) 第一种方式:使用命令的方式 第二种方式:设置MySQL事务不默认提交的方式 结 三、在JDBC中操作事务(掌握) 第一种方式:使用命令的方式 第…...

PHP是如何并行异步处理HTTP请求的?

文章精选推荐 1 JetBrains Ai assistant 编程工具让你的工作效率翻倍 2 Extra Icons:JetBrains IDE的图标增强神器 3 IDEA插件推荐-SequenceDiagram,自动生成时序图 4 BashSupport Pro 这个ides插件主要是用来干嘛的 ? 5 IDEA必装的插件&…...

linux之kylin系统nginx的安装

一、nginx的作用 1.可做高性能的web服务器 直接处理静态资源(HTML/CSS/图片等),响应速度远超传统服务器类似apache支持高并发连接 2.反向代理服务器 隐藏后端服务器IP地址,提高安全性 3.负载均衡服务器 支持多种策略分发流量…...

Python:操作 Excel 折叠

💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在CSDN上与你们相遇~💖 本博客的精华专栏: 【自动化测试】 【测试经验】 【人工智能】 【Python】 Python 操作 Excel 系列 读取单元格数据按行写入设置行高和列宽自动调整行高和列宽水平…...

抖音增长新引擎:品融电商,一站式全案代运营领跑者

抖音增长新引擎:品融电商,一站式全案代运营领跑者 在抖音这个日活超7亿的流量汪洋中,品牌如何破浪前行?自建团队成本高、效果难控;碎片化运营又难成合力——这正是许多企业面临的增长困局。品融电商以「抖音全案代运营…...

全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比

目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec? IPsec VPN 5.1 IPsec传输模式(Transport Mode) 5.2 IPsec隧道模式(Tunne…...

Mac下Android Studio扫描根目录卡死问题记录

环境信息 操作系统: macOS 15.5 (Apple M2芯片)Android Studio版本: Meerkat Feature Drop | 2024.3.2 Patch 1 (Build #AI-243.26053.27.2432.13536105, 2025年5月22日构建) 问题现象 在项目开发过程中,提示一个依赖外部头文件的cpp源文件需要同步,点…...

力扣-35.搜索插入位置

题目描述 给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。 请必须使用时间复杂度为 O(log n) 的算法。 class Solution {public int searchInsert(int[] nums, …...

Redis:现代应用开发的高效内存数据存储利器

一、Redis的起源与发展 Redis最初由意大利程序员Salvatore Sanfilippo在2009年开发,其初衷是为了满足他自己的一个项目需求,即需要一个高性能的键值存储系统来解决传统数据库在高并发场景下的性能瓶颈。随着项目的开源,Redis凭借其简单易用、…...

iview框架主题色的应用

1.下载 less要使用3.0.0以下的版本 npm install less2.7.3 npm install less-loader4.0.52./src/config/theme.js文件 module.exports {yellow: {theme-color: #FDCE04},blue: {theme-color: #547CE7} }在sass中使用theme配置的颜色主题,无需引入,直接可…...

什么是VR全景技术

VR全景技术,全称为虚拟现实全景技术,是通过计算机图像模拟生成三维空间中的虚拟世界,使用户能够在该虚拟世界中进行全方位、无死角的观察和交互的技术。VR全景技术模拟人在真实空间中的视觉体验,结合图文、3D、音视频等多媒体元素…...

Python训练营-Day26-函数专题1:函数定义与参数

题目1:计算圆的面积 任务: 编写一个名为 calculate_circle_area 的函数,该函数接收圆的半径 radius 作为参数,并返回圆的面积。圆的面积 π * radius (可以使用 math.pi 作为 π 的值)要求:函数接收一个位置参数 radi…...