计算机视觉算法岗面试题

大佬的面试经验:https://www.nowcoder.com/discuss/128148
以及大佬的博客:https://blog.csdn.net/liuxiao214/article/details/83043170
根据大佬的面试经验一点一点填坑吧。

视频分类

思路:
1.通过将视频的每一帧视为一幅单独的图像,利用二维 CNN 进行处理。这种方法将视频分类问题简化为图像分类问题。每帧视频图像都有类别输出,并且根据各帧输出的类别,选择频率最高的类别作为视频的分类结果。
2.创建一个单一的网络,将二维 CNN 与一个 RNN 结合在一起。这个想法是,CNN 将考虑到图像分量,而 RNN 将考虑每个视频的序列信息。这种类型的网络可能非常难以训练,因为要优化的参数数量非常大。
3.使用三维卷积网络,其中三维卷积网络是二维 CNN 的在 3D 张量(时间,图像宽度,图像高度)上运行的扩展。这种方法是图像分类的另一个自然延伸,但三维卷积网络可能很难训练。
4.基于智能方法的直觉。它们可以用于存储视频中每个帧的离线功能,而不是直接使用 CNN 进行分类。这个想法基于,特征提取可以非常有效地进行迁移学习,如前面章节所示。在提取所有的特征之后,可以将它们作为一组输入传递给RNN,其将在多个帧中学习序列并输出最终的分类。
5.第四种方法的简单变体,其中最后一层是 MLP 而不是 RNN。在某些情况下,就计算需求而言,这种方法可以更简单并且成本更低。
6.第四种方法的变体,其中特征提取阶段采用三维 CNN 来提取空间和视觉特征,然后将这些特征传递给 RNN 或 MLP。

细粒度分类

细粒度分类:同一类中不同子类物体间的分类。
1.Part-based R-CNN。
2.Bilinear deep network models。
3.FCN attention。

你知道attention起源是用在哪里?pixel还是frame,是soft还是hard

对于 Attention的作用角度出发,可以分为: 空间注意力 Spatial Attention,时间注意力 Temporal Attention
这样的分类更多的是从应用层面上;而从 Attention的作用方法上,可以将其分为 Soft Attention 和 Hard Attention,这既我们所说的, Attention输出的向量分布是一种one-hot的独热分布还是soft的软分布,这直接影响对于上下文信息的选择作用。
attention机制:https://blog.csdn.net/xiewenbo/article/details/79382785
Soft Attention:传统的Attention Mechanism就是Soft Attention,即通过确定性的得分计算来得到attended之后的编码隐状态。Soft Attention是参数化的(Parameterization),因此可导,可以被嵌入到模型中去,直接训练。梯度可以经过Attention Mechanism模块,反向传播到模型其他部分。
Hard Attention:是一个随机的过程。Hard Attention不会选择整个encoder的隐层输出做为其输入,Hard Attention会依概率Si来采样输入端的隐状态一部分来进行计算,而不是整个encoder的隐状态。为了实现梯度的反向传播,需要采用蒙特卡洛采样的方法来估计模块的梯度。
两种Attention Mechanism都有各自的优势,但目前更多的研究和应用还是更倾向于使用Soft Attention,因为其可以直接求导,进行梯度反向传播

网络用的损失函数是什么

  1. L1 loss:绝对差平均损失,又称MAE
    .在这里插入图片描述
    2.L2 loss:平方差平均损失,又称MSE
    在这里插入图片描述
    3.Smooth L1 loss,又称Huber损失
    在这里插入图片描述
    4.BCE loss,二分类用的交叉熵损失,用的时候需要在该层前面加上 Sigmoid 函数
    在这里插入图片描述
    5.BCEWithlogitsLoss,将sigmoid函数集成到BCE loss上
    6.CrossEntoryLoss,交叉熵损失函数
    第一种形式:
    在这里插入图片描述
    第二种形式:
    在这里插入图片描述
    softmax的交叉熵:
    在这里插入图片描述
    在这里插入图片描述
    7.NllLoss:负对数似然损失。

监督学习和无监督学习

监督学习(supervised learning):已知数据和其一一对应的标签,训练一个智能算法,将输入数据映射到标签的过程。监督学习是最常见的学习问题之一,就是人们口中常说的分类问题。比如已知一些图片是猪,一些图片不是猪,那么训练一个算法,当一个新的图片输入算法的时候算法告诉我们这张图片是不是猪。

无监督学习(unsupervised learning):已知数据不知道任何标签,按照一定的偏好,训练一个智能算法,将所有的数据映射到多个不同标签的过程。相对于有监督学习,无监督学习是一类比较困难的问题,所谓的按照一定的偏好,是比如特征空间距离最近,等人们认为属于一类的事物应具有的一些特点。举个例子,猪和鸵鸟混杂在一起,算法会测量高度,发现动物们主要集中在两个高度,一类动物身高一米左右,另一类动物身高半米左右,那么算法按照就近原则,75厘米以上的就是高的那类也就是鸵鸟,矮的那类是第二类也就是猪,当然这里也会出现身材矮小的鸵鸟和身高爆表的猪会被错误的分类。

强化学习(reinforcement learning):智能算法在没有人为指导的情况下,通过不断的试错来提升任务性能的过程。“试错”的意思是还是有一个衡量标准,用棋类游戏举例,我们并不知道棋手下一步棋是对是错,不知道哪步棋是制胜的关键,但是我们知道结果是输还是赢,如果算法这样走最后的结果是胜利,那么算法就学习记忆,如果按照那样走最后输了,那么算法就学习以后不这样走。

弱监督学习(weakly supervised learning): 已知数据和其一一对应的弱标签,训练一个智能算法,将输入数据映射到一组更强的标签的过程。标签的强弱指的是标签蕴含的信息量的多少,比如相对于分割的标签来说,分类的标签就是弱标签,如果我们知道一幅图,告诉你图上有一只猪,然后需要你把猪在哪里,猪和背景的分界在哪里找出来,那么这就是一个已知若标签,去学习强标签的弱监督学习问题。

半监督学习(semi supervised learning) :已知数据和部分数据一一对应的标签,有一部分数据的标签未知,训练一个智能算法,学习已知标签和未知标签的数据,将输入数据映射到标签的过程。半监督通常是一个数据的标注非常困难,比如说医院的检查结果,医生也需要一段时间来判断健康与否,可能只有几组数据知道是健康还是非健康,其他的只有数据不知道是不是健康。那么通过有监督学习和无监督的结合的半监督学习就在这里发挥作用了。

多示例学习(multiple instance learning) :已知包含多个数据的数据包和数据包的标签,训练智能算法,将数据包映射到标签的过程,在有的问题中也同时给出包内每个数据的标签。多事例学习引入了数据包的概念,比如说一段视频由很多张图组成,假如1000张,那么我们要判断视频里是否有猪出现,一张一张的标注每一帧是否有猪太耗时,所以人们看一遍说这个视频里有猪或者没猪,那么就得到了多示例学习的数据,1000帧的数据不是每一个都有猪出现,只要有一帧有猪,那么我们就认为这个包是有猪的,所有的都没有猪,才是没有猪的,从这里面学习哪一段视频(1000张)有猪哪一段视频没有就是多事例学习的问题。

softmax loss

softmax的交叉熵:
在这里插入图片描述
在这里插入图片描述

LR为什么要用sigmoid函数

在这里插入图片描述

3. LR 损失函数为什么用极大似然函数?

在这里插入图片描述
1.因为我们想要让每一个样本的预测都要得到最大的概率,即将所有的样本预测后的概率进行相乘都最大,也就是极大似然函数.
2.对极大似然函数取对数以后相当于对数损失函数,由上面梯度更新的公式可以看出,对数损失函数的训练求解参数的速度是比较快的,而且更新速度只和x,y有关,比较的稳定。
3.为什么不用平方损失函数
如果使用平方损失函数,梯度更新的速度会和 sigmod 函数的梯度相关,sigmod 函数在定义域内的梯度都不大于0.25,导致训练速度会非常慢。
而且平方损失会导致损失函数是 theta 的非凸函数,不利于求解,因为非凸函数存在很多局部最优解

softmax交叉熵损失函数求导

在这里插入图片描述
https://blog.csdn.net/qian99/article/details/78046329

softmax和logistic回归的区别和联系

1.softmax用来解决多分类问题,lr解决二分类问题
2.softmax输出每一类的概率值,并确定概率最大的类是正确的,lr只区别是还是不是。事实上softmax是lr的一般情况。

https://blog.csdn.net/chnguoshiwushuang/article/details/80514626

全连接的作用

因为用到了所有的局部特征,所以叫全连接。将学到的“分布式特征表示”映射到样本标记空间的作用。

GD、SGD、mini batch GD的区别

GD:梯度下降法的物理意义很好理解,就是沿着当前点的梯度方向进行线搜索,找到下一个迭代点
SGD:随机梯度下降法,每次计算梯度时,只随机的选取一个样本来计算梯度,这样就大大的减小了计算的复杂度,随机梯度下降法速度快,但每次的方向不稳定,甚至可能向反方向。
mini batch GD:故每次计算梯度时,选取一部分样本,即小批量梯度下降法。

结构体占多少字节

在这里插入图片描述

S3D了解吗?

边缘检测算子有哪些

1.差分算子。
一阶微分:
2.Roberts算子,对角线方向相邻两象素之差近似梯度幅值检测边缘,对噪声敏感,无法抑制噪声的影响。
3.Sobel算子,该算子包含两组3 * 3的矩阵,分别为横向及纵向,将之与图像作平面卷积,即可分别得出横向及纵向的亮度差分近似值,在结合横向和纵向
4.Prewitt算子,一阶微分算子的边缘检测,模板3 * 3利用像素点上下、左右邻点的灰度差,在边缘处达到极值检测边缘,去掉部分伪边缘,对噪声具有平滑作用 。
二阶微分
5.Laplacian算子,存在噪声情况下,使用Laplacian算子检测边缘之前需要先进行低通滤波,模板3 * 3。
6.Log算子,进行高斯滤波再进行拉普拉斯算子检测,模板5 * 5。
非微分
7.Canny算子:
1)使用高斯滤波器,以平滑图像,滤除噪声。
2)计算图像中每个像素点的梯度强度和方向。
3)应用非极大值(Non-Maximum Suppression)抑制,以消除边缘检测带来的杂散响应。
4)应用双阈值(Double-Threshold)检测来确定真实的和潜在的边缘。
5)通过抑制孤立的弱边缘最终完成边缘检测。

霍夫变换

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

函数中的局部变量在内存中如何申请

1、栈区:由编译器自动分配 存放函数的参数值,局部变量的值等,操作方式类似于数据结构中的栈。
2、堆区:一般由程序员分配释放,若程序员不释放,程序结束时 可能 有系统收回。它与数据结构中的堆是两回事。分配方式类似于链表。
3、全局区(静态区):全局变量和静态变量是存储放在一块的,初始化的全局变量和静态变量在一个区域,未初始化的在相邻的另一个区域。程序结束后由系统释放。
4、文字常量区:常量字符串就存放在这里。程序结束后有系统自动释放。
5、程序代码区:存放函数体的二进制代码。

程序运行中有两个存储空间可用,一个是栈,是归属于进程本身的,另外一个是堆,所有进程共用的。
局部变量在声明周期为函数内部,其存储空间位于栈中。当进入函数时,会对根据局部变量需求,在栈上申请一段内存空间,供局部变量使用。当局部变量生命周期结束后,在栈上释放。分配较大内存的时候可以用动态内存分配,malloc,new。

C++中的static

类体中的数据成员的声明前加上static关键字,该数据成员就成为了该类的静态数据成员。
作用:1.隐藏;2.保持变量内容的持久;3.默认初始化为0(static变量)。
https://blog.csdn.net/m0_37962600/article/details/80038089

说一下SVM核函数

在线性不可分的情况下,支持向量机首先在低维空间中完成计算,然后通过核函数将输入空间映射到高维特征空间,最终在高维特征空间中构造出最优分离超平面,从而把平面上本身不好分的非线性数据分开。核函数的价值在于它虽然也是讲特征进行从低维到高维的转换,但核函数绝就绝在它事先在低维上进行计算,而将实质上的分类效果表现在了高维上,也就如上文所说的避免了直接在高维空间中的复杂计算。
1.多项式核函数
2.高斯核函数
3.线性核函数
4.字符串核函数

PCA

PCA(principal Component Analysis),即主成分分析方法,是一种使用最广泛的数据压缩算法。它可以通过线性变换将原始数据变换为一组各维度线性无关的表示,以此来提取数据的主要线性分量。
具体可以看这篇文章:https://blog.csdn.net/hustqb/article/details/78394058
伪代码:
去除平均值
计算协方差矩阵
计算协方差矩阵的特征值和特征向量
将特征值排序
保留前N个最大的特征值对应的特征向量
将数据转换到上面得到的N个特征向量构建的新空间中(实现了特征压缩)

L1、L2范数

在这里插入图片描述

sigmoid优缺点

优点:可以将函数值的范围压缩到[0,1],可以压缩数据,且幅度不变。在特征相差比较复杂或是相差不是特别大时效果比较好。可以看到sigmoid函数处处连续便于求导;便于前向传输。
缺点:激活函数计算量大,反向传播求误差梯度时,求导涉及除法。反向传播时,很容易就会出现梯度消失的情况,从而无法完成深层网络的训练

对Resnet的理解

在这里插入图片描述
1.避免梯度消失,解决网络退化。 2.残差模块可以更容易学习更细致的信息。

inception网络的优化

相似度计算

1.余弦距离
在这里插入图片描述
2.欧式距离
在这里插入图片描述
3.汉明距离
汉明距离/Hamming Distance也能用来计算两个向量的相似度;即通过比较向量每一位是否相同,若不同则汉明距离加1,这样得到汉明距离。向量相似度越高,对应的汉明距离越小。如10001001和10110001有3位不同。
4.马氏距离
在这里插入图片描述
如果我们以厘米为单位来测量人的身高,以克(g)为单位测量人的体重。每个人被表示为一个两维向量,如一个人身高173cm,体重50000g,表示为(173,50000),根据身高体重的信息来判断体型的相似程度。
我们已知小明(160,60000);小王(160,59000);小李(170,60000)。根据常识可以知道小明和小王体型相似。但是如果根据欧几里得距离来判断,小明和小王的距离要远远大于小明和小李之间的距离,即小明和小李体型相似。这是因为不同特征的度量标准之间存在差异而导致判断出错。

图像的特征提取有哪些算法

①基于颜色特征:如颜色直方图、颜色集、颜色矩、颜色聚合向量等;
②基于纹理特征:如Tamura纹理特征、自回归纹理模型、Gabor变换、小波变换、MPEG7边缘直方图等;
③基于形状特征:如傅立叶形状描述符、不变矩、小波轮廓描述符等

1、LBP特征提取算法
LBP(Local Binary Patterns,局部二值模式)是提取局部特征作为判别依据的,为一种有效的纹理描述算子,度量和提取图像局部的纹理信息,对光照具有不变性。有多种改进型,LBP结合BP神经网络已经用于人脸识别等领域。LBP的基本思想是定义于像素的8邻域中, 以中心像素的灰度值为阈值, 将周围8 个像素的值与其比较, 如果周围的像素值小于中心像素的灰度值, 该像素位置就被标记为0, 否则标记为1. 每个像素得到一个二进制组合, 就像00010011. 每个像素有8个相邻的像素点,即有2^8种可能性组合。
在这里插入图片描述
在这里插入图片描述
2.HOG特征提取算法
方向梯度直方图(Histogram of Oriented Gradient, HOG)特征是一种在计算机视觉和图像处理中用来进行物体检测的特征描述子。它通过计算和统计图像局部区域的梯度方向直方图来构成特征。Hog特征结合SVM分类器已经被广泛应用于图像识别中,尤其在行人检测中获得了极大的成功。需要提醒的是,HOG+SVM进行行人检测的方法是法国研究人员Dalal在2005的CVPR上提出的,而如今虽然有很多行人检测算法不断提出,但基本都是以HOG+SVM的思路为主。
不变性:具有光照不变性,不具有尺寸和旋转不变性。
应用:HoG算法提取的是图像各个像素梯度的统计直方图,一般会将这些梯度直方图转化成一个向量,用于分类器的训练输入。

3.Haar特征提取算子
常和AdaBoost结合用于识别人脸。Haar特征很简单,分为三类:边缘特征、线性特征、中心特征和对角线特征,组合成特征模板。特征模板内有白色和黑色两种矩形,并定义该模板的特征值为白色矩形像素和减去黑色矩形像素和。Haar特征值反映了图像的灰度变化情况。例如:脸部的一些特征能由矩形特征简单的描述,如:眼睛要比脸颊颜色要深,鼻梁两侧比鼻梁颜色要深,嘴巴比周围颜色要深等。但矩形特征只对一些简单的图形结构,如边缘、线段较敏感,所以只能描述特定走向(水平、垂直、对角)的结构。
在这里插入图片描述
4.LoG特征提取算法
LoG(DoG是一阶边缘提取)是二阶拉普拉斯-高斯边缘提取算法,先高斯滤波然后拉普拉斯边缘提取。Laplace算子对通过图像进行操作实现边缘检测的时,对离散点和噪声比较敏感。于是,首先对图像进行高斯卷积滤波进行降噪处理,再采用Laplace算子进行边缘检测,就可以提高算子对噪声抗干扰能力, 这一个过程中高斯-拉普拉斯(Laplacian of Gaussian(LOG))边缘检测算子就诞生了。
5.Harris角点特征提取算法
http://www.cnblogs.com/zhchoutai/p/7182438.html
6.SIFT特征提取算子
SIFT算子是一种检测局部特征的算法,该算法通过求一幅图中的特征点及其有关尺寸和方向的描述子得到特征并进行图像特征点匹配,获得了良好效果。每个特征点的SIFT特征是128维向量,因此计算量巨大。
不变性:具有尺寸和旋转不变性。
改进型:PCA-SIFT,如名称所说“主成分SIFT特征”,主要提取了128维特征向量中的20个特征,大大减少了计算。
http://www.cnblogs.com/liuchaogege/p/5155739.html
7.SURF特征提取算法
SURF是SIFT角点检测算法的改进版,主要体现在速度上,SURF是SIFT速度的3倍。SIFT在尺度和旋转变换的情况下匹配效果比SURF好,而SURF在亮度变化下匹配效果比较好。
http://www.cnblogs.com/tornadomeet/archive/2012/08/17/2644903.html

yolo、ssd、faster rcnn的区别

yolo v1:没有使用多层特征,没有使用anchor机制,使用网格预测,每个网格随机预测2个box,直接预测x,y,w,h,损失函数也不一样,使用全连接。
yolo v3:使用多层特征,使用anchor机制,使用网格预测,anchor使用kmeans算法产生,使用3层特征,每层特征使用3个大小的anchor,没有直接预测x,y,w,h,损失函数也不一样,没有使用全连接。
在这里插入图片描述
ssd:使用多层特征(38, 38), (19, 19), (10, 10), (5, 5), (3, 3), (1, 1),使用anchor机制,使用特征图预测,特征图上的每一个特征都预测4个anchor,没有直接预测x,y,w,h,损失函数不一样。
在这里插入图片描述
d是先验框,b是预测框
在这里插入图片描述
在这里插入图片描述
3.faster rcnn
在这里插入图片描述
两步走:RPN+ROIP
RPN特征图预测anchor,每个特征点预测9个anchor大小,最后得到ROI区域进行池化,最后分类和边框回归。

ROI层是怎么实现的,怎么做的映射

1.根据输入image,将ROI映射到feature map对应位置;首先计算rois映射到feature map的坐标,即原始坐标*spacial_scale(大小为所有stride的乘积分之一),然后针对每个输出来进行计算,即每个输出点都代表原先的一块区域,这个区域大小为bin_h= roi_height / pooled_ height, bin_w=roi_width / pooled_width.遍历所有top的点所映射回feature map的区域,并找到最大值,记录最大值所在的位置。
2.将映射后的区域划分为相同大小的sections(sections数量与输出的维度相同);
3.对每个sections进行max pooling操作;

python传参会改变原值吗

赋值不会,但append会。

BN层的moving——mean怎么求得

为什么使用BN层
1.可以选择较大的学习率,使得训练速度增长很快,具有快速收敛性。
2.可以不去理会Dropout,L2正则项参数的选择,如果选择使用BN,甚至可以去掉这两项。
3.去掉局部响应归一化层(LRN)。(AlexNet中使用的方法,BN层出来之后这个就不再用了)
4.可以把训练数据打乱,防止每批训练的时候,某一个样本被经常挑选到。
在这里插入图片描述
batch_norm 在test的时候,用的是固定的mean和var, 而这个固定的mean和var是通过训练过程中对mean和var进行移动平均得到的。所以需要在训练时把BN层的参数保存下来,然后在预测时加载.
在这里插入图片描述

C++的多态

在这里插入图片描述
http://c.biancheng.net/view/264.html

pooling层的反向传播

在这里插入图片描述

手动实现卷积

def conv2d(img, kernel):
    height, width, in_channels = img.shape
    kernel_height, kernel_width, in_channels, out_channels = kernel.shape
    out_height = height - kernel_height + 1
    out_width = width - kernel_width + 1
    feature_maps = np.zeros(shape=(out_height, out_width, out_channels))
    for oc in range(out_channels):              # Iterate out_channels (# of kernels)
        for h in range(out_height):             # Iterate out_height
            for w in range(out_width):          # Iterate out_width
                for ic in range(in_channels):   # Iterate in_channels
                    patch = img[h: h + kernel_height, w: w + kernel_width, ic]
                    feature_maps[h, w, oc] += np.sum(patch * kernel[:, :, ic, oc])

    return feature_maps

有哪些轻量化模型?

一、SequeezeNet:
核心思想:
1.使用1x1卷积核代替3x3卷积核,减少参数量;
2.通过squeeze layer限制通道数量,减少参数量;
3.借鉴inception思想,将1x1和3x3卷积后结果进行concat;为了使其feature map的size相同,3x3卷积核进行了padding;
4.减少池化层,并将池化操作延后,给卷积层带来更大的激活层,保留更多地信息,提高准确率;
5.使用全局平均池化代替全连接层;
1-3通过fire module实现,如下图所示:
在这里插入图片描述网络结构:
在这里插入图片描述二、Xception
核心思想:
主要采用depthwise separable convolution思想(这个后面在mobile net中详细解释)
首先xception类似于下图,但是区别有两点:
在这里插入图片描述
1.Xception中没有relu激活函数;
2.图4是先1x1卷积,后通道分离;xception是先进行通道分离,即depthwise separable convolution,然后再进行1x1卷积。
3.进行残差连接时,不再是concat,而是采用加法操作。
网络结构:
在这里插入图片描述三、MobileNet
核心思想:
1.主要采用depthwise separable convolution,就是分离卷积核;
2.设置宽度因子width multipler和分辨率因子resolution multiplier;
在这里插入图片描述与普通卷积的计算量相比,N为通道数,Dk为特征图的大小:
在这里插入图片描述
怎么才能使网络进一步压缩呢?可以进一步减少feature map的通道数和size,通过宽度因子减少通道数,分辨率因子减少size。

1、宽度因子α在这里插入图片描述
2、分辨率因子ρ
这里写图片描述
两个参数都属于(0,1]之间,当为1时则是标准mobileNet。
基本模块:
在这里插入图片描述
网络结构:
在这里插入图片描述四、ShuffleNet
核心思想:
1.借鉴resnext分组卷积思想,但不同的是采用1x1卷积核;
2.进行通道清洗,加强通道间的信息流通,提高信息表示能力。
分组卷积和通道清洗:
在这里插入图片描述Shuffle的方法:
1.卷积后一共得到g×n个输出通道的feature map;
2.将feature map 进行 reshape为(g,n);
3.进行转置为(n,g);
4.对转置结果flatten,再分回g组作为下一层的输入。
三种Shuffle unit:
在这里插入图片描述网络结构:
在这里插入图片描述

计算一层的参数量、计算量

https://zhuanlan.zhihu.com/p/31575074 在这里插入图片描述

inception v1-v3的发展:

在这里插入图片描述
Inception V1网络使用1x1,3x3,5x5的卷积核进行卷积运算和池化操作可以获得输入图像的不同信息,并行处理这些运算并结合所有结果可以获得更好的图像表征。Inception V2网络加入批归一化层,使每层输出都规范化到N(0,1)的高斯分布上,此外使用2个3×3的卷积层代替inception模块中5x5的卷积核,既降低了参数数量,又加速了计算。Inception V3网络将部分inception结构进行分解,在输出为17×17×768的层使用1x7,7x1的卷积核,在输出为8×8×1280的层使用1×3,3×1的卷积核,这样既加速了计算,又增加了网络的深度,使网络的非线性增加,得到更丰富的空间特征。

Resnet

https://blog.csdn.net/lanran2/article/details/80247515
在这里插入图片描述

撕代码:iou计算、k-means、NMS非极大值抑制

iou:

def IOU(rectangle A, rectangleB):
    W = min(A.RT.x, B.RT.x) - max(A.LB.x, B.LB.x)
    H = min(A.RT.y, B.RT.y) - max(A.LB.y, B.LB.y)
    if W <= 0 or H <= 0:
        return 0;
    SA = (A.RT.x - A.LB.x) * (A.RT.y - A.LB.y)
    SB = (B.RT.x - B.LB.x) * (B.RT.y - B.LB.y)
    cross = W * H
    return cross/(SA + SB - cross)

kmeans:

def kmeans(self, boxes, k, dist=np.median):
    box_number = boxes.shape[0]
    distances = np.empty((box_number, k))
    last_nearest = np.zeros((box_number,))
    np.random.seed()
    clusters = boxes[np.random.choice(
        box_number, k, replace=False)]  # init k clusters
    while True:

        distances = 1 - self.iou(boxes, clusters)
        current_nearest = np.argmin(distances, axis=1)
        if (last_nearest == current_nearest).all():
            break  # clusters won't change
        for cluster in range(k):
            clusters[cluster] = dist(  # update clusters
                boxes[current_nearest == cluster], axis=0)

        last_nearest = current_nearest

    return clusters

NMS:

def py_cpu_nms(dets, thresh):
    """Pure Python NMS baseline."""
    x1 = dets[:, 0]
    y1 = dets[:, 1]
    x2 = dets[:, 2]
    y2 = dets[:, 3]
    scores = dets[:, 4]

    areas = (x2 - x1 + 1) * (y2 - y1 + 1)
    order = scores.argsort()[::-1]

    keep = []
    while order.size > 0:
        i = order[0]
        keep.append(i)
        xx1 = np.maximum(x1[i], x1[order[1:]])
        yy1 = np.maximum(y1[i], y1[order[1:]])
        xx2 = np.minimum(x2[i], x2[order[1:]])
        yy2 = np.minimum(y2[i], y2[order[1:]])

        w = np.maximum(0.0, xx2 - xx1 + 1)
        h = np.maximum(0.0, yy2 - yy1 + 1)
        inter = w * h
        ovr = inter / (areas[i] + areas[order[1:]] - inter)

        inds = np.where(ovr <= thresh)[0]
        order = order[inds + 1]

return keep

过拟合怎么做

Parameter Norm Penalties(参数范数惩罚);Dataset Augmentation (数据集增强);Early Stopping(提前终止);Parameter Tying and Parameter Sharing (参数绑定与参数共享);Bagging and Other Ensemble Methods(Bagging 和其他集成方法);dropout;regularization; batch normalizatin。是解决Overfitting的常用手段。

n位字符串,循环右移m位,要求时间复杂度线性,空间复杂度为o(n)

分析:首先,循环左移的意思类似于二进制串的循环左移,对于给定的字符串S(此处的字符串仅是指字符组成的串,并不是指编程语言中的字符串类型,因为大部分编程语言中的字符串类型是无法对字符串的某一字符进行修改的,只能对整个串进行修改),如S=‘abcdefghijkl’,对其循环左移3位,则变为S=‘defghijklabc’。通过对例子分析,循环左移3位等价于循环右移了len(S)-3=9位。
其次,其要求空间复杂度为O(1),因此不能通过对字符串分段复制再拼接的方式实现,因为该种方法的空间复杂度为O(n).
最后,具体的实现方式与采用的数据结构有关系,若对字符串的存储是通过链表进行的,则实现循环左移的方式很简单,只需将第m+1个节点变为链首,前m个节点拼接到最后一个节点后面即可。
如果字符串是通过数组的方式进行存储,则可采用三次反转的方式,首先分别对前m个字符、后n-m个字符进行反转(n为字符串长度),然后对整个串再次进行反转即可。

一条语句判断数x是否2的n次幂

二进制

int fun(int x)
{
    return !(x&(x-1));
}

图像哈希算法

1.均值哈希算法:
第一步,缩小尺寸。最快速的去除高频和细节,将图片缩小到8x8的尺寸,总共64个像素。摒弃不同尺寸、比例带来的图片差异。
第二步,简化色彩。将缩小后的图片,转为64级灰度。也就是说,所有像素点总共只有64种颜色。
第三步,计算平均值。计算所有64个像素的灰度平均值。
第四步,比较像素的灰度。将每个像素的灰度,与平均值进行比较。大于或等于平均值,记为1;小于平均值,记为0。
第五步,计算哈希值。将上一步的比较结果,组合在一起,就构成了一个64位的整数,这就是这张图片的指纹。组合的次序并不重要,只要保证所有图片都采用同样次序就行了。
如果图片放大或缩小,或改变纵横比,结果值也不会改变。增加或减少亮度或对比度,或改变颜色,对hash值都不会太大的影响。最大的优点:计算速度快!

如果想比较两张图片,为每张图片构造hash值并且计算不同位的个数。如果不相同的数据位不超过5,就说明两张图片很相似;如果大于10,就说明这是两张不同的图片。

2.感知哈希算法:
第一步,缩小尺寸。最快速的去除高频和细节,将图片缩小到8x8的尺寸,总共64个像素。摒弃不同尺寸、比例带来的图片差异。
第二步,简化色彩。将缩小后的图片,转为64级灰度。也就是说,所有像素点总共只有64种颜色。
第三步,计算DCT(离散余弦变换)。DCT是把图片分解频率聚集和梯状形,虽然JPEG使用8 * 8的DCT变换,在这里使用32 * 32的DCT变换。
第四步,缩小DCT。虽然DCT的结果是32 * 32大小的矩阵,但我们只要保留左上角的8*8的矩阵,这部分呈现了图片中的最低频率。
第五步,计算平均值。计算所有64个值的平均值。
第六步,进一步减小DCT。这是最主要的一步,根据8 * 8的DCT矩阵,设置0或1的64位的hash值,大于等于DCT均值的设为”1”,小于DCT均值的设为“0”。结果并不能告诉我们真实性的低频率,只能粗略地告诉我们相对于平均值频率的相对比例。只要图片的整体结构保持不变,hash结果值就不变。能够避免伽马校正或颜色直方图被调整带来的影响。
第七步,计算哈希值。将64bit设置成64位的长整型,组合的次序并不重要,只要保证所有图片都采用同样次序就行了。将32 * 32的DCT转换成32 * 32的图像。
将上一步的比较结果,组合在一起,就构成了一个64位的整数,这就是这张图片的指纹。组合的次序并不重要,只要保证所有图片都采用同样次序就行了(例如,自左到右、自顶向下、big-endian)。

得到指纹以后,就可以对比不同的图片,看看64位中有多少位是不一样的。在理论上,这等同于计算汉明距离。如果不相同的数据位不超过5,就说明两张图片很相似;如果大于10,就说明这是两张不同的图片。

3.差异哈希算法
第一步,缩小尺寸,缩放到9 * 8尺寸。
第二步,转换灰度值,转换到0-255之间。
第三步,差异值计算,差异值是通过计算每行相邻像素的强度对比得出的。我们的图片为9 * 8的分辨率,那么就有8行,每行9个像素。差异值是每行分别计算的,也就是第二行的第一个像素不会与第一行的任何像素比较。每一行有9个像素,那么就会产生8个差异值,这也是为何我们选择9作为宽度,因为8bit刚好可以组成一个byte,方便转换为16进制值。
如果前一个像素的颜色强度大于第二个像素,那么差异值就设置为True(也就是1),如果不大于第二个像素,就设置为False(也就是0)。
第四步,转化为hash值,将差异值数组中每一个值看做一个bit,每8个bit组成为一个16进制值,将16进制值连接起来转换为字符串,就得出了最后的dHash值。
第五步,计算汉明距离,如果不相同的数据位不超过5,就说明两张图片很相似;如果大于10,就说明这是两张不同的图片。

boost、Adaboost

筛子六个面,每个面的概率不一样,要求实现一个掷筛子的函数。

1.choice

np.random.seed(1)
p = np.array([0.1, 0.1, 0.2, 0.2, 0.2, 0.2])
index = np.random.choice([1, 2, 3, 4, 5, 6], p = p.ravel())

2.uniform:随机生成0-1数,根据所需概率划分0-1区间
def random_pick(some_list,probabilities):
  x=random.uniform(0,1)
  cumulative_probability=0.0
  for item,item_probability in zip(some_list,probabilities):
    cumulative_probability+=item_probability
    if x < cumulative_probability: break
  return item

线性回归和逻辑回归的区别

逻辑回归多了一个Sigmoid函数,使样本能映射到[0,1]之间的数值,用来做分类问题。
1.线性回归用来预测,逻辑回归用来分类。
2.线性回归是拟合函数,逻辑回归是预测函数
3.线性回归的参数计算方法是最小二乘法,逻辑回归的参数计算方法是梯度下降

为什么数组查询比链表要快?而插入删除比链表效率低

1、数据存储结构分为顺序存储、链接存储、索引存储、散列存储。
2、数组属于顺序存储,用一段连续的内存位置来存储。
3、链表属于链接存储,用一组任意的存储单元来存储,不要求物理上相邻。
因为CPU缓存会读入一段连续的内存,顺序存储符合连续的内存,所以顺序存储可以被缓存处理,而链接存储并不是连续的,分散在堆中,所以只能内存去处理。
所以数组查询比链表要快。
而数组大小固定,插入和删除都需要移动元素,链表可以动态扩充,插入删除不需要移动元素,只需要更改元素中的指针。所以链表的插入删除比数组效率高。

如何理解LSTM

在这里插入图片描述
https://blog.csdn.net/menc15/article/details/71271566

如何解决RNN的梯度爆炸和消失

在这里插入图片描述

多标签问题

1.问题转换:
①重新组合
②二元关联
③分类器链
2.改编算法
修改全连接
3.集成方法

精确率高、召回率低是为什么

在这里插入图片描述

一个人有很多框,什么原因造成的

两种情况:
1.框不是重叠的,模型没有训练好。
2.框有重叠,非极大值抑制没有做好,模型没有训练好。

图像旋转、旋转矩阵、像素点怎么填充在这里插入图片描述

openpose

openpose的核心是提出一种利用Part Affinity Fields(PAFs)的自下而上的人体姿态估计算法。研究自下而上算法(得到关键点位置再获得骨架)而不是自上而下算法(先检测人,再回归关键点),是因为后者运算时间会随着图像中人的个数而显著增加,而自下而上所需计算时间基本不变。

光流怎么计算

https://blog.csdn.net/u011076940/article/details/60766423

xrange与range的区别

首先我们看看range: range([start,] stop[, step]),根据start与stop指定的范围以及step设定的步长,生成一个序列。注意这里是生成一个序列。

xrange的用法与range相同,即xrange([start,] stop[, step])根据start与stop指定的范围以及step设定的步长,他所不同的是xrange并不是生成序列,而是作为一个生成器。即他的数据生成一个取出一个。

所以相对来说,xrange比range性能优化很多,因为他不需要一下子开辟一块很大的内存,特别是数据量比较大的时候。

注意:
1、xrange和range这两个基本是使用在循环的时候。
2、 当需要输出一个列表的时候,就必须要使用range了。

shell命令

查看文件大小命令
df -h
du -h --max-depth=1 /home
https://www.cnblogs.com/lixuwu/p/5944062.html
查看文件多少行命令
wc -l filename 就是查看文件里有多少行
wc -w filename 看文件里有多少个word。
wc -L filename 文件里最长的那一行是多少个字。

待更新…

Python程序的执行过程 解释型语言和编译型语言

当python程序运行时,编译的结果则是保存在位于内存中的PyCodeObject中,当Python程序运行结束时,Python解释器则将PyCodeObject写回到pyc文件中。当python程序第二次运行时,首先程序会在硬盘中寻找pyc文件,如果找到,则直接载入,否则就重复上面的过程。
.pyc的过期时间:每次在载入之前都会先检查一下py文件和pyc文件保存的最后修改日期,如果不一致则重新生成一份pyc文件。

A. 其实Python是否保存成pyc文件和我们在设计缓存系统时是一样的,我们可以仔细想想,到底什么是值得扔在缓存里的,什么是不值得扔在缓存里的。

B. 在跑一个耗时的Python脚本时,我们如何能够稍微压榨一些程序的运行时间,就是将模块从主模块分开。(虽然往往这都不是瓶颈)

C. 在设计一个软件系统时,重用和非重用的东西是不是也应该分开来对待,这是软件设计原则的重要部分。

D. 在设计缓存系统(或者其他系统)时,我们如何来避免程序的过期,其实Python的解释器也为我们提供了一个特别常见而且有效的解决方案。

优化器有哪些,怎么演进的,平时怎么用,如何调参数

猜你喜欢

转载自blog.csdn.net/qq_38109843/article/details/89598570