(学习笔记)U-net++代码解读

news2024/11/19 20:27:46

U-net++

    • 声明:本文只提供代码部分。
    • 声明:内容为题主学习时的疑问,仅供初学者参考。
    • python: 3.10
  • U-net++结构图
  • 遇到的问题
    • 1. albumentations包安装的问题
    • 2. AttributeError: module 'albumentations.augmentations.transforms' has no attribute 'RandomRotate90'
    • 3. torch没安cuda
  • 代码解读(主要解决py语法问题)
    • 1.读取配置文件
    • 2.os.makedirs()
    • 3.yaml.dump()
    • 4.losses.\__dict\__()
    • 5.cudnn.benchmark
    • 6.filter()
    • 7.glob+basename+splitext
    • 8. train_test_split()
    • 9. Compose()
    • 10. Dateset()
    • 11. DataLoader()
    • 12.OrderedDict()
    • 13.train()
      • 13.1 AverageMeter()
      • 13.2 tqdm()
      • 13.3 获取数据
      • 13.4 model()开始训练
        • 13.4.1 前向传播
      • 13.5 criterion()
      • 13.6 iou_score()
      • 13.7 方向传播,梯度优化
      • 13.8 更新进度条
    • validate() 和train类似跳过
    • 14. scheduler.step()

声明:本文只提供代码部分。

代码地址

声明:内容为题主学习时的疑问,仅供初学者参考。

python: 3.10

U-net++结构图

在这里插入图片描述

遇到的问题

1. albumentations包安装的问题

最开始的问题是找不到源,试了好多个命令都没用。最后通过github找到了解决办法。
使用的aniconda的命令。

conda install -c conda-forge albumentations

github链接

2. AttributeError: module ‘albumentations.augmentations.transforms’ has no attribute ‘RandomRotate90’

只需重新impor talbumentations即可。具体办法参见该链接第二个问题

3. torch没安cuda

如果已经安装了cuda可以忽略,题主没有GPU因此需要使用CPU训练。
解决办法: 将代码train和val代码里面的所有的.cuda()更改成.cpu(),这样就在CPU上跑起来了。
在这里插入图片描述

代码解读(主要解决py语法问题)

首先找到train.py的入口main函数,如图所示打断点。
在这里插入图片描述

1.读取配置文件

跳进这个函数。
在这里插入图片描述

def parse_args():
    parser = argparse.ArgumentParser()

    parser.add_argument('--name', default=None,
                        help='model name: (default: arch+timestamp)') # 指定网络的名字,就是U-net++
    parser.add_argument('--epochs', default=100, type=int, metavar='N',
                        help='number of total epochs to run')# 指定迭代次数
    parser.add_argument('-b', '--batch_size', default=8, type=int,
                        metavar='N', help='mini-batch size (default: 16)')#指定batch_size
    
    # model
    parser.add_argument('--arch', '-a', metavar='ARCH', default='NestedUNet',
                        choices=ARCH_NAMES,
                        help='model architecture: ' +
                        ' | '.join(ARCH_NAMES) +
                        ' (default: NestedUNet)')  # 指定网络架构
    parser.add_argument('--deep_supervision', default=False, type=str2bool)
    parser.add_argument('--input_channels', default=3, type=int,
                        help='input channels')
    parser.add_argument('--num_classes', default=1, type=int,
                        help='number of classes')
    parser.add_argument('--input_w', default=96, type=int,
                        help='image width')
    parser.add_argument('--input_h', default=96, type=int,
                        help='image height')
    
    # loss
    parser.add_argument('--loss', default='BCEDiceLoss',
                        choices=LOSS_NAMES,
                        help='loss: ' +
                        ' | '.join(LOSS_NAMES) +
                        ' (default: BCEDiceLoss)')
    config = parser.parse_args()

    return config

这段代码的作用是为了配置模型、损失函数、数据、优化器的各种参数,给每个参数定义一个名字,给一个默认值。
比如: parser.add_argument('--epochs', default=100, type=int, metavar='N', help='number of total epochs to run')# 指定迭代次数
这个的作用是,添加一个epochs(迭代次数)参数,默认值是100,数据类型为int,help:相当与一个说明语句。
这样定义好参数后,便于后续统一管理和了解参数情况。并且py提供的这个argparse类,会根据自己定义的参数生成说明文档(因为参数是自己定义的,传参有误我们也得知道哪里错了),报错也能知道是哪里错了。
在这里插入图片描述
最后的cofig相当于一个字典结构。

2.os.makedirs()

209行的含义是给’name’的值命名,%s%s为占位符,用来存放%连接的名字。
在这里插入图片描述
209行运行前后对比:
在这里插入图片描述
210行运行结果为:
在该path下创建一个目录,exist_ok=True的含义是:若目录存在也不会报错。

3.yaml.dump()

在这里插入图片描述
就是打开该path的文件,然后将config字典的内容存到该文件中。部分结果如下:
在这里插入图片描述

4.losses._dict_()

在这里插入图片描述

在该项目中,有一个losses.py这个文件,里面有相应的类实现。首先losses.dict[xxx]是从losses.py这个文件里扫描xxx这个类,并返回相应的属性值。即创建了一个相应的criterion对象。

5.cudnn.benchmark

    cudnn.benchmark = True

大部分情况下,设置这个 flag 可以让内置的 cuDNN 的 auto-tuner 自动寻找最适合当前配置的高效算法,来达到优化运行效率的问题。
此代码为GPU的优化选项,详情参考。

6.filter()

    params = filter(lambda p: p.requires_grad, model.parameters())

filter()有过滤的功能,其中第一个参数为True(表示需要梯度更新),第二个参数会返回该模型的所有可学习的参数,并过滤出仅仅需要梯度优化的参数。将这些参数以列表的形式赋给params。

7.glob+basename+splitext

在这里插入图片描述

261行的代码:
glob()获取指定路径下符合特定条件的文件路径列表。join()这个函数就是拼接好文件路径。最后将所有符合条件的文件路径返回给img_ids。
262行的代码:
首先是遍历261行获取好的文件路径,basename是获取p路径的基本名称,即将路径中的目录部分去除,只保留文件名部分。splitext()函数将文件名和扩展名分开,并返回。[0]的含义是取文件名赋值给img_ids。

最终img_ids只包含文件名(不包括路径与扩展名)。

8. train_test_split()

在这里插入图片描述
将img_ids(文件名)按0.2的比例分成训练集和测试集。
详细解释

9. Compose()

数据增强部分代码(注释在下面)。

    train_transform = Compose([
        # transforms.RandomRotate90(),
        # transforms.Flip(),
        albu.RandomRotate90(),
        albu.Flip(),
        OneOf([
            transforms.HueSaturationValue(),  #随机改变输入图像的色调、饱和度和值
            transforms.RandomBrightness(),    #随机改变亮度
            transforms.RandomContrast(),      #随机改变输入图像的对比度
        ], p=1),#按照归一化的概率选择执行哪一个
        # transforms.Resize(config['input_h'], config['input_w']),
        albu.Resize(config['input_h'], config['input_w']),   # 采用缩放的形式将图像变到期望大小
        transforms.Normalize(),
    ])
    
 #验证集就不增强了
    val_transform = Compose([
        # transforms.Resize(config['input_h'], config['input_w']),
        albu.Resize(config['input_h'], config['input_w']),
        transforms.Normalize(),
    ])

10. Dateset()

定义好本地路径相关的信息。
在这里插入图片描述

11. DataLoader()

创建一个用于训练数据的数据加载器。
代码注释如下:
在这里插入图片描述

12.OrderedDict()

该函数会定义一个有序字典,方便后续打印。

在这里插入图片描述

13.train()

将字典,训练集,模型,损失函数,优化器都传进去。
在这里插入图片描述

13.1 AverageMeter()

在这里插入图片描述
在这里插入图片描述

13.2 tqdm()

创建一个进度条。总共为train_loader的长度。
在这里插入图片描述

13.3 获取数据

通过train_loader获取输入数据和目标值。
在这里插入图片描述

13.4 model()开始训练

在这里插入图片描述

13.4.1 前向传播

从此NestedUNet模型中的,forward开始运行:

class VGGBlock(nn.Module):
    def __init__(self, in_channels, middle_channels, out_channels):  # 3,32,32
        super().__init__()
        self.relu = nn.ReLU(inplace=True)
        self.conv1 = nn.Conv2d(in_channels, middle_channels, 3, padding=1)   # 输入是3,输出是32
        self.bn1 = nn.BatchNorm2d(middle_channels)
        self.conv2 = nn.Conv2d(middle_channels, out_channels, 3, padding=1)
        self.bn2 = nn.BatchNorm2d(out_channels)

    def forward(self, x):
        out = self.conv1(x)
        out = self.bn1(out)
        out = self.relu(out)

        out = self.conv2(out)
        out = self.bn2(out)
        out = self.relu(out)

        return out


class UNet(nn.Module):
    def __init__(self, num_classes, input_channels=3, **kwargs):
        super().__init__()

        nb_filter = [32, 64, 128, 256, 512]

        self.pool = nn.MaxPool2d(2, 2)
        self.up = nn.Upsample(scale_factor=2, mode='bilinear', align_corners=True)#scale_factor:放大的倍数  插值

        self.conv0_0 = VGGBlock(input_channels, nb_filter[0], nb_filter[0])
        self.conv1_0 = VGGBlock(nb_filter[0], nb_filter[1], nb_filter[1])
        self.conv2_0 = VGGBlock(nb_filter[1], nb_filter[2], nb_filter[2])
        self.conv3_0 = VGGBlock(nb_filter[2], nb_filter[3], nb_filter[3])
        self.conv4_0 = VGGBlock(nb_filter[3], nb_filter[4], nb_filter[4])

        self.conv3_1 = VGGBlock(nb_filter[3]+nb_filter[4], nb_filter[3], nb_filter[3])
        self.conv2_2 = VGGBlock(nb_filter[2]+nb_filter[3], nb_filter[2], nb_filter[2])
        self.conv1_3 = VGGBlock(nb_filter[1]+nb_filter[2], nb_filter[1], nb_filter[1])
        self.conv0_4 = VGGBlock(nb_filter[0]+nb_filter[1], nb_filter[0], nb_filter[0])

        self.final = nn.Conv2d(nb_filter[0], num_classes, kernel_size=1)


    def forward(self, input):
        x0_0 = self.conv0_0(input)
        x1_0 = self.conv1_0(self.pool(x0_0))
        x2_0 = self.conv2_0(self.pool(x1_0))
        x3_0 = self.conv3_0(self.pool(x2_0))
        x4_0 = self.conv4_0(self.pool(x3_0))

        x3_1 = self.conv3_1(torch.cat([x3_0, self.up(x4_0)], 1))
        x2_2 = self.conv2_2(torch.cat([x2_0, self.up(x3_1)], 1))
        x1_3 = self.conv1_3(torch.cat([x1_0, self.up(x2_2)], 1))
        x0_4 = self.conv0_4(torch.cat([x0_0, self.up(x1_3)], 1))

        output = self.final(x0_4)
        return output


class NestedUNet(nn.Module):
    def __init__(self, num_classes, input_channels=3, deep_supervision=False, **kwargs):
        super().__init__()

        nb_filter = [32, 64, 128, 256, 512]

        self.deep_supervision = deep_supervision

        self.pool = nn.MaxPool2d(2, 2)
        self.up = nn.Upsample(scale_factor=2, mode='bilinear', align_corners=True)

        self.conv0_0 = VGGBlock(input_channels, nb_filter[0], nb_filter[0]) #3,32,32  输入3,中间32,输出32(特征图个数)
        self.conv1_0 = VGGBlock(nb_filter[0], nb_filter[1], nb_filter[1])  # 32,64,64
        self.conv2_0 = VGGBlock(nb_filter[1], nb_filter[2], nb_filter[2])
        self.conv3_0 = VGGBlock(nb_filter[2], nb_filter[3], nb_filter[3])
        self.conv4_0 = VGGBlock(nb_filter[3], nb_filter[4], nb_filter[4])

        self.conv0_1 = VGGBlock(nb_filter[0]+nb_filter[1], nb_filter[0], nb_filter[0])
        self.conv1_1 = VGGBlock(nb_filter[1]+nb_filter[2], nb_filter[1], nb_filter[1])
        self.conv2_1 = VGGBlock(nb_filter[2]+nb_filter[3], nb_filter[2], nb_filter[2])
        self.conv3_1 = VGGBlock(nb_filter[3]+nb_filter[4], nb_filter[3], nb_filter[3])

        self.conv0_2 = VGGBlock(nb_filter[0]*2+nb_filter[1], nb_filter[0], nb_filter[0])
        self.conv1_2 = VGGBlock(nb_filter[1]*2+nb_filter[2], nb_filter[1], nb_filter[1])
        self.conv2_2 = VGGBlock(nb_filter[2]*2+nb_filter[3], nb_filter[2], nb_filter[2])

        self.conv0_3 = VGGBlock(nb_filter[0]*3+nb_filter[1], nb_filter[0], nb_filter[0])
        self.conv1_3 = VGGBlock(nb_filter[1]*3+nb_filter[2], nb_filter[1], nb_filter[1])

        self.conv0_4 = VGGBlock(nb_filter[0]*4+nb_filter[1], nb_filter[0], nb_filter[0])

        if self.deep_supervision:
            self.final1 = nn.Conv2d(nb_filter[0], num_classes, kernel_size=1)
            self.final2 = nn.Conv2d(nb_filter[0], num_classes, kernel_size=1)
            self.final3 = nn.Conv2d(nb_filter[0], num_classes, kernel_size=1)
            self.final4 = nn.Conv2d(nb_filter[0], num_classes, kernel_size=1)
        else:
            self.final = nn.Conv2d(nb_filter[0], num_classes, kernel_size=1)


    def forward(self, input):
        print('input:',input.shape)
        x0_0 = self.conv0_0(input) # 8,32,96,96
        print('x0_0:',x0_0.shape)
        x1_0 = self.conv1_0(self.pool(x0_0))    # 下采样
        print('x1_0:',x1_0.shape)
        x0_1 = self.conv0_1(torch.cat([x0_0, self.up(x1_0)], 1))#00和10维度不一样,因此要将x1_0升维、拼接完之后为8,96,96,96再执行卷积,8,32,96,96
        print('x0_1:',x0_1.shape)

        x2_0 = self.conv2_0(self.pool(x1_0))
        print('x2_0:',x2_0.shape)
        x1_1 = self.conv1_1(torch.cat([x1_0, self.up(x2_0)], 1)) # x2_0up后(8,128,48,48),拼接后(8,192,48,48),卷积后(8,64,48,48)
        print('x1_1:',x1_1.shape)
        x0_2 = self.conv0_2(torch.cat([x0_0, x0_1, self.up(x1_1)], 1))
        print('x0_2:',x0_2.shape)

        x3_0 = self.conv3_0(self.pool(x2_0))
        print('x3_0:',x3_0.shape)
        x2_1 = self.conv2_1(torch.cat([x2_0, self.up(x3_0)], 1))
        print('x2_1:',x2_1.shape)
        x1_2 = self.conv1_2(torch.cat([x1_0, x1_1, self.up(x2_1)], 1))
        print('x1_2:',x1_2.shape)
        x0_3 = self.conv0_3(torch.cat([x0_0, x0_1, x0_2, self.up(x1_2)], 1))
        print('x0_3:',x0_3.shape)
        x4_0 = self.conv4_0(self.pool(x3_0))
        print('x4_0:',x4_0.shape)
        x3_1 = self.conv3_1(torch.cat([x3_0, self.up(x4_0)], 1))
        print('x3_1:',x3_1.shape)
        x2_2 = self.conv2_2(torch.cat([x2_0, x2_1, self.up(x3_1)], 1))
        print('x2_2:',x2_2.shape)
        x1_3 = self.conv1_3(torch.cat([x1_0, x1_1, x1_2, self.up(x2_2)], 1))
        print('x1_3:',x1_3.shape)
        x0_4 = self.conv0_4(torch.cat([x0_0, x0_1, x0_2, x0_3, self.up(x1_3)], 1))
        print('x0_4:',x0_4.shape)    #(8,32,96,96)

        if self.deep_supervision:
            output1 = self.final1(x0_1)
            output2 = self.final2(x0_2)
            output3 = self.final3(x0_3)
            output4 = self.final4(x0_4)
            return [output1, output2, output3, output4]

        else:
            output = self.final(x0_4)
            return output  #(8,1,96,96)

网络流程图如下所示:
请添加图片描述

13.5 criterion()

进入损失函数。
在这里插入图片描述

class BCEDiceLoss(nn.Module):
    def __init__(self):
        super().__init__()

    def forward(self, input, target):
        bce = F.binary_cross_entropy_with_logits(input, target)
        smooth = 1e-5    # 平滑因子,防止分母为0
        input = torch.sigmoid(input)    #  将输入的对数几率转化为概率值。
        num = target.size(0)
        input = input.view(num, -1)    # 将input转化为2维张量。
        target = target.view(num, -1)
        intersection = (input * target)   #input是概率,target是0/1,因此计算结果是预测的每个样本的正样本像素的概率。
        dice = (2. * intersection.sum(1) + smooth) / (input.sum(1) + target.sum(1) + smooth) # 预测结果和真实标签之间的相似度
        dice = 1 - dice.sum() / num   # 计算了平均Dice系数,并将其减去1,以得到Dice损失
        return 0.5 * bce + dice


13.6 iou_score()

计算iou,交并比。

def iou_score(output, target):
    smooth = 1e-5  # 平滑值

    if torch.is_tensor(output):
        output = torch.sigmoid(output).data.cpu().numpy()
    if torch.is_tensor(target):
        target = target.data.cpu().numpy()
    output_ = output > 0.5   # 预测值大于0.5为True
    target_ = target > 0.5  # 目标值大于0.5为True
    intersection = (output_ & target_).sum()   # 交集
    union = (output_ | target_).sum()          # 并集

    return (intersection + smooth) / (union + smooth)  # iou

13.7 方向传播,梯度优化

在这里插入图片描述

13.8 更新进度条

在这里插入图片描述

validate() 和train类似跳过

14. scheduler.step()

因为本文使用的余弦退火LR学习率更新方式,调度器通过余弦函数来调整学习率。
在这里插入图片描述

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

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

相关文章

0.在Linux Centos7下安装MySQL及其配置

个人主页:Lei宝啊 愿所有美好如期而遇 目录 1.检查是否已有MySQL 2. 检查系统安装包 3. 卸载这些默认安装包 4. 获取mysql官⽅yum源 5.安装mysql的yum源,对⽐前后yum源 6.看看能不能正常⼯作 7. 安装mysql服务 8.查看配置⽂件和数据存储位置 …

【编程必备知识】文件操作

文章目录 前言1. 认识文件1.1 树型结构组织和目录1.2 文件路径1.2.1 绝对路径1.2.2 相对路径 1.3 文件类型 2. Java 中操作文件2.1 File 概述2.1.1 构造方法2.1.2 成员方法 2. 2 代码示例示例1: 观察 get 系列的特点和差异示例2: 普通文件的创建示例3: 普通文件的删除示例4: 观…

手写Spring系列【一】IOC的简单实现笔记

前言: 👏作者简介:我是笑霸final,一名热爱技术的在校学生。 📝个人主页:个人主页1 || 笑霸final的主页2 📕系列专栏:项目专栏 📧如果文章知识点有错误的地方,…

uni-app:文本超出部分用省略号表示

效果 前 后 核心代码 white-space: nowrap; /* 强制不换行 */ text-overflow: ellipsis; /* 超过部分省略号代替 */ overflow: hidden; /* 必须同时设置overflow:hidden才能生效 */ 完整代码 <template><view><view class"all_style"><view c…

「才得吹嘘身渐稳」,也来谈谈大模型

要问2023年的科技领域什么消息最博人眼球&#xff0c;那么22年底发布、23年迅速跻身顶流的ChatGPT一定占有一席之地。随着ChatGPT的“爆火出圈”&#xff0c;国内外大厂纷纷布局「生成式语言模型」研发赛道&#xff0c;各类应用也如雨后春笋般层出不穷&#xff0c;让人眼花缭乱…

SpringBoot的配置文件——.yml和.properties

目录 1. Spring Boot 配置文件的使用场景 2. 配置文件的两种格式 2.0 特殊说明&#xff1a; 2.1 .properties 2.1.1 格式 2.2.2 缺陷 2.2.3 解决中文乱码的问题 2.2 .yml 2.2.3 格式 配置数据库连接 注意转义字符 ​编辑 ​编辑 配置null 配置对象 从.yml读取文件举例 Stud…

v-on/@ 事件处理指令修饰符-stop、prevent、once

v-on/事件修饰符&#xff1a; 一、.stop 阻止单机事件继续传播 event.stopProgagetion() eg: <h3>事件修饰符</h3> <div click"todo"> <div click.stop"doThis"> 单机事件会继续传递 </div> </div> 点击 单机事…

【Java 进阶篇】Java Web 编写注册页面案例

当涉及到创建一个Java Web注册页面时&#xff0c;你将需要涵盖很多不同的主题&#xff0c;包括HTML、CSS、Java Servlet和数据库连接。在这篇文章中&#xff0c;我们将详细介绍每个步骤&#xff0c;以帮助你创建一个完整的注册页面。 1. 介绍 注册页面是许多Web应用程序的关键…

STM32标准库代码转为LL库代码-详解

概述 由于标准库&#xff0c;ST公司逐步不再维护&#xff0c;比较老旧的项目&#xff0c;都是使用标准库来开发&#xff0c;如果想使用LL库&#xff0c;需要借助《SPL2LL转换器》实现。 1、LL库简介 LL库&#xff0c;即STM32Cube Low-Layer&#xff0c;也叫Cube LL、Cube底层…

文件上传 [极客大挑战 2019]Upload 1

题目来源&#xff1a;buuctf [极客大挑战 2019]Upload 1 打开题目 是一道文件上传题 我们上传png和jpg格式的一句话木马上去看看 上传失败了&#xff0c;应该是在后端也对我们的文件内容进行了检测&#xff0c;检测到我们的一句话木马里面包含<? 那我们重新换个一句话木…

【软件工程】常见软件过程模型及其优缺点

软件过程模型 1. 瀑布模型2. V模型3. 原型模型4. 增量模型5. 螺旋模型6. 喷泉模型 1. 瀑布模型 描述&#xff1a; 瀑布模型是将软件开发划分为不同的阶段&#xff0c;只有上一个阶段完成了才能进入到下一个阶段&#xff0c;也就是按照需求分析、设计、实现、测试、运行和维护这…

UML类图是什么?怎么画?

在软件开发和系统设计领域&#xff0c;UML&#xff08;Unified Modeling Language&#xff09;类图是一种强大的工具&#xff0c;用于可视化和表示软件系统的结构和关系。如果你曾经在软件开发中遇到过“UML类图是什么&#xff1f;”这个问题&#xff0c;那么你来对地方了。本文…

简要归纳UE5 Lumen全局光照原理

一、Jim kajiya老爷子的渲染方程&#xff1a; 求全局光照就是求解渲染方程&#xff0c;我们将两边都有未知数的渲染方程变换成离散形式&#xff1a; 更形象的描述这个离散的渲染方程&#xff1a; 要给每个三角形着色就得先判断光线有没有和它相交&#xff0c;以下是求光线和三…

3D 生成重建006-3DFuse 形状引导一致性的文生3d的方法

3D生成重建006-3DFuse 形状引导一致性的文生3d的方法 文章目录 0 论文介绍1 论文方法1.1 semantic code1.2 稀疏深度信息PointE1.3 lora部分 2 效果 0 论文介绍 在004-DreamFusion and SJC 中dreamfusion提到将2D观测结果“提升”到3D世界的任务本质上是模糊的&#xff0c;并…

1810_spacemacs缺少evil-unimpaired以及evil-ediff安装失败解决

全部学习汇总&#xff1a; GreyZhang/editors_skills: Summary for some common editor skills I used. (github.com) 安装的时候遇到evil-unimpaired找不到的问题&#xff0c;查了一下网络上很多人都遇到这样的问题&#xff0c;但是问题千奇八怪。更要命的可能是我遇到的提示跟…

【ARM AMBA5 CHI 入门 12.1 -- CHI 链路层详细介绍 】

文章目录 CHI 版本介绍1.1 CHI 链路层介绍1.1.1 Flit 切片介绍1.1.2 link layer credit(L-Credit)机制1.1.3 Channel1.1.4 Port1.1. RN Node 接口定义1.1.6 SN Node 接口定义1.2 Channel interface signals1.2.1 Request, REQ, channel1.2.2 Response, RSP, channel1.2.3 Snoop…

一个完整的初学者指南Django-part2

介绍 欢迎来到 Django 教程的第二部分&#xff01;在上一课中&#xff0c;我们安装了项目所需要的一切软件&#xff0c;希望你们在学习这篇文章之前&#xff0c;安装了 Python 3.6&#xff0c;并且在虚拟环境中运行Django 1.11。因为&#xff0c;在本篇文章中&#xff0c;我们…

并购交易:埃克森美孚商谈以250美元/股的价格收购先锋自然资源

来源&#xff1a;猛兽财经 作者&#xff1a;猛兽财经 猛兽财经获悉&#xff0c;埃克森美孚(XOM)正在商谈以250美元/股的价格收购先锋自然资源(PXD)。 彭博社援引知情人士的消息报道称&#xff0c;一项全股票交易最早可能于周三宣布。按照每股250美元的价格计算&#xff0c;先锋…

【动态规划】198. 打家劫舍、213. 打家劫舍 II、337. 打家劫舍 III

提示&#xff1a;努力生活&#xff0c;开心、快乐的一天 文章目录 198. 打家劫舍&#x1f4a1;解题思路&#x1f914;遇到的问题&#x1f4bb;代码实现&#x1f3af;题目总结 213. 打家劫舍 II&#x1f4a1;解题思路&#x1f914;遇到的问题&#x1f4bb;代码实现&#x1f3af;…

postman发送POST请求,模拟请求头界面的响应信息

postman发送POST请求 示例&#xff1a;微信公众平台创建用户标签接口&#xff0c;业务操作如下&#xff1a; 1、打开微信公众平台&#xff0c;微信扫码登录&#xff1a;https://mp.weixin.qq.com/debug/cgi-bin/sandbox?tsandbox/login 同时&#xff0c;我也为大家准备了一份…