CLIP__视频笔记
Posted Blue_Whale2020
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CLIP__视频笔记相关的知识,希望对你有一定的参考价值。
learning transferable visual models from natural language supervision
高新能的迁移学习模型,结合了文本和图像信息
CLIP不在imagenet 128k的数据集上做预训练,能取得与预训练的ResNet50有同样的效果
clip的监督信号来自自然语言处理
网络的输入是图片-文本对,分别经过encoder提取特征,这个encoder可以是一个resnet,或者是一个vision transformer。然后在这些特征上进行对比学习,文本里的encoder可以是CBOW或者是tesxt trnaosformer。
在clip的对比学习中,配对的样本是正样本,如上图左矩阵中对角线的部分,所以共有n^2-n个副样本,clip的训练是在4亿张数据上进行的
clip的推理
Prompt template: 首先使用一组单词,将之加入句式中组成句子,然后进入test encoder编码器抽取特征,其实直接使用单词抽取特征也是可以的,但是clip在训练的过程中,text encoder接受的是一组句子,所以推理为了与训练的过程保持一致,还是采取了将单词编码成句子的方式。
于是将imagenet上1000类的图片,编码成这样的1000类文本特征。
在分类过程中,网络接受任意一张图片,经过image encoder抽取特征,将得到的特征与文本特征计算 cosine similarity,取出最相似的文本特征,就得到了那个对应的类别。
在Prompt template的过程中,类别单词可以不仅限于imageent的1000类,所以clip做到了类别的拓展。 这是之前任何一个在imagenet上预;训练的模型都做不到的,摆脱了categorical label的限制。
由于clip把视觉的语义和文字的语义联系到了一起,学习到的特征语义性非常强,迁移的效果也非常好。
clip的有趣应用
style clip:把stylegan和clip结合到了一起,使用文字信息引导图像的生成
clip draw:做法更简单,用文字信息生成抽象的画,在普通的gpu上不到一分钟就可以生成
open-vocabulary object detection via vision and language knowledge distillation: 使用clip来做目标检测,
原来的目标检测只能分辨玩具,clip的数据能做更细粒度的分类
github:johanmodin/clifs 用于视频检索,直接输入关键词,网络模型就检索视频里的每一帧,与文本特征相匹配,返回包含检索目标的图片。
———————————————————————————————————————————
有限制的类别限制了模型的泛化性,灵感来自于自然语言处理。
在自然语言处理的自监督训练模型中,不论使用atuoregessive(自回归预测)还是masked language(掩码完形填空)的方式,目标函数与下游任务无关,目的仅仅在于提取出一个高效有用的特征
作者尝试了小模型resnet 大模型vision transformer两种模型,结果发现迁移学习的性能和网络模型的大小是成正比的
作者为了进一步验证clip学习到特征的有效性,尝试了liner-prob,在模型训练好了之后,freeze the backbone,只训练分类头,发现clip也比之前的工作性能好,计算更高效。
这种多模态模型的训练是很困难的,首先作者借鉴了VirTex的多模态训练工作,在图像中使用CNN进行训练,在文本中使用Transformer训练。同时对比学习对无监督的训练也有诸多好处,把预测性任务转为对比学习的任务之后,学习效率提高了4倍
由于数据集过大,temperature被设计为一个可学习的参数,没有调节。除了使用random crop之外没有使用其他数据增强的方式,在moco simlcr中十分重要的非线性投射层,也被简化为了linear-projection
有关如何在多个gpu上训练大模型
第3节
zero-shot研究动机,原来的对比学习目标都是抽取特征,如moco simCLR DINO这些方法,但是对比学习想迁移到其他数据还是需要有标签的finetune,还有可能遇到数据集不好迁移,distribution shift的问题。那如何只做一次 训练一个模型,这就是zero-shot transfer。
Prompt engineering :一个模型微调中很流行的概念,在CLIP中,就是使用文本信息引导图片分类
另外,如果使用一个单词作为图片的prompt,经常会有歧义性的这个问题
所以把每一个单词都放到提示模板里 "a photo of label",具体的使用中,作者使用了80个这样的模板,最后把结果综合起来会是更好的结果
CLIP的局限性
CLIP只能和resnet50这种basline模型打成平手,但是和真正的state of art还有10几个点的差距,当然可以通过增大数据规模的方式来弥补这个差距,但是得还需要在4亿的基础上再*1000,所以对于openAI这种硬件条件来说也是无法训练的,所以需要找到提高训练效率的方法
另外,clip不是万能的方法,在很多困难的数据集中,例如找出图片中有多少个物体、区分视频中的异常帧,在这些数据集中,clip的性能和瞎猜差不多
另外虽然clip的泛化性能很好,但是如果训练数据和测试数据之间真的已经out of distribution的话,那clip的泛化性能也会变得很差,例如clip在minst数据集上性能很差
clip的分类任务还是从给定的类别里作选择,选出相似或者不相似,另外一种更灵活的方式是直接为图片生成标题,以后可能会将生成式模型的损失函数和对比模型的损失函数结合
clip利用数据效率不高,训练一共用了128亿张图片,自监督学习和self-training(伪标签的方式可能会有更高的利用效率
虽然clip一直在做zero-shot,但是是一直在imagenet上做测试的,网络和超参的调整也都以imagenet的性能为导向,所以可能imagenet给予了一种隐含的指示
OpenAI这批的clip训练数据是网上爬的,所以会有种族社会和宗教的偏见
clip存在一种很奇怪的现象,从zero-shot迁移到few-shot的过程中,不给训练样本的性能反而比给了样本的性能还要差
1:34简短的代码实战
Java基础知识_毕向东_Java基础视频教程笔记(5-10)
06天-05-面向对象(帮助文档的制作javadoc):
java文档生成命令:
javadoc -d filepatn demo.java -author -version(可选)
一个类中默认会有一个空参数的构造函数,这个默认的构造函数的权限和所属类一致
默认构造函数的权限是随着的类的变化而变化的。
06天-06-面向对象(静态代码块):
静态代码块的特点:随着类的加载而加载,只执行一次,用于给类的初始化。
非静态代码块的特点:随着类的实例建立而分配内存空间初始化。
构造代码块的特点:随着类的实例而初始化,在非静态代码块初始化后。
new对象过程:
1.加载类文件到内存; 2.初始化类的静态变量和函数; 3.分配堆内存地址;
4.在堆内存建立对象的特有属性,并进行默认初始化; 5.对属性显示初始化
6.对对象构造代码块初始化;7.对对象对应的构造函数初始化;
8.将堆内存地址赋给栈内存对象的实例变量。
06天-09-面向对象(单例设计模式):
设计模式:解决某一类问题最行之有效的方法
07天-01-面向对象(继承-概述):
继承 extends:1.提高了代码的复用性
2.让类与类之间产生了关系,有了这个关系才有多态的特性
重载:只看同名函数的参数列表
重写:子父类方法要一模一样
继承:子类的所有构造函数,默认都会访问父类中的空参数构造函数
子类实例化过程:
子类每个构造函数的第一行都有一句隐式super();
当父类没有空参数构造函数时,子类必须手动通过super语句指定访问父类构造函数
当子类的构造函数第一行也可以指定this语句访问本类构造函数间接访问父类构造函数
07天-07-面向对象(final关键字):
final:最终,作为一个修饰符
1.可以修饰类、函数、变量
2.被final修饰的类不可以被继承,为了避免被继承,被子类覆写功能
3.被final修饰的方法不可以被覆写
4.被final修饰的变量是一个常量只能赋值一次,可以是成员变量或者局部变量
5.内部类定义在类中的局部位置上时,只能访问该局部被final修饰的局部变量
抽象类的特点:
1.抽象方法一定在抽象类中
2.抽象方法和抽象类都必须被abstract关键字修饰
3.抽象类不可以用new创建对象,因为调用抽象方法没意义
4.抽象类中的方法要被使用,必须由子类覆写所有抽象方法,建立子类对象调用
5.抽象类比一般类多了抽象函数,并且不可以实例化
模板方法设计模式:
在定义功能时,功能的一部分是确定,但是有一部分是不确定,而确定的部分在
使用不确定的部分,那么就将不确定的部分暴露出去,由该类的子类实现
07天-12-面向对象(接口):
接口定义时特点:
1.接口中常见定义:常量、抽象方法
2.接口中的成员都有固定修饰符,可以省略
常量:public static final 方法:public abstract
接口:是不可以创建对象的,因为有抽象方法,需要被子类实现,子类对接口中
的抽象方法全部覆盖后,子类才可以实例化,否则子类是一个抽象类
接口可以被类多实现,也是对类多继承不支持的转换形式
类与类:继承关系,单继承
接口与接口:继承关系,多继承
类与接口:实现关系,多实现
08天-01-面向对象(多态-概念):
多态:可以理解为事物存在的多种体现形态
多态的体现:父类的引用可以指向子类的对象,父类的引用可以接收自己子类对象
多态的前提:必须是类与类之间有关系,要么是继承,要么是实现,并存在覆盖
多态的好处:多态的出现大大提高了程序的扩展性
多态的弊端:提高了扩展性,但是只能使用父类的引用访问父类中的成员
09天-01-面向对象(内部类访问规则):
内部类的访问规则:
1.内部类可以直接访问外部类中的成员,包括私有。
之所以可以直接访问外部类中的成员,是因为内部类中持有一个外部类的引用:
格式特点:外部类名.this.变量名
2.外部类要访问内部类,必须建立内部类对象
3.当内部类中定义了静态成员,该内部类必须是static类
当内部类在成员位置时:
内部类访问权限可以是private,但是外部类必须是default或者public
内部类访问修饰符可以是static,并具备static的特性
访问内部类:
当内部类定义在外部类的成员位置上,而且非私有,可以在外部其他类中访问
当外部类中的静态方法访问内部类时,内部类也必须时static的
格式: 外部类名.内部类名 变量名=外部类对象.内部类对象
在外部其他类中,直接访问static内部类的非静态成员
格式: new 外部类名.内部类().非静态成员;
在外部其他类中,直接访问static内部类的静态成员
格式: 外部类.内部类.静态成员;
内部类定义在局部时:
1.不可以被成员修饰符修饰
2.可以直接访问外部类中的成员,因为还持有外部类的引用
但是不可访问它所在的局部变量,只能访问被final修饰的局部变量
09天-04-面向对象(匿名内部类):
1.匿名内部类其实就是内部类的简写格式
2.定义匿名内部类的前提:内部类必须是继承一个类或者实现接口
3.匿名内部类的格式: new 父类或者接口(){定义子类的内容};
4.其实匿名内部类就是一个匿名子类对象
5.匿名内部类中定义的方法最好不要超过3个
09天-05-面向对象(异常)
异常:就是程序在运行时出现不正常情况
异常由来:问题也是现实生活中一个具体的事物,也可以通过java类的形式
进行描述,并封装成对象。其实是java对不正常情况进行描述后对象的体现
对于问题的划分:两种:
一种是严重问题,java通过error类进行描述,一般不编写针对性代码处理
一种是非严重问题,java通过exception类进行描述,使用针对性代码处理
自定义异常:自定义类必须是继承Exception类
继承Exception原因:
异常体系有一个特点,因为异常类和异常对象都被抛出,他们都具备可抛性
这个可抛性是Throwable这个体系中独有的特点。只有这个体系中的类和对象
才可以被throw和throws操作。
在函数上通过throws关键字声明该函数有可能会出现异常,在被调用的地方
try-catch处理或者继续抛出去
method thorws ArithmeticException,ArrayIndexOutofBoundsException
当函数内部出现throw抛出异常,那么必须要给对应的处理动作
1.要么在函数内部try-catc处理
2.要么在函数上声明抛给调用者处理
throw和throws的区别:
throw:使用在函数内,后面跟的是异常对象
throws:使用在函数上,后面跟的异常类,可以跟多个,用逗号隔开
Exception中有一个RuntimeException运行时异常,其子类有如下特点:
如果在函数内抛出该异常,函数上可以不用声明,编译通过
如果在函数上声明了该异常,调用者可以不用进行处理
原因:该类异常是因为不需要让调用者处理。当异常发生时,希望程序停止,
因为在运行时出现了无法继续运行的情况,停止程序对代码进行修正
自定异常时:如果该异常的发生,无法再继续进行运算,
就让自定义异常继承RuntimeException类
对于异常分为两类:
1.编译时被检测的异常
2.编译时不被检测的异常(运行时异常,RuntimeException以及其子类)
finally 里面的语句无论是否有异常都会执行,在return前执行除了System.exit(0);
异常在子父类覆盖中的体现:
1.子类在覆盖父类时,如果父类的方法抛出异常,那么子类的覆盖方法,
只能抛出父类的异常或者该异常的子类
2.如果父类方法抛出多个异常,那么子类在覆盖该方法时,只能抛出父类异常的子集
3.如果父类或者接口的方法中没有异常抛出,那么子类在覆盖方法时,也不
能抛异常。如果子类方法发生了异常,必须进行try-catch处理,不能抛出
异常总结:异常是对问题的描述,将问题进行对象的封装。
异常体系: Throwable
--Error
--Exception --RuntimeException
异常体系的特点:异常体系中的所有类以及建立的对象都具备可抛性,
也就是说可以被throw和throws关键字操作,也只有异常体系具备这个特点。
throw和throws的用法:
throw定义在函数内,用于抛出异常对象;
throws定义在函数上,用于抛出异常类,可以抛出多个用逗号隔开。
注:当函数内容有throw抛出异常对象,并未进行try处理,必须要在函数
上声明,否则编译失败。RuntimeException除外,可以不用throws或者try。
如果函数声明了异常,调用者需要进行处理,可以throws或者try
异常有两种:
编译时被检测的异常:
该异常被标识,代表这类异常可以被处理。
在编译时,如果没有处理(没有抛也没有try),编译失败。
运行时异常(编译时不检测):
该异常的发生,建议不处理,让程序停止,需要对代码进行修正
在编译时,不需要处理,编译器不检查
注意:finally中定义的通常是关闭资源,除了System.exit(0);其他情况都会执行
自定义异常:定义异常类继承Exception或者RuntimeException
1.为了让自定义类具备可抛性;
2.让该类具备操作异常的共性方法,并按java面向对象思想将程序中的异常封装
异常的好处:1.将问题进行封装
2.将正常流程代码和问题处理代码相分离,方便阅读
异常的处理原则:
1.处理方式有两种:try或者throws
2.调用到抛出异常的功能时,抛出几个就处理几个。
3.多个catch,父类的catch放到最下面
4.catch内需要定义正对性的处理方式,不要简单的输出printStackTrace语句,
也不要不写,当捕获到的异常,本功能处理不了时,可以继续在catch中抛出
异常的注意事项:在子类覆盖父类方法时,
1.子类抛出的异常必须是父类的异常的子类或者子集;
2.如果父类或者接口没有异常抛出时,子类覆盖出现异常只能try不能抛出去
this:代表本类对象,哪个对象调用this所在函数,this就代表哪个对象
final: 1.修饰类,变量(成员变量,静态变量,局部变量),函数
2.修饰的类不可以被继承; 3.修饰的函数不可以被覆盖
4.修饰的变量是一个常量,只能赋值一次
多态类调用:成员变量看左边,函数看右边实际实例化的是哪个类
注:throw单独存在时,下面不要定义语句,因为执行不到。
包package:包与包之间访问,被访问包中的类以及类中的成员,需要public修饰
不同包中的子类还可以直接访问父类中被protected权限修饰的成员
包与包之间可以使用的权限只有两种:public、protected
public protected default private
同一个类中 yes yes yes yes
同一个包中 yes yes yes no
子类 yes yes no no
不同包中 yes no no no
java编译:javac -d sourceFolder ClassName.java .或者省略表示当前目录
java运行:java package.ClassName
java打包:jar -cfv packageFilePath.jar packA packB
查看包:jar -tvf packageName >d:\jar.txt 输出详细信息到jar.txt里
以上是关于CLIP__视频笔记的主要内容,如果未能解决你的问题,请参考以下文章