用Pytorch构建一个喵咪识别模型

news/2024/7/24 14:08:22/

 本文参加新星计划人工智能(Pytorch)赛道:https://bbs.csdn.net/topics/613989052

目录

一、前言

二、问题阐述及理论流程

2.1问题阐述

2.2猫咪图片识别原理 

三、用PyTorch 实现 

3.1PyTorch介绍

3.2PyTorch 构建模型的五要素

3.3PyTorch 实现的步骤

3.3.1.数据

3.3.2模型

3.3.3损失函数

3.3.4优化器

3.3.5迭代训练

四、我用了哪些方法防止过拟合?

4.1控制网络规模

4.2数据增强

4.3正则化

4.4K 折交叉验证

五、用自己的图片验证

5.1输入数据

5.2代码实现 

5.3结果输出及分析

完整代码


一、前言

        舍友最近养了只猫咪,看起来很好看,但是你绝对想不到它拉的shi巨臭啊,哈哈哈哈,就很离谱。刚好最近在学习Pytorch,心血来潮,就用Pytorch来做个喵咪识别模型并,于是就有了本篇博文。

     

 

二、问题阐述及理论流程

2.1问题阐述

现一共有 259 张图片,总体分为两类:

有猫咪类

无猫咪类 

2.2猫咪图片识别原理 

三、用PyTorch 实现 

3.1PyTorch介绍

  PyTorch 是一个开源的深度学习框架,它的底层基于 Torch ,但实现与运用全部由 python 来完成。该框架主要用于人工智能领域的科学研究与应用开发。

3.2PyTorch 构建模型的五要素

1.数据:包括数据读取,数据清洗,进行数据划分和数据预处理。

2.模型:包括构建模型模块,组织复杂网络,初始化网络参数,定义网络层。

3.损失函数:包括创建损失函数,设置损失函数超参数,要根据不同任务选择合适的损失函数。

4.优化器:包括根据梯度使用某种优化器更新参数,管理模型参数,调整学习率。

5.迭代训练:组织上述 4 个模块进行反复训练。观察训练效果,绘制 Loss/ Accuracy 曲线或者用 TensorBoard 进行可视化分析。

3.3PyTorch 实现的步骤

3.3.1.数据

        在深度学习时会遇到各种不同形式的数据,如文本、图片、音频等,而每种数据又有多种文件类型。因此拿到数据,我们首先应该了解它的内部结构。

  h5py 文件是一种 " Dataset " 和 " Group " 二合一的容器:

  • 「Dataset」: 类似数组组织的数据的集合,像 numpy 数组一样工作;

  • 「Group」: 包含了其它 Dataset 和 其它 Group ,像字典一样工作。


读取下载好的 h5py 文件(以含有 209 张图片的测试集为例)

import h5pyf = h5py.File("/home/tian/dataset/catvnocat/train/train_catvnoncat.h5","r")#"r"代表读取模式
for key in f.keys():print(key)#输出
#list_classes
#train_set_x
#train_set_y

依次打印出这三个" key "下的内容 

print(f["list_classes"])
print(f["train_set_x"])
print(f["train_set_y"])#输出
#<HDF5 dataset "list_classes": shape (2,), type "|S7">
#<HDF5 dataset "train_set_x": shape (209, 64, 64, 3), type "|u1">
#<HDF5 dataset "train_set_y": shape (209,), type "<i8">

可以得到三个 Dataset 的相关信息:

  • list_classes:包含两个元素 ' non-cat ' 和' cat ',代表无猫和有猫这两个大类。

  • train_set_x :一个四维张量,形状为 209 * 64 * 64 * 3。代表一共有 209 张图片,其中每张图片以像素大小为 64 * 64 的三通道矩阵存储信息。

  • train_set_y :一个一维数组,元素全部存储着 209 张图片对应的标签,其中有猫为 1 ,无猫为 0 。


该 h5py 文件的结构如下图所示:

制作数据集

  从torch.utils.data中引入DatasetDataset是能够表示数据集的抽象类,一般有三个方法:

  • 「__init__方法」

    用于类的初始化,负责创建类的实例属性并进行赋值,并在实例化类后自动执行。这里我创建的 MyData 类中包含以下属性:

    • Archive:文件的路径及对文件的操作,只读或写入

    • Image:样本中的图片或者包含全部图片信息的像素矩阵

    • Label:样本中的标签

    • Transform:可能要对数据进行的变换或增强

  • 「__getitem__方法」

    所有子类都必须重写该方法,该方法通过索引(index)或键(key)访问样本,返回值为 样本和标签。

  • 「__len__方法」

    返回数据集的大小。

 

from torch.utils.data import Datasetclass MyDataset(Dataset):def __init__(self, archive , image , label , transform = None ):self.Archive = h5.File(archive, 'r')self.Images = self.Archive[image]self.Labels = self.Archive[label]self.Transform = transformdef __getitem__(self,index):image = self.Images[index]label = self.Labels[index]if self.Transform is not None:image = self.Transforms(image)  return image ,labeldef __len__(self):return len(self.Labels)train_dataset = MyDataset('/home/tian/dataset/catvnocat/train/train_catvnoncat.h5','train_set_x','train_set_y',train_transformer)
test_dataset = MyDataset('/home/tian/dataset/catvnocat/test/test_catvnoncat.h5','test_set_x','test_set_y',test_transformer)

读取数据集

  从torch.utils.data引入DataLoader,它帮助我们从Dataset中加载样本数据。它联合了数据集 Dataset 和采样器 Sampler,使其本身可以像一个迭代器一样工作。前者提供数据来源,后者提供索引。

from torch.utils.data import Dataloadertrain_loader = DataLoader(train_dataset, batch_size = batch_size_train, shuffle=True)
test_loader = DataLoader(test_dataset, batch_size = batch_size_test, shuffle=False)

shuffle = True指的是将样本打乱,一般只针对训练集。

3.3.2模型

  该神经网络采用简单的 2 隐藏层全连接的方式,并在每一层采用 ReLU 函数作为激活函数,最后通过 Softmax 函数输出预测概率,以达到二分类的目的。

class Net(nn.Module):def __init__(self, in_dim, n_hidden_1,n_hidden_2,out_dim):super(Net, self).__init__()self.layer1 = nn.Sequential(nn.Linear(in_dim, n_hidden_1),nn.BatchNorm1d(n_hidden_1), nn.ReLU(True),nn.Dropout(0.25))self.layer2 = nn.Sequential(nn.Linear(n_hidden_1, n_hidden_2),nn.BatchNorm1d(n_hidden_2), nn.ReLU(True),nn.Dropout(0.25))self.layer3 = nn.Sequential(nn.Linear(n_hidden_2, out_dim), nn.Softmax(dim = 1))def forward(self, x):x = self.layer1(x)x = self.layer2(x)x = self.layer3(x)return x

3.3.3损失函数

  交叉熵损失函数是二分类问题常用的损失函数,可以直接在torch.nn里直接调用,其形式为:

criterion = nn.CrossEntropyLoss()

3.3.4优化器

  在 torch.optim中直接调用随机梯度下降法 SGD:

optimizer = optim.SGD(model.parameters(), lr = learning_rate, weight_decay = 1e-4)

3.3.5迭代训练

  一切准备工作就绪,进行迭代训练。也可以根据需要绘制 Loss/ Accuracy 曲线观察 train_loss 和 val_loss,并以此为依据来调试超参数。

for epoch in range(num_epoches+1):model.train()    for data in train_loader:img, label = dataimg = img.view(img.size(0), -1)  img = Variable(img)label = Variable(label)out = model(img.to(torch.float32))loss = criterion(out, label)_, pred = torch.max(out, 1)acc = (pred == label).sum().item() / (len(train_dataset))optimizer.zero_grad()loss.backward()optimizer.step()model.eval()eval_loss = 0eval_acc = 0        for data in test_loader:img, label = dataimg = img.view(img.size(0), -1)out = model(img.to(torch.float32))loss_1 = criterion(out, label)eval_loss += loss_1.data.item()*label.size(0)_, pred = torch.max(out, 1)eval_acc += (pred == label).sum().item() / len(test_dataset)if epoch%50 == 0:train_losses.append(loss.data.item())train_acc.append(acc)test_losses.append(loss_1.data.item())test_acc.append(eval_acc)print('epoch: {}'.format(epoch))print('Train Loss: {:.4}, Train_Acc: {:.4}'.format(loss.data.item(), acc))print('Test Loss: {:.4f}, Test_Acc: {:.4f}'.format(eval_loss / (len(test_dataset)),eval_acc))fig = plt.figure()
plt.plot(train_counter, train_losses, color='blue')
plt.plot(test_counter, test_losses, '--',color='red')
plt.legend(['Train Loss', 'Test Loss'], loc='upper right')
plt.xlabel('number of training examples seen')
plt.ylabel('negative log likelihood loss')fig = plt.figure()
plt.plot(train_counter, train_acc, color='blue')
plt.plot(test_counter, test_acc, '--',color='red')
plt.legend(['Train Acc', 'Test Acc'], loc='lower right')
plt.xlabel('number of training examples seen')
plt.ylabel('Acc')plt.show()

「结果展示」

         可以看到,过拟合的情况没有发生,并且训练集和测试集的准确率都接近 90%,相对于原本的准确率有了较大的提高。

四、我用了哪些方法防止过拟合?

4.1控制网络规模

  当神经网络具有过多的神经元时,训练集中包含的有限信息量不足以训练隐藏层中的所有神经元,很可能导致过拟合。因此要控制网络规模,既不能太宽也不能太深。

4.2数据增强

  样本量少是造成过拟合的主要原因之一,但我们往往很难从源头上解决这一问题。数据增强通过对现有的样本(以图片为例)进行各种不同的变换(如随机自定义大小裁剪、随机翻转、随机旋转、增加色彩对比度等),然后适当增加训练迭代次数,从而达到样本量扩张的效果。

  本文采用了以下手段进行数据增强:

  • 对输入图片随机裁剪,将原本像素大小为64的图片裁剪成像素大小为48的图片

  • 在水平方向上对一半的图片进行随机翻转

  • 在垂直方向上对一半的图片进行随机翻转

  • 对图在一定角度内进行旋转

from torchvision import transformstrain_transformer = transforms.Compose([transforms.ToPILImage(),transforms.RandomResizedCrop(48),transforms.RandomHorizontalFlip(), transforms.RandomRotation((-15, 15)),transforms.ToTensor(),transforms.Normalize(mean=[0.5, 0.5, 0.5], std=[0.5, 0.5, 0.5])
])test_transformer = transforms.Compose([transforms.ToPILImage(),transforms.Resize(48),transforms.ToTensor(),transforms.Normalize(mean=[0.5, 0.5, 0.5], std=[0.5, 0.5, 0.5])
])

 测试集大多数情况下不进行数据增强,这里为了适应训练集数据增强后的图片大小对测试集进行了尺寸缩放,同样变为像素大小为的图片。

4.3正则化

  • 「Drop_out」

  作为常用的预防过拟合的方法之一,它的主要思想是让隐藏层的节点在每次迭代时有一定几率失效,从而避免对某个节点的强依赖,让反向传播的修正值可以更加平衡的分布到各个参数上。也在一定程度上降低了网络复杂度。

  • 「weight_decay」

  过拟合时模型会拟合很多位置较偏的点,导致拟合函数在某些小区间剧烈变化,权重 w 的绝对值很大。此方法通过控制权重 w 的大小来缓解过拟合的情况。

4.4K 折交叉验证

  以模型调优的思路来缓解过拟合。在训练每种模型时,通过k折交叉验证得到k组不同的训练集和测试集,并将每组的误差平均作为衡量模型泛化能力的准则,从而选择出泛化能力最好的(即最不容易发生过拟合)的模型。

kf = KFold(n_splits = 7, shuffle=True)

五、用自己的图片验证

        训练神经网络最终的目的就是为了应用,因此最后一个环节我们用自己的图片来验证“猫咪识别器”的性能如何。


5.1输入数据

有猫咪类

 无猫咪类

 

5.2代码实现 

from PIL import Image
def trans_pic(img_dir,width,height):image = Image.open(img_dir) #打开图片resized_image = image.resize((width, height), Image.ANTIALIAS)data = np.asarray(resized_image)#转换为矩阵image = Image.fromarray(data)  #将之前的矩阵转换为图片#image.show()#调用本地软件显示图片,win10是叫照片的工具return datapath_cat = [r"/home/tian/Pictures/cat_1.jpg",r"/home/tian/Pictures/cat_2.jpg",r"/home/tian/Pictures/cat_3.jpg",r"/home/tian/Pictures/cat_4.jpg",r"/home/tian/Pictures/cat_5.jpg"]path_nocat = [r"/home/tian/Pictures/nocat_1.jpg",r"/home/tian/Pictures/nocat_2.jpg",r"/home/tian/Pictures/nocat_3.jpg",r"/home/tian/Pictures/nocat_4.jpg",r"/home/tian/Pictures/nocat_5.jpg"]for i in range(5): a = test_transformer(trans_pic(path_cat[i],48,48)).view(1, -1)b = test_transformer(trans_pic(path_nocat[i],48,48)).view(1, -1)out_1 = model(a.to(torch.float32))out_2 = model(b.to(torch.float32))_, pred_1= torch.max(out_1, 1)_, pred_2= torch.max(out_2, 1) if pred_1 == 1:print("第",i+1,"张猫咪图片识别正确")if pred_1 == 0:print("第",i+1,"张猫咪图片识别错误")if pred_2 == 1:print("第",i+1,"张非猫咪图片识别错误")if pred_2 == 0:print("第",i+1,"张非猫咪图片识别正确")print("\n")

5.3结果输出及分析

「结果输出」

第 1 张猫咪图片识别正确
第 1 张非猫咪图片识别正确第 2 张猫咪图片识别正确
第 2 张非猫咪图片识别正确第 3 张猫咪图片识别正确
第 3 张非猫咪图片识别错误第 4 张猫咪图片识别正确
第 4 张非猫咪图片识别错误第 5 张猫咪图片识别正确
第 5 张非猫咪图片识别正确

「结果分析」

  • 猫咪图片:都能识别正确。

  • 非猫咪图片:第三张、第四张图片出现了识别错误。

    • 对于风景图这种与猫咪图片差别很大的图片,识别器能轻松地辨别;

    • 对于老虎、老鼠这些与猫咪在特征上有很多相似地方的动物,猫咪识别器显然还不具备能力将他们很好地区分开来。

  因此在图片识别领域,我们总是需要更合适的网络结构、更大规模的数据以及更合适的超参数选择。

完整代码

import numpy as np
import h5py as h5
import torch
from torch.utils.data import Dataset,DataLoader
import torch.nn.functional as F
from torch import nn, optim
from torch.autograd import Variable
from torchvision import datasets, transforms
from matplotlib import pyplot as pltbatch_size_train = 209
batch_size_test = 50
learning_rate = 0.0075
num_epoches = 3500
momentum = 0.5train_transformer = transforms.Compose([transforms.ToPILImage(),transforms.RandomResizedCrop(48),transforms.RandomHorizontalFlip(),transforms.RandomVerticalFlip(),transforms.RandomRotation((-15, 15)),transforms.ToTensor(),transforms.Normalize(mean=[0.5, 0.5, 0.5], std=[0.5, 0.5, 0.5])
])test_transformer = transforms.Compose([transforms.ToPILImage(),transforms.Resize(48), transforms.ToTensor(),transforms.Normalize(mean=[0.5, 0.5, 0.5], std=[0.5, 0.5, 0.5])
])class MyDataset(Dataset):def __init__(self, archive,image,label,transform = None):self.archive = h5.File(archive, 'r')self.images = self.archive[image]self.labels = self.archive[label]self.transform = transformdef __getitem__(self,index):image = self.images[index]label = self.labels[index]if self.transform is not None:image = self.transform(image)  return image ,labeldef __len__(self):return len(self.labels)train_dataset = MyDataset('/home/tian/dataset/catvnocat/train/train_catvnoncat.h5','train_set_x','train_set_y',train_transformer)
test_dataset = MyDataset('/home/tian/dataset/catvnocat/test/test_catvnoncat.h5','test_set_x','test_set_y',test_transformer)
train_loader = DataLoader(train_dataset, batch_size=batch_size_train, shuffle=True)
test_loader = DataLoader(test_dataset, batch_size=batch_size_test, shuffle=False)class Batch_Net(nn.Module):def __init__(self, in_dim, n_hidden_1,n_hidden_2,out_dim):super(Batch_Net, self).__init__()self.layer1 = nn.Sequential(nn.Linear(in_dim, n_hidden_1),nn.BatchNorm1d(n_hidden_1), nn.ReLU(True),nn.Dropout(0.25))#,nn.Dropout(0.3))self.layer2 = nn.Sequential(nn.Linear(n_hidden_1, n_hidden_2),nn.BatchNorm1d(n_hidden_2), nn.ReLU(True),nn.Dropout(0.25))#,nn.Dropout(0.5))#,nn.Dropout(0.3))#,nn.Dropout(0.5))self.layer3 = nn.Sequential(nn.Linear(n_hidden_2, out_dim),nn.Softmax(dim = 1))def forward(self, x):x = self.layer1(x)x = self.layer2(x)x = self.layer3(x)return x#构建模型实例 
model = Batch_Net(48*48*3,90,10,2)criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(model.parameters(), lr=learning_rate,weight_decay= 1e-4)train_losses = []
train_acc = []
train_counter = [i * len(train_loader)*50 for i in range(num_epoches // 50 + 1)]
test_losses = []
test_acc = []
test_counter = [i * len(test_loader)*50 for i in range(num_epoches // 50 + 1)]for epoch in range(num_epoches+1):model.train()for data in train_loader:img, label = dataimg = img.view(img.size(0), -1)  img = Variable(img)label = Variable(label)out = model(img.to(torch.float32))loss = criterion(out, label)_, pred = torch.max(out, 1)acc = (pred == label).sum().item() / (len(train_dataset))optimizer.zero_grad()loss.backward()optimizer.step()model.eval()eval_loss = 0eval_acc = 0for data in test_loader:img, label = dataimg = img.view(img.size(0), -1)out = model(img.to(torch.float32))loss_1 = criterion(out, label)eval_loss += loss_1.data.item()*label.size(0)_, pred = torch.max(out, 1)eval_acc += (pred == label).sum().item() / len(test_dataset)if epoch%50 == 0:train_losses.append(loss.data.item())train_acc.append(acc)test_losses.append(loss_1.data.item())test_acc.append(eval_acc)print('epoch: {}'.format(epoch))print('Train Loss: {:.4}, Train_Acc: {:.4}'.format(loss.data.item(), acc))print('Test Loss: {:.4f}, Test_Acc: {:.4f}'.format(eval_loss / (len(test_dataset)),eval_acc))fig = plt.figure()
plt.plot(train_counter, train_losses, color='blue')
plt.plot(test_counter, test_losses, '--',color='red')
plt.legend(['Train Loss', 'Test Loss'], loc='upper right')
plt.xlabel('number of training examples seen')
plt.ylabel('negative log likelihood loss')fig = plt.figure()
plt.plot(train_counter, train_acc, color='blue')
plt.plot(test_counter, test_acc, '--',color='red')
plt.legend(['Train Acc', 'Test Acc'], loc='lower right')
plt.xlabel('number of training examples seen')
plt.ylabel('Acc')plt.show()

http://www.ppmy.cn/news/33738.html

相关文章

Mybatis(一):环境搭建

Mybatis&#xff08;一&#xff09;&#xff1a;环境搭建前言一、MyBatis简介1、MyBatis历史2、MyBatis特性3、MyBatis下载4、和其它持久化层技术对比二、搭建MyBatis1、开发环境2、创建maven工程2.1 打包方式&#xff1a;jar2.2 引入依赖3、创建MyBatis的核心配置文件4、创建m…

hash值——软件中的唯一标识符

在软件中&#xff0c;“ hash”这个词有多种含义&#xff0c;但是我们在这里讨论的是维基百科所谓的 “cryptographic hash function”.。 hash是什么 简而言之&#xff0c;hash是字母和数字的字符串&#xff0c;意味着通过一个较小的、唯一的代码来识别一组信息。您可能在其…

RapidAI/paddleocr_convert:PaddleOCR中模型快速转换为ONNX格式

目录RapidAI/paddleocr_convert使用步骤更新日志RapidAI/paddleocr_convert 本仓库主要是针对性地将PaddleOCR中推理模型转换为ONNX格式。注意&#xff1a; 输入&#xff1a;推理模型的url或者本地tar路径输出&#xff1a;转换后的ONNX模型如果是识别模型&#xff0c;需要提供对…

图形视图框架 事件处理(item)

在图形界面框架中的事件都是先由视图进行接收&#xff0c;然后传递给场景&#xff0c;再由场景传递给图形项。通过键盘处理的话&#xff0c;需要设置焦点&#xff0c;在QGraphicsScene中使用setFoucesItem&#xff08;&#xff09;函数可以设置焦点&#xff0c;或者图形项使用s…

技术分享 | PBM备份恢复

作者&#xff1a;张洪 爱可生南区 DBA 团队成员&#xff0c;主要负责mysql故障处理及相关技术支持。爱好旅游&#xff0c;摄影。 本文来源&#xff1a;原创投稿 *爱可生开源社区出品&#xff0c;原创内容未经授权不得随意使用&#xff0c;转载请联系小编并注明来源。 概述 Per…

下载并导入MySQL示例数据库employees

MySQL示例数据库employees一、下载employees数据库二、MySQL官方参考手册三、具体步骤3.1 下载test_db3.2 在test_db-master中打开cmd(进入test_db-master目录)3.3 run-install3.4 验证employee数据3.5 show databases\tables & select * from departments**3.6 select * f…

前端git必备技能,如何合并分支以及出现合并冲突后如何解决

文章目录一、合并分支二、可能出现的冲突和解决三、过程分享一、合并分支 注意&#xff0c;我们常说的master或main主干也可以理解为分支&#xff0c;可以是分支合并到主干&#xff0c;或分支合并到分支。 需求&#xff1a;cloudweb的2.6.0和2.6.1是并行开发的&#xff0c;现…

linux中写定时任务

场景&#xff1a;我们生产环境中有大量的日志记录&#xff0c;但是我们的磁盘没有太大&#xff0c;需要定时清理磁盘 文章目录crond 定时任务详解安装定时任务crontab服务启动与关闭crontab操作crontab 命令test.sh查看日志丢弃linux中的执行日志Linux进入nano模式方式一方式二…

【8】核心易中期刊推荐——人工智能与机器人

🚀🚀🚀NEW!!!核心易中期刊推荐栏目来啦 ~ 📚🍀 核心期刊在国内的应用范围非常广,核心期刊发表论文是国内很多作者晋升的硬性要求,并且在国内属于顶尖论文发表,具有很高的学术价值。在中文核心目录体系中,权威代表有CSSCI、CSCD和北大核心。其中,中文期刊的数…

【代码随想录-刷题学习JavaScript】day2-part02数组

继续数组的部分 977.有序数组的平方 &#xff0c;209.长度最小的子数组 &#xff0c;59.螺旋矩阵II 今天会有个小结 一、LeetCode977.有序数组的平方 文章讲解 视频讲解 二、LeetCode 209.长度最小的子数组 题目建议&#xff1a; 本题关键在于理解滑动窗口&#xff0c;这个滑动…

太强了,英伟达面对ChatGPT还有这一招...

大家好&#xff0c;我是 Jack。 今年可谓是 AI 元年&#xff0c;ChatGPT、AIGC、VITS 都火了一波。 我也先后发布了这几期视频&#xff1a; 这是一个大模型的时代&#xff0c;AI 能在文本、图像、音频等领域大放异彩&#xff0c;得益于大模型。而想要预训练大模型&#xff0c…

int *p = a、p = a、*p = a

int *p &a; //初始化一个int *类型指针&#xff0c;同时将变量a的地址存入p指针这里是一个特殊用法&#xff0c;仅在初始化变量的时候可以使用&#xff0c;应分为两个部分去进行理解。int *p; //初始化一个int * 类型指针pp &a; //将变量a的地址存入p指针&#xff0c…

基于深度学习的动物识别系统(YOLOv5清新界面版,Python代码)

摘要&#xff1a;动物识别系统用于识别和统计常见动物数量&#xff0c;通过深度学习技术检测日常几种动物图像识别&#xff0c;支持图片、视频和摄像头画面等形式。在介绍算法原理的同时&#xff0c;给出Python的实现代码、训练数据集以及PyQt的UI界面。动物识别系统主要用于常…

哈夫曼编码、哈夫曼树

已知一个文件中出现的各字符及其对应的率如下表所示。若采用定长编码&#xff0c;则该文件中字符的码长应为( )。若采用Huffman编码&#xff0c;则字符序列face的编码应为&#xff08; ) 字符abcdef频率4513121695码长决定了可以显示几位字符&#xff0c;题中一共有6位&#x…

【Linux】环境变量(基本概念 常见环境变量 测试PATH 环境变量相关命令)

文章目录环境变量基本概念常见环境变量测试PATH别的环境变量通过系统调用获取或设置环境变量环境变量相关命令export: 设置一个新的环境变量set: 显示本地定义的shell变量和环境变量unset: 清除环境变量通过代码如何获取环境变量环境变量 基本概念 环境变量(environment vari…

ThreadPool线程池源码解析

ThreadPool线程池源码解析 文章目录前言一、基本使用二、执行流程三、源码分析ThreadPoolExecutor 中重要属性ThreadPoolExecutor 内部类Workerexecute&#xff08;&#xff09;方法addWorker(command, true)方法runWorker(worker )方法getTask()方法shutdown和shutdownNow四、…

Java栈和队列·下

Java栈和队列下2. 队列(Queue)2.1 概念2.2 实现2.3 相似方法的区别2.4 循环队列3. 双端队列 (Deque)3.1 概念4.java中的栈和队列5. 栈和队列面试题大家好&#xff0c;我是晓星航。今天为大家带来的是 Java栈和队列下 的讲解&#xff01;&#x1f600; 继上一个讲完的栈后&…

1.9 日本蜡烛图技术之支撑和压力的其他含义

破低反涨和破高反跌形态 支撑和压力的研究不能局限于涨跌幅边界研究&#xff0c;用K线图来验证会注意到很多突破来临的信号破低反涨形态 一种移动和反向移动&#xff0c;价格跌破支撑&#xff0c;然后反弹重新上涨通常建立新的支撑线 破高反跌形态&#xff1a;突破压力后&…

hadoop理论基础(一)

1.hadoop的组成2 HDFS概述HDFS&#xff08;Hadoop Distributed File System&#xff09;是一个分布式文件系统&#xff08;1&#xff09;NameNode:存储文件的元数据;如文件名、文件目录结构、文件属性&#xff0c;以及每个文件的块列表和块所在的DataNode等。(2)DataNode:在本地…

【测试开发篇4】测试模型

目录 一、软件测试V模型 编码前 概要设计&#xff1a; 详细设计&#xff1a; 编码后&#xff1a; 单元测试&集成测试 系统测试 验收测试 V模型的特点 优点&#xff1a; 缺点&#xff1a; 二、软件测试W模型 编码之前&#xff1a; 编码的时候&#xff1a; 编…