使用pytorch深度学习框架搭建神经网络

news2024/11/15 23:42:41

简介

现在主流有两个框架pytorch和TensorFlow,本文主要介绍pytorch

  • PyTorch:由 Facebook 的人工智能研究小组开发和维护。PyTorch 以其动态计算图(Dynamic Computational Graph)和易用性著称,非常适合研究人员和开发者进行实验和快速原型开发。
  • TensorFlow:由 Google 开发和维护。TensorFlow 是一个更加成熟和全面的框架,支持大规模的生产环境部署,特别是在云计算和分布式计算方面具有优势。

神经网络搭建步骤

数据集介绍

 数据集为CIFAR10,

CIFAR-10 数据集由 10 个类的 60000 张 32x32 彩色图像组成,每个类有 6000 张图像。有 50000 张训练图像和 10000 张测试图像。图像大小为3x32x32

数据集分为 5 个训练批次和 1 个测试批次,每个批次有 10000 张图像。测试批次包含每个类中随机选择的 1000 张图像。训练批次包含按随机顺序排列的剩余图像,但某些训练批次可能包含来自一个类的图像多于另一个类的图像。在它们之间,训练批次正好包含来自每个类的 5000 张图像。

以下是数据集中的类,以及每个类的 10 张随机图像:

运行下列代码会导入数据集,没有下载的会自动下载

datasets导入数据集

dataloader分发数据,每批次送入64图片进入网络训练

transform更改图片数据的类型,比如将PIL改成tensor类型

train_data = torchvision.datasets.CIFAR10("./dataset",train=True,transform=torchvision.transforms.ToTensor(),download=True)
test = train_data.classes
print(test)
test_data = torchvision.datasets.CIFAR10("./dataset",train=False,transform=torchvision.transforms.ToTensor(),download=True)
train_dataloader = DataLoader(train_data,batch_size=64)
test_dataloader = DataLoader(test_data,batch_size=64)

 

搭建网络 

由官网可知(官网链接:PyTorch documentation — PyTorch 2.4 documentation),使用pytorch搭建网络至少需要重写2个函数,一个__init__() 初始化函数,另一个forward()前向传播函数,下图为官网截图:

按照官网给的例子我们重写,我们的网络结构如下图所示 

网络结构如下图所示

 

代码思路:输入:3x32x32--->最后输出10个参数,具体过程如下图所示:

 二维卷积参数计算公式如下图,根据输入输出计算padding和stride

 

代码实现

class Wisdom(nn.Module):
    def __init__(self):
        super(Wisdom, self).__init__()
        self.model1 = Sequential(
            nn.Conv2d(3, 32, 5, padding=2),
            nn.MaxPool2d(2),
            nn.Conv2d(32, 32, 5, padding=2),
            nn.MaxPool2d(2),
            nn.Conv2d(32, 64, 5, padding=2),
            nn.MaxPool2d(2),
            nn.Flatten(),
            nn.Linear(1024, 64),
            nn.Linear(64, 10)

        )

    def forward(self, x):
        x = self.model1(x)

        return x

 不使用sequential()

class Wisdom(nn.Module):
    def __init__(self):
        super(Wisdom, self).__init__()
        self.conv1=Conv2d(3,32,5,padding=2)
        self.maxpool1=MaxPool2d(2)
        self.conv2=Conv2d(32,32,5,padding=2)
        self.maxpool2=MaxPool2d(2)
        self.conv3=Conv2d(32,64,5,padding=2)
        self.maxpool3=MaxPool2d(2)
        self.flatten=Flatten()
        self.linear1=Linear(1024,64)
        self.linear2= Linear(64, 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 x

实例化神经网络对象,损失函数,优化器

#创建神经网络
wisdom = Wisdom()
wisdom=wisdom.cuda()
#损失函数
loss_fn= nn.CrossEntropyLoss()
loss_fn=loss_fn.cuda()
#优化器
learn_rate =0.01
optimizer = torch.optim.SGD(wisdom.parameters(),lr=learn_rate)

损失函数(Loss Function)

常见的损失函数包括:

选择哪种损失函数取决于具体的任务和模型类型。在训练过程中,目标是最小化损失函数的值,从而提高模型的预测准确性。

优化器

优化器(Optimizer)是机器学习中用于调整模型参数以最小化损失函数的算法。优化器通过迭代过程逐步更新模型的权重和偏置,以找到损失函数的最小值。以下是一些常用的优化器:

设置网络参数

使用writer = SummaryWriter("logs_train")可以可视化整个训练过程
#设置网络的一些参数
#记录的训练次数
total_train_step = 0
#记录测试次数
total_test_step = 0
#训练的轮数
epoch=10
#添加tensorboard
writer = SummaryWriter("logs_train")

 训练和验证网络并将重要信息可视化屏幕

重要代码解析:

wisdom.train()标志网络进入训练状态

loss = loss_fn(outputs,targets)计算损失函数

optimizer.zero_grad() 梯度置零,防止上个梯度对本轮训练产生影响
loss.backward()反向传播
optimizer.step()梯度更新

wisdom.eval()模型进入测试状态

将损失值和精度闯入writer并绘制曲线图

writer.add_scalar("test_loss", total_test_loss, total_test_step) writer.add_scalar("test_accuracy", total_accuracy/test_data_size, total_test_step)

torch.save(wisdom,"./model_train/wisdom_{}.pth".format(i))保存训练好模型
for i in range(epoch):
    print("----第{}轮开始----".format(i+1))
    #开始训练
    #进入训练状态
    wisdom.train()

    for data in train_dataloader:
        imgs,targets = data
        imgs=imgs.cuda()
        targets=targets.cuda()
        outputs = wisdom(imgs)
        loss = loss_fn(outputs,targets)
        #优化器调优
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
        total_train_step += 1
        if total_train_step % 100 ==0:
            print("训练次数:{},loss:{}:".format(total_train_step,loss))
            writer.add_scalar("train_loss",loss.item(),total_train_step)

    #模型测试
    #模型进入测试状态
    wisdom.eval()
    total_test_loss=0
    total_accuracy = 0
    with torch.no_grad():# 提高推理速度和节省内存
        for data in test_dataloader:
            imgs,targets = data
            imgs = imgs.cuda()
            targets = targets.cuda()
            outputs = wisdom(imgs )
            loss = loss_fn(outputs,targets)
            total_test_loss=total_test_loss+loss.item()
            accuracy = (outputs.argmax(1)==targets).sum()
            total_accuracy=total_accuracy+accuracy

    print("整体测试集合的loss:{}".format(total_test_loss))
    print("整体测试集合的准确率:{}".format(total_accuracy/test_data_size))
    writer.add_scalar("test_loss", total_test_loss, total_test_step)
    writer.add_scalar("test_accuracy", total_accuracy/test_data_size, total_test_step)
    total_test_step +=1

    torch.save(wisdom,"./model_train/wisdom_{}.pth".format(i))
    print("模型已经保存!")
    #torch.save(wisdom.state_dict(),"./model_train/wisdom_{}.pth".format(i))
writer.close()

使用GPU加速训练

确保电脑有显卡并正确安装驱动,而且要正确下载对应cuda 

下载教程:

进入pytorch官网

根据自己的系统选择,一般使用anaconda 在Windows下进行python环境管理,复制红框部分,在Anaconda Prompt 粘贴运行,注意自己的cuda版本是否支持

查看cuda版本,打开英伟达控制面板,桌面右键或者系统右下角,然后点击系统信息,之后点击组件

GPU程序设置

在神经网络,损失函数的实例对象后加.cuda()即可,以及在图片数据后加.cuda()

wisdom=wisdom.cuda()
loss_fn=loss_fn.cuda()
imgs=imgs.cuda()
targets=targets.cuda()

 保存模型

torch.save(wisdom,"./model_train/wisdom_{}.pth".format(i))

使用训练好的网络进行分类任务

加载网络模型

model = torch.load("./model_train/wisdom_49.pth")

若出现runtime error 将模型加载方式换成下列语句,将GPU训练的模型映射到CPU

出现runtimer error 将模型加载方式换成下列语句,将GPU训练的模型映射到CPU

或者将分类的图片进行cuda加速

image = image.cuda()#使用GPU训练的模型需要加CUDA

 使用SummaryWriter使训练可视化

打开Anaconda Prompt再激活环境后运行下列命令:

tensorboard --logdir "D:\pyc_workspace\learn_pytorch\logs_train

上列的地址根据train.py代码中的这个语句确定

writer = SummaryWriter("logs_train")

一定要改成自己的文件地址,具体操作见下图

可视化结果如下图所示

 

最后解释一个语句,with torch.no_grad()提高推理速度和节省内存

with torch.no_grad():# 提高推理速度和节省内存
        for data in test_dataloader:
            imgs,targets = data
            imgs = imgs.cuda()
            targets = targets.cuda()
            outputs = wisdom(imgs )
            loss = loss_fn(outputs,targets)
            total_test_loss=total_test_loss+loss.item()
            accuracy = (outputs.argmax(1)==targets).sum()
            total_accuracy=total_accuracy+accuracy

程序汇总 

train.py

使用cpu训练网络

import torchvision
from torch.nn import Conv2d, MaxPool2d, Flatten, Linear, Sequential
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter

from model import *

train_data = torchvision.datasets.CIFAR10("./dataset",train=True,transform=torchvision.transforms.ToTensor(),download=True)

test_data = torchvision.datasets.CIFAR10("./dataset",train=False,transform=torchvision.transforms.ToTensor(),download=True)

#length长度
train_data_size = len(train_data)
test_data_size = len(test_data)
print("训练集长度:{}".format(train_data_size))
print("测试集长度:{}".format(test_data_size))

#使用dataloader加载数据集
train_dataloader = DataLoader(train_data,batch_size=64)
test_dataloader = DataLoader(test_data,batch_size=64)

#创建神经网络
wisdom = Wisdom()
#损失函数
loss_fn= nn.CrossEntropyLoss()
#优化器
learn_rate =0.01
optimizer = torch.optim.SGD(wisdom.parameters(),lr=learn_rate)

#设置网络的一些参数
#记录的训练次数
total_train_step = 0
#记录测试次数
total_test_step = 0
#训练的轮数
epoch=10
#添加tensorboard
writer = SummaryWriter("logs_train")
#tensorboard --logdir "D:\pyc_workspace\learn_pytorch\logs_train"

for i in range(epoch):
    print("----第{}轮开始----".format(i+1))
    #开始训练
    #进入训练状态
    wisdom.train()

    for data in train_dataloader:
        imgs,targets = data
        outputs = wisdom(imgs)
        loss = loss_fn(outputs,targets)
        #优化器调优
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
        total_train_step += 1
        if total_train_step % 100 ==0:
            print("训练次数:{},loss:{}:".format(total_train_step,loss))
            writer.add_scalar("train_loss",loss.item(),total_train_step)

    #模型测试
    #模型进入测试状态
    wisdom.eval()
    total_test_loss=0
    total_accuracy = 0
    with torch.no_grad():
        for data in test_dataloader:
            imgs,targets = data
            outputs = wisdom(imgs )
            loss = loss_fn(outputs,targets)
            total_test_loss=total_test_loss+loss.item()
            accuracy = (outputs.argmax(1)==targets).sum()
            total_accuracy=total_accuracy+accuracy

    print("整体测试集合的loss:{}".format(total_test_loss))
    print("整体测试集合的准确率:{}".format(total_accuracy/test_data_size))
    writer.add_scalar("test_loss", total_test_loss, total_test_step)
    writer.add_scalar("test_accuracy", total_accuracy/test_data_size, total_test_step)
    total_test_step +=1

    torch.save(wisdom,"./model_train/wisdom_{}.pth".format(i))
    print("模型已经保存!")
    #torch.save(wisdom.state_dict(),"./model_train/wisdom_{}.pth".format(i))
writer.close()

train_gpu.py 

使用GPU训练网络

import torch
import torchvision
from torch import nn
from torch.nn import Conv2d, MaxPool2d, Flatten, Linear, Sequential
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter


train_data = torchvision.datasets.CIFAR10("./dataset",train=True,transform=torchvision.transforms.ToTensor(),download=True)
test = train_data.classes
print(test)
test_data = torchvision.datasets.CIFAR10("./dataset",train=False,transform=torchvision.transforms.ToTensor(),download=True)

class Wisdom(nn.Module):
    def __init__(self):
        super(Wisdom, self).__init__()
        self.model1 = Sequential(
            nn.Conv2d(3, 32, 5, padding=2),
            nn.MaxPool2d(2),
            nn.Conv2d(32, 32, 5, padding=2),
            nn.MaxPool2d(2),
            nn.Conv2d(32, 64, 5, padding=2),
            nn.MaxPool2d(2),
            nn.Flatten(),
            nn.Linear(1024, 64),
            nn.Linear(64, 10)

        )

    def forward(self, x):
        x = self.model1(x)

        return x

#length长度
train_data_size = len(train_data)
test_data_size = len(test_data)
print("训练集长度:{}".format(train_data_size))
print("测试集长度:{}".format(test_data_size))

#使用dataloader加载数据集
train_dataloader = DataLoader(train_data,batch_size=64)
test_dataloader = DataLoader(test_data,batch_size=64)

#创建神经网络
wisdom = Wisdom()
wisdom=wisdom.cuda()
#损失函数
loss_fn= nn.CrossEntropyLoss()
loss_fn=loss_fn.cuda()
#优化器
learn_rate =0.01
optimizer = torch.optim.SGD(wisdom.parameters(),lr=learn_rate)

#设置网络的一些参数
#记录的训练次数
total_train_step = 0
#记录测试次数
total_test_step = 0
#训练的轮数
epoch=10
#添加tensorboard
writer = SummaryWriter("logs_train")
#tensorboard --logdir "D:\pyc_workspace\learn_pytorch\logs_train"

for i in range(epoch):
    print("----第{}轮开始----".format(i+1))
    #开始训练
    #进入训练状态
    wisdom.train()

    for data in train_dataloader:
        imgs,targets = data
        imgs=imgs.cuda()
        targets=targets.cuda()
        outputs = wisdom(imgs)
        loss = loss_fn(outputs,targets)
        #优化器调优
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
        total_train_step += 1
        if total_train_step % 100 ==0:
            print("训练次数:{},loss:{}:".format(total_train_step,loss))
            writer.add_scalar("train_loss",loss.item(),total_train_step)

    #模型测试
    #模型进入测试状态
    wisdom.eval()
    total_test_loss=0
    total_accuracy = 0
    with torch.no_grad():# 提高推理速度和节省内存
        for data in test_dataloader:
            imgs,targets = data
            imgs = imgs.cuda()
            targets = targets.cuda()
            outputs = wisdom(imgs )
            loss = loss_fn(outputs,targets)
            total_test_loss=total_test_loss+loss.item()
            accuracy = (outputs.argmax(1)==targets).sum()
            total_accuracy=total_accuracy+accuracy

    print("整体测试集合的loss:{}".format(total_test_loss))
    print("整体测试集合的准确率:{}".format(total_accuracy/test_data_size))
    writer.add_scalar("test_loss", total_test_loss, total_test_step)
    writer.add_scalar("test_accuracy", total_accuracy/test_data_size, total_test_step)
    total_test_step +=1

    torch.save(wisdom,"./model_train/wisdom_{}.pth".format(i))
    print("模型已经保存!")
    #torch.save(wisdom.state_dict(),"./model_train/wisdom_{}.pth".format(i))
writer.close()

test.py

利用神经网络模型进行分类,记得把

img_path ="dog.jpg"改成自己的路径
import torch
import torchvision
from PIL import Image
from torch import nn
from torch.nn import Sequential

train_data = torchvision.datasets.CIFAR10("./dataset",train=True,transform=torchvision.transforms.ToTensor(),download=True)
classes_list = train_data.classes#分类物体列表

img_path ="dog.jpg"
# img_path ="airplane.jpg"
image = Image.open(img_path)
#image = image.convert("RGB")#只保留为3通道

transform = torchvision.transforms.Compose([torchvision.transforms.Resize((32,32,)),torchvision.transforms.ToTensor()])
image = transform(image)
print(image.shape)
class Wisdom(nn.Module):
    def __init__(self):
        super(Wisdom, self).__init__()
        self.model1 = Sequential(
            nn.Conv2d(3, 32, 5, padding=2),
            nn.MaxPool2d(2),
            nn.Conv2d(32, 32, 5, padding=2),
            nn.MaxPool2d(2),
            nn.Conv2d(32, 64, 5, padding=2),
            nn.MaxPool2d(2),
            nn.Flatten(),
            nn.Linear(1024, 64),
            nn.Linear(64, 10)

        )

    def forward(self, x):
        x = self.model1(x)

        return x

#加载网络模型
model = torch.load("./model_train/wisdom_49.pth")
#出现runtimer error 将模型加载方式换成下列语句,将GPU训练的模型映射到CPU
#model = torch.load("./model_train/wisdom_9.pth",map_location=torch.device("cpu"))
print(model)

image=torch.reshape(image,(1,3,32,32))#增加batch_size维度
model.eval()
with torch.no_grad():
    image = image.cuda()#使用GPU训练的模型需要加CUDA
    output = model(image)
print(output)
classes_index=output.argmax(1).item()
print(classes_list)

print("测试图片为:{}".format(classes_list[classes_index]))

总结:------>多看官网 <------

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

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

相关文章

智谱发布新一代基座模型

自 2023 年 3 月发布第一代语言基座模型 ChatGLM 以来&#xff0c;我们经过对基座模型的深入探索&#xff0c;在模型性能和模态上取得了显著的提升。 基于此&#xff0c;在KDD 2024大会上&#xff0c;我们发布了新一代基座模型&#xff0c;包括语言模型GLM-4-Plus、文生图模型…

数据仓库系列15:数据集成的常见挑战有哪些,如何应对?

在大数据时代&#xff0c;数据集成已成为数据仓库建设中不可或缺的一部分。无论是来自多个数据库、外部数据源&#xff0c;还是实时数据流的整合&#xff0c;数据集成都面临着诸多挑战。那么&#xff0c;这些挑战具体是什么&#xff0c;我们又该如何应对呢&#xff1f;本文将通…

Elasticsearch(一):单节点安装并开启ssl

单节点安装并开启ssl 1、概述2、安装2.1、前期准备2.2、下载和解压Elasticsearch2.3、创建用户和配置权限2.4、生成证书2.4.1、创建CA&#xff08;证书颁发机构&#xff09;2.4.2、与CA签署证书&#xff08;生成节点证书&#xff09; 2.5、 为Elasticsearch配置 证书2.6、启动 …

第4章-08-用Python Requests库模拟浏览器访问接口

🏆作者简介,黑夜开发者,CSDN领军人物,全栈领域优质创作者✌,CSDN博客专家,阿里云社区专家博主,2023年CSDN全站百大博主。 🏆数年电商行业从业经验,历任核心研发工程师,项目技术负责人。 🏆本文已收录于专栏:Web爬虫入门与实战精讲,后续完整更新内容如下。 文章…

【奔驰中国-注册安全分析报告】

前言 由于网站注册入口容易被黑客攻击&#xff0c;存在如下安全问题&#xff1a; 暴力破解密码&#xff0c;造成用户信息泄露短信盗刷的安全问题&#xff0c;影响业务及导致用户投诉带来经济损失&#xff0c;尤其是后付费客户&#xff0c;风险巨大&#xff0c;造成亏损无底洞…

什么是基于云的 SIEM

随着企业不断将业务迁移到数字世界&#xff0c;网络威胁的领域也在不断扩大&#xff0c;随着时间流逝&#xff0c;新的威胁不断出现&#xff0c;手段也变得更加巧妙。一个关键问题出现了&#xff1a;组织如何保护其敏感数据、资产和声誉免受网络威胁&#xff1f;这就是基于云的…

Linux中路由功能及ip_forward转发配置

操作系统中路由功能有着至关重要的作用&#xff0c;它决定了网络数据包如何在网络中传输&#xff0c;最终到达目的地。本文简要介绍Linux中的路由功能实现以及IP转发的配置&#xff0c;并验证在容器环境下配置net.ipv4.ip_forward的必要性&#xff0c;以加深理解。 1、Linux中路…

8.6 数据库基础技术-数据库的控制

并发控制 封锁协议 一级封锁协议 二级封锁协议 三级封锁协议 数据库故障和备份 真题 1

案例练习理解ThreadLocal以及应用场景

目录 案例练习 应用场景 ThreadLocal&#xff1a;用来解决多线程程序下并发问题&#xff0c;通过为每一个线程创建一份共享变量的副本保证线程之间的变量的访问和修改互不影响。 案例练习 1.三个销售卖小米SU7&#xff0c;求他们的总销售。使用CountDownLatch维护三个线程 …

跑腿代购系统开发:重塑便捷生活的新篇章

在快节奏的现代生活中&#xff0c;时间成为了最宝贵的资源之一。随着移动互联网技术的飞速发展&#xff0c;人们对于高效、便捷的生活服务需求日益增长&#xff0c;跑腿代购服务应运而生&#xff0c;并迅速成为连接消费者与日常所需商品及服务的重要桥梁。为了满足这一市场需求…

C++:继承用法详解~

在学完C的类和对象&#xff0c;并掌握了类的核心语法与基本用法之后&#xff1b;我们就得去学习一下继承的语法&#xff0c;与继承的用法。简单概括一下&#xff0c;继承是C中一种代码复用的手段&#xff0c;它允许我们&#xff0c;对已有的类&#xff0c;增添新的成员函数或变…

28 TreeView组件

Tkinter ttk.Treeview 组件使用指南 ttk.Treeview 是 Tkinter 的一个高级控件&#xff0c;用于显示和管理层次化数据。它类似于电子表格或列表视图&#xff0c;但提供了更丰富的功能&#xff0c;如可展开的节点、多列显示等。ttk 模块是 Tkinter 的一个扩展&#xff0c;提供了…

NVM安装及配置

一&#xff1a;下载nvm安装包 https://github.com/coreybutler/nvm-windows/releases 二&#xff1a;安装步骤 三&#xff1a;检查环境变量 &#xff08;1&#xff09;、检查用户变量和系统变量中是否有NVM_HOME和NVM_SYMLINK。一般情况下&#xff0c;安装nvm后&#xff0c;系…

Java分布式架构知识体系及知识体系图

Java分布式架构整体知识体系是一个庞大而复杂的领域&#xff0c;它涵盖了多个方面&#xff0c;旨在帮助开发者构建高性能、高可用、可扩展的分布式系统。以下是对Java分布式架构整体知识体系的概述&#xff1a; 一、分布式理论基础 CAP理论&#xff1a; 一致性&#xff08;Con…

GUI编程04:课堂练习及总结

本节内容视频链接&#xff1a;6、课堂练习讲解及总结_哔哩哔哩_bilibilihttps://www.bilibili.com/video/BV1DJ411B75F?p6&vd_sourceb5775c3a4ea16a5306db9c7c1c1486b5 根据前三节学习到的Frame、Panel、Button知识&#xff0c;画出一下窗口界面&#xff1a; 实现代码如下…

避坑之:深信服AC跨三层取MAC(核心交换机是锐捷S7808C_RGOS 11.0(4)B2P1)

今天碰到一个奇怪的现象&#xff0c;深信服AC对接锐捷交换机做跨三层取MAC&#xff0c;怎么都获取不到。 一、坑1&#xff1a;交换机不回应snmp报文 1.1 排查锐捷交换机配置 配置上看着没有问题&#xff0c;重新配置了community 1.2 查看snmp报文是否通畅 我的笔记本是win10…

选对文档版本管理软件:10款工具详解

本篇文章中提到的工具包括&#xff1a;1.PingCode&#xff1b;2.Worktile&#xff1b;3.联想Filez&#xff1b;4.蓝凌云&#xff1b;5.阿里云盘&#xff1b;6.360亿方云&#xff1b;7.无忧企业文档&#xff1b;8.DocStar ECM&#xff1b;9.Dropbox Business&#xff1b;10.Shar…

APP 数据抓取 - Charles 抓包工具的使用(Charles 端口配置、CA 证书配置、Charles Android 模拟器配置)

前言说明 此文章是我在学习 Charles APP 抓包时编写&#xff0c;内容都是亲测有效&#xff0c;文章内容也有参考其他人&#xff0c;参考文章如下&#xff1a; Android 手机使用 charles 抓 https 请求&#xff08;保姆级教程&#xff09;网易 mumu 模拟器安装下载 charles 的…

JAVAEE初阶第二节——多线程基础(上)

系列文章目录 JAVAEE初阶第二节——多线程基础(上) 计算机的工作原理 认识线程&#xff08;Thread&#xff09;Thread 类及常见方法线程的状态 文章目录 系列文章目录JAVAEE初阶第二节——多线程基础(上) 计算机的工作原理 一.认识线程&#xff08;Thread&#xff09;1.概念 …

Leetcode面试经典150题-28.找出字符串第一个匹配项的下标

解法都在代码里&#xff0c;不懂就留言或者私信&#xff0c;比第一题稍微难点 用KMP解这个题简直就像大炮打蚂蚁&#xff0c;但是没办法&#xff0c;现在都是这么卷 package dataStructure.bigFactory;public class _28Strstr {public static int strStr(String s1, String s…