Pytorch使用预训练好的卷积神经网络进行推理预测

news2025/1/18 8:51:20

本小节将会介绍如何利用已经预训练好的卷积神经网络模型对一张图像进行预测,并且通过可视化的方法,查看模型是如何得到其预测结果的。

我们直接看一个实例,利用已经预训练好的VGG16卷积神经网络对一张图像获取一些特定层的输出,并将这些输出可视化,并观察VGG16对图像的特征提取情况。

import torch
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import requests
import cv2
from torch import nn
import torch.nn.functional as F
from torchvision import models
from torchvision import transforms
from PIL import Image

vgg16=models.vgg16(pretrained=True)
im=Image.open("C:\\Users\\zex\\Downloads\\Compressed\\validation\\validation\\n7\\n704.jpg")
imarray=np.asarray(im)/255.0
plt.figure()
plt.imshow(imarray)
plt.show()

通过PIL库读取图像,并转化为Numpy数组后,使用matplotlib库进行可视化,得到的图像下图所示:

 图像输入VGG16模型之前,需要对该图像进行预处理,将其处理为网络可接受的输入。

#将图像处理为VGG16可以处理的形式
data_transforms=transforms.Compose([
    transforms.Resize((224,224)),#重置图像分辨率
    transforms.ToTensor(),#转化为张量并归一化至[0-1]
    #图像标准化处理
    transforms.Normalize([0.485,0.456,0.406],[0.229,0.224,0.225])
])
input_im=data_transforms(im).unsqueeze(0)

在获取图像的中间特征之前,先定义一个辅助函数get_activation,该函数可以更方便地获取、保存所需要的中间特征输出。

#定义一个辅助函数,获取指定层名称的特征
activation={}#保存不同层的输出
def get_activation(name):
    def hook(model,input,output):
        activation[name]=output.detach()
    return hook

下面我们获取vgg16网络中的第四层(也即经过第一次最大值池化后的特征映射)

#获取中间的卷积后的图像特征
vgg16.features[4].register_forward_hook(get_activation("maxpool1"))
_=vgg16(input_im)
maxpool1=activation["maxpool1"]
print(maxpool1.shape)

上面的程序通过钩子技术,即vgg16.features[4].register_forward_hook(),获取vgg16.features下的第四层向前输出结果,并将结果保存在字典activation下maxpool1所对应的结果。从输出中可知一张图像获取了64个112×112的特征映射,将特征映射可视化的程序及结果如下所示

plt.figure(figsize=(11,6))
for i in range(maxpool1.shape[1]):
    plt.subplot(6,11,i+1)
    plt.imshow(maxpool1.data.numpy()[0,i,:,:],cmap="gray")
    plt.axis("off")
plt.subplots_adjust(wspace=0.1,hspace=0.1)
plt.show()

 从上图的结果发现,很多特征映射都能分辨出原始图形所包含的内容,反映了网络中的较浅层能够获取图像的较大粒度的特征。接下来将获取更深层次的特征映射,获取vgg16.features[21]层的输出,程序及可视化结果如下:

vgg16.eval()
vgg16.features[21].register_forward_hook(get_activation("layer21_conv"))
_=vgg16(input_im)
layer21_conv=activation["layer21_conv"]
print(layer21_conv.shape)
plt.figure(figsize=(12,6))
for i in range(72):
    plt.subplot(6,12,i+1)
    plt.imshow(layer21_conv.data.numpy()[0,i,:,:],cmap="gray")
    plt.axis("off")
plt.subplots_adjust(hspace=0.1,wspace=0.1)
plt.show()

从上图可以发现更深层次的映射已经不能分辨出图像的具体内容,说明更深的特征映射能从图像中提取更细粒度的特征。

针对已经预训练好的卷积神经网络,导入模型后,可以直接使用该模型对图像数据进行预测,输出图像所对应的类别。下图所对应的json文件中包含着ImageNet图像用于图像分类的1000个类别标签,这也是PyTorch中预训练模型所对应的类别标签。

 下面将使用预训练好的VGG16网络,对图片进行预测。在进行预测之前,首先需要读取VGG16模型对应的1000个标签,并将其预处理。

import json
jsonfile = r'E:\PythonWorkSpace\pytorch_project\pytorch_demo\Dataset\my_labels.json'
with open(jsonfile, 'r') as load_f:
    load_json = json.load(load_f)
labels = {int(key): value for (key, value) in load_json.items()}

接下来导入vgg16网络模型对图像进行预测。

vgg16.eval()
im_pre=vgg16(input_im)
softmax=nn.Softmax(dim=1)
im_pre_prob=softmax(im_pre)
prob,prelab=torch.topk(im_pre_prob,5)
prob=prob.data.numpy().flatten()
prelab=prelab.numpy().flatten()
for i,lab in enumerate(prelab):
    print("index:",lab,"label:",labels[lab],"||",prob[i])

上面的程序输出了预测可能性最大的前5个类别,得到的结果如下所示: 

index: 382 label: squirrel monkey, Saimiri sciureus || 0.56855154
index: 380 label: titi, titi monkey || 0.36315396
index: 381 label: spider monkey, Ateles geoffroyi || 0.06263459
index: 384 label: indri, indris, Indri indri, Indri brevicaudatus || 0.0024695916
index: 371 label: patas, hussar monkey, Erythrocebus patas || 0.0021503093

 在预测结果中,预测概率最大的是第382类squirrel monkey可能性为56.85%,其次是380类titi monkey 可能性为6.26%。

以上案例的完整代码:

import torch
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import requests
import cv2
from torch import nn
import torch.nn.functional as F
from torchvision import models
from torchvision import transforms
from PIL import Image

vgg16=models.vgg16(pretrained=True)
im=Image.open("C:\\Users\\zex\\Downloads\\Compressed\\validation\\validation\\n7\\n704.jpg")
imarray=np.asarray(im)/255.0
plt.figure()
plt.imshow(imarray)
plt.show()
#将图像处理为VGG16可以处理的形式
data_transforms=transforms.Compose([
    transforms.Resize((224,224)),#重置图像分辨率
    transforms.ToTensor(),#转化为张量并归一化至[0-1]
    #图像标准化处理
    transforms.Normalize([0.485,0.456,0.406],[0.229,0.224,0.225])
])
input_im=data_transforms(im).unsqueeze(0)

#定义一个辅助函数,获取指定层名称的特征
activation={}#保存不同层的输出
def get_activation(name):
    def hook(model,input,output):
        activation[name]=output.detach()
    return hook
#获取中间的卷积后的图像特征
# vgg16.features[4].register_forward_hook(get_activation("maxpool1"))
# _=vgg16(input_im)
# maxpool1=activation["maxpool1"]
# print(maxpool1.shape)
#
# plt.figure(figsize=(11,6))
# for i in range(maxpool1.shape[1]):
#     plt.subplot(6,11,i+1)
#     plt.imshow(maxpool1.data.numpy()[0,i,:,:],cmap="gray")
#     plt.axis("off")
# plt.subplots_adjust(wspace=0.1,hspace=0.1)
# plt.show()
vgg16.eval()
vgg16.features[21].register_forward_hook(get_activation("layer21_conv"))
_=vgg16(input_im)
layer21_conv=activation["layer21_conv"]
print(layer21_conv.shape)
plt.figure(figsize=(12,6))
for i in range(72):
    plt.subplot(6,12,i+1)
    plt.imshow(layer21_conv.data.numpy()[0,i,:,:],cmap="gray")
    plt.axis("off")
plt.subplots_adjust(hspace=0.1,wspace=0.1)
plt.show()

import json
jsonfile = r'E:\PythonWorkSpace\pytorch_project\pytorch_demo\Dataset\my_labels.json'
with open(jsonfile, 'r') as load_f:
    load_json = json.load(load_f)
labels = {int(key): value for (key, value) in load_json.items()}

vgg16.eval()
im_pre=vgg16(input_im)
softmax=nn.Softmax(dim=1)
im_pre_prob=softmax(im_pre)
prob,prelab=torch.topk(im_pre_prob,5)
prob=prob.data.numpy().flatten()
prelab=prelab.numpy().flatten()
for i,lab in enumerate(prelab):
    print("index:",lab,"label:",labels[lab],"||",prob[i])

针对一幅图像使用已经预训练好的深度学习网络,为了便于观察图像中哪些位置的内容对分类结果影响较大,可以输出图像的类激活热力图。计算图像类激活热力图数据,可以使用卷积神经网络中最后一层网络输出和其对应的梯度,但需要先定义一个新的网络,并且输出网络的卷积核梯度。

import torch
import torch.nn as nn
import torchvision.models


class MyVGG16Net(nn.Module):
    def __init__(self):
        super(MyVGG16Net, self).__init__()
        #使用预训练好的vgg16模型
        self.vgg=models.vgg16(pretrained=True)
        #切分vgg16模型,便于获取卷积层的输出
        self.features_conv=self.vgg.features[:30]
        #使用Vgg原始的最大池化层
        self.max_pool=self.vgg.features[30]
        self.avgpool=self.vgg.avgpool
        #使用vgg16的分类层
        self.classifier=self.vgg.classifier
        #生成梯度占位符
        self.gradients=None
    #定义获取梯度的钩子函数
    def activations_hook(self,grad):
        self.gradients=grad
    def forward(self,x):
        x=self.features_conv(x)
        #注册钩子函数
        h=x.register_hook(self.activations_hook)
        #对卷积后的输出使用最大池化层
        x=self.max_pool(x)
        x=self.avgpool(x)
        x=x.view((1,-1))
        x=self.classifier(x)
        return x
    #定义获取梯度的方法
    def get_activations_gradient(self):
        return self.gradients
    #定义获取卷积层输出的方法
    def get_activations(self,x):
        return self.features_conv(x)
    

上面的程序定义了一个新的函数类MyVGG16Net,其使用预训练好的VGC16网络为基础,用于获取图像在全连接层前的特征映射和对应的梯度信息。在类MyVGG16Net中定义activations_hook()函数来辅助获取图像在对应层的梯度信息,并定义get_activations_gradient()方法来获取梯度。在forward()函数中,使用x.register_hook()注册一个钩子,保存最后一层的特征映射的梯度信息,并使用get_activations()方法获取特征映射的输出。

接下来使用定义好的函数类初始化一个新的卷积神经网络vggcam,并对一张老虎图像进行预测。

class MyVGG16Net(nn.Module):
    def __init__(self):
        super(MyVGG16Net, self).__init__()
        #使用预训练好的vgg16模型
        self.vgg=models.vgg16(pretrained=True)
        #切分vgg16模型,便于获取卷积层的输出
        self.features_conv=self.vgg.features[:30]
        #使用Vgg原始的最大池化层
        self.max_pool=self.vgg.features[30]
        self.avgpool=self.vgg.avgpool
        #使用vgg16的分类层
        self.classifier=self.vgg.classifier
        #生成梯度占位符
        self.gradients=None
    #定义获取梯度的钩子函数
    def activations_hook(self,grad):
        self.gradients=grad
    def forward(self,x):
        x=self.features_conv(x)
        #注册钩子函数
        h=x.register_hook(self.activations_hook)
        #对卷积后的输出使用最大池化层
        x=self.max_pool(x)
        x=self.avgpool(x)
        x=x.view((1,-1))
        x=self.classifier(x)
        return x
    #定义获取梯度的方法
    def get_activations_gradient(self):
        return self.gradients
    #定义获取卷积层输出的方法
    def get_activations(self,x):
        return self.features_conv(x)

im=Image.open("C:\\Users\\zex\\Desktop\\tiger.jpg")#一张老虎图片
#将图像处理为VGG16可以处理的形式
data_transforms=transforms.Compose([
    transforms.Resize((224,224)),#重置图像分辨率
    transforms.ToTensor(),#转化为张量并归一化至[0-1]
    #图像标准化处理
    transforms.Normalize([0.485,0.456,0.406],[0.229,0.224,0.225])
])
input_im=data_transforms(im).unsqueeze(0)

vggcam=MyVGG16Net()
vggcam.eval()
im_pre=vggcam(input_im)
softmax=nn.Softmax(dim=1)
im_pre_prob=softmax(im_pre)
prob,prelab=torch.topk(im_pre_prob,5)
prob=prob.data.numpy().flatten()
prelab=prelab.numpy().flatten()

#读取ImageNet数据集1000类别json文件
jsonfile = r'E:\PythonWorkSpace\pytorch_project\pytorch_demo\Dataset\my_labels.json'
with open(jsonfile, 'r') as load_f:
    load_json = json.load(load_f)
labels = {int(key): value for (key, value) in load_json.items()}
for i,lab in enumerate(prelab):
    print("index:",lab,"label:",labels[lab],"||",prob[i])

网络预测结果如下:

index: 292 label: tiger, Panthera tigris || 0.6837202
index: 282 label: tiger cat || 0.22213535
index: 133 label: bittern || 0.04011252
index: 340 label: zebra || 0.020502226
index: 290 label: jaguar, panther, Panthera onca, Felis onca || 0.013023969

下面开始计算所需要的特征映射与梯度信息

上面的程序在使用vggcam.get_activations_gradient()方法获取梯度信息gradients后,将每个通道的梯度信息计算均值,然后将特征映射的每个通道乘以相应的梯度均值,在经过ReLU函数运算后即可得到类激活热力图的取值heatmap,将heatmap的取值处理到0~1之间,即可对其进行可视化,得到如下图所示的类激活热力图。 

#获取相对于模型参数的输出梯度
im_pre[:,prelab[0]].backward()
#获取模型的梯度
gradients=vggcam.get_activations_gradient()

#计算梯度相应通道的均值
mean_gradients=torch.mean(gradients,dim=[0,2,3])
#获取图像在相应卷积层输出的卷积特征
activations=vggcam.get_activations(input_im).detach()
#每个通道乘以相应的梯度均值
for i in range(len(mean_gradients)):
    activations[:,i,:,:] *=mean_gradients[i]
#计算所有通道的均值输出得到的热力图
heatmap=torch.mean(activations,dim=1).squeeze()
#使用relu函数作用于热力图
heatmap=F.relu(heatmap)
#对热力图进行标准化
heatmap /=torch.max(heatmap)
heatmap=heatmap.numpy()
#可视化热力图
plt.matshow(heatmap)
plt.show()

 直接观察图像的类激活热力图,并不能很好地反应原始图像中哪些地方的内容对图像的分类结果影响更大。所以针对获得的类激活热力图可以将其和原始图像融合,更方便观察图像中对分类结果影响更大的图像内容。

import  cv2
import numpy as np
#将CAM热力图融合到原始图像上去
img=cv2.imread("C:\\Users\\zex\\Desktop\\tiger.jpg")
heatmap=cv2.resize(heatmap,(img.shape[1],img.shape[0]))
heatmap=np.uint8(255 * heatmap)
heatmap=cv2.applyColorMap(heatmap,cv2.COLORMAP_JET)
Grad_cam_img=heatmap *0.4 +img
Grad_cam_img=Grad_cam_img / Grad_cam_img.max()
#可视化图像
b,g,r=cv2.split(Grad_cam_img)
Grad_cam_img=cv2.merge([r,g,b])
plt.figure()
plt.imshow(Grad_cam_img)
plt.show()

 上图显示了预测结果响应的主要位置,图像中老虎身体中间部位的内容对预测的结果影响更大

本案例的完整代码如下:

import matplotlib.pyplot as plt
import torch
import torch.nn as nn
import torchvision.models as models
from torchvision import transforms
from PIL import Image
import json
import torch.nn.functional as F
import matplotlib.pyplot as plt

class MyVGG16Net(nn.Module):
    def __init__(self):
        super(MyVGG16Net, self).__init__()
        #使用预训练好的vgg16模型
        self.vgg=models.vgg16(pretrained=True)
        #切分vgg16模型,便于获取卷积层的输出
        self.features_conv=self.vgg.features[:30]
        #使用Vgg原始的最大池化层
        self.max_pool=self.vgg.features[30]
        self.avgpool=self.vgg.avgpool
        #使用vgg16的分类层
        self.classifier=self.vgg.classifier
        #生成梯度占位符
        self.gradients=None
    #定义获取梯度的钩子函数
    def activations_hook(self,grad):
        self.gradients=grad
    def forward(self,x):
        x=self.features_conv(x)
        #注册钩子函数
        h=x.register_hook(self.activations_hook)
        #对卷积后的输出使用最大池化层
        x=self.max_pool(x)
        x=self.avgpool(x)
        x=x.view((1,-1))
        x=self.classifier(x)
        return x
    #定义获取梯度的方法
    def get_activations_gradient(self):
        return self.gradients
    #定义获取卷积层输出的方法
    def get_activations(self,x):
        return self.features_conv(x)

im=Image.open("C:\\Users\\zex\\Desktop\\tiger.jpg")
#将图像处理为VGG16可以处理的形式
data_transforms=transforms.Compose([
    transforms.Resize((224,224)),#重置图像分辨率
    transforms.ToTensor(),#转化为张量并归一化至[0-1]
    #图像标准化处理
    transforms.Normalize([0.485,0.456,0.406],[0.229,0.224,0.225])
])
input_im=data_transforms(im).unsqueeze(0)

vggcam=MyVGG16Net()
vggcam.eval()
im_pre=vggcam(input_im)
softmax=nn.Softmax(dim=1)
im_pre_prob=softmax(im_pre)
prob,prelab=torch.topk(im_pre_prob,5)
prob=prob.data.numpy().flatten()
prelab=prelab.numpy().flatten()


jsonfile = r'E:\PythonWorkSpace\pytorch_project\pytorch_demo\Dataset\my_labels.json'
with open(jsonfile, 'r') as load_f:
    load_json = json.load(load_f)
labels = {int(key): value for (key, value) in load_json.items()}
for i,lab in enumerate(prelab):
    print("index:",lab,"label:",labels[lab],"||",prob[i])

#获取相对于模型参数的输出梯度
im_pre[:,prelab[0]].backward()
#获取模型的梯度
gradients=vggcam.get_activations_gradient()

#计算梯度相应通道的均值
mean_gradients=torch.mean(gradients,dim=[0,2,3])
#获取图像在相应卷积层输出的卷积特征
activations=vggcam.get_activations(input_im).detach()
#每个通道乘以相应的梯度均值
for i in range(len(mean_gradients)):
    activations[:,i,:,:] *=mean_gradients[i]
#计算所有通道的均值输出得到的热力图
heatmap=torch.mean(activations,dim=1).squeeze()
#使用relu函数作用于热力图
heatmap=F.relu(heatmap)
#对热力图进行标准化
heatmap /=torch.max(heatmap)
heatmap=heatmap.numpy()
#可视化热力图
plt.matshow(heatmap)
plt.show()

import  cv2
import numpy as np
#将CAM热力图融合到原始图像上去
img=cv2.imread("C:\\Users\\zex\\Desktop\\tiger.jpg")
heatmap=cv2.resize(heatmap,(img.shape[1],img.shape[0]))
heatmap=np.uint8(255 * heatmap)
heatmap=cv2.applyColorMap(heatmap,cv2.COLORMAP_JET)
Grad_cam_img=heatmap *0.4 +img
Grad_cam_img=Grad_cam_img / Grad_cam_img.max()
#可视化图像
b,g,r=cv2.split(Grad_cam_img)
Grad_cam_img=cv2.merge([r,g,b])
plt.figure()
plt.imshow(Grad_cam_img)
plt.show()

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

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

相关文章

通过python理解光的偏振

文章目录基本原理椭圆偏振光基本原理 光是横波,可以写成E⃗A⃗cos(ωt−k⃗r⃗)\vec E \vec{A}cos(\omega t-\vec k\vec r)EAcos(ωt−kr),振动方向与传播方向垂直,而在三维空间中,与光线垂直的乃是法平面。换言之,光…

【Minecraft开服】Windows搭建我的世界MC服务器「公网远程联机」

文章目录1. Java环境搭建2.安装我的世界Minecraft服务3. 启动我的世界服务4.局域网测试连接我的世界服务器5. 安装cpolar内网穿透6. 创建隧道映射内网端口7. 测试公网远程联机8. 配置固定TCP端口地址8.1 保留一个固定tcp地址8.2 配置固定tcp地址9. 使用固定公网地址远程联机简单…

【计算机网络-网络层】IPv4 和 IPv6

文章目录第一部分:IPv4(IP 协议版本 4)1 IP 数据报1.1 IP 数据报格式1.2 相关例题2 分类编址(两级结构,网络号定长)2.1 IP 地址的表示方法2.2 IP 分类编址2.3 IP 地址的特殊用途3 无分类编址 CIDR&#xff…

PyTorch 之 神经网络 Mnist 分类任务

文章目录一、Mnist 分类任务简介二、Mnist 数据集的读取三、 Mnist 分类任务实现1. 标签和简单网络架构2. 具体代码实现四、使用 TensorDataset 和 DataLoader 简化本文参加新星计划人工智能(Pytorch)赛道:https://bbs.csdn.net/topics/613989052 一、Mnist 分类任…

recyclerview中树状结构的实现,加载本地中文件夹信息

引文: 在项目实现中,对于树状图结构的分析一直无法实现正确的效果,结果查看别人的项目都不要适合我的应用场景,但是查看其实原理是差不多的,但是我没有看明白,所以一直在看这方面的东西。查阅并修改他人的代…

ADSP21489之CCES开发笔记(九)

21489评估板调试SigmaStudio,录音,算法效果对比等等,依此写上该文章,以便有兴趣的朋友参考之用。 一、硬件链路图 二、导入21489Demo程序 2.1、Demo路径:2.2、导入ADI的21489的Demo程序 修改相关代码 oCommConfig.n…

小白学Pytorch系列--Torch.optim API Base class(1)

小白学Pytorch系列–Torch.optim API Base class(1) torch.optim是一个实现各种优化算法的包。大多数常用的方法都已得到支持,而且接口足够通用,因此将来还可以轻松集成更复杂的方法。 如何使用优化器 使用手torch.optim您必须构造一个优化器对象&…

下载和阅读Android源码

目录一、如何下载AOSP1.全量下载2.单个下载目录结构二、如何阅读AOSP1.要阅读哪些源码2.阅读源码的顺序和方式2.1 阅读顺序2.2 阅读方式3.用什么工具来阅读3.1 下载安装Source Insight3.2 导入AOSP源码3.3查看源码三、其他一、如何下载AOSP 源码下载是我们分析源码的开始&…

ctfshow愚人杯web复现

easy_signin 题目url base64解码是face.png&#xff0c;尝试flag.txt和flag.php&#xff0c;base64加密后传入都不对&#xff0c;用index.php加密后传入&#xff0c;看源码 将后面的base64解密得到flag 被遗忘的反序列化 源码 <?php# 当前目录中有一个txt文件哦 error_r…

Unity- 游戏结束以及重启游戏

文章目录游戏结束以及重启游戏建个游戏结束页面编写委托类 游戏主角 以及 ui管理类的脚本重启游戏游戏结束以及重启游戏 思路&#xff1a;利用Canvas创建好覆盖全屏的结束页面&#xff0c;默认关闭。游戏结束时&#xff0c;玩家控制的对象发起委托&#xff0c;ui管理收下委托&…

electron+vue3全家桶+vite项目搭建【六】集成vue-i18n 国际化

文章目录注意引入1.引入依赖2.集成vue i18n3.测试代码4.封装多语言切换组件5.测试多语言切换6.优化代码注意 已发现 9.2.2版本的vue-i18n 如果使用cnpm安装&#xff0c;打包会报错&#xff0c;使用npm或者pnpm安装依赖没有问题 引入 如果需要多语言支持&#xff0c;那么最好…

【100个 Unity实用技能】 | Lua中获取当前时间戳,时间戳和时间格式相互转换、时间戳转换为多久之前

Unity 小科普 老规矩&#xff0c;先介绍一下 Unity 的科普小知识&#xff1a; Unity是 实时3D互动内容创作和运营平台 。包括游戏开发、美术、建筑、汽车设计、影视在内的所有创作者&#xff0c;借助 Unity 将创意变成现实。Unity 平台提供一整套完善的软件解决方案&#xff…

【AI大比拼】文心一言 VS ChatGPT-4

摘要&#xff1a;本文将对比分析两款知名的 AI 对话引擎&#xff1a;文心一言和 OpenAI 的 ChatGPT&#xff0c;通过实际案例让大家对这两款对话引擎有更深入的了解&#xff0c;以便大家选择合适的 AI 对话引擎。 亲爱的 CSDN 朋友们&#xff0c;大家好&#xff01;近年来&…

Python自动录入ERP系统数据

大家好&#xff0c;我是毕加锁。 今天给大家带来的是用Python解决Excel问题的最佳姿势 文末送书&#xff01; 文末送书&#xff01; 文末送书&#xff01; 项目总体情况 软件&#xff1a;Pycharm 环境: Python 3.7.9(考虑到客户可能会有不同操作系统&#xff0c;为了兼容性…

【小程序】django学习笔记3

今天我们来做数据库和django的关联。 根据之前的代码应该看得出来我想做一个获取访客的ip地址并计算访问次数的app&#xff0c;所以必然会用到数据库。 这里选择用的是mysql(因为免费) 不一样的是这里我们打算用django提供的orm框架对数据库进行操作。 一. 环境准备 首先安…

SLAM面试笔记(3) - 视觉SLAM

目录 1 紧耦合、松耦合的区别 &#xff08;1&#xff09;紧耦合和松耦合的区别 &#xff08;2&#xff09;紧耦合和松耦合的分类 &#xff08;3&#xff09;为什么要使用紧耦合 2 SIFT和SUFT的区别 3 视差与深度的关系 4 闭环检测常用方法 5 描述PnP算法 6 梯度下降法…

SQL基础

目录 1.库操作 2.表操作 3.表操作--修改 4.表操作 --删表 5.添加数据 管理数据 查询表中数据&#xff08;重点&#xff09; 判空条件 1.模糊条件查询 2.聚合查询&#xff08;函数&#xff09; 3.排序查询 4.分页查询 5.分组查询&#xff08;配合聚合函数用于统计&a…

C++模拟实现读写锁

文章目录一、读者写者问题二、读写锁1.读写锁的概念2.读写锁的设计(1)成员变量(2)构造函数和析构函数(3)readLock函数(4)readUnlock函数(5)writeLock函数(6)writeUnlock函数3.RWLock类代码三、测试读写锁一、读者写者问题 在编写多线程的时候&#xff0c;有一种情况是非常常见…

为什么黑客不黑/攻击赌博网站?如何入门黑客?

攻击了&#xff0c;只是你不知道而已&#xff01; 同样&#xff0c;对方也不会通知你&#xff0c;告诉你他黑了赌博网站。 攻击赌博网站的不一定是正义的黑客&#xff0c;也可能是因赌博输钱而误入歧途的法外狂徒。之前看过一个警方破获的真实案件&#xff1a;28岁小伙因赌博…

Linux 操作系统原理作业 - 行人与机动车问题

大三上学期操作系统原理这门课中&#xff0c;老师给了一道作业《行人与机动车问题》&#xff1b; 即Linux多线程下处理行人与机动车谁优先的问题&#xff0c;需要用到多线程和互斥量&#xff1b; 行人 - 机动 车问题 假设有一个路口&#xff0c;有很多行人和机动车需要通过&a…