重新认识CLIP文本侧编码器
CLIP模型,对于关注近几年深度学习发展的同学肯定是不陌生的。CLIP虽然名义上属于多模态领域,可是其大力出奇迹的出圈程度让很多不是这个方向的人也了解了这个模型。CLIP的核心思想很简单:通过文本编码器对文本进行编码,然后再通过图像编码器对图像进行编码,之后将两个编码向量点乘并使用对比损失优化文本编码器和图像编码器。用CLIP论文里的一幅图就能很清晰地描述它:
image-20230826195857753
但今天要讨论的主题不是CLIP模型和它使用大规模图文对+对比学习实现很强的Zero
Shot能力,而是在那个看似平平无奇的Text
Encoder,在上图里它是一个紫色的梯形。文本通过这个编码器被编码为文本特征向量。
CLIP的文本编码器
如果粗看这副图不看论文的话,我们能大概想象出这个Encoder大概是像BERT一样,采用双向自注意力机制,然后取[CLS]标记(也就是每句话开头插入的那个标记)对应的向量作为文本特征向量。但很不幸,这个猜想是错误的,而且如果我们保持这样的看法的话很可能会错误地使用CLIP。
事实上,这个文本编码器是一个GPT-2结构的模型。这个模型使用的不 ...
20230825刷题近况
BM 46 最小的K个数
url:牛客
BM46
考察知识点:堆、快速排序
有了堆这把锤子之后眼里就多了最大K个、最小K个这些钉子,正好实践一下。
12345678910111213141516171819202122232425import heapq## 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可## # @param input int整型一维数组 # @param k int整型 # @return int整型一维数组#class Solution: def GetLeastNumbers_Solution(self , input: List[int], k: int) -> List[int]: # write code here if len(input) == 0 or k == 0: return [] heap = [] for i in range(k): heapq.heappush(heap, -input[i]) ...
从滑动窗口最大值到数据结构——堆
BM 45 滑动窗口的最大值
url:牛客
BM45
最开始做这道题的时候我想着一个窗口里求最大值应该是没啥捷径的,就在窗口里比最大值即可。然后滑动之后就需要观察上一次的最后一个元素是不是上一个窗口的最大值,如果不是的话,就把上个窗口的最大值和当前窗口的第一个值比对,哪个大哪个就是当前窗口的最大值。如果是的话,那这个窗口的最大值就需要重新算。
实现的代码如下:
1234567891011121314151617181920212223242526272829## 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可## # @param num int整型一维数组 # @param size int整型 # @return int整型一维数组#class Solution: def maxInWindows(self , num: List[int], size: int) -> List[int]: # write code here if len(num)==0 or size==0 or len(num) < si ...
20230823刷题近况
二叉树后面是“堆、栈、队列”的题目,这节题目不算很多。感觉过不了多久就要到动态规划章节了,非常恐怖。
BM 43 包含min函数的栈
url:牛客
BM43
考察知识点:栈、最小值
这个题的最小函数处理还是比较巧妙,使用一个最小函数的辅助栈,每次插入元素时判断辅助栈栈顶元素与要插入的元素大小关系,如果小于栈顶元素则插入该元素,否则再次压入一个栈顶元素。通过这样的操作,把算最小元素的复杂度都分散到插入时了,还比较巧妙。
123456789101112131415161718192021222324# -*- coding:utf-8 -*-class Solution: stack = [] min_stack = [] def push(self, node): # write code here self.stack.append(node) val = 10001 if len(self.min_stack) == 0 else self.min_stack[-1] if node < ...
20230821刷题近况
感觉写了一个世纪,终于把二叉树的章节过完了。还是挺充实开心的,以前确实没这么亲密地接触过二叉树。
## BM 39 序列化二叉树
url:BM
39
考察知识点:二叉树的遍历,序列化及反序列化
序列化及反序列化的定义:
序列化:把对象转化为可传输的字节序列过程称为序列化。
反序列化:把字节序列还原为对象的过程称为反序列化。
用层次遍历序列化和反序列化二叉树,实现如下:
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253# -*- coding:utf-8 -*-# class TreeNode:# def __init__(self, x):# self.val = x# self.left = None# self.right = Noneclass Solution: def Serialize(self, root): # write code here ...
20230820刷题近况
BM 36 判断是不是平衡二叉树
url:牛客
BM36
考察知识点:二叉树遍历,递归
平衡二叉树的定义:它是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。
诀窍:自顶向下递归时传递深度,避免向上合并时重复计算深度。
12345678910111213141516171819202122232425262728293031323334353637383940414243# class TreeNode:# def __init__(self, x):# self.val = x# self.left = None# self.right = None## 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可## # @param pRoot TreeNode类 # @return bool布尔型#class Solution: def IsBalanced_Tree(self, left: TreeNode, right: TreeNode, current_de ...
20230819刷题近况
BM31 对称的二叉树
url: 牛客
BM31
考察知识点: 二叉树、层次遍历
求解对称问题的常规思路就是从左边遍历一遍再从右边遍历一遍,然后如果对应位置相同就是对称的。
对于二叉树,很关键的一点的就是层次遍历的时候记得要把指向空值的节点也算进去,不然有可能发生位置不对的事。
123456789101112131415161718192021222324252627282930313233343536# class TreeNode:# def __init__(self, x):# self.val = x# self.left = None# self.right = None## 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可## # @param pRoot TreeNode类 # @return bool布尔型#class Solution: def isSymmetrical(self , pRoot: TreeNode) -> bool: # write code ...
二叉树的遍历
二叉树的遍历方式
graph TD;
A[树的遍历方式]
B[顺序遍历]
C[层次遍历]
D[前序遍历]
E[中序遍历]
F[后序遍历]
A-->B;
A-->C;
B-->D;
B-->E;
B-->F;
二叉树的遍历方式可以分为前序遍历(先序遍历)、中序遍历、后序遍历和层次遍历。前3种遍历方式的“序”指的是父节点相对于左右子节点的顺序。前序遍历就是先遍历父节点,之后再遍历左右节点;中序则是先访问左节点,再访问父节点最后访问右节点;后序是先遍历左右节点,最后访问父节点。层次遍历就是安装从上到下、从左到右顺序访问二叉树的每个节点。
从效果上来说,前序遍历相当于先访问到叶子节点后回溯到上一个节点,然后再访问到下一个叶子节点,即等价于深度优先遍历(DFS)。而层次遍历则是按层依次访问,等价于广度优先遍历(BFS)。
在本文里,将使用Python语言里实现前序、中序和后序遍历以及层次遍历,其中前序、中序和后序有递归和非递归两种实现方式。用牛客里的BM
23 二叉树的前序遍历, BM
24 二叉树的中序遍历, B ...
20230807~20230814近况
最近的事情说多不多,但是很杂乱,想起个名字基本都挺难,就偷懒写个近况。自从上次没签那个实习合同之后,我也没再继续找实习了,一是想找一个门槛稍微高一点,去了真正能学到东西的实习;二是觉得还是应该做做编程题,把之前分治法、动态规划的东西捡起来一点,这样也能增加一点找实习的成功率;三是最近看到了一个金融大模型的比赛,如果能拿到名次的话也能放到简历里充实一下经历。
## 实习方面的情况
先说找实习的事吧,听师兄说找算法实习不需要笔试,只需要面试通过就可以了。如果是找NLP方向的实习的话,需要了解Transformer结构,BERT和它对应的变种模型(RoBERTa、XLM-RoBERTa)的基础知识,然后再加上面试时会考几道现场编程的题目。这倒是让我安心了一些,这些要补上可能都没那么难。但是也有可能有新的变化,GPT系列的LLM这么猛,NLP实习岗问一些关于这些大语言模型的事也不是没可能。所以感觉生成式语言模型的东西也可以了解一下。但总之找实习这事我没那么着急了,一是如果找一个学不太到东西的实习也比较浪费时间;二是我确实也还很欠缺NLP的基础知识,趁这段时间补补不是坏事。
## 面试编程题准备 ...
20230725近况
最近一个月一直很忙,然后也基本没时间写博客啥的。最近才终于有空来总结一下这一个月左右的近况。
先说学校这边的事。小论文一路磕磕绊绊最后还是把实验做完把论文写完了,心路历程是从刚开始做的忐忑不安,到找到提点方法之后的信心倍增,再到消融实验成功的信心爆棚,最后到写论文的时候又忐忑不安了。总的来说,实验效果还是可以的,但是写论文的水平属实比较差。给投出去之后,论文没几天就在所谓的“复审”阶段,听师姐说之前有师兄也是这样最后被退稿了。。。然后就非常不安地度过了几天,但是后来再看的时候已经进入外审阶段了,应该暂时不需要记挂了。
再就是完成了人生阶段第一次给学者发邮件交流学术问题,虽然都是写了中文然后谷歌翻译成英文的,各种格式也很暴露英文水平,但不管怎么样,我确实是用英文跟别人交流过了。对方邮件回复得很快,对我的问题解答也很清晰,我确实也很佩服人家的学术水平。给别人发邮件主要是他论文数据集的设定和那个数据集的标准设定有一些不一样,而且他方法里的一些预处理细节我不太清楚,因此导致没办法正确地把他的方法在新的设定上实现。所以我问了,本来做好了等个几天的准备的,没想到很快,在他的帮助下我在两天内就把代码 ...