结合Boosting理论与深度ResNet:ICML2018论文代码详解与实现

本文主要是介绍结合Boosting理论与深度ResNet:ICML2018论文代码详解与实现,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

代码见:JordanAsh/boostresnet: A PyTorch implementation of BoostResNet

原始论文:Huang F, Ash J, Langford J, et al. Learning deep resnet blocks sequentially using boosting theory[C]//International Conference on Machine Learning. PMLR, 2018: 2058-2067.

代码解析及功能实现

这段代码实现了一个训练ResNet块并逐层训练的过程。这个过程结合了Boosting理论,通过逐层训练ResNet块来提高分类性能。

代码前期准备

import torch
import sys
import pickle
import os
import numpy as np
import torchfile
from torch import nn
from torch.autograd import Variable
import argparse

导入了必要的库,包括PyTorch、NumPy、系统操作、数据加载和命令行参数解析库。

解析命令行参数

parser = argparse.ArgumentParser()
parser.add_argument('--gammaFirst', default=0.5, help='initial gamma')
parser.add_argument('--checkEvery', default=10000, help='how frequently to check gamma requirement - 10k for cifar, 5k for svhn')
parser.add_argument('--data', default='SVHN.t7', help='load data')
parser.add_argument('--gammaThresh',default=-0.0001, help='gamma threshold to stop training layer')
parser.add_argument('--lr', default=0.001, help='learning rate')
parser.add_argument('--maxIters', default=10000, help='maximum iterations before stopping train layer')
parser.add_argument("--transform", help='do CIFAR-style image transformations?', action="store_true")
parser.add_argument('--printEvery', default=100, help='how frequently to print')
parser.add_argument('--batchSize', default=100, help='batch size')
parser.add_argument('--modelPath', default='model.pt', help='output model')
opt = parser.parse_args()

解析命令行参数,设置各种训练超参数,包括初始gamma值、检查gamma的频率、数据集路径、gamma阈值、学习率、最大迭代次数、是否进行数据变换、打印频率、批处理大小和模型保存路径。

加载数据

data = torchfile.load(opt.data) # load dataset in torch format (assuming already normalized)
Xtrain = data.Xtrain
Ytrain = data.Ytrain - 1
Xtest = data.Xtest
Ytest = data.Ytest - 1
cut = int(np.shape(Xtrain)[0] / opt.batchSize * opt.batchSize) # cut off a few samples for simplicity
nTrain = cut
Xtrain = Xtrain[:cut]
Ytrain = Ytrain[:cut]
cut = int(np.shape(Xtest)[0] / opt.batchSize * opt.batchSize)
Xtest = Xtest[:cut]
Ytest = Ytest[:cut]
nTest = cut
numClasses = 10

加载并处理数据集,将训练集和测试集按批处理大小进行裁剪,以确保数据大小是批处理大小的整数倍。

定义打印函数

def printer(print_arr):for v in print_arr: sys.stdout.write(str(v) + '\t')sys.stdout.write('\n')sys.stdout.flush()

定义一个打印函数,用于在控制台打印输出。

加载ResNet模型并构建块

import fbrn
model = fbrn.tmp
model.load_state_dict(torch.load('fbrn.pth'))
allBlocks = {}
allBlocks[0] = nn.Sequential(model[0], model[1], model[2])
for i in range(8): allBlocks[1 + i] = model[3][i] 
for i in range(8): allBlocks[9 + i] = model[4][i] 
for i in range(8): allBlocks[17+ i] = model[5][i]
criterion = nn.CrossEntropyLoss().cuda()
nFilters = 15; rounds = 25

加载预训练的ResNet模型,并将其分成多个块,分别存储在allBlocks字典中。定义损失函数为交叉熵损失。

  1. allBlocks[0] 包含 model 的第 0 层到第 2 层,使用 nn.Sequential 将这些层组合在一起。
  2. for i in range(8): allBlocks[1 + i] = model[3][i]model 的第 3 层的 8 个子层分别存储在 allBlocks 的索引 1 到 8。
  3. for i in range(8): allBlocks[9 + i] = model[4][i]model 的第 4 层的 8 个子层分别存储在 allBlocks 的索引 9 到 16。
  4. for i in range(8): allBlocks[17 + i] = model[5][i]model 的第 5 层的 8 个子层分别存储在 allBlocks 的索引 17 到 24。

这样,allBlocks 字典就包含了模型的所有层,并且这些层被分割成了不同的块,每个块对应一个连续的索引范围。

分块的意义

这段代码将模型分为了三个主要的残差块(residual blocks):

  1. 第 0 块:allBlocks[0] 包含模型的第 0 层到第 2 层。
  2. 第 1 块:allBlocks[1]allBlocks[8] 包含模型的第 3 层的 8 个子层。
  3. 第 2 块:allBlocks[9]allBlocks[16] 包含模型的第 4 层的 8 个子层。
  4. 第 3 块:allBlocks[17]allBlocks[24] 包含模型的第 5 层的 8 个子层。

数据增强函数

def transform(X):tmp = np.zeros((np.shape(X)[0], 3, 38, 38))tmp[:, :, 2:34, 2:34] = Xfor i in range(np.shape(X)[0]):r1 = np.random.randint(4)r2 = np.random.randint(4)X[i] = tmp[i, :, r1 : r1 + 32, r2 : r2 + 32]if np.random.uniform() > .5:X[i] = X[i, :, :, ::-1]return X

定义数据增强函数,用于CIFAR样式的图像变换,进行随机裁剪和水平翻转。

模型评估函数

def getPerformance(net, X, Y, n):acc = 0.model.eval()Xoutput = np.zeros((X.shape[0], 10))for batch in range(int(X.shape[0] / opt.batchSize)):start = batch * opt.batchSize; stop = (batch + 1) * opt.batchSize - 1ints = np.linspace(start, stop, opt.batchSize).astype(int)data = Variable(torch.from_numpy(X[ints])).float().cuda()for i in range(n): data = allBlocks[i](data)output = net(data)acc += np.mean(torch.max(output, 1)[1].cpu().data.numpy() == Y[ints])Xoutput[ints] = output.cpu().data.numpy()acc /= (X.shape[0] / opt.batchSize)model.train()return acc, Xoutput

定义模型评估函数,用于在训练和测试数据集上计算模型的准确率。

初始化模型统计数据

a_previous = 0.0
a_current = -1.0
s = np.zeros((nTrain, numClasses))
cost = np.zeros((nTrain, numClasses))
Xoutput_previous = np.zeros((nTrain, numClasses))
Ybatch = np.zeros((opt.batchSize))
YbatchTest = np.zeros((opt.batchSize))
gamma_previous = opt.gammaFirst
totalIterations = 0; tries = 0

初始化一些变量,用于存储模型统计数据、损失、输出和其他辅助数据。

逐层训练模型

for n in range(rounds):gamma = -1Z = 0# create cost function  for i in range(nTrain):localSum = 0for l in range(numClasses):if l != Ytrain[i]:cost[i][l] = np.exp(s[i][l] - s[i][int(Ytrain[i])])localSum += cost[i][l]cost[i][int(Ytrain[i])] = -1 * localSumZ += localSum# fetch the correct classification layersbk = allBlocks[n]ci = nn.Sequential(model[6], model[7], model[8])if n < 17: ci = nn.Sequential(allBlocks[17], ci)if n < 9: ci = nn.Sequential(allBlocks[9], ci)modelTmp = nn.Sequential(bk, ci, nn.Softmax(dim=0))modelTmp = modelTmp.cuda()optimizer = torch.optim.Adam(modelTmp.parameters(), lr=opt.lr) tries = 0XbatchTest = torch.zeros(opt.batchSize, nFilters, 32, 32)while (gamma < opt.gammaThresh and ((opt.checkEvery * tries) < opt.maxIters)):accTrain = 0; accTest = 0; err = 0;for batch in range(1, opt.checkEvery + 1):optimizer.zero_grad()# get batch of training samplesints = np.random.random_integers(np.shape(Xtrain)[0] - 1, size=(opt.batchSize))Xbatch = Xtrain[ints]Ybatch = Variable(torch.from_numpy(Ytrain[ints])).cuda().long()# do transformationsif opt.transform: Xbatch = transform(Xbatch)data = Variable(torch.from_numpy(Xbatch)).float().cuda()for i in range(n): data = allBlocks[i](data)# get gradientsoutput = modelTmp(data)loss = torch.exp(criterion(output, Ybatch))loss.backward()err += loss.data[0]# evaluate training accuracyoutput = modelTmp(data)accTrain += np.mean(torch.max(output, 1)[1].cpu().data.numpy() == Ytrain[ints])# get test accuracy model.eval()ints = np.random.random_integers(np.shape(Xtest)[0] - 1, size=(opt.batchSize))Xbatch = Xtest[ints]data = Variable(torch.from_numpy(Xbatch)).float().cuda()for i in range(n): data = allBlocks[i](data)output = modelTmp(data)accTest += np.mean(torch.max(output, 1)[1].cpu().data.numpy() == Ytest[ints])model.train()if batch % opt.printEvery == 0:accTrain /= opt.printEveryaccTest /= opt.printEveryerr /= opt.printEveryprinter([n, rounds, totalIterations + batch + (opt.checkEvery * tries), err, accTrain, accTest])accTrain = 0;accTest = 0; err = 0;optimizer.step()totalIterations += opt.checkEverytries += 1# get performance of new layera_current, Xoutput_previous = getPerformance(modelTmp, Xtrain, Ytrain, n + 1)gamma = (a_current - a_previous) / (1 - a_current)a_previous = a_currentprinter([n, gamma, opt.gammaThresh])if gamma < opt.gammaThresh:breakelse:s += np.log(Xoutput_previous)

逐层训练ResNet块,使用Boosting理论来增强分类性能。具体步骤包括:

  1. 计算损失函数。
  2. 加载对应的ResNet块。
  3. 进行优化迭代,计算训练和测试集上的准确率,并根据gamma值判断是否继续训练。

保存模型

torch.save(model.state_dict(), opt.modelPath)

保存训练好的模型。

核心代码

初始化部分

a_previous = 0.0
a_current = -1.0
s = np.zeros((nTrain, numClasses))
cost = np.zeros((nTrain, numClasses))
Xoutput_previous = np.zeros((nTrain, numClasses))
Ybatch = np.zeros((opt.batchSize))
YbatchTest = np.zeros((opt.batchSize))
gamma_previous = opt.gammaFirst
totalIterations = 0; tries = 0

这里初始化了一些变量,包括模型的统计信息、训练样本的预测输出、批量训练样本等。其中:

  • a_previousa_current 是当前和之前的提升系数。
  • s 是一个保存每个训练样本在每个类别上的累积输出。
  • cost 是样本的代价矩阵。
  • Xoutput_previous 是上一轮的输出。
  • gamma_previous 是上一轮的提升系数。
  • totalIterationstries 用于记录总迭代次数和尝试次数。

1.初始化阶段(主循环)

for n in range(rounds):gamma = -1Z = 0
  • gamma = -1Z = 0 初始化了一些用于计算的变量。
  • rounds 是算法的迭代轮数。在代码中设置为25,每轮迭代都会添加一个新的残差块,并调整模型参数。
  • 每一轮次训练前将 gammaZ 置零。

2.计算代价函数

    for i in range(nTrain):localSum = 0for l in range(numClasses):if l != Ytrain[i]:cost[i][l] = np.exp(s[i][l] - s[i][int(Ytrain[i])])localSum += cost[i][l]cost[i][int(Ytrain[i])] = -1 * localSumZ += localSum

这个部分计算每个训练样本的代价函数,并将计算所有错误分类的代价,存储在 cost 数组中。

每个训练样本的成本通过计算每个类别的错误分类代价 cost。如果样本 i 的真实类别为 Ytrain[i],则计算该样本在其他类别上的成本之和 localSum,并将 localSum 赋值给该样本真实类别的成本(取负值)。

  • cost[i][l] = np.exp(s[i][l] - s[i][int(Ytrain[i])]) 计算样本 i i i 在类别 l l l 上的代价。
  • cost[i][int(Ytrain[i])] = -1 * localSum 将当前样本在其真实类别上的代价设为负的 localSum
  • Z 是所有样本的总代价。

3. 获取当前分类层

    bk = allBlocks[n]ci = nn.Sequential(model[6], model[7], model[8])if n < 17: ci = nn.Sequential(allBlocks[17], ci)if n < 9:  ci = nn.Sequential(allBlocks[9], ci)modelTmp = nn.Sequential(bk, ci, nn.Softmax(dim=0))modelTmp = modelTmp.cuda()

这段代码的作用是创建一个临时模型 modelTmp,它由当前迭代的残差块 bk 和一些预定义的分类层 ci 组成。以下是具体解释:

  • bk 表示当前迭代的残差块。
  • ci 表示后续的分类层,包含模型中的一些层。

根据当前迭代次数 n,动态调整 ci 的层次结构:

  • 如果当前迭代次数 n 小于 17,那么在分类层 ci 前面加上第 17 块的残差块。
  • 如果当前迭代次数 n 小于 9,那么在分类层 ci 前面加上第 9 块的残差块。

这样的设计使得模型在不同的迭代次数 n 下,分类层 ci 的结构不同,逐步增加模型的复杂性。这个结构确保了模型能够逐层学习和调整,从而提高分类性能。

4.1 优化器设置

    optimizer = torch.optim.Adam(modelTmp.parameters(), lr=opt.lr) tries = 0XbatchTest = torch.zeros(opt.batchSize, nFilters, 32, 32)

使用 Adam 优化器,并初始化 XbatchTest 用于测试。

Adam 优化器是什么?大概的数学原理是什么?是对应的梯度下降算法吗?还是什么其他的算法?

Adam(Adaptive Moment Estimation)是一种基于一阶梯度的优化算法,结合了动量和自适应学习率两个方法。它在深度学习中被广泛使用,因为它在处理稀疏梯度和非平稳目标上表现良好。
Adam的数学原理:

  • 计算每个参数的梯度的一阶动量(平均值)和二阶动量(方差)。
  • 对每个参数的更新使用动量和学习率的校正。

具体来说,Adam 优化器的步骤如下:

  1. 初始化动量和二阶动量。
  2. 在每次迭代中更新动量和二阶动量。
  3. 根据动量和二阶动量校正参数更新步长。

具体的更新公式为:

  1. m t = β 1 m t − 1 + ( 1 − β 1 ) g t m_t = \beta_1 m_{t-1} + (1 - \beta_1) g_t mt=β1mt1+(1β1)gt
  2. v t = β 2 v t − 1 + ( 1 − β 2 ) g t 2 v_t = \beta_2 v_{t-1} + (1 - \beta_2) g_t^2 vt=β2vt1+(1β2)gt2
  3. m ^ t = m t 1 − β 1 t \hat{m}_t = \frac{m_t}{1 - \beta_1^t} m^t=1β1tmt
  4. v ^ t = v t 1 − β 2 t \hat{v}_t = \frac{v_t}{1 - \beta_2^t} v^t=1β2tvt
  5. θ t = θ t − 1 − η m ^ t v ^ t + ϵ \theta_t = \theta_{t-1} - \eta \frac{\hat{m}_t}{\sqrt{\hat{v}_t} + \epsilon} θt=θt1ηv^t +ϵm^t
    其中:
  • g t g_t gt 是梯度。
  • m t m_t mt v t v_t vt 分别是一阶和二阶动量。
  • β 1 \beta_1 β1 β 2 \beta_2 β2 是动量系数,通常取 0.9 0.9 0.9 0.999 0.999 0.999
  • ϵ \epsilon ϵ 是一个小常数,用于防止分母为零,通常取 1 0 − 8 10^{-8} 108
  • η \eta η 是学习率。

4.2 训练循环

在这里插入图片描述

while (gamma < opt.gammaThresh and ((opt.checkEvery * tries) < opt.maxIters)):accTrain = 0; accTest = 0; err = 0;for batch in range(1, opt.checkEvery+1):optimizer.zero_grad()

zero_grad():在每次反向传播之前,将所有参数的梯度缓存清零。在 PyTorch 中,梯度是累加的,所以需要在每次迭代开始前清零。

在满足 gamma 小于阈值和最大迭代次数限制的条件下,开始训练循环。

关于 opt.gammaThreshgamma

这里的 opt.gammaThresh 对应算法中的 γ t \gamma_t γt,而 gamma 对应的是 γ \gamma γ。代码中的逻辑 while (gamma < opt.gammaThresh) 实际上在检查当前的 γ \gamma γ 是否小于阈值。这是因为我们希望 γ \gamma γ 足够大,代表模型的分类能力足够强,当 γ \gamma γ 小于阈值时,停止训练。

具体来说:

  • gamma 初始化为 -1,表示最差情况。
  • 当训练时,更新 gamma 的值,如果 gamma 达到或超过 opt.gammaThresh,则说明模型性能达到预期,可以停止训练。
获取训练样本批次
            ints = np.random.random_integers(np.shape(Xtrain)[0] - 1, size=(opt.batchSize))Xbatch = Xtrain[ints]Ybatch = Variable(torch.from_numpy(Ytrain[ints])).cuda().long()

从训练集中随机选择一个批次样本,并将其转换为 PyTorch 变量。

数据变换和前向传播
            if opt.transform: Xbatch = transform(Xbatch)data = Variable(torch.from_numpy(Xbatch)).float().cuda()for i in range(n): data = allBlocks[i](data)

如果指定了数据变换,则对数据进行变换,然后进行前向传播,通过前 n 个残差块处理数据。

获取梯度和更新权重
            output = modelTmp(data)loss = torch.exp(criterion(output, Ybatch))loss.backward()err += loss.data[0]output = modelTmp(data)accTrain += np.mean(torch.max(output,1)[1].cpu().data.numpy() == Ytrain[ints])model.eval()ints = np.random.random_integers(np.shape(Xtest)[0] - 1, size=(opt.batchSize))Xbatch = Xtest[ints]data = Variable(torch.from_numpy(Xbatch)).float().cuda()for i in range(n): data = allBlocks[i](data)output = modelTmp(data)accTest += np.mean(torch.max(output,1)[1].cpu().data.numpy() == Ytest[ints])model.train()

在训练过程中,通过交叉熵+指数损失函数计算并累积损失 err

criterion = nn.CrossEntropyLoss().cuda()

计算训练准确率 accTrain 和测试准确率 accTest

打印和梯度裁剪
            if batch % opt.printEvery == 0:accTrain /= opt.printEveryaccTest  /= opt.printEveryerr /= opt.printEveryprinter([n, rounds, totalIterations + batch + (opt.checkEvery * tries), err, accTrain, accTest])accTrain = 0; accTest = 0; err = 0;for p in modelTmp.parameters(): p.grad.data.clamp_(-.1, .1)            optimizer.step()
  • 每隔 opt.printEvery 次批量训练输出一次当前状态,包括错误率、训练准确率和测试准确率。
  • 进行梯度裁剪,防止梯度爆炸。
  • step():执行一步优化算法,即根据当前的梯度和动量更新模型参数。

梯度裁剪对应的代码是:

for p in modelTmp.parameters(): p.grad.data.clamp_(-.1, .1)

这段代码通过限制梯度的值在 [-0.1, 0.1] 范围内,防止梯度爆炸。这对于稳定训练过程非常重要,尤其是深度神经网络,梯度可能会在反向传播过程中变得非常大。

计算 gamma

        accTrain, Xoutput = getPerformance(modelTmp, Xtrain, Ytrain, n)gamma_current = -1 * np.sum(Xoutput * cost) / Zgamma = (gamma_current ** 2 - gamma_previous ** 2)/(1 - gamma_previous ** 2) if gamma > 0: gamma = np.sqrt(gamma)else: gamma = -1 * np.sqrt(-1 * gamma)a_current = 0.5 * np.log((1 + gamma_current) / (1 - gamma_current))

更新模型参数,并在每个批量训练后进行一次梯度下降。

  1. 计算当前模型的性能,得到 gamma_current
  2. 根据 gamma_currentgamma_previous 更新 gamma

公式:
γ t ← γ ~ t + 1 2 − γ ~ t 2 1 − γ ~ t 2 \gamma_t \leftarrow \sqrt{\frac{\tilde{\gamma}_{t+1}^2 - \tilde{\gamma}_t^2}{1 - \tilde{\gamma}_t^2}} γt1γ~t2γ~t+12γ~t2

其中:

  • gamma_current 是当前训练轮次的 γ t \gamma_t γt
  • gamma_previous 是前一次训练轮次的 γ t \gamma_t γt
为什么这样处理负数的情况?

γ \gamma γ 为负数时,我们使用以下公式进行更新:
γ = − 1 ∗ − 1 ∗ γ ~ t + 1 2 − γ ~ t 2 1 − γ ~ t 2 \gamma = -1 * \sqrt{-1 * \frac{\tilde{\gamma}_{t+1}^2 - \tilde{\gamma}_t^2}{1 - \tilde{\gamma}_t^2}} γ=111γ~t2γ~t+12γ~t2

这样处理的原因是:

  • γ \gamma γ 的计算可能会因为 γ ~ t + 1 2 − γ ~ t 2 \tilde{\gamma}_{t+1}^2 - \tilde{\gamma}_t^2 γ~t+12γ~t2 的值而导致根号内出现负数。这在数学上是不可接受的。
  • 为了避免这种情况,取负号后再开方,以确保 γ \gamma γ 的计算结果是一个实数。负号处理后仍然保持 γ \gamma γ 的真实值,因为 γ \gamma γ 本身可以是负数或正数。

这个处理方式巧妙地避免了计算过程中根号内为负数的问题,同时保持了 γ \gamma γ 的实际含义。

尝试次数和权重更新

        tries += 1if (gamma > opt.gammaThresh or ((opt.checkEvery * tries) >= opt.maxIters)):totalIterations = totalIterations + (tries * opt.checkEvery)printer([gamma, gamma_current, gamma_previous])printer(['a_{t+1}:', a_current, 'gamma_t:', gamma])    s += Xoutput * a_current - Xoutput_previous * a_previousaccTest, _ = getPerformance(modelTmp, Xtest, Ytest, n)    printer(['t', rounds, 'numBatches:', tries * opt.checkEvery, 'test accuracy:', accTest])    gamma_previous = gamma_current

更新 tries,如果 gamma 达到阈值或尝试次数达到最大迭代次数,则记录迭代次数并打印信息。最后更新累积输出 sgamma_previous

这篇关于结合Boosting理论与深度ResNet:ICML2018论文代码详解与实现的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1071293

相关文章

Python使用Tenacity一行代码实现自动重试详解

《Python使用Tenacity一行代码实现自动重试详解》tenacity是一个专为Python设计的通用重试库,它的核心理念就是用简单、清晰的方式,为任何可能失败的操作添加重试能力,下面我们就来看... 目录一切始于一个简单的 API 调用Tenacity 入门:一行代码实现优雅重试精细控制:让重试按我

深度解析Spring Security 中的 SecurityFilterChain核心功能

《深度解析SpringSecurity中的SecurityFilterChain核心功能》SecurityFilterChain通过组件化配置、类型安全路径匹配、多链协同三大特性,重构了Spri... 目录Spring Security 中的SecurityFilterChain深度解析一、Security

Redis客户端连接机制的实现方案

《Redis客户端连接机制的实现方案》本文主要介绍了Redis客户端连接机制的实现方案,包括事件驱动模型、非阻塞I/O处理、连接池应用及配置优化,具有一定的参考价值,感兴趣的可以了解一下... 目录1. Redis连接模型概述2. 连接建立过程详解2.1 连php接初始化流程2.2 关键配置参数3. 最大连

Python实现网格交易策略的过程

《Python实现网格交易策略的过程》本文讲解Python网格交易策略,利用ccxt获取加密货币数据及backtrader回测,通过设定网格节点,低买高卖获利,适合震荡行情,下面跟我一起看看我们的第一... 网格交易是一种经典的量化交易策略,其核心思想是在价格上下预设多个“网格”,当价格触发特定网格时执行买

Python标准库之数据压缩和存档的应用详解

《Python标准库之数据压缩和存档的应用详解》在数据处理与存储领域,压缩和存档是提升效率的关键技术,Python标准库提供了一套完整的工具链,下面小编就来和大家简单介绍一下吧... 目录一、核心模块架构与设计哲学二、关键模块深度解析1.tarfile:专业级归档工具2.zipfile:跨平台归档首选3.

idea的终端(Terminal)cmd的命令换成linux的命令详解

《idea的终端(Terminal)cmd的命令换成linux的命令详解》本文介绍IDEA配置Git的步骤:安装Git、修改终端设置并重启IDEA,强调顺序,作为个人经验分享,希望提供参考并支持脚本之... 目录一编程、设置前二、前置条件三、android设置四、设置后总结一、php设置前二、前置条件

python设置环境变量路径实现过程

《python设置环境变量路径实现过程》本文介绍设置Python路径的多种方法:临时设置(Windows用`set`,Linux/macOS用`export`)、永久设置(系统属性或shell配置文件... 目录设置python路径的方法临时设置环境变量(适用于当前会话)永久设置环境变量(Windows系统

python中列表应用和扩展性实用详解

《python中列表应用和扩展性实用详解》文章介绍了Python列表的核心特性:有序数据集合,用[]定义,元素类型可不同,支持迭代、循环、切片,可执行增删改查、排序、推导式及嵌套操作,是常用的数据处理... 目录1、列表定义2、格式3、列表是可迭代对象4、列表的常见操作总结1、列表定义是处理一组有序项目的

python使用try函数详解

《python使用try函数详解》Pythontry语句用于异常处理,支持捕获特定/多种异常、else/final子句确保资源释放,结合with语句自动清理,可自定义异常及嵌套结构,灵活应对错误场景... 目录try 函数的基本语法捕获特定异常捕获多个异常使用 else 子句使用 finally 子句捕获所

C++11范围for初始化列表auto decltype详解

《C++11范围for初始化列表autodecltype详解》C++11引入auto类型推导、decltype类型推断、统一列表初始化、范围for循环及智能指针,提升代码简洁性、类型安全与资源管理效... 目录C++11新特性1. 自动类型推导auto1.1 基本语法2. decltype3. 列表初始化3