卷积神经网络-基础篇Basic-CNN

news2024/9/29 9:22:24

卷积神经网络-基础篇Basic-CNN

CNN的全称是"Convolutional Neural Network"(卷积神经网络)。而神经网络是一种模仿生物神经网络(动物的中枢神经系统,特别是大脑)结构和功能的数学模型或计算模型。

CNN原理

CNN被广泛应用在图像识别领域,那么CNN是如何实现图像识别的呢?我们根据图中的例子来解释CNN的原理。

在这里插入图片描述

输入图像: 12828的图像(CWH)

卷积层(Convolutional Layer): 保留图像的空间特征,假设卷积结果为42424(CWH),依然是三维张量

📌相比于全连接层:把图像提取为一维张量,丧失了原有的空间信息

池化层(Max Pooling Layer):主要作用是下采样(downsampling),却不会损坏识别结果

📌例如,做一个2*2的下采样,像素变成了12*12,但是他的通道数是不发生改变的,依然为4.
下采样的目的:减少数据的数据量,降低运算需求,最终达到要求输出的是10维向量(仅针对这个例子)

全连接层(Fully Connected Layer) -:主要作用是分类

📌利用全连接层,把8*4*4的三维张量,展开成一维张量

最终可以利用上面的操作来解决一个分类操作

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8mPeNiIO-1671273456402)(image/image_JnjroXNxMh.png)]

📌我们把卷积层和池化层一起称为特征提取器(Feature Extraction),通过卷积运算能在里面找到某种特征。后面的全连接层是个分类器

卷积层(Convolutional Layer)

那么卷基层是如何提取特征的呢?我们都知道卷积就是2个函数的叠加,应用在图像上,则可以理解为拿一个滤镜放在图像上,找出图像中的某些特征,而我们需要找到很多特征才能区分某一物体,所以我们会有很多滤镜,通过这些滤镜的组合,我们可以得出很多的特征。

例如下面的图像中,我们要从三个通道同都选出一个小块来做卷积,做完卷积之后他的C*W*H都有可能发生改变。

在这里插入图片描述

那这个块在图像的左上角依次向右滑动,把整个图像遍历一遍,然后对每一个块进行卷积运算,最后得到输出的卷积结果。

我们先从简单的情况开始考虑,假设我们有一组灰度图片,这样图片就可以表示为一个矩阵,假设我们的图片大小为5 * 5,那么我们就可以得到一个5 * 5的矩阵,接下来,我们用一组过滤器(Filter)来对图片过滤,过滤的过程就是求卷积的过程。假设我们的Filter的大小为3 * 3,我们从图片的左上角开始移动Filter,并且把每次矩阵相乘的结果记录下来。可以通过下面的过程来演示。

在这里插入图片描述

计算的时候要拿块中的所有像素值和权重相乘,在求和。所以能够包含原始图像里面的所有信息。

卷积操作其实就是每次取一个特定大小的矩阵F(蓝色矩阵中的绿色部分),然后将其对输入X(图中蓝色矩阵)依次扫描并进行内积的运算过程。 可以看到,绿色部分每移动一个位置就会计算得到一个卷积值(红色矩阵),当F扫描完成后就得到了整个卷积后的结果Y(红色矩阵)。

同时,我们将这个特定大小的矩阵F称为卷积核,即convolutional kernel或kernel或filter或detector,它可以是一个也可以是多个;将卷积后的结果Y称为特征图,即feature map,并且每一个卷积核卷积后都会得到一个对应的特征图;最后,对于输入X的形状,都会用三个维度来进行表示,即宽(width),高(high)和通道(channel)。

接下来我们来看一下卷积的运算过程

单通道卷积

假设我们有个1*5*5的单通道图像,3*3的卷积核。我们首先在input中画出一个3*3的矩阵,然后和卷积核做数乘(对应元素相乘)

在这里插入图片描述

之后我们开始遍历整个input,最后可以得到output

在这里插入图片描述

多通道单卷积

以3通道为例,每个通道与不同的卷积核做卷积,得到不同的结果。每一个通道都要配一个卷积核。

算出来的3个矩阵我们要进行加法操作,例如下面做的是3*3的卷积核

在这里插入图片描述

将来在画图中就可以用下面的方式来进行表示

在这里插入图片描述

在n个通道中,做3*3的卷积核时

在这里插入图片描述

多通道多卷积

滤波器filter是卷积核kernel的集合,filter中kernel的个数与输入图像的通道数channel要严格对应(例如,灰度图是单通道则为1个kernel,RGB图是3通道则为3个kernel)。一个filter对应图像的一种特征,比如亮度,锐度,纹理等,一个卷积层可以有过多个filter,用来提取对应数量的特征,并送往下一层。

需要在多通道单卷积的基础上,增加多个卷积核来进行卷积运算。

  • 每一个卷积核输出后通道数都为1。
  • 每一个卷积核的通道数量要求和输入通道数相同。
  • 卷积核的总数和输出的通道数一样的

然后把这些输出的通道,都叠在一起

在这里插入图片描述

总体来说可以概况成下面

在这里插入图片描述

卷积层代码

import torch

in_channels, out_channels = 5, 10  # 定义了输入和输出的通道数
width, height = 100, 100  # 图像的大小
kernel_size = 3  # 卷积核大小
batch_size = 1

# 在pytorch中所有输入的数据都需要是小批量的数据,所以要加一个batch_size
# torch.randn:用来生成随机数字的tensor,这些随机数字满足标准正态分布(0~1)。
input = torch.randn(batch_size,
                    in_channels,
                    width,
                    height)
# nn.Conv2d:对由多个输入平面组成的输入信号进行二维卷积  至少要设置以下三个值
conv_layer = torch.nn.Conv2d(in_channels,
                             out_channels,
                             kernel_size=kernel_size)
output = conv_layer(input)

print(input.shape)
print(output.shape)
print(conv_layer.weight.shape) # 卷积层权重的shape


# ===============输出结果===================
torch.Size([1, 5, 100, 100])
torch.Size([1, 10, 98, 98])
torch.Size([10, 5, 3, 3])


卷积层的其他一些参数

torch.nn.Conv2d(in_channels, out_channels, kernel_size, stride=1, padding=0, dilation=1, groups=1, bias=True)

padding

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cRU3hXxU-1671273456406)(image/image_z2o-Nx_lf2.png)]

我们输入的图像为5*5,我们想要输出的图像也为5*5,则需要在原始的输入图像外侧添加一圈0

在这里插入图片描述

代码演示

import torch

input = [3, 4, 6, 5, 7,
         2, 4, 6, 8, 2,
         1, 6, 7, 8, 4,
         9, 7, 4, 6, 2,
         3, 7, 5, 4, 1]

input = torch.Tensor(input).view(1, 1, 5, 5)  # B=1,C=1,W=5,H=5

conv_layer = torch.nn.Conv2d(1, 1, kernel_size=3, padding=1, bias=False)  # 输入通道和输出通道为1,卷积核为3,padding=1

kernel = torch.Tensor([1, 2, 3, 4, 5, 6, 7, 8, 9]).view(1, 1, 3, 3) #构造一个卷积核 用view来改变形状 Output=1 input=1 W=3 H=3
conv_layer.weight.data = kernel.data

output = conv_layer(input)
print(output)

# ===============输出结果===================
tensor([[[[ 91., 168., 224., 215., 127.],
          [114., 211., 295., 262., 149.],
          [192., 259., 282., 214., 122.],
          [194., 251., 253., 169.,  86.],
          [ 96., 112., 110.,  68.,  31.]]]], grad_fn=<SlowConv2DBackward0>)

在上面的代码中,通过torch.nn.Conv2d定义了一个二维卷积层,并使用一个大小为3x3的卷积核。在这个例子中,输入数据为一个包含1个通道的5x5的图像,卷积核将沿着图像的水平和垂直方向滑动,对每个3x3的局部窗口应用卷积运算,并输出一个1x5x5的二维张量。可以使用output = conv_layer(input)来计算卷积层的输出。

在这段代码中,输入图像的大小为5x5。因为卷积层使用了1的padding,因此输出图像的大小也为5x5。如果没有使用padding,那么输出图像的大小将会比输入图像的大小小。具体而言,输出图像的大小将会比输入图像的大小小2个像素。例如,如果输入图像的大小为5x5,那么输出图像的大小为3x3。使用padding可以避免这种情况,即保持输入和输出图像的大小相同。

stride步长

在这里插入图片描述

把stride设为2时,一个5*5的输入图像做完3*3的卷积就变成了2*2的输出图像

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FhY7EBwb-1671273456408)(image/image_4a2E-uGI7C.png)]

可以有效的减少图像的宽度和高度

代码演示

import torch

input = [3, 4, 6, 5, 7,
         2, 4, 6, 8, 2,
         1, 6, 7, 8, 4,
         9, 7, 4, 6, 2,
         3, 7, 5, 4, 1]

input = torch.Tensor(input).view(1, 1, 5, 5)  # B=1,C=1,W=5,H=5

conv_layer = torch.nn.Conv2d(1, 1, kernel_size=3, stride=2, bias=False)  # 输入通道和输出通道为1,卷积核为3,stride=2

kernel = torch.Tensor([1, 2, 3, 4, 5, 6, 7, 8, 9]).view(1, 1, 3, 3) #构造一个卷积核 用view来改变形状 Output=1 input=1 W=3 H=3
conv_layer.weight.data = kernel.data

output = conv_layer(input)
print(output)

# ===============输出结果===================
tensor([[[[211., 262.],
          [251., 169.]]]], grad_fn=<SlowConv2DBackward0>)

池化层(Max Pooling Layer)

在下采样中用的比较多的时max pooling layer,最大池化层,它不存在权重

比如我们在使用一个2*2的MaxPooling时,默认他的stride=2

我们把一个4*4的图像按照2*2来划分,在每一个2*2的矩阵中找出最大值,重新拼成2*2的输出。

在这里插入图片描述

所以,他只会在一个通道中做MaxPooling,通道与通道之间不会去找最大值。

📌在做MaxPooling时,通道数不会发生改变,但是图像的大小会在2*2MaxPooling基础上的会变成原来的一半

代码演示

import torch

input = [3, 4, 6, 5, 7,
         2, 4, 6, 8, 2,
         1, 6, 7, 8, 4,
         9, 7, 4, 6, 2,
         3, 7, 5, 4, 1]

input = torch.Tensor(input).view(1, 1, 5, 5)  # B=1,C=1,W=5,H=5

maxpooling_layer = torch.nn.MaxPool2d(kernel_size=2)  # 我们设置kernel_size=2时默认stride=2步长

output = maxpooling_layer(input)
print(output)

# ===============输出结果===================
tensor([[[[4., 8.],
          [9., 8.]]]])


实现一个简单的卷积神经网络

输入图像:(batch,1,28,28)

  • 第一层

    第一个卷积层: 卷积核5*5,输入通道=1,输出通道=10

    输出图像:(batch,10,24,24)

    第一个池化层: 卷积核2*2

    输出图像:(batch,10,12,12)

  • 第二层

    第二个卷积层: 卷积核5*5,输入通道=10,输出通道=20

    输出图像:(batch,20,8,8)

    第二个池化层: 卷积核2*2

    输出图像:(batch,20,4,4) 总共320个元素

全连接层:输入通道=320,输出通道=10

输出预测:(batch,10)

在这里插入图片描述

接下来我们来把之前的全连接神经网络改成卷积神经网络

在这里插入图片描述

构建模型代码

在这里插入图片描述

代码演示:

import torch
from torchvision import transforms
from torchvision import datasets
from torch.utils.data import DataLoader  # 加载数据集
import torch.nn.functional as F  # 激活函数
import torch.optim as optim

# prepare dataset

batch_size = 64
# 我们拿到的图片是pillow,我们要把他转换成模型里能训练的tensor也就是张量的格式
transform = transforms.Compose([transforms.ToTensor(), transforms.Normalize((0.1307,), (0.3081,))])  # 归一化,均值和方差
# 加载训练集,pytorch十分贴心的为我们直接准备了这个数据集,注意,即使你没有下载这个数据集
# 在函数中输入download=True,他在运行到这里的时候发现你给的路径没有,就自动下载
train_dataset = datasets.MNIST(root='../dataset/mnist/', train=True, download=True, transform=transform)
train_loader = DataLoader(train_dataset, shuffle=True, batch_size=batch_size)
# 同样的方式加载一下测试集
test_dataset = datasets.MNIST(root='../dataset/mnist/', train=False, download=True, transform=transform)
test_loader = DataLoader(test_dataset, shuffle=False, batch_size=batch_size)


# design model using class

class Net(torch.nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        # 定义了我们第一个要用到的卷积层,因为图片输入通道为1,第一个参数就是1
        # 输出的通道为10,kernel_size是卷积核的大小,这里定义的是5x5的
        self.conv1 = torch.nn.Conv2d(1, 10, kernel_size=5)
        self.conv2 = torch.nn.Conv2d(10, 20, kernel_size=5)
        # 再定义一个池化层
        self.pooling = torch.nn.MaxPool2d(2)
        # 最后是我们做分类用的线性层
        self.fc = torch.nn.Linear(320, 10)

    def forward(self, x):
        # Flatten data from (n,1,28,28) to (n,784)
        batch_size = x.size(0)   # 这里面的0是x大小第1个参数,自动获取batch大小
        # 输入x经过一个卷积层,之后经历一个池化层,最后用relu做激活
        x = F.relu(self.pooling(self.conv1(x)))
        x = F.relu(self.pooling(self.conv2(x)))
        # 为了给我们最后一个全连接的线性层用
        # 我们要把一个二维的图片(实际上这里已经是处理过的)20x4x4张量变成一维的
        x = x.view(batch_size, -1)  # flatten -1 此处自动算出的是320
        # 经过线性层,确定他是0~9每一个数的概率
        x = self.fc(x)
        return x


model = Net()  # 实例化模型

# construct loss and optimizer
# 定义一个损失函数,来计算我们模型输出的值和标准值的差距
criterion = torch.nn.CrossEntropyLoss()
# 定义一个优化器,训练模型咋训练的,就靠这个,他会反向的更改相应层的权重
optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.5) # lr为学习率


# training cycle forward, backward, update

def train(epoch):
    running_loss = 0.0
    for batch_idx, data in enumerate(train_loader, 0):  # 每次取一个样本
        # 获得一个批次的数据和标签
        inputs, target = data
        # 优化器清零
        optimizer.zero_grad()
        # 正向计算一下
        outputs = model(inputs)
        # 计算损失
        loss = criterion(outputs, target)
        # 反向求梯度
        loss.backward()
        # 更新权重
        optimizer.step()
        # 把损失加起来
        running_loss += loss.item()
        if batch_idx % 300 == 299:
            print('[%d,%5d] loss: %.3f' % (epoch + 1, batch_idx + 1, running_loss / 2000))
            running_loss = 0.0


def test():
    correct = 0
    total = 0
    with torch.no_grad():  # 不用算梯度
        for data in test_loader:
            images, labels = data
            outputs = model(images)
            # 我们取概率最大的那个数作为输出
            _, predicted = torch.max(outputs.data, dim=1)  # dim = 1 列是第0个维度,行是第1个维度
            total += labels.size(0)
            # 计算正确率
            correct += (predicted == labels).sum().item()  # 张量之间的比较运算
    print('accuracy on test set: %d %% [%d/%d]' % (100 * correct / total, correct, total))


if __name__ == '__main__':
    for epoch in range(10):
        train(epoch)
        test()


输出结果

[1,  300] loss: 0.106
[1,  600] loss: 0.032
[1,  900] loss: 0.023
accuracy on test set: 96 % [9661/10000]
[2,  300] loss: 0.017
[2,  600] loss: 0.016
[2,  900] loss: 0.015
accuracy on test set: 97 % [9788/10000]
[3,  300] loss: 0.013
[3,  600] loss: 0.012
[3,  900] loss: 0.011
accuracy on test set: 98 % [9825/10000]
[4,  300] loss: 0.010
[4,  600] loss: 0.011
[4,  900] loss: 0.009
accuracy on test set: 98 % [9839/10000]
[5,  300] loss: 0.009
[5,  600] loss: 0.009
[5,  900] loss: 0.009
accuracy on test set: 98 % [9869/10000]
[6,  300] loss: 0.008
[6,  600] loss: 0.008
[6,  900] loss: 0.008
accuracy on test set: 98 % [9826/10000]
[7,  300] loss: 0.007
[7,  600] loss: 0.007
[7,  900] loss: 0.007
accuracy on test set: 98 % [9854/10000]
[8,  300] loss: 0.006
[8,  600] loss: 0.007
[8,  900] loss: 0.007
accuracy on test set: 98 % [9865/10000]
[9,  300] loss: 0.006
[9,  600] loss: 0.006
[9,  900] loss: 0.006
accuracy on test set: 98 % [9875/10000]
[10,  300] loss: 0.005
[10,  600] loss: 0.006
[10,  900] loss: 0.006
accuracy on test set: 98 % [9861/10000]

使用GPU来实现模型

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

代码演示

import torch
from torchvision import transforms
from torchvision import datasets
from torch.utils.data import DataLoader
import torch.nn.functional as F
import torch.optim as optim

# prepare dataset

batch_size = 64
transform = transforms.Compose([transforms.ToTensor(), transforms.Normalize((0.1307,), (0.3081,))])  # 归一化,均值和方差
train_dataset = datasets.MNIST(root='../dataset/mnist/', train=True, download=True, transform=transform)
train_loader = DataLoader(train_dataset, shuffle=True, batch_size=batch_size)
test_dataset = datasets.MNIST(root='../dataset/mnist/', train=False, download=True, transform=transform)
test_loader = DataLoader(test_dataset, shuffle=False, batch_size=batch_size)


# design model using class

class Net(torch.nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        self.conv1 = torch.nn.Conv2d(1, 10, kernel_size=5)
        self.conv2 = torch.nn.Conv2d(10, 20, kernel_size=5)
        self.pooling = torch.nn.MaxPool2d(2)
        self.fc = torch.nn.Linear(320, 10)

    def forward(self, x):
        # Flatten data from (n,1,28,28) to (n,784)
        batch_size = x.size(0)
        x = F.relu(self.pooling(self.conv1(x)))
        x = F.relu(self.pooling(self.conv2(x)))
        x = x.view(batch_size, -1)  # flatten -1 此处自动算出的是320
        x = self.fc(x)
        return x


model = Net()
# 使用GPU
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
model.to(device)

# construct loss and optimizer
criterion = torch.nn.CrossEntropyLoss()
optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.5)


# training cycle forward, backward, update

def train(epoch):
    running_loss = 0.0
    for batch_idx, data in enumerate(train_loader, 0):
        # 获得一个批次的数据和标签
        inputs, target = data
        # 使用GPU
        inputs, target = inputs.to(device), target.to(device)

        optimizer.zero_grad()
        outputs = model(inputs)
        loss = criterion(outputs, target)
        loss.backward()
        optimizer.step()

        running_loss += loss.item()
        if batch_idx % 300 == 299:
            print('[%d,%5d] loss: %.3f' % (epoch + 1, batch_idx + 1, running_loss / 2000))
            running_loss = 0.0


def test():
    correct = 0
    total = 0
    with torch.no_grad():
        for data in test_loader:
            images, labels = data
            # 使用GPU
            images, labels = images.to(device), labels.to(device)
            outputs = model(images)
            _, predicted = torch.max(outputs.data, dim=1)  # dim = 1 列是第0个维度,行是第1个维度
            total += labels.size(0)
            correct += (predicted == labels).sum().item()  # 张量之间的比较运算
    print('accuracy on test set: %d %% [%d/%d]' % (100 * correct / total, correct, total))


if __name__ == '__main__':
    for epoch in range(10):
        train(epoch)
        test()

输出结果

[1,  300] loss: 0.100
[1,  600] loss: 0.028
[1,  900] loss: 0.020
accuracy on test set: 96 % [9649/10000]
[2,  300] loss: 0.016
[2,  600] loss: 0.015
[2,  900] loss: 0.013
accuracy on test set: 97 % [9765/10000]
[3,  300] loss: 0.011
[3,  600] loss: 0.011
[3,  900] loss: 0.011
accuracy on test set: 97 % [9792/10000]
[4,  300] loss: 0.010
[4,  600] loss: 0.009
[4,  900] loss: 0.009
accuracy on test set: 98 % [9842/10000]
[5,  300] loss: 0.008
[5,  600] loss: 0.008
[5,  900] loss: 0.008
accuracy on test set: 98 % [9856/10000]
[6,  300] loss: 0.007
[6,  600] loss: 0.007
[6,  900] loss: 0.007
accuracy on test set: 98 % [9853/10000]
[7,  300] loss: 0.006
[7,  600] loss: 0.007
[7,  900] loss: 0.007
accuracy on test set: 98 % [9857/10000]
[8,  300] loss: 0.006
[8,  600] loss: 0.006
[8,  900] loss: 0.006
accuracy on test set: 98 % [9868/10000]
[9,  300] loss: 0.005
[9,  600] loss: 0.005
[9,  900] loss: 0.006
accuracy on test set: 98 % [9879/10000]
[10,  300] loss: 0.005
[10,  600] loss: 0.006
[10,  900] loss: 0.005
accuracy on test set: 98 % [9884/10000]


最终结果

在这里插入图片描述

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

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

相关文章

Supervisor详解

是用Python开发的一个client/server服务&#xff0c;是Linux/Unix系统下的一个进程管理工具&#xff0c;不支持Windows系统。它可以很方便的监听、启动、停止、重启一个或多个进程。用Supervisor管理的进程&#xff0c;当一个进程意外被杀死&#xff0c;supervisort监听到进程死…

蓝桥杯C/C++百校真题赛(1期)Day1题解(九进制转十进制、数字三角形)

Q1 进制转化 进制转化&#xff0c;口算啥的都行。 #include <iostream> using namespace std; int main() {cout << 2 2 * 9 2 * 9 * 9 * 9 << endl;return 0; }Q2 数字三角形 #include<iostream> using namespace std;const int N 110; int f[N][…

QT 项目 智能家居系统 上位机

有哪些文件 &#xff1a; 头文件&#xff1a; 1. auidio .h 语音识别 模块 2. camera.h 人脸识别登录模块 3. chooselevelscene.h 翻金币游戏的 4. dataconfig.h 翻金币游戏的 关卡 的数据 5.entry_mode.h 登录方式的界面类 6.luck_draw.h 开心一天的界面类 …

[附源码]Node.js计算机毕业设计公司办公自动化系统Express

项目运行 环境配置&#xff1a; Node.js最新版 Vscode Mysql5.7 HBuilderXNavicat11Vue。 项目技术&#xff1a; Express框架 Node.js Vue 等等组成&#xff0c;B/S模式 Vscode管理前后端分离等等。 环境需要 1.运行环境&#xff1a;最好是Nodejs最新版&#xff0c;我…

CS61A Proj 4

更好的阅读体验 Project 4: Scheme Interpreter Eval calls apply, which just calls eval again! When does it all end? Introduction Note: If you’re interested in an alternate version of this project that gives you considerably less scaffolding and guidanc…

【大数据技术Hadoop+Spark】Spark架构、原理、优势、生态系统等讲解(图文解释)

一、Spark概述 Spark最初由美国加州伯克利大学&#xff08;UCBerkeley&#xff09;的AMP&#xff08;Algorithms&#xff0c; Machines and People&#xff09;实验室于2009年开发&#xff0c;是基于内存计算的大数据并行计算框架&#xff0c;可用于构建大型的、低延迟的数据分…

你评论,我赠书~【TFS-CLUB社区 第9期赠书活动】〖HTML5+CSS3+JavaScript从入门到精通(微课精编版)(第2版)〗等你来拿

文章目录❤️‍&#x1f525; 赠书活动 - 《Python从入门到精通&#xff08;微课精编版&#xff09;》❤️‍&#x1f525; 编辑推荐❤️‍&#x1f525; 抽奖方式与截止时间❤️‍&#x1f525; 赠书活动 → 获奖名单❤️‍&#x1f525; 赠书活动 - 《Python从入门到精通&…

详细复习云开发~小程序【云数据库、云函数】

文章目录一&#xff0c;云数据库1-1&#xff0c;在数据库里新建集合(数据表)1-2&#xff0c;数据库权限管理1-3&#xff0c;数据库的增删改查1-3-1&#xff0c;查询 get()1-3-2&#xff0c;条件查询 where()1-3-3&#xff0c;查询单条数据doc()1-3-4&#xff0c;添加数据 add()…

NC22 合并两个有序的数组 - java语言实现

文章目录1. 题目描述2. 题目解读3. 思路4. 代码实现总结✨✨✨学习的道路很枯燥&#xff0c;希望我们能并肩走下来&#xff01; 编程真是一件很奇妙的东西。你只是浅尝辄止&#xff0c;那么只会觉得枯燥乏味&#xff0c;像对待任务似的应付它。但你如果深入探索&#xff0c;就会…

用 Python 将 html 转为 pdf、word

在日常中有时需将 html 文件转换为 pdf、word 文件。网上免费的大多数不支持多个文件转换的情况&#xff0c;而且在转换几个后就开始收费了。 转 pdf 转 pdf 中使用 pdfkit 库&#xff0c;它可以让 web 网页直接转为 pdf 文件&#xff0c;多个 url 可以合并成一个文件。 安装…

供应科研试剂Biotin-PEG-Thiol,Biotin-PEG-SH,生物素peg巯基

一&#xff1a;产品描述 1、名称 英文&#xff1a;Biotin-PEG-Thiol&#xff0c;Biotin-PEG-SH 中文&#xff1a;生物素-聚乙二醇-巯基 2、CAS编号&#xff1a;N/A 3、所属分类&#xff1a;Biotin PEG Thiol PEG 4、分子量&#xff1a;可定制&#xff0c;1k、2k、3.4k、1…

linux red hat 8.0 搭建httpd服务

简介&#xff1a; Apache HTTP Server&#xff08;简称Apache&#xff09;&#xff0c;是Apache软件基金会的一个开源的网页服务器&#xff0c;可以在大多数电脑操作系统中运行&#xff0c;由于其具有的跨平台性和安全性&#xff0c;被广泛使用&#xff0c;是最流行的Web服务器…

Altium Designer输出GERBER文件与华秋DFM对比

Altium Designer是原Protel软件开发商Altium公司推出的PCB设计软件。Altium Designer &#xff08;AD&#xff09;软件一款功能强大、界面友好、操作简单、易容上手等优点&#xff0c;&#xff0c;因此成为各电子工程师、PCB设计工程师、电子发烧友首选EDA设计工具。掌握AD软件…

【简单项目实战】用C++实现通讯录管理系统 | [普通实现]

目录 ●功能介绍 ●案例 ●代码展示 ●结果展示 ●功能介绍 用C设计一个程序&#xff0c;能够提供以下功能&#xff1a; 1.录入联系人的基本信息。包括姓名、性别、年龄、电话号和地址。 2.展示所有已录入联系人的基本信息。以姓名、性别、年龄、电话号和地址的方式按列…

链表的实际应用

1. 删除链表中等于给定值 val 的所有节点。 链接&#xff1a;203. 移除链表元素 - 力扣&#xff08;Leetcode&#xff09; 假设&#xff1a;我们有这么个链表&#xff1a; 我们需要删除所有date域为key的结点。 假设key为4&#xff1a; 思路&#xff08;快慢指针&#xff09…

54、反射(reflection)

一、入门 反射机制的重要性在于&#xff1a;通过外部文件配置&#xff0c;在不修改源码情况下来控制程序&#xff0c;也符合设计模式的ocp原则&#xff08;开闭原则&#xff1a;不修改源码&#xff0c;扩容功能&#xff09; package hspedu.reflection_question;import hsped…

你知道的都不对!Python应该这样学

你们所说的什么要怎样数据分析、爬虫、Web 等&#xff0c;在我看来那不是精通 Python&#xff0c;而是精通某一领域&#xff0c;抛开 Python 换用另一门语言也可&#xff0c;在我看来&#xff0c;精通 Python 语言大约需要如下这些步骤&#xff08;你有你的学习方法&#xff09…

SpringBoot-TwoDay

thymeleaf常用配置 server:port: 8096 spring:datasource:driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3305/mybatis?useSSlfalseusername: rootpassword: rootthymeleaf:cache: false# 降低代码审查的严格度mode: LEGACYHTML5# 配置了前缀pref…

jsp+ssm计算机毕业设计宠物商店管理系统【附源码】

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; JSPSSM mybatis Maven等等组成&#xff0c;B/S模式 Mave…

Docker笔记--搭建私有仓库、上传镜像、拉取镜像

目录 1--搭建私有仓库 2--将镜像上传到私有仓库 3--从私有仓库拉取镜像 4--补充测试 1--搭建私有仓库 ① 拉取私有仓库镜像 docker pull registry ② 启动私有仓库容器 docker run -id --nameregistry_test -p 5000:5000 registry ③ 打开浏览器&#xff0c;输入以下地址…