精华内容
下载资源
问答
  • 常用代码
    千次阅读
    2022-03-05 15:04:14

    自制第一人称:

    1、新建一个球、一个摄像机,把球和摄像机放在一个位置。

    2、把下面代码托付给球。

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;

    public class Move3 : MonoBehaviour
    {
        public float sensitivityX = 5f;
        public float sensitivityY = 5f;

        public float sensitivetyKeyBoard = 0.1f;
        public float sensitivetyMouseWheel = 10f;

        private GameObject Playercamera;
        public Rigidbody rigidbody;
        public float speed = 5;

        void Start()
        {
           // undefined
           Playercamera = GameObject.Find("PlayerCamera");
        }

        void Update()
        {
          //  undefined
          //滚轮实现镜头缩进和拉远
      if (Input.GetAxis("Mouse ScrollWheel") != 0)
            {
               // undefined

    Playercamera.GetComponent<Camera>().fieldOfView = Playercamera.GetComponent<Camera>().fieldOfView - Input.GetAxis("Mouse ScrollWheel") * sensitivetyMouseWheel;
            }
            //鼠标右键实现视角转动,类似第一人称视角  
            if (Input.GetMouseButton(0))
            {
               // undefined
          
    float rotationX = Input.GetAxis("Mouse X") * sensitivityX;
                transform.Rotate(0, rotationX, 0);

                float rotationY = Input.GetAxis("Mouse Y") * sensitivityY;
                Playercamera.transform.Rotate(-rotationY, 0, 0);
            }

        }
        void FixedUpdate()
        {
           // undefined
          //控制移动
      float h = Input.GetAxis("Horizontal");
            float v = Input.GetAxis("Vertical");

            //朝一个方向移动 new Vector3(h, 0, v) * speed * Time.deltaTime是个向量
            transform.Translate(new Vector3(h, 0, v) * speed * Time.deltaTime);
            //移动到一个位置
            //rigidbody.MovePosition(transform.position + new Vector3(h, 0, v) * speed * Time.deltaTime);
        }
    }
     

    更多相关内容
  • VBA常用代码合集

    万次阅读 多人点赞 2020-12-19 11:13:11
    VBA常用代码模版Tp0️⃣—零零散散小功能(持续更新)Tp1️⃣—输出活动页面筛选后的行数Tp2️⃣—创建数组存放数据Tp2-1 静态数组Tp2-2 动态数组Tp3️⃣ 创建字典存放数据Tp4️⃣ 优化代码运行速度 Tp0️⃣—零零散...

    Tp0️⃣—零零散散小功能(持续更新)

    • 剪切列
    • 替换字符
    • 取消复制剪切状态
    • 浮点数向上取值
    • 区域添加边框
    • 区域设置颜色
    • 调整列宽、行高
    • 待更新
    '  小功能集合
    Sub Demos()
    
    	'	剪切一列到指定列
    	With ThisWorkbook.Sheets(2)    
    		.[AI:AI].Cut    
    		.[AE:AE].Select    
    		Selection.Insert Shift:=xlToRight
    	End With
    
    	'	替换字符,将(空白)替换为空
    	With worksheet.[C:C]
    		.Replace "(空白)", ""
    	End With
    	
    	'	取消复制剪贴状态
    	Application.CutCopyMode = False
    	   
    	'	将带有小数的数据向上取整
    	NewData = Application.WorksheetFunction.RoundUp(Datas, 0)
    
    	' 	单元格区域添加边框
    	.Range("A4:N" & .Range("A9999").End(xlUp).Row).Borders.LineStyle = xlContinuous
    
    	'  -------------单元格标色-------------
    	'  指定区域标色
    	With Range("C2:G9")
        	.Interior.ColorIndex = 0	' 无填充颜色
         	.Interior.ColorIndex = 3	' 红色
         	.Interior.ColorIndex = 5	' 蓝色              
        End With
        
    	' 实现自动调整行高、列宽
    	Rows("1:5").EntireRow.AutoFit			' 调整1至5行行高
        Columns("A:AA").EntireColumn.AutoFit    ' 调整A至AA列列宽
        ' 设置行高、列宽为固定值
        Rows("1:5").RowHeight = 15				' 设置1至5行行高为15
        Columns("A:AA").ColumnWidth = 15		' 设置A至AA列列宽为15
    
    End Sub
    

    颜色索引-Range属性
    Excel颜色索引

    Tp1️⃣—输出活动页面筛选后的行数

    ' 获取活动页面筛选后的行数
    Sub RowCntAfterFilter()
    
        Dim rngCell As Range
        Dim lngRowCnt As Long
        For Each rngCell In [a1].CurrentRegion.SpecialCells(xlCellTypeVisible).Areas
            lngRowCnt = lngRowCnt + rngCell.Rows.Count
        Next rngCell
    	rows_count =  lngRowCnt - 1   '可视区行数
        MsgBox "筛选后数据行数为:" & rows_count 
        Set rngCell = Nothing
        
    End Sub
    

    Tp2️⃣—创建数组存放数据

    通过数组可以快速对数据进行处理
    前提:表格数据须规范,不考虑合并单元格
    一维数组:数字(1,2,3,4),字符串(a,b,c,d)
    二维数组:((1,1),(1,2),(1,3),(2,1),(2,2),(2,3)) 表格结构、行列转置、计算、遍历、统计…
    多维数组:不是很熟悉,不敢乱说( ̄□ ̄||)
    简单介绍静态数组动态数组的使用

    Tp2-1 静态数组

    Sub SetArray()
    	’   静态数组可直接通过 变量名=数组()的方式设置
    	array_number = Array(1,2,3,4,5)
    	array_string = Array("张三","李四","王五","Sugar","Smile")
    	
    	'  可遍历,参数:count,Index 取值:data = array_data(1)
    	'  赋值
    	.[A1:A5] = array_number 
    	.[B1:B5] = array_string
    
    	'存放单元格区域数据到数组(二维数组的快捷应用)
    	Dim arr As Variant       '定义一个Variant类型的变量,名称为arr
       	arr = Range("A1:C3").Value '将A1:C3中保存的数据存储到数组arr里
       	Range("E1:G3").Value = arr '将数组ar写入E1:G3单元格区域
    
    End Sub
    

    Tp2-2 动态数组

    Sub VimArray()
    
    	'自定义动态数组长度n,上界为0
    	Dim n As Integer
    	n = 0
    
    	Dim SupArr() As String	 ' 定义动态数组存放供应商名称
    	With ActiveSheet   
        	For i = 2 To .[A1048576].End(xlUp).Row
            	ReDim Preserve SupArr(n)		 '  给动态数组重定义一个实际的大小
            	n = n + 1
            	SupArr(n - 1) = .Cells(i, 3).Value  ' 存到动态数组里去
        	Next i
    	End With
    
    End Sub
    

    Tp3️⃣ 创建字典存放数据

    通过字典可以快速对数据进行处理
    存放键值对关系,key具有唯一性,
    参数:count,keys,values,Item
    需要创建字典对象后使用

    '与Excel单元格结合,创建字典存放数据
    Sub RngDict()
    
    	Dim DicManForm As Object
    	Set DicManForm = CreateObject("Scripting.Dictionary")
    	key_MaxRow = ActiveSheet.[A66666].End(xlUp).Row	'活动工作表A列的最后一行的行数
    	
        '对A列进行遍历
        For key_Row = 2 To key_MaxRow
        	'取A列不重复的值作为字典的key,索引值唯一
        	KeyXX = ActiveSheet.Cells(key_Row, 1).Value
         	'导入条件:不为空,不重复
         	If KeyXX <> "" And DicManForm.Exists(KeyXX) = False Then
                DicManForm.Add KeyXX, key_Row
          	End If
        Next
        '通过key值,重设对应的value,key不存在时会报错
        DicManForm(key) = value
    	Set DicManForm = Nothing
    
    End Sub
    

    Tp4️⃣ 优化代码运行速度

    为了加快代码的执行速度,最简单的方式,将代码的执行过程设置为不显示,可以在代码执行时,临时关闭后续设置:自动重算自动刷新弹窗警告
    温馨提示:以下代码需要成对出现,设置False后,末尾改回True

    Sub AppSetting()
    
    	’  程序开始
        With Application
            .ScreenUpdating = False		'  关闭屏幕刷新
            .EnableEvents = False		'  关闭事件触发
            .DisplayAlerts = False		'  关闭弹窗提示
        End With
        
        ' Your Code				'   调用程序运行的主体代码
    
    	’程序末尾
        With Application
            .ScreenUpdating = True		'  恢复屏幕刷新
            .EnableEvents = True		'  恢复事件触发
            .DisplayAlerts = True		'  恢复弹窗提示
        End With
        
    End Sub
    

    好久不见、更新继续

    Tp5️⃣ 轻松实现工作簿加密

    Sub 解除全部工作表保护()
        Dim n As Integer
        For n = 1 To Sheets.Count
            Sheets(n).Unprotect
        Next n
    End Sub
    
    Sub 为指定工作表加指定密码保护表()
        Sheet10.Protect Password:="123"
    End Sub
    
    Sub 在有密码的工作表执行代码()
        Sheets("1").Unprotect Password:=123 '假定表名为“1”,密码为“123”  打开工作表
        Range("C:C").SpecialCells(xlCellTypeBlanks).EntireRow.Hidden = True   '隐藏C列空值行
        Sheets("1").Protect Password:=123    '重新用密码保护工作表
    End Sub
    

    Tp6️⃣ 通过对话框选择文件-1

    ' 设置选择文件的弹出窗口,自主选择文件
    Sub FilePicker()
        
        Open_Path = ThisWorkbook.Sheets("操作界面").[B4]
        
        '新建一个对话框对象
        Set FileDialogObject = Application.FileDialog(msoFileDialogFilePicker)
        
        '配置对话框
        With FileDialogObject
            
            .Title = "请选择目标文件所在的文件夹:"
            
            '添加判断,改变对话框默认打开的路径
            '默认打开上次的文件路径
            If Open_Path = "" Then
            .InitialFileName = "C:\"
            Else
            .InitialFileName = Open_Path
            End If
            
        End With
        
        '显示对话框
        FileDialogObject.Show
        '获取选择对话框选择的文件
        Set paths = FileDialogObject.SelectedItems
        
        With Sheets("操作界面")
            .[I:I].Clear
            file_ = paths.Item(1)       '包含绝对路径的文件名
            .[B4].Value = paths.Parent.InitialFileName      '当前文件所在目录
            .[B6].Value = Right(file_, Len(file_) - Len(paths.Parent.InitialFileName))  '获取文件
            
            '选择多个文件时,遍历所选文件,并写入I列
            If paths.Count > 1 Then
                i_Row = 2
                For Each Item In paths
                    .Range("I" & i_Row) = Item
                    i_Row = i_Row + 1
                Next
            End If
            
        End With
        
    End Sub
    
    

    Tp7️⃣ 通过对话框选择文件-2

    '通过对话框选择文件路径
    Sub FolderPicker()
        
        Open_Path = ThisWorkbook.Sheets("操作界面").[B4]
        
        '新建一个对话框对象
        Set FolderDialogObject = Application.FileDialog(msoFileDialogFolderPicker)
        
        '配置对话框
        '配置对话框
        With FolderDialogObject
            
            .Title = "请选择目标文件所在的文件夹:"
            
            '添加判断,改变对话框默认打开的路径
            '默认打开上次的文件路径
            If Open_Path = "" Then
            .InitialFileName = "C:\"
            Else
            .InitialFileName = Open_Path
            End If
            
        End With
        
        FolderDialogObject.Show '显示对话框
        
        Set paths = FolderDialogObject.SelectedItems            '获取选择对话框选择的文件夹
        Set fso = CreateObject("Scripting.filesystemobject")    '取目标文件
        Set myf = fso.getfolder(paths.Item(1))                  '从指定路径下获取文件
        
        With Sheets("操作界面")
            .[I:I].Clear
            .[B4].Value = paths.Item(1)
            
            i_Row = 2
            For Each file In myf.Files
    '            .Range("I" & i_Row) = file             '记录绝对路径+文件名
                .Range("I" & i_Row) = file.Name         '记录文件名
                i_Row = i_Row + 1
            Next
            
        End With
        
    End Sub
    
    

    Tp8️⃣ 从目录页自动跳转至明细页

    在这里插入图片描述
    **小提示:**权限分配表中的合并单元格,其中有一个小技巧,请参考另一篇针对筛选单元格的笔记
    ------------如何解决筛选时只显示第一行------------

    Private Sub Worksheet_SelectionChange(ByVal Target As Range)
    
        Dim Rng, oRng As Range      ' 定义变量Rng、oRng为单元格
        
        Set Rng = Range("B2:B18")   ' 设定Rng为可操作区域单元格
        Set oRng = Selection        ' 设定oRng为选中单元格
        
        '如果所选单元格在可操作区域外,退出本次运行
        If Application.Intersect(oRng, Rng) Is Nothing Then Exit Sub
    
        Application.ScreenUpdating = False
    
        ' 多选则退出,单选设置筛选值
        If Selection.Count > 1 Then Exit Sub Else AimValue = Selection.Value
        
        ' 自动跳转至目标工作表进行筛选
        With Sheets("权限分配表")
    
            If .FilterMode = True Then .ShowAllData
            .Range("A1").AutoFilter Field:=1, Criteria1:=AimValue, _
             Operator:=xlAnd
            .Activate
        
        End With
        
        Application.ScreenUpdating = True
        
    End Sub
    
    

    Tp9️⃣ 选择区域自动设置或取消值

    Private Sub Worksheet_SelectionChange(ByVal Target As Range)
    
        
        Application.ScreenUpdating = False
        Application.DisplayAlerts = False
        
        On Error Resume Next
    
        Dim Rng, oRngs, oRng As Range     ' 定义变量Rng、oRng为单元格
        Dim Aim As String                 ' 定义变量Aim为字符串
    
        Aim = "√"                  ' 设定目标值
        
        Set Rng = Range("D2:H706")  ' 设定Rng为可操作区域单元格
        Set oRngs = Selection       ' 设定oRngs为选中单元格
        
    
    
        '如果所选单元格在可操作区域外,退出本次运行
        If Intersect(oRngs, Rng) Is Nothing Then Exit Sub
    
            
    '    Selection.FormulaR1C1 = Aim      '直接设置所选区域内的值为"√"
    
        ' 针对选择区域,有值清空,空值设定Aim
        For Each oRng In oRngs
        
            If oRng.FormulaR1C1 = "" Then oRng.FormulaR1C1 = Aim Else oRng.FormulaR1C1 = ""
    
        Next
        
        On Error GoTo 0
    
        Application.ScreenUpdating = True
        Application.DisplayAlerts = True
    
    End Sub
    
    
    
      未完待续、、、
      期待下次相遇
    
    展开全文
  • 常用代码托管工具

    千次阅读 2022-01-13 17:17:01
    常用代码托管工具1. Github2. Gitlab 1. Github Github简介 由 Git (著名的 Git 版本控制软件) 和 Hub( 「 中心 」 的意思) 两个词合成。 Github 全球最大的开源项目聚集地,到目前为止 Github 汇集了全球 7300+...

    1. Github

    1.1 Github简介

    由 Git (著名的 Git 版本控制软件) 和 Hub( 「 中心 」 的意思) 两个词合成。
    Github 全球最大的开源项目聚集地,到目前为止 Github 汇集了全球 7300+ 万开发者,4000+ 万组织机构,2+亿代码仓库。
    Github地址:https://github.com/
    什么是GitHub,为什么用GitHub:https://github.com/git-guides
    在这里插入图片描述

    1.2 Github版本区别

    GitHub服务方案列表
    GitHub的三类(8种)服务方案:
    第一类是免费方案。免费用户账号可以创建任意数量的开放式项目(版本库),并且可以为开放式项目设置任意数量的协同者。

    第二类是需要付费的个人账号方案。付费的个人账号允许托管私有版本库,即可以创建只有自己及指定的私有协同者才能够访问的版本库,而其他人不能访问。根据允许创建的私有版本库数量及私有版本库协同者数量,提供了三种收费标准(7美元/月、12美元/月 和 22美元/月)。

    第三类是需要付费的组织账号方案。使用付费的组织账号,可以突破私有项目的协同者数量限制,并使用更易管理的团队(Team)对项目进行授权。关于如何通过团队配置授权参见“4.3. 组织和团队”。组织账号的付费标准较个人账号更高(有25美元/月、50美元/月、100美元/月 和 200美元/月),但同时也可以创建更多的私有版本库和拥有更大的托管空间。

    收费详情:https://www.shouce.ren/api/view/a/9949
    在这里插入图片描述

    2. Gitlab

    2.1 Gitlab简介

    由 Git (著名的 Git 版本控制软件) 和 Lab( laboratory 的缩写,是「 实验室 」 的意思) 两个词合成。

    Gitlab比较适合企业使用,个人项目用 Gitlab 也很好。能够创建免费的私有仓库。目前很多企业都是使用内部搭建的Gitlab作为代码托管工具,常见的搭配方式:Gitlab + Docker + Jenkins 协同运作。

    Gitlab网址:https://gitlab.com
    在这里插入图片描述

    2.2 Gitlab版本区别

    Gitlab分三个版本,免费版,高级版,永久版。

    收费详情:https://about.gitlab.com/pricing/
    在这里插入图片描述

    3. Gitee

    3.1 Gitee简介

    Gitee国内最大的开源社区 OSChina 的代码托管平台。截止到目前为止 Gitee汇集了全球 600+ 万开发者,1500万+代码仓库,18万+企业客户,3200+高校。提供团队协作开发。可创建 1000 个项目,不限私有或公有。
    最重要的是国内,网速超快,极大的提高效率,Github真的很慢。
    Gitee网址:https://gitee.com/
    在这里插入图片描述

    3.2 Gitee版本区别

    Gitee分为5个版本,免费,基础,标准,高级,尊享版,费用功能各有不同,可以根据需要选取。
    收费详情:https://gitee.com/enterprises#price
    在这里插入图片描述

    5. Codeup

    5.1 Codeup简介

    阿里云效代码管理 Codeup 是阿里云出品的一款企业级代码管理平台,提供代码托管、代码评审、代码扫描、质量检测等功能,全方位保护企业代码资产,帮助企业实现安全、稳定、高效的研发管理。
    还是比较推荐的,安全,大厂背书。
    Codeup具体介绍:https://help.aliyun.com/document_detail/153402.html
    在这里插入图片描述

    5.2 Codeup版本区别

    阿里云效开放所有基础功能不限人数免费使用。高级版功能更丰富,容量更充足。
    收费详情:https://help.aliyun.com/document_detail/173288.html
    在这里插入图片描述

    6. CODING

    6.1 CODING 简介

    腾讯CODING CODING (码市)是国内首个一站式云端软件服务平台。
    云端软件开发协作平台,目前已累积 30 万开发者,50 万个项目。

    CODING DevOps 包括代码托管、项目管理、测试管理、持续集成、制品库等多款产品和服务,涵盖软件开发从构想到交付的一切所需,使研发团队在云端高效协同,实践敏捷开发与 DevOps,提升软件交付质量与速度。
    https://cloud.tencent.com/product/coding
    在这里插入图片描述

    6.2 CODING 版本区别

    CODING 目前有3个版本,标准版不限成员数,不限项目数,但是容量有限,集成时长限制等。高级版包含标准版所有功能,更多高级功能及资源扩展。性能包包含标准版所有功能,单独升级持续集成资源包。
    收费详情:https://cloud.tencent.com/product/coding
    在这里插入图片描述

    7. 其他

    还有很多其他平台就不一一介绍,最常见的就是以上几种。

    展开全文
  • Pytorch 常用代码

    千次阅读 2022-08-07 00:27:23
    pytorch常用代码

    Pytorch 常用代码

    本文代码基于PyTorch 1.0版本,需要用到以下包

    import collections
    import os
    import shutil
    import tqdm
    
    import numpy as np
    import PIL.Image
    import torch
    import torchvision
    

    1. 基础配置

    检查PyTorch版本

    torch.__version__               # PyTorch version
    torch.version.cuda              # Corresponding CUDA version
    torch.backends.cudnn.version()  # Corresponding cuDNN version
    torch.cuda.get_device_name(0)   # GPU type
    

    更新PyTorch

    PyTorch将被安装在anaconda3/lib/python3.7/site-packages/torch/目录下。

    conda update pytorch torchvision -c pytorch
    

    固定随机种子

    torch.manual_seed(0)
    torch.cuda.manual_seed_all(0)
    

    指定程序运行在特定GPU卡上

    在命令行指定环境变量

    CUDA_VISIBLE_DEVICES=0,1 python train.py
    

    或在代码中指定

    os.environ['CUDA_VISIBLE_DEVICES'] = '0,1'
    

    判断是否有CUDA支持

    torch.cuda.is_available()
    

    设置为cuDNN benchmark模式

    Benchmark模式会提升计算速度,但是由于计算中有随机性,每次网络前馈结果略有差异。

    torch.backends.cudnn.benchmark = True
    

    如果想要避免这种结果波动,设置

    torch.backends.cudnn.deterministic = True
    

    清除GPU存储

    有时Control-C中止运行后GPU存储没有及时释放,需要手动清空。在PyTorch内部可以

    torch.cuda.empty_cache()
    

    或在命令行可以先使用ps找到程序的PID,再使用kill结束该进程

    ps aux | grep python
    kill -9 [pid]
    

    或者直接重置没有被清空的GPU

    nvidia-smi --gpu-reset -i [gpu_id]
    

    2. 张量处理

    张量基本信息

    tensor.type()   # Data type
    tensor.size()   # Shape of the tensor. It is a subclass of Python tuple
    tensor.dim()    # Number of dimensions.
    

    数据类型转换

    # Set default tensor type. Float in PyTorch is much faster than double.
    torch.set_default_tensor_type(torch.FloatTensor)
    
    # Type convertions.
    tensor = tensor.cuda()
    tensor = tensor.cpu()
    tensor = tensor.float()
    tensor = tensor.long()
    

    torch.Tensor与np.ndarray转换

    # torch.Tensor -> np.ndarray.
    ndarray = tensor.cpu().numpy()
    
    # np.ndarray -> torch.Tensor.
    tensor = torch.from_numpy(ndarray).float()
    tensor = torch.from_numpy(ndarray.copy()).float()  # If ndarray has negative stride
    

    torch.Tensor与PIL.Image转换

    PyTorch中的张量默认采用N×D×H×W的顺序,并且数据范围在[0, 1],需要进行转置和规范化。

    # torch.Tensor -> PIL.Image.
    image = PIL.Image.fromarray(torch.clamp(tensor * 255, min=0, max=255
        ).byte().permute(1, 2, 0).cpu().numpy())
    image = torchvision.transforms.functional.to_pil_image(tensor)  # Equivalently way
    
    # PIL.Image -> torch.Tensor.
    tensor = torch.from_numpy(np.asarray(PIL.Image.open(path))
        ).permute(2, 0, 1).float() / 255
    tensor = torchvision.transforms.functional.to_tensor(PIL.Image.open(path))  # Equivalently way
    

    np.ndarray与PIL.Image转换

    # np.ndarray -> PIL.Image.
    image = PIL.Image.fromarray(ndarray.astypde(np.uint8))
    
    # PIL.Image -> np.ndarray.
    ndarray = np.asarray(PIL.Image.open(path))
    

    从只包含一个元素的张量中提取值

    这在训练时统计loss的变化过程中特别有用。否则这将累积计算图,使GPU存储占用量越来越大。

    value = tensor.item()
    

    张量形变

    张量形变常常需要用于将卷积层特征输入全连接层的情形。相比torch.view,torch.reshape可以自动处理输入张量不连续的情况。

    tensor = torch.reshape(tensor, shape)
    

    打乱顺序

    tensor = tensor[torch.randperm(tensor.size(0))]  # Shuffle the first dimension
    

    水平翻转

    PyTorch不支持tensor[::-1]这样的负步长操作,水平翻转可以用张量索引实现。

    # Assume tensor has shape N*D*H*W.
    tensor = tensor[:, :, :, torch.arange(tensor.size(3) - 1, -1, -1).long()]
    

    复制张量

    有三种复制的方式,对应不同的需求。

    # Operation                 |  New/Shared memory | Still in computation graph |
    tensor.clone()            # |        New         |          Yes               |
    tensor.detach()           # |      Shared        |          No                |
    tensor.detach.clone()()   # |        New         |          No                |
    

    拼接张量

    注意torch.cat和torch.stack的区别在于torch.cat沿着给定的维度拼接,而torch.stack会新增一维。例如当参数是3个10×5的张量,torch.cat的结果是30×5的张量,而torch.stack的结果是3×10×5的张量。

    tensor = torch.cat(list_of_tensors, dim=0)
    tensor = torch.stack(list_of_tensors, dim=0)
    

    将整数标记转换成独热(one-hot)编码

    PyTorch中的标记默认从0开始。

    N = tensor.size(0)
    one_hot = torch.zeros(N, num_classes).long()
    one_hot.scatter_(dim=1, index=torch.unsqueeze(tensor, dim=1), src=torch.ones(N, num_classes).long())
    

    得到非零/零元素

    torch.nonzero(tensor)               # Index of non-zero elements
    torch.nonzero(tensor == 0)          # Index of zero elements
    torch.nonzero(tensor).size(0)       # Number of non-zero elements
    torch.nonzero(tensor == 0).size(0)  # Number of zero elements
    

    判断两个张量相等

    torch.allclose(tensor1, tensor2)  # float tensor
    torch.equal(tensor1, tensor2)     # int tensor
    

    张量扩展

    # Expand tensor of shape 64*512 to shape 64*512*7*7.
    torch.reshape(tensor, (64, 512, 1, 1)).expand(64, 512, 7, 7)
    

    矩阵乘法

    # Matrix multiplication: (m*n) * (n*p) -> (m*p).
    result = torch.mm(tensor1, tensor2)
    
    # Batch matrix multiplication: (b*m*n) * (b*n*p) -> (b*m*p).
    result = torch.bmm(tensor1, tensor2)
    
    # Element-wise multiplication.
    result = tensor1 * tensor2
    

    计算两组数据之间的两两欧式距离

    # X1 is of shape m*d, X2 is of shape n*d.
    dist = torch.sqrt(torch.sum((X1[:,None,:] - X2) ** 2, dim=2))
    

    3. 模型定义

    卷积层

    最常用的卷积层配置是

    conv = torch.nn.Conv2d(in_channels, out_channels, kernel_size=3, stride=1, padding=1, bias=True)
    conv = torch.nn.Conv2d(in_channels, out_channels, kernel_size=1, stride=1, padding=0, bias=True)
    

    如果卷积层配置比较复杂,不方便计算输出大小时,可以利用如下可视化工具辅助

    Convolution Visualizerezyang.github.io

    GAP(Global average pooling)层

    gap = torch.nn.AdaptiveAvgPool2d(output_size=1)
    

    双线性汇合(bilinear pooling)[1]

    X = torch.reshape(N, D, H * W)                        # Assume X has shape N*D*H*W
    X = torch.bmm(X, torch.transpose(X, 1, 2)) / (H * W)  # Bilinear pooling
    assert X.size() == (N, D, D)
    X = torch.reshape(X, (N, D * D))
    X = torch.sign(X) * torch.sqrt(torch.abs(X) + 1e-5)   # Signed-sqrt normalization
    X = torch.nn.functional.normalize(X)                  # L2 normalization
    

    多卡同步BN(Batch normalization)

    当使用torch.nn.DataParallel将代码运行在多张GPU卡上时,PyTorch的BN层默认操作是各卡上数据独立地计算均值和标准差,同步BN使用所有卡上的数据一起计算BN层的均值和标准差,缓解了当批量大小(batch size)比较小时对均值和标准差估计不准的情况,是在目标检测等任务中一个有效的提升性能的技巧。

    vacancy/Synchronized-BatchNorm-PyTorchgithub.com图标

    现在PyTorch官方已经支持同步BN操作

    sync_bn = torch.nn.SyncBatchNorm(num_features, eps=1e-05, momentum=0.1, affine=True, 
                                     track_running_stats=True)
    

    将已有网络的所有BN层改为同步BN层

    def convertBNtoSyncBN(module, process_group=None):
        '''Recursively replace all BN layers to SyncBN layer.
    
        Args:
            module[torch.nn.Module]. Network
        '''
        if isinstance(module, torch.nn.modules.batchnorm._BatchNorm):
            sync_bn = torch.nn.SyncBatchNorm(module.num_features, module.eps, module.momentum, 
                                             module.affine, module.track_running_stats, process_group)
            sync_bn.running_mean = module.running_mean
            sync_bn.running_var = module.running_var
            if module.affine:
                sync_bn.weight = module.weight.clone().detach()
                sync_bn.bias = module.bias.clone().detach()
            return sync_bn
        else:
            for name, child_module in module.named_children():
                setattr(module, name) = convert_syncbn_model(child_module, process_group=process_group))
            return module
    

    类似BN滑动平均

    如果要实现类似BN滑动平均的操作,在forward函数中要使用原地(inplace)操作给滑动平均赋值。

    class BN(torch.nn.Module)
        def __init__(self):
            ...
            self.register_buffer('running_mean', torch.zeros(num_features))
    
        def forward(self, X):
            ...
            self.running_mean += momentum * (current - self.running_mean)
    

    计算模型整体参数量

    num_parameters = sum(torch.numel(parameter) for parameter in model.parameters())
    

    类似Keras的model.summary()输出模型信息

    sksq96/pytorch-summarygithub.com图标

    模型权值初始化

    注意model.modules()和model.children()的区别:model.modules()会迭代地遍历模型的所有子层,而model.children()只会遍历模型下的一层。

    # Common practise for initialization.
    for layer in model.modules():
        if isinstance(layer, torch.nn.Conv2d):
            torch.nn.init.kaiming_normal_(layer.weight, mode='fan_out',
                                          nonlinearity='relu')
            if layer.bias is not None:
                torch.nn.init.constant_(layer.bias, val=0.0)
        elif isinstance(layer, torch.nn.BatchNorm2d):
            torch.nn.init.constant_(layer.weight, val=1.0)
            torch.nn.init.constant_(layer.bias, val=0.0)
        elif isinstance(layer, torch.nn.Linear):
            torch.nn.init.xavier_normal_(layer.weight)
            if layer.bias is not None:
                torch.nn.init.constant_(layer.bias, val=0.0)
    
    # Initialization with given tensor.
    layer.weight = torch.nn.Parameter(tensor)
    

    部分层使用预训练模型

    注意如果保存的模型是torch.nn.DataParallel,则当前的模型也需要是torch.nn.DataParallel。torch.nn.DataParallel(model).module == model。

    model.load_state_dict(torch.load('model,pth'), strict=False)
    

    将在GPU保存的模型加载到CPU

    model.load_state_dict(torch.load('model,pth', map_location='cpu'))
    

    4. 数据准备、特征提取与微调

    图像分块打散(image shuffle)/区域混淆机制(region confusion mechanism,RCM)[2]

    # X is torch.Tensor of size N*D*H*W.
    # Shuffle rows
    Q = (torch.unsqueeze(torch.arange(num_blocks), dim=1) * torch.ones(1, num_blocks).long()
         + torch.randint(low=-neighbour, high=neighbour, size=(num_blocks, num_blocks)))
    Q = torch.argsort(Q, dim=0)
    assert Q.size() == (num_blocks, num_blocks)
    
    X = [torch.chunk(row, chunks=num_blocks, dim=2)
         for row in torch.chunk(X, chunks=num_blocks, dim=1)]
    X = [[X[Q[i, j].item()][j] for j in range(num_blocks)]
         for i in range(num_blocks)]
    
    # Shulle columns.
    Q = (torch.ones(num_blocks, 1).long() * torch.unsqueeze(torch.arange(num_blocks), dim=0)
         + torch.randint(low=-neighbour, high=neighbour, size=(num_blocks, num_blocks)))
    Q = torch.argsort(Q, dim=1)
    assert Q.size() == (num_blocks, num_blocks)
    X = [[X[i][Q[i, j].item()] for j in range(num_blocks)]
         for i in range(num_blocks)]
    
    Y = torch.cat([torch.cat(row, dim=2) for row in X], dim=1)
    

    得到视频数据基本信息

    import cv2
    video = cv2.VideoCapture(mp4_path)
    height = int(video.get(cv2.CAP_PROP_FRAME_HEIGHT))
    width = int(video.get(cv2.CAP_PROP_FRAME_WIDTH))
    num_frames = int(video.get(cv2.CAP_PROP_FRAME_COUNT))
    fps = int(video.get(cv2.CAP_PROP_FPS))
    video.release()
    

    TSN每段(segment)采样一帧视频[3]

    K = self._num_segments
    if is_train:
        if num_frames > K:
            # Random index for each segment.
            frame_indices = torch.randint(
                high=num_frames // K, size=(K,), dtype=torch.long)
            frame_indices += num_frames // K * torch.arange(K)
        else:
            frame_indices = torch.randint(
                high=num_frames, size=(K - num_frames,), dtype=torch.long)
            frame_indices = torch.sort(torch.cat((
                torch.arange(num_frames), frame_indices)))[0]
    else:
        if num_frames > K:
            # Middle index for each segment.
            frame_indices = num_frames / K // 2
            frame_indices += num_frames // K * torch.arange(K)
        else:
            frame_indices = torch.sort(torch.cat((                              
                torch.arange(num_frames), torch.arange(K - num_frames))))[0]
    assert frame_indices.size() == (K,)
    return [frame_indices[i] for i in range(K)]
    

    提取ImageNet预训练模型某层的卷积特征

    # VGG-16 relu5-3 feature.
    model = torchvision.models.vgg16(pretrained=True).features[:-1]
    # VGG-16 pool5 feature.
    model = torchvision.models.vgg16(pretrained=True).features
    # VGG-16 fc7 feature.
    model = torchvision.models.vgg16(pretrained=True)
    model.classifier = torch.nn.Sequential(*list(model.classifier.children())[:-3])
    # ResNet GAP feature.
    model = torchvision.models.resnet18(pretrained=True)
    model = torch.nn.Sequential(collections.OrderedDict(
        list(model.named_children())[:-1]))
    
    with torch.no_grad():
        model.eval()
        conv_representation = model(image)
    

    提取ImageNet预训练模型多层的卷积特征

    class FeatureExtractor(torch.nn.Module):
        """Helper class to extract several convolution features from the given
        pre-trained model.
    
        Attributes:
            _model, torch.nn.Module.
            _layers_to_extract, list<str> or set<str>
    
        Example:
            >>> model = torchvision.models.resnet152(pretrained=True)
            >>> model = torch.nn.Sequential(collections.OrderedDict(
                    list(model.named_children())[:-1]))
            >>> conv_representation = FeatureExtractor(
                    pretrained_model=model,
                    layers_to_extract={'layer1', 'layer2', 'layer3', 'layer4'})(image)
        """
        def __init__(self, pretrained_model, layers_to_extract):
            torch.nn.Module.__init__(self)
            self._model = pretrained_model
            self._model.eval()
            self._layers_to_extract = set(layers_to_extract)
        
        def forward(self, x):
            with torch.no_grad():
                conv_representation = []
                for name, layer in self._model.named_children():
                    x = layer(x)
                    if name in self._layers_to_extract:
                        conv_representation.append(x)
                return conv_representation
    

    其他预训练模型

    Cadene/pretrained-models.pytorchgithub.com图标

    微调全连接层

    model = torchvision.models.resnet18(pretrained=True)
    for param in model.parameters():
        param.requires_grad = False
    model.fc = nn.Linear(512, 100)  # Replace the last fc layer
    optimizer = torch.optim.SGD(model.fc.parameters(), lr=1e-2, momentum=0.9, weight_decay=1e-4)
    

    以较大学习率微调全连接层,较小学习率微调卷积层

    model = torchvision.models.resnet18(pretrained=True)
    finetuned_parameters = list(map(id, model.fc.parameters()))
    conv_parameters = (p for p in model.parameters() if id(p) not in finetuned_parameters)
    parameters = [{'params': conv_parameters, 'lr': 1e-3}, 
                  {'params': model.fc.parameters()}]
    optimizer = torch.optim.SGD(parameters, lr=1e-2, momentum=0.9, weight_decay=1e-4)
    

    5. 模型训练

    常用训练和验证数据预处理

    其中ToTensor操作会将PIL.Image或形状为H×W×D,数值范围为[0, 255]的np.ndarray转换为形状为D×H×W,数值范围为[0.0, 1.0]的torch.Tensor。

    train_transform = torchvision.transforms.Compose([
        torchvision.transforms.RandomResizedCrop(size=224,
                                                 scale=(0.08, 1.0)),
        torchvision.transforms.RandomHorizontalFlip(),
        torchvision.transforms.ToTensor(),
        torchvision.transforms.Normalize(mean=(0.485, 0.456, 0.406),
                                         std=(0.229, 0.224, 0.225)),
     ])
     val_transform = torchvision.transforms.Compose([
        torchvision.transforms.Resize(256),
        torchvision.transforms.CenterCrop(224),
        torchvision.transforms.ToTensor(),
        torchvision.transforms.Normalize(mean=(0.485, 0.456, 0.406),
                                         std=(0.229, 0.224, 0.225)),
    ])
    

    训练基本代码框架

    for t in epoch(80):
        for images, labels in tqdm.tqdm(train_loader, desc='Epoch %3d' % (t + 1)):
            images, labels = images.cuda(), labels.cuda()
            scores = model(images)
            loss = loss_function(scores, labels)
            optimizer.zero_grad()
            loss.backward()
            optimizer.step()
    

    标记平滑(label smoothing)[4]

    for images, labels in train_loader:
        images, labels = images.cuda(), labels.cuda()
        N = labels.size(0)
        # C is the number of classes.
        smoothed_labels = torch.full(size=(N, C), fill_value=0.1 / (C - 1)).cuda()
        smoothed_labels.scatter_(dim=1, index=torch.unsqueeze(labels, dim=1), value=0.9)
    
        score = model(images)
        log_prob = torch.nn.functional.log_softmax(score, dim=1)
        loss = -torch.sum(log_prob * smoothed_labels) / N
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
    

    Mixup[5]

    beta_distribution = torch.distributions.beta.Beta(alpha, alpha)
    for images, labels in train_loader:
        images, labels = images.cuda(), labels.cuda()
    
        # Mixup images.
        lambda_ = beta_distribution.sample([]).item()
        index = torch.randperm(images.size(0)).cuda()
        mixed_images = lambda_ * images + (1 - lambda_) * images[index, :]
    
        # Mixup loss.    
        scores = model(mixed_images)
        loss = (lambda_ * loss_function(scores, labels) 
                + (1 - lambda_) * loss_function(scores, labels[index]))
    
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
    

    L1正则化

    l1_regularization = torch.nn.L1Loss(reduction='sum')
    loss = ...  # Standard cross-entropy loss
    for param in model.parameters():
        loss += lambda_ * torch.sum(torch.abs(param))
    loss.backward()
    

    不对偏置项进行L2正则化/权值衰减(weight decay)

    bias_list = (param for name, param in model.named_parameters() if name[-4:] == 'bias')
    others_list = (param for name, param in model.named_parameters() if name[-4:] != 'bias')
    parameters = [{'parameters': bias_list, 'weight_decay': 0},                
                  {'parameters': others_list}]
    optimizer = torch.optim.SGD(parameters, lr=1e-2, momentum=0.9, weight_decay=1e-4)
    

    梯度裁剪(gradient clipping)

    torch.nn.utils.clip_grad_norm_(model.parameters(), max_norm=20)
    

    计算Softmax输出的准确率

    score = model(images)
    prediction = torch.argmax(score, dim=1)
    num_correct = torch.sum(prediction == labels).item()
    accuruacy = num_correct / labels.size(0)
    

    可视化模型前馈的计算图

    szagoruyko/pytorchvizgithub.com图标

    可视化学习曲线

    有Facebook自己开发的Visdom和Tensorboard(仍处于实验阶段)两个选择。

    facebookresearch/visdomgithub.com图标

    torch.utils.tensorboard - PyTorch master documentationpytorch.org

    # Example using Visdom.
    vis = visdom.Visdom(env='Learning curve', use_incoming_socket=False)
    assert self._visdom.check_connection()
    self._visdom.close()
    options = collections.namedtuple('Options', ['loss', 'acc', 'lr'])(
        loss={'xlabel': 'Epoch', 'ylabel': 'Loss', 'showlegend': True},
        acc={'xlabel': 'Epoch', 'ylabel': 'Accuracy', 'showlegend': True},
        lr={'xlabel': 'Epoch', 'ylabel': 'Learning rate', 'showlegend': True})
    
    for t in epoch(80):
        tran(...)
        val(...)
        vis.line(X=torch.Tensor([t + 1]), Y=torch.Tensor([train_loss]),
                 name='train', win='Loss', update='append', opts=options.loss)
        vis.line(X=torch.Tensor([t + 1]), Y=torch.Tensor([val_loss]),
                 name='val', win='Loss', update='append', opts=options.loss)
        vis.line(X=torch.Tensor([t + 1]), Y=torch.Tensor([train_acc]),
                 name='train', win='Accuracy', update='append', opts=options.acc)
        vis.line(X=torch.Tensor([t + 1]), Y=torch.Tensor([val_acc]),
                 name='val', win='Accuracy', update='append', opts=options.acc)
        vis.line(X=torch.Tensor([t + 1]), Y=torch.Tensor([lr]),
                 win='Learning rate', update='append', opts=options.lr)
    

    得到当前学习率

    # If there is one global learning rate (which is the common case).
    lr = next(iter(optimizer.param_groups))['lr']
    
    # If there are multiple learning rates for different layers.
    all_lr = []
    for param_group in optimizer.param_groups:
        all_lr.append(param_group['lr'])
    

    学习率衰减

    # Reduce learning rate when validation accuarcy plateau.
    scheduler = torch.optim.lr_scheduler.ReduceLROnPlateau(optimizer, mode='max', patience=5, verbose=True)
    for t in range(0, 80):
        train(...); val(...)
        scheduler.step(val_acc)
    
    # Cosine annealing learning rate.
    scheduler = torch.optim.lr_scheduler.CosineAnnealingLR(optimizer, T_max=80)
    # Reduce learning rate by 10 at given epochs.
    scheduler = torch.optim.lr_scheduler.MultiStepLR(optimizer, milestones=[50, 70], gamma=0.1)
    for t in range(0, 80):
        scheduler.step()    
        train(...); val(...)
    
    # Learning rate warmup by 10 epochs.
    scheduler = torch.optim.lr_scheduler.LambdaLR(optimizer, lr_lambda=lambda t: t / 10)
    for t in range(0, 10):
        scheduler.step()
        train(...); val(...)
    

    保存与加载断点

    注意为了能够恢复训练,我们需要同时保存模型和优化器的状态,以及当前的训练轮数。

    # Save checkpoint.
    is_best = current_acc > best_acc
    best_acc = max(best_acc, current_acc)
    checkpoint = {
        'best_acc': best_acc,    
        'epoch': t + 1,
        'model': model.state_dict(),
        'optimizer': optimizer.state_dict(),
    }
    model_path = os.path.join('model', 'checkpoint.pth.tar')
    torch.save(checkpoint, model_path)
    if is_best:
        shutil.copy('checkpoint.pth.tar', model_path)
    
    # Load checkpoint.
    if resume:
        model_path = os.path.join('model', 'checkpoint.pth.tar')
        assert os.path.isfile(model_path)
        checkpoint = torch.load(model_path)
        best_acc = checkpoint['best_acc']
        start_epoch = checkpoint['epoch']
        model.load_state_dict(checkpoint['model'])
        optimizer.load_state_dict(checkpoint['optimizer'])
        print('Load checkpoint at epoch %d.' % start_epoch)
    

    计算准确率、查准率(precision)、查全率(recall)

    # data['label'] and data['prediction'] are groundtruth label and prediction 
    # for each image, respectively.
    accuracy = np.mean(data['label'] == data['prediction']) * 100
    
    # Compute recision and recall for each class.
    for c in range(len(num_classes)):
        tp = np.dot((data['label'] == c).astype(int),
                    (data['prediction'] == c).astype(int))
        tp_fp = np.sum(data['prediction'] == c)
        tp_fn = np.sum(data['label'] == c)
        precision = tp / tp_fp * 100
        recall = tp / tp_fn * 100
    

    6. 模型测试

    计算每个类别的查准率(precision)、查全率(recall)、F1和总体指标

    import sklearn.metrics
    
    all_label = []
    all_prediction = []
    for images, labels in tqdm.tqdm(data_loader):
         # Data.
         images, labels = images.cuda(), labels.cuda()
         
         # Forward pass.
         score = model(images)
         
         # Save label and predictions.
         prediction = torch.argmax(score, dim=1)
         all_label.append(labels.cpu().numpy())
         all_prediction.append(prediction.cpu().numpy())
    
    # Compute RP and confusion matrix.
    all_label = np.concatenate(all_label)
    assert len(all_label.shape) == 1
    all_prediction = np.concatenate(all_prediction)
    assert all_label.shape == all_prediction.shape
    micro_p, micro_r, micro_f1, _ = sklearn.metrics.precision_recall_fscore_support(
         all_label, all_prediction, average='micro', labels=range(num_classes))
    class_p, class_r, class_f1, class_occurence = sklearn.metrics.precision_recall_fscore_support(
         all_label, all_prediction, average=None, labels=range(num_classes))
    # Ci,j = #{y=i and hat_y=j}
    confusion_mat = sklearn.metrics.confusion_matrix(
         all_label, all_prediction, labels=range(num_classes))
    assert confusion_mat.shape == (num_classes, num_classes)
    

    将各类结果写入电子表格

    import csv
    
    # Write results onto disk.
    with open(os.path.join(path, filename), 'wt', encoding='utf-8') as f:
         f = csv.writer(f)
         f.writerow(['Class', 'Label', '# occurence', 'Precision', 'Recall', 'F1',
                     'Confused class 1', 'Confused class 2', 'Confused class 3',
                     'Confused 4', 'Confused class 5'])
         for c in range(num_classes):
             index = np.argsort(confusion_mat[:, c])[::-1][:5]
             f.writerow([
                 label2class[c], c, class_occurence[c], '%4.3f' % class_p[c],
                     '%4.3f' % class_r[c], '%4.3f' % class_f1[c],
                     '%s:%d' % (label2class[index[0]], confusion_mat[index[0], c]),
                     '%s:%d' % (label2class[index[1]], confusion_mat[index[1], c]),
                     '%s:%d' % (label2class[index[2]], confusion_mat[index[2], c]),
                     '%s:%d' % (label2class[index[3]], confusion_mat[index[3], c]),
                     '%s:%d' % (label2class[index[4]], confusion_mat[index[4], c])])
             f.writerow(['All', '', np.sum(class_occurence), micro_p, micro_r, micro_f1, 
                         '', '', '', '', ''])
    

    7. PyTorch其他注意事项

    模型定义

    • 建议有参数的层和汇合(pooling)层使用torch.nn模块定义,激活函数直接使用torch.nn.functional。torch.nn模块和torch.nn.functional的区别在于,torch.nn模块在计算时底层调用了torch.nn.functional,但torch.nn模块包括该层参数,还可以应对训练和测试两种网络状态。使用torch.nn.functional时要注意网络状态,如
    def forward(self, x):
        ...
        x = torch.nn.functional.dropout(x, p=0.5, training=self.training)
    
    • model(x)前用model.train()和model.eval()切换网络状态。
    • 不需要计算梯度的代码块用with torch.no_grad()包含起来。model.eval()和torch.no*_*grad()的区别在于,model.eval()是将网络切换为测试状态,例如BN和随机失活(dropout)在训练和测试阶段使用不同的计算方法。torch.no_grad()是关闭PyTorch张量的自动求导机制,以减少存储使用和加速计算,得到的结果无法进行loss.backward()。
    • torch.nn.CrossEntropyLoss的输入不需要经过Softmax。torch.nn.CrossEntropyLoss等价于torch.nn.functional.log_softmax + torch.nn.NLLLoss。
    • loss.backward()前用optimizer.zero_grad()清除累积梯度。optimizer.zero_grad()和model.zero_grad()效果一样。

    PyTorch性能与调试

    • torch.utils.data.DataLoader中尽量设置pin_memory=True,对特别小的数据集如MNIST设置pin_memory=False反而更快一些。num_workers的设置需要在实验中找到最快的取值。
    • 用del及时删除不用的中间变量,节约GPU存储。
    • 使用inplace操作可节约GPU存储,如
    x = torch.nn.functional.relu(x, inplace=True)
    

    此外,还可以通过torch.utils.checkpoint前向传播时只保留一部分中间结果来节约GPU存储使用,在反向传播时需要的内容从最近中间结果中计算得到。

    • 减少CPU和GPU之间的数据传输。例如如果你想知道一个epoch中每个mini-batch的loss和准确率,先将它们累积在GPU中等一个epoch结束之后一起传输回CPU会比每个mini-batch都进行一次GPU到CPU的传输更快。
    • 使用半精度浮点数half()会有一定的速度提升,具体效率依赖于GPU型号。需要小心数值精度过低带来的稳定性问题。
    • 时常使用assert tensor.size() == (N, D, H, W)作为调试手段,确保张量维度和你设想中一致。
    • 除了标记y外,尽量少使用一维张量,使用n*1的二维张量代替,可以避免一些意想不到的一维张量计算结果。
    • 统计代码各部分耗时
    with torch.autograd.profiler.profile(enabled=True, use_cuda=False) as profile:
        ...
    print(profile)
    

    或者在命令行运行

    python -m torch.utils.bottleneck main.py
    

    参考资料

    参考

    1. ^T.-Y. Lin, A. RoyChowdhury, and S. Maji. Bilinear CNN models for fine-grained visual recognition. In ICCV, 2015.
    2. ^Y. Chen, Y. Bai, W. Zhang, and T. Mei. Destruction and construction learning for fine-grained image recognition. In CVPR, 2019.
    3. ^L. Wang, Y. Xiong, Z. Wang, Y. Qiao, D. Lin, X. Tang, and L. V. Gool. Temporal segment networks: Towards good practices for deep action recognition. In ECCV, 2016.
    4. ^C. Szegedy, V. Vanhoucke, S. Ioffe, J. Shlens, and Z. Wojna: Rethinking the Inception architecture for computer vision. In CVPR, 2016.
    5. ^H. Zhang, M. Cissé, Y. N. Dauphin, and D. Lopez-Paz. mixup: Beyond empirical risk minimization. In ICLR, 2018.
    展开全文
  • css常用代码大全,html+css代码

    万次阅读 多人点赞 2017-12-28 21:24:46
    css常用代码大全,html+css代码 html+css可以很方便的进行网页的排版布局,还能减少很多不必要的代码。 一.文本设置 1、font-size: 字号参数  2、font-style: 字体格式 3、font-weight: 字体粗细 ...
  • R语言常用代码

    千次阅读 2021-06-28 08:47:43
    表格查看数据框 DT::datatable(df,filter='top') R包的安装 rm(list = ls()) options()$repos options()$BioC_mirror options(BioC_mirror="https://mirrors.ustc.edu.cn/bioc/") ...options()$repos option
  • 十种常用代码编辑器

    千次阅读 2021-11-06 19:37:09
    1.vs code 微软推出的轻量级代码编译器,是本人使用最多的编译器(主要是好玩的插件多),支持几乎所有主流的开发语言的语法高亮、智能代码补全、自定义热键、括号匹配、代码片段、代码对比 Diff、GIT 等特性,支持插件...
  • c++常用代码(持续更新)

    千次阅读 2021-06-29 10:52:16
    #include <iostream> #include <string> #include <chrono> void Run() { for (int i = 0; i < 1000000000; ++i) { } } int main() ... auto afterTime = std::chrono::steady_.
  • IDEA——常用代码模板

    千次阅读 2020-09-04 21:09:52
    IDEA 提供了一些内置的代码模板,可以让开发者快速方便的使用,当然 eclipse 中也是有的,比如输入 syso 快速生成输出语句,main 快速生成主函数等。 一、输出模板 1、sout,最基本的输出语句,快速生成System.out...
  • 数学建模常用代码总结-Python&MATLAB

    万次阅读 多人点赞 2020-05-16 14:53:10
    数学建模常用代码总结-Python&MATLAB 数学建模过程中有许多可复用的基础代码,在此对 python 以及 MATLAB 中常用代码进行简单总结,该总结会进行实时更新。 一、文件读取 python (pandas) 文件后缀名(扩展名...
  • jupyter notebook常用代码

    千次阅读 2020-08-21 11:47:32
    jupyter notebook常用代码 加载test.py的代码 %load /Users/chenqionghe/test.py 运行代码 %run 你的代码文件.py
  • MATLAB常用代码(完结)

    万次阅读 多人点赞 2020-12-01 10:53:37
    1.退出MATLAB 关闭MATLAB桌面 在命令窗口执行quit或exit命令 2.开平方-sqrt(x) 3.指数函数exp(x) 4.clc清除窗口显示内容的命令 5.who、whos命令用来清除工作空间的变量 ...6.clear命令用来清除工作空间的变量 ...
  • C++ 常用代码大全

    万次阅读 多人点赞 2020-02-14 10:47:08
    相信看了那么多内容,大家都差不多会运用这些代码了 如果各位觉得有帮助,请 关注一下或点个赞 ,如果觉得没帮助,那也请 不要在评论区里喷我 如果您觉得还有可补充的,欢迎 在评论区里补充 ,如果您还有问题,...
  • Java常用代码汇总(经典代码)

    万次阅读 多人点赞 2018-09-20 15:44:57
    8.java分页代码实现 1 public class PageBean { 2 private int curPage; //当前页 3 private int pageCount; //总页数 4 private int rowsCount; //总行数 5 private int pageSize=10; //每页多少行 ...
  • web前端常用代码

    千次阅读 2018-11-02 10:54:14
    文字两端对齐 .text-justify{ width: 100px; display: inline-block; text-align: justify; text-align-last: justify; } 超出一行用...代替 .online{ display: block; /*设置为flex ...... width...
  • python入门常用代码

    万次阅读 多人点赞 2018-04-11 16:23:42
    1.print直接输出&gt;&gt; print(1) 1 &gt;&gt;&gt; print("Hello World") Hello World 各种变量&gt;&gt;&gt; x = 12 &gt;&gt;&gt; print(x) ...
  • Intellij IDEA快捷生成常用代码

    千次阅读 2017-11-17 10:28:42
    在使用Intellij IDEA开发的时候,利用快捷键快捷生成我们想写的代码。  可以减少简单重复的工作,同时也可以提供我们的工作效率。  总结了一些如下:  //psvm 生成main 方法 public static void main(String...
  • HTML常用代码合集速查表

    千次阅读 2020-05-25 17:07:05
    (换行) (水平线) 各种文本样式: 粗体文本 计算机代码 强调文本 斜体文本 键盘输入 预格式化文本 更小的文本 重要的文本 (缩写) (联系信息) (文字方向) (从另一个源引用的部分) (工作的名称) (删除...
  • 链接:https://pan.baidu.com/s/1vPQaUrZ2UbY7BS4wiHGnXw 提取码:68ee
  • 网页中QQ常用代码

    千次阅读 2018-05-26 15:22:58
    另:几个常用的Package命令: 新浪微博(编辑界面):com.sina.weibo com.sina.weibo.EditActivity 腾讯微博(编辑界面):com.tencent.WBlog com.tencent.WBlog.activity.MicroblogInput 微信: ...
  • 通过分析github上5000个开源python项目,找出了最常用的库,word文档列举了最常用的前50个,相应代码以网址形式给出,整理非常全面,方便学习。
  • 常用代码快捷键

    千次阅读 2021-03-11 13:22:45
    更新时间:2021年3月11日 第一版,现在只是写常用的,后续会慢慢添加完善 通用快捷键: Ctrl + G 跳转到指定的代码行 Ctrl + Shift + ←/→ 选当前光标左边或右边连续的字符 Ctrl + C 对选中的内容...
  • stata做计量入门常用代码一览!

    千次阅读 2018-08-12 23:52:15
    常用的 命令参考如下: 一、statsby的命令格式及说明 statsby命令格式为: statsby [exp_list] [, options ]: command 其具体内容,请参见STATA的help文件,即: help statsby 在分组回归中,statsby最重要的...
  • R语言常用代码(入门)

    万次阅读 多人点赞 2020-05-14 22:07:32
    R语言常用代码 安装所需要的包 # 安装包 install.packages("packagename") # 加载包 library(packagesname) 设置工作路径 // 使用getwd()函数来显示当前工作目录; getwd() //使用setwd()函数更改当前目录; ...
  • Excel VBA编程的常用代码
  • 太实用了!Excel VBA常用代码

    万次阅读 多人点赞 2018-12-19 11:36:27
    前两天有两位朋友留言想收集一些VBA的常用代码,今天开始会陆续分享一些! 记得收藏好哦,因为今后你应用到稍大型Excel VBA程序时,这其中某些代码肯定会用到。 来看看都是哪些常用代码: ...
  • Python常用代码

    万次阅读 2021-07-31 00:42:58
    1、 安装库 如: pip install pyinstaller #默认为最新版库 安装指定版本库 如: pip install pyinstaller==3.4 #3.4为版本号 2、卸载库 如: pip uninstall pyinstaller 3、打包exe 如: pyinstaller -F -w -i D:\1...
  • 常用的html代码大全

    千次阅读 2021-06-08 16:15:49
    导语:html代码,我们暂时抛开代码二字,大家有听说过html是什么吗?好吧,小编承认这又是一个高大上的专业名词。还是由小编来为大家详细介绍一下吧。...今天小编就来为大家简单介绍一下常用的html代码吧。...
  • 蓝桥杯常用代码模板总结(C/C++)

    千次阅读 2021-03-18 20:50:01
    蓝桥杯基础算法总结(C/C++) ...C++代码: void BubbleSort(int a[], int n) { for (int i = 0; i < n - 1; i++) { for (int j = 0; j < n - i - 1; j++) { if (a[j] > a[j + 1]) {

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 2,392,451
精华内容 956,980
关键字:

常用代码

友情链接: myCanny.rar