k互近邻算法 rerank

2023-11-12

建议读者手中有re-ranking的代码,或者看过某个行人充实别的代码。

一,re-ranking大致流程:

   re-ranking是一个图像检索问题,给定一个probe,要从图片集gallery中找出与它相似的图片。如:

既然是检索问题,那么ranking前得到的ranking list就很重要,ranking list有没有使用某些算法得到,这有着很大区别,如下图:

L是没有用算法的ranking list,可以看到AP只有9.05%,准确率非常低,而用了算法的ranking list则可以达到51.98%。所以可以说 re-ranking 是高度依赖ranking list 的质量的。

那之前获取ranking list的算法有哪些呢?

这里主要叫一个 k-nearest neighbors (k近邻)算法。顾名思义,就是从gallery中选择与probe最相似的前k个嘛。

按理来说 ,这种方法应该效果挺好的,但实验中证明,获得k近邻时,很有可能有false match的噪音数据参杂进这个ranking list中,如下图:

其中P1,P2,P3,P4都为true match,但却没有全在比较前的位置,false match中的N1,N2却排到了一个比较靠前的位置,因此就引出了今天要讲的算法 k-reciprocal nearest neighbor(k相互近邻)算法。

 

二,k-reciprocal nearest neighbor 算法

这个算法的思路就是:如果两张图片A,B相似,那么B应该会在A的前K个近邻里面,反过来,A也会在B的前K个近邻里面。但如果两张图C,D不相似,即使C在D的前K个近邻里面,D也不会在C的前K个近邻里面。如下图:

那么这个k-reciprocal nearest neighbor算法主要的过程是怎么实现呢?

假设我们有一个图片probe p,和图片集gallery g:

我们首先要计算 p 和所有 g 中的图片的马氏距离 杰卡德距离(jaccard distance)。

其中马氏距离用于获得 initial ranking list,杰卡德距离用于获得 k-reciprocal 的 ranking list。

马氏距离好理解,它可以看作是忽略了量纲的欧式距离。

(马氏距离与欧式距离,余弦距离的关系可看这个博客:https://blog.csdn.net/u014453898/article/details/98657357

杰卡德距离就要稍微讲一下了:

2.1杰卡德(jaccard)距离是什么?

杰卡德(jaccard)距离的公式是:

其中R,R星,p,k是什么呢,我们一一来看:

gi 为 gallery集中的图片。p为probe。

R是符合 k-reciprocal nearest neighbors 的图片集合,注意它是一个集合,可以定义为:(而R星只是做了扩展的R,等下会说)

这里又出现了N,那我们看看,既然R是符合k相互近邻的图片集合,那N就是K近邻的图片集合嘛,N定义如下:

(|N(p,k)|表示N中候选图片的数目)

那么到这里,我们看回R的定义公式就可以很清楚地看到,R(p,k)是以p作为probe,在gallery图片集中,能与p能有k相互近邻的图片集合

根据前面的描述,k-reciprocal nearest neighbors(K相互近邻)比k-nearest neighbors(K近邻)  和probe p更相关。然而,由于照明姿态视图遮挡的变化,正样本图像可能被从k-nearest neighbors中排除,并且随后不被包括在k-reciprocal nearest neighbors中。为了解决这个问题,我们根据以下条件将R(p,k)中每个候选项的1/2 k-reciprocal nearest neighbors增量地添加到更鲁棒的集合R*(p,k)中:

稍微通俗讲一下,这个R星的形成公式:

我们已经知道R(p,k)是一个集合,里面全是gallery中符合p的k-reciprocal nearest neighbors(K相互近邻)的图片gi

然后我们现在要做的就是遍历这些gi,每一个拿出来就是q,然后我们再用这个q作为新的probe,在gallery图片集里做k变成原来一半的k-reciprocal nearest neighbors 得到R(q,1/2k),若R(p,k)R(q,1/2k)的交集中的图片数大于等于2/3乘R(q,1/2k)中的图片数目的话,就把R(p,k)R(q,1/2k)的并集作为R星(p,k)

下面用一个比较距离的例子来呈现R星的形成:

首先Q作为probe,蓝色框即为Q的k-reciprocal nearest neighbors(K相互近邻)集R(Q,20)R(Q,20)中的C单独拿出来作为q,同时K减一半,即K = 20/2 = 10,所以第二行即为R(C,10)R(Q,20)与R(C,10)的的并集(即相同的图片)数为2,而R(C,10)的个数为3。 2/3 乘 3 = 2 ,符合R星(Q,20)就为R(Q,20)与R(C,10)的交集。(第三行)。

知道R星是什么,就不难看懂杰卡德(jaccard)距离了:

改造杰卡德(jaccard)距离            

然而,这样的杰卡德(jaccard)距离还是有缺点的:

1.取交集和并集的操作非常耗时间,尤其是在需要计算所有图像对的情况下。一个可选方式是将近邻集编码为一个等价的但是更简单的向量,以减少计算复杂度。

2.这种距离计算方法将所有的近邻样本都认为是同等重要的,而实际上,距离更接近于probe的更可能是正样本。因此,根据原始的距离将大的权值分配给较近的样本这一做法是合理的。

3.为了得到鲁棒的距离度量,结合原始距离和Jaccard距离是有必要的。

为了克服上述缺点,我们开始改造Jaccard距离。首先,将k-reciprocal nearest neighbors(缩写k-rnn)集合编码为N维的二值向量=,其中每个元素由以下指示函数定义:

接着,为了给每一个元素根据原始距离来重新分配权值,我们采用了高斯核。于是将向量改写为:

于是,计算Jaccard距离时用到的交集和并集的基数就改写为:

最后,我们终于得到了改造过的Jaccard距离:

2.2 k-reciprocal nearest neighbor 算法与马氏距离和杰卡德距离

从上图可以看出,在Feature Extraction(特征提取)阶段,灰色的是提取probe p和gallery中每张图片各自的外观特征(这用需要做re ranking的神经网络来完成),绿色的是提取probe p与gallery中每张图片的K-reciprocal特征V,公式是上述的Vp,g公式。灰色特征形成马氏距离后,就可以作为原始距离(intial distance),绿色则作为杰卡德(jaccard)距离,然后两个距离聚合在一起就成了最终距离(final distance),final distance可以用于最终的ranking list。到这整个流程就完成了。

距离聚合公式:(入是自己手动设置的)

 

三,代码讲解部分

3.1 在输入re-ranking代码前,作的一些预处理

首先用到的网络(用于提取图片外观特征的网络)是Mutiple Granularity Network(MGN),数据集是Market-1501。

在讲re-ranking代码之前,先说说MGN,MGN是把每张图片都处理成一个(1x2048)的向量来代替原来的图片

re-ranking部分用到数据集Market-1501的两个文件夹如下图:

bounding_box_test作为gallery图片集,一共19733张,但是里面有些图片id是-1的,MGN舍弃了这部分,所以真正读入的图片为15914张。所以gallery的图片数就是15914。

query则是作为probe,只不过里面有很多个probe,一共3369张。

在进入re-ranking代码前:

预处理先对 query 和 gallery 进行特征提取,注意这里不是一张张提取,而是整个集合的图片一起提取特征,所以输出的是一个大矩阵。

用MGN提取query的特征,由于一张图片会转换成1x2048的向量,所以拥有3369张图片的query的特征就是3369x2048的矩阵。(用qf表示这个矩阵)

同理用MGN提取gallery的特征,得到15914x2048的矩阵。(用gf表示这个矩阵)

特征提取的代码如下:

大家只要关注红框处就行,红框处给每个表示图片的向量做了向量的单位化!!!这个很重要!单位化后的向量的模就为1。

这个很重要的原因是,提取了qf和gf之后,就开始算马氏距离了,但是代码不是用马氏距离的公式来算马氏距离,而是使用了一个小技巧,用余弦距离来算马氏距离,为什么可以这样子呢,参考链接:https://blog.csdn.net/u014453898/article/details/98657357

余弦距离为:

当两向量的模为1时,向量相乘的积就是它们的余弦距离。并且MGN在读入数据集时,就应该做过标准化了,因此数据的均值为0,标准差为1,这种情况下,马氏距离又等于欧式距离,余弦距离与欧式距离有转换公式,所以马氏距离可以用余弦距离表示:

因此可以通过qfgf两个矩阵相乘得到两个矩阵的余弦距离:

上面四条代码:

q_g_dist 表示:qf 和 gf的余弦距离。维度3369x15914,表示3329张probe和各自15914张gallery的余弦距离。

q_q_dist 表示:qf自己的余弦距离。维度为3369x3369,表示每张probe 和 其他probe的余弦距离。

g_g_dist 表示:gf自己的余弦距离。维度为15914x15914,表示每张gallery和 其他gallery的余弦距离。

最后一条代码:把三个距离矩阵送入re_ranking() 做k-reciprocal nearest neighbors的re-ranking

3.3 k-reciprocal nearest neighbors的re-ranking代码解析 :

re_ranking()函数的输入参数为3个距离矩阵。和一些默认的参数:

下面re-ranking的代码分三部分讲:

第一部分代码:

函数的第一步,是作3个距离矩阵的聚合:

简写q_g_dist 为 qq,则得到的 original_dist 矩阵如下:

original_dist的维度是 :(3369+15914)x(3369+15914) = 19283 x 19283

19283 是 query 和 gallery 加起来的总图片数目。

所以original_dist 矩阵表示的是,全部图片各自与其他图片的余弦距离。

然后:就做余弦距离转马氏距离的操作:

 #这里代码少了一个平方根,应该不影响效果

转换完马氏距离后,就做了一个归一化,把每列最大数max的找出来,然后让该列的全部成员除max,再转置:(此时的矩阵就不再对称了)

original_dist = np.transpose(1. * original_dist/np.max(original_dist,axis = 0)) #归一化
   
   

解下来,就开始定义V了,V矩阵的维度和original_dist 一样,初始化为全0。

还记得V是什么吗?V是算出杰卡德(jaccard)距离的一个中间变量啊:

但代码这里只是先初始下 一下V,还没进行真正的操作,接下来是用original_dist 矩阵来弄出 initial rank,就是原始排列:

initial_rank = np.argpartition( original_dist, range(1,k1+1) )
   
   

作用从对original_dist的每行从小到大进行排列,排前k1个(k1=20),返回的是索引号,但是original_dist维度是没有变的:

排序号之后,就成 intial_rank 了。

接着有一个大循环:


   
   
  1. query_num = q_g_dist.shape[ 0]
  2. all_num = original_dist.shape[ 0]
  3. for i in range(all_num):
  4. # k-reciprocal neighbors
  5. k_reciprocal_index = k_reciprocal_neigh( initial_rank, i, k1) #取出互相是前20的
  6. k_reciprocal_expansion_index = k_reciprocal_index
  7. for j in range(len(k_reciprocal_index)): #遍历与第i张图片互相是前20的每张图片
  8. candidate = k_reciprocal_index[j]
  9. candidate_k_reciprocal_index = k_reciprocal_neigh( initial_rank, candidate, int(np.around(k1/ 2)))
  10. if len(np.intersect1d(candidate_k_reciprocal_index,k_reciprocal_index))> 2./ 3*len(candidate_k_reciprocal_index):
  11. k_reciprocal_expansion_index = np.append(k_reciprocal_expansion_index,candidate_k_reciprocal_index)
  12. #增广k_reciprocal_neigh数据,形成k_reciprocal_expansion_index
  13. k_reciprocal_expansion_index = np.unique(k_reciprocal_expansion_index) #避免重复,并从小到大排序
  14. weight = np.exp(-original_dist[i,k_reciprocal_expansion_index]) #第i张图片与其前20+图片的权重
  15. V[i,k_reciprocal_expansion_index] = 1.*weight/np.sum(weight) #V记录第i个对其前20+个近邻的权重,其中有0有非0,非0表示没权重的,就似乎非前20+的
  16. original_dist = original_dist[:query_num,] #original_dist裁剪到 只有query x query+g

很容易看出,实现的每一张图片(query+gallery)都实现以下操作:

形成一个V矩阵,

这个矩阵表示图i,对应其R星(k_reciprocal_expansion_index)每张图片的权重,当然大部分会是0,表示不相似嘛,非0的就是相似度。且V走了个归一化,权重weight除了每行weight的总和。

这一部分代码以下面一句代码结尾:

original_dist = original_dist[:query_num,] #original_dist裁剪到 只有query x query+g
   
   

表示orginal_dist矩阵进行裁剪,只划到有query的地方:(3369是query集的图片数,19283是query+gallery的图片数)

第二部分代码:

第二部分就用到K2了。

这个K2跟之前的K有什么区别呢,首先K肯定是大于K2(MGN里,K2设置成6)的,我们来看看这段代码写了什么:

首先,它先创建了一个维度跟V一样的V_qe,并初始化为0。

然后遍历所有图片,并进行了一个匪夷所思的操作:

在initial_rank里,每行都取k2列,就是每张图片都取前k2个,当然我们前面已经知道initial_rank里的前k个元素(红色框)是从小打到排好序的了,因此这次取的前k2个,肯定也是从小到大排好序的:(如蓝色框)

第i行的k2就如绿色部分。当然我们前面已经知道initial_rank里的元素全是图片索引号,因此V_qe就把从initial_rank中拿出来的k2个索引号,在V中,寻找相对应的K2张图片的数据。然后再做一个均值化,把K2行数值变成一行,作为V_qe[i,:]的数据。

那这样做有什么用呢?

原理如下:

好了,得到V_qe后,V的作用就淘汰了,用V_qe直接代替V。

第三部分代码:

(ps:query_num为3369,是query集的图片数。all_num为19283,为query+gallery的图片数)

这一部分的代码功能是实现杰卡德(jaccard)距离的计算。这里比较关键的是列表 invIndex 和 indNonZero 。(注意:这里的V已经被V_qe代替了)

未免大家忘了,先前情回顾一下杰卡德距离的计算公式:

代码一开始,我们可以看到invIndex的定义:

找出V_qe矩阵每一列中不为0元素的行索引号。并把该行索引号加入到invIndex中。

然后开始定义杰卡德(jaccard)距离的维度:

可以看到jaccard_dist变量的维度和orginal_dist的维度是一样的,并初始化为0,而original_dist的维度之前已经被裁剪过变成3369x19283了:

所以jaccard_dist的维度也是3369x19283。即 (query集图片数)x(query+gallery图片数)

接下来的代码就到了一个循环:这个循环里面定义了indNonZero,indNonZero是以行为单位遍历V_qe中不为0的列,返回改行不为0元素的列索引。举个例子如下图:

由上图可以看出:

invIndex :是 以列为单位(即纵向)先遍历全部图片(query+gallery),每张图又各自与其他图作比对,返回不为0的图片号(行号)

indNonZero:invIndex完成遍历后,就开始indNonZero的遍历,和invIndex相反,indNonZero以行为单位(横向)遍历全部 图片,图上图,当遍历第一张图(i = 0行)时,返回i=0行里 不为0元素的列号,如上图V_qe中红色圈。

indImages:当i=0时,如上图V_qe中的蓝色椭圆 ,返回与图i有相似的图(0,2),然后又找与(0,2)有相似的图,0是(0,1),2是(0,1,2),正好为上图中indImages。当i继续加的时候,indImages也同理生成。

接下来就进入到一个子循环:

遍历indNonZero。

也是以 i = 0为例开始讲解,V[i,indNonZero[j]] 就是 前面图V_qe里,第i行不为0的元素的列号,如(i,0),(i,2)

可能这两行代码看起来很复杂,但其实它计算的temp_min就是下图黄色框这部分:

算出temp_min后,就可以算杰卡德(jaccard)距离了。上面的公式就是杰卡德距离公式,而代码用了一个小技巧实现:

这里可能就有小伙伴很奇怪了,怎么分母变成了 2 - temp_min呢?怎么来的呢?

为了说明,我们先举一个例子看看:

可以看出,两个向量的最大值和最小值符合这种关系:

两向量元素之和 - min的和 = max的和。反之亦然。

所以我们猜测,代码这样写的原因是因为两向量的和加起来为2。

那怀着这个猜测,我们看看是否正确:

上述的V已经变成V_qe就不用说的了,那我们探索一下V_qe的值由谁决定,是由V决定的对不对,那我们看看V的矩阵:

前情回顾一下:

V矩阵是做了归一化的,所以V矩阵中的每一行加起来都是一,V_qe矩阵的每一行是由K2个V矩阵向量均值化而来的,因此V_qe的每一行也是加起来为1。因此两个V_qe矩阵向量加起来就为2。

所以:

杰卡德距离公式:

可以这样实现:

得到杰卡德距离后,就可以算最后距离(final_dist)了:

代码是:

lambda_value 作为re_ranking函数的默认参数,是人为手工设置的超参数。

得到的final dist矩阵是:

进行裁剪 一下:

得到最后的final dist矩阵:

3369表示query集中的图片数,15914表示gallery集中的图片数。矩阵中的元素(i,j)表示query中第i张图片和gallery中第j张图片的 final dist。用作最后ranking的依据。

 

 

-----------------------------------------------------

最后奉上基于k-reciprocal Encoding的re-ranking代码:


   
   
  1. #!/usr/bin/env python2/python3
  2. # -*- coding: utf-8 -*-
  3. """
  4. Created on Mon Jun 26 14:46:56 2017
  5. @author: luohao
  6. Modified by Houjing Huang, 2017-12-22.
  7. - This version accepts distance matrix instead of raw features.
  8. - The difference of `/` division between python 2 and 3 is handled.
  9. - numpy.float16 is replaced by numpy.float32 for numerical precision.
  10. Modified by Zhedong Zheng, 2018-1-12.
  11. - replace sort with topK, which save about 30s.
  12. """
  13. """
  14. CVPR2017 paper:Zhong Z, Zheng L, Cao D, et al. Re-ranking Person Re-identification with k-reciprocal Encoding[J]. 2017.
  15. url:http://openaccess.thecvf.com/content_cvpr_2017/papers/Zhong_Re-Ranking_Person_Re-Identification_CVPR_2017_paper.pdf
  16. Matlab version: https://github.com/zhunzhong07/person-re-ranking
  17. """
  18. """
  19. API
  20. q_g_dist: query-gallery distance matrix, numpy array, shape [num_query, num_gallery]
  21. q_q_dist: query-query distance matrix, numpy array, shape [num_query, num_query]
  22. g_g_dist: gallery-gallery distance matrix, numpy array, shape [num_gallery, num_gallery]
  23. k1, k2, lambda_value: parameters, the original paper is (k1=20, k2=6, lambda_value=0.3)
  24. Returns:
  25. final_dist: re-ranked distance, numpy array, shape [num_query, num_gallery]
  26. """
  27. import numpy as np
  28. def k_reciprocal_neigh( initial_rank, i, k1):
  29. forward_k_neigh_index = initial_rank[i,:k1+ 1] #第i个图片的前20个相似图片的索引号
  30. backward_k_neigh_index = initial_rank[forward_k_neigh_index,:k1+ 1]
  31. fi = np.where(backward_k_neigh_index==i)[ 0] #返回backward_k_neigh_index中等于i的图片的行索引号
  32. return forward_k_neigh_index[fi] #返回与第i张图片 互相为k_reciprocal_neigh的图片索引号
  33. def re_ranking(q_g_dist, q_q_dist, g_g_dist, k1=20, k2=6, lambda_value=0.3):
  34. # The following naming, e.g. gallery_num, is different from outer scope.
  35. # Don't care about it.
  36. original_dist = np.concatenate(
  37. [np.concatenate([q_q_dist, q_g_dist], axis= 1),
  38. np.concatenate([q_g_dist.T, g_g_dist], axis= 1)],
  39. axis= 0)
  40. original_dist = 2. - 2 * original_dist #np.power(original_dist, 2).astype(np.float32) 余弦距离转欧式距离
  41. original_dist = np.transpose( 1. * original_dist/np.max(original_dist,axis = 0)) #归一化
  42. V = np.zeros_like(original_dist).astype(np.float32)
  43. #initial_rank = np.argsort(original_dist).astype(np.int32)
  44. # top K1+1
  45. initial_rank = np.argpartition( original_dist, range( 1,k1+ 1) ) #取前20,返回索引号
  46. query_num = q_g_dist.shape[ 0]
  47. all_num = original_dist.shape[ 0]
  48. for i in range(all_num):
  49. # k-reciprocal neighbors
  50. k_reciprocal_index = k_reciprocal_neigh( initial_rank, i, k1) #取出互相是前20的
  51. k_reciprocal_expansion_index = k_reciprocal_index
  52. for j in range(len(k_reciprocal_index)): #遍历与第i张图片互相是前20的每张图片
  53. candidate = k_reciprocal_index[j]
  54. candidate_k_reciprocal_index = k_reciprocal_neigh( initial_rank, candidate, int(np.around(k1/ 2)))
  55. if len(np.intersect1d(candidate_k_reciprocal_index,k_reciprocal_index))> 2./ 3*len(candidate_k_reciprocal_index):
  56. k_reciprocal_expansion_index = np.append(k_reciprocal_expansion_index,candidate_k_reciprocal_index)
  57. #增广k_reciprocal_neigh数据,形成k_reciprocal_expansion_index
  58. k_reciprocal_expansion_index = np.unique(k_reciprocal_expansion_index) #避免重复,并从小到大排序
  59. weight = np.exp(-original_dist[i,k_reciprocal_expansion_index]) #第i张图片与其前20+图片的权重
  60. V[i,k_reciprocal_expansion_index] = 1.*weight/np.sum(weight) #V记录第i个对其前20+个近邻的权重,其中有0有非0,非0表示没权重的,就似乎非前20+的
  61. original_dist = original_dist[:query_num,] #original_dist裁剪到 只有query x query+g
  62. if k2 != 1:
  63. V_qe = np.zeros_like(V,dtype=np.float32)
  64. for i in range(all_num): #遍历所有图片
  65. V_qe[i,:] = np.mean(V[initial_rank[i,:k2],:],axis= 0) #第i张图片在initial_rank前k2的序号的权重平均值
  66. #第i张图的initial_rank前k2的图片对应全部图的权重平均值
  67. #若V_qe中(i,j)=0,则表明i的前k2个相似图都与j不相似
  68. V = V_qe
  69. del V_qe
  70. del initial_rank
  71. invIndex = []
  72. for i in range(all_num):
  73. invIndex.append(np.where(V[:,i] != 0)[ 0])
  74. jaccard_dist = np.zeros_like(original_dist,dtype = np.float32)
  75. for i in range(query_num):
  76. temp_min = np.zeros(shape=[ 1,all_num],dtype=np.float32)
  77. indNonZero = np.where(V[i,:] != 0)[ 0]
  78. indImages = []
  79. indImages = [invIndex[ind] for ind in indNonZero]
  80. for j in range(len(indNonZero)):
  81. temp_min[ 0,indImages[j]] = temp_min[ 0,indImages[j]]+ np.minimum(V[i,indNonZero[j]],V[indImages[j],indNonZero[j]])
  82. jaccard_dist[i] = 1-temp_min/( 2.-temp_min)
  83. final_dist = jaccard_dist*( 1-lambda_value) + original_dist*lambda_value
  84. del original_dist
  85. del V
  86. del jaccard_dist
  87. final_dist = final_dist[:query_num,query_num:]
  88. return final_dist

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

k互近邻算法 rerank 的相关文章

  • Neon intrinsics

    1 介绍 在上篇中 介绍了ARM的Neon 本篇主要介绍Neon intrinsics的函数用法 也就是assembly之前的用法 NEON指令是从Armv7架构开始引入的SIMD指令 其共有16个128位寄存器 发展到最新的Arm64架构
  • mysql设置wait timeout_mysql修改wait_timeout_MySQL

    bitsCN com mysql修改wait timeout mysql mysql gt show global variables like wait timeout 其默认值为8小时 mysql的一个connection空闲时间超过8
  • TypeScript中类的继承

    特点 避免重复创建类 减少代码数量 通过extends关键字继承父类 通过super继承父类的属性和方法 实例 class Person1 定义属性 name string age number gender string construc
  • transformer序列预测示例

    本文参考 python量化 将Transformer模型用于股票价格预测 蚂蚁爱Python的博客 CSDN博客 transformer 股票 一 Transformer初步架构图 二 transformer各组件信息 1 position
  • Maven执行mvn clean compile命令遇到Fatal error compiling: 无效的标记: --release错误解决办法

    Maven执行mvn clean compile命令会报如下图所示的错误 由图可知 maven compiler plugin插件编译时用到了 release选项 而我的jdk是1 8 不支持该选项 此时我的maven compiler p
  • linux学成之路(基础篇(二十三)MySQL服务(中)

    目录 MySQL服务之SQL语句 一 SQL语句类型 一 DDL语句 二 DML语句 三 DCL语句 四 DQL 语句 二 数据库操作 一 查看 二 创建 三 进入 四 删除数据库 五 更改数据库名称 六 更改字符集 三 数据表管理 一 数
  • Hadoop HDFS shell 命令行常用操作

    前言 Hadoop HDFS shell的命令和Linux的shell命令有类似的地方 基本上会使用Linux命令的话 把HDFS的理论理解一下就可以了 一 创建文件夹 hadoop fs mkdir p
  • 【915程序设计】21西交大软件专硕915程序设计真题讲解

    28 马鞍点 include
  • 【华为OD机试c++】Excel单元格数值统计【 2023 Q1

    华为OD机试 题目列表 2023Q1 点这里 2023华为OD机试 刷题指南 点这里 题目描述 Excel 工作表中对选定区域的数值进行统计的功能非常实用 仿照Excel的这个功能 请对给定表格中选中区域中的单元格进行求和统计 并输出统计结
  • Halide学习笔记---Halide语言设计的初衷

    Halide语言设计初衷 我们正处于一个数据密集的时代 4D广场相机 图形渲染 3D打印 图像传感器 高质量医学图像等 每天生产大量的图像数据 面对这样一个图像时代 急需要针对图像处理算法设计的高性能图像处理编程语言 在这样的需求下 Hal
  • 第五届蓝桥杯——java c组 1/a 的分数称为单位分数

    形如 1 a 的分数称为单位分数 可以把1分解为若干个互不相同的单位分数之和 例如 1 1 2 1 3 1 9 1 18 1 1 2 1 3 1 10 1 15 1 1 3 1 5 1 7 1 9 1 11 1 15 1 35 1 45 1
  • 一文读懂 React16.0-16.6 新特性(实践 思考)

    首先 把我知道从16 0开始到现在为止新特性全部列举出来 v16 0 render 支持返回数组和字符串 createPortal 支持自定义 DOM 属性 Error Boundary Fiber SSR优化 减少文件体积v16 1 re
  • 对区块链钱包的简单认识

    钱包是存储和使用数字货币的工具 在区块链领域有举足轻重的地位 在对钱包分类之前 需要先理解几个概念 钱包地址 它类似于银行卡号 一个人可以拥有多张银行卡 所以他也可以拥有多个钱包地址 一个钱包地址只能对应一个私钥 在一个钱包中 可以拥有多个
  • VMware导入别人的虚拟机

    根据老师发的文件 将分卷压缩文件下载到一个文件夹中 选择解压第一个文件 即可得到所有资源 可以看出得到如下文件 这里需要导入Vmware中 我查询了几种导入的方法 1 导入OVF 首先选择导入ovf文件 直接点击打开虚拟机 选择导入Ubun
  • Go 每日一库之 cobra

    简介 cobra是一个命令行程序库 可以用来编写命令行程序 同时 它也提供了一个脚手架 用于生成基于 cobra 的应用程序框架 非常多知名的开源项目使用了 cobra 库构建命令行 如Kubernetes Hugo etcd等等等等 本文
  • $('#dg').datagrid('getSelections');", 得到的rows.length在多选情况下总为1, 不选择时为0.

    dg datagrid getSelections 得到的rows length在多选情况下总为1 不选择时为0 方案 title ID field dataId width 80 hidden true 的field一定要与idField
  • 订单系统设计 —— 订单管理

    文章目录 一 方案背景 1 1 考虑因素 1 2 数据特点 二 方案演进 三 MySQL架构 3 1 单库单表 3 2 读写分离 3 3 垂直拆分 3 4 数据归档 冷热分离 3 5 分库分表 方案1 路由表 方案2 哈希 四 MySQL
  • windows linux环境搭建

    1 windows中linux环境wsl 2 powershell scoop https zhuanlan zhihu com p 463284082 powershell通过scoop可以安装各种软件 安装git就是 scoop ins

随机推荐

  • 提升UE5写实效果的项目设置

    随着虚幻引擎5 Unreal Engine 5 简称UE5 的发布 游戏开发者和数字艺术家们迎来了一个全新的机会 可以在其强大的渲染引擎下创建更加逼真和令人惊叹的游戏和虚拟场景 然而 要实现出色的写实效果 需要合理设置项目并运用一些技巧和策
  • 使用IDEA2023创建Servlet模板,使其右键显示Servlet选项

    使用IDEA2023创建Servlet模板 使其右键显示Servlet选项 之前在IDEA2022及以前可以通过一些方法创建Servlet模板 但我不知道为什么2023版本没有作用 下面提供另一种方式实现Servlet的创建 直接参考IDE
  • 系统化程序分析

    左志强 南京大学计算机系副研究员 研究领域包括程序分析 编译技术 系统软件等 本文以技术文章的方式回顾左老师在 SIG 程序分析 技术沙龙上的分享 回顾视频也已经上传 B 站 欢迎小伙伴们点开观看 SIG 程序分析技术沙龙回顾 面向千万行代
  • 单电源运放和双电源运放及其供电方式选择与转换的注意事项

    文章目录 前言 一 运放之双电源供电和单电源供电 1 如何区分单电源运放和双电源运放 2 单电源供电运放特性 3 运放的两种供电模式转换 4 单端偏置的缺陷 二 仿真验证 1 两阶高通滤波放大电路 两端偏置 2 两阶高通滤波放大电路 单端偏
  • 20-10-026-安装-KyLin-2.6.0-单机版安装(MAC官网下载)-spark引擎

    文章目录 1 视界 1 官网 2 安装要求 2 1 软件要求 2 2 硬件要求 2 3 Hadoop 环境 3 本次环境 4 HBASE 1 2 0安装 5 kylin 安装 6 检查zk jar 7 启动Hbase 8 添加依赖 9 添加
  • VS附加到进程调试

    操作 要附加到进程中调试外部可执行文件 您需要使用Visual Studio的 调试附加 功能 以下是附加到进程中调试外部可执行文件的步骤 打开您要调试的源代码文件或可执行文件 打开Visual Studio 选择 调试 菜单 然后选择 附
  • ffmpeg读取rtsp并保存到mp4文件

    本文章只讲述mp4文件的录像 至于音频录入 会在下个文章中介绍 总体思路为 初始化 连接相机获取码流 读取码流中的视频 创建输出mp4上下文 写mp4头 循环读取码流 写入mp4 写文件尾 关闭文件 第一步 初始化网络环境 环境注册 av
  • 信号、signal 函数、sigaction 函数

    文章目录 1 信号的基本概念 2 利用 kill 命令发送信号 3 信号处理的相关动作 4 信号与 signal 函数 4 1 signal 函数示例一 4 2 signal 函数示例二 5 利用 sigaction 函数进行信号处理 6
  • mysql对表的操作

    mysql对表的操作 表的概念 表是包含数据库中所有数据的数据库对象 表中的数据库对象包含列 索引 触发器 其中触发器是指用户定义的事务命令集合 当对一个表中的数据进行插入 更新或者删除时 这组命令就会自动执行 可以确保数据的安全性和完整性
  • npm : 无法加载文件 D:\Nodejs\node_global\npm.ps1,因为在此系统上禁止运行脚本

    npm 无法加载文件 D Nodejs node global npm ps1 因为在此系统上禁止运行脚本 1 问题详情 2 解决方法 1 问题详情 npm 无法加载文件 D Nodejs node global npm ps1 因为在此系
  • Kudu-客户端API编程、生态整合(Spark、Flink、Impala)

    文章目录 Kudu客户端API编程 客户端API核心类 Java编程接口 环境准备 创建表 插入数据 查询数据 修改表结构 更新数据 删除数据 更新和插入 删除表 Hadoop生态整合 整合概述 集成Spark Spark shell中操作
  • computed中不能写异步逻辑也就是不能发请求,如何解决

    其实不好解决 哈哈 不过仔细想想有以下几种解决方案 1 computed中的数据只要变化 computed值就会动态计算 所以你只要在交互之处 比如input 点击事件等操作中 发请求改得到结果赋值给相应的影响computed的data值
  • [1179]hive的lateral view用法

    文章目录 1 lateral view 简介 2 实操 2 1 建表 hive 2 2 插入数据 2 3 转成多行 2 4 汇总求和 1 lateral view 简介 hive函数 lateral view 主要功能是将原本汇总在一条 行
  • 关于附件下载的路径处理

    在网站附件下载中 往往我们不要直接暴露附件的存放地址 比如 a href file test doc 我的成功可以复制 a 点击下载的时候链接就是 http 192 169 1 87 file test zip 这样总感觉不够好 太直接了
  • JP《乡村振兴振兴战略下传统村落文化旅游设计》许少辉书香续,山水长

    JP 乡村振兴振兴战略下传统村落文化旅游设计 许少辉书香续 山水长
  • 条件编译小结

    编码的时候经常要用到条件编译 每次都到网上去查比较浪费时间 今天总结一下以备后用 编译器 GCC ifdef GNUC if GNUC gt 3 GCC3 0以上 Visual C ifdef MSC VER 非VC编译器很多地方也有定义
  • UnityVR--小程序4--第一人称控制器

    在没有VR设备的情况下 可以在Windows系统中运行我们之前做好的小游戏 只需要将VR场景中的OVRPlayerController更换成我们自己制作的第一人称控制器就行 之后可以用键盘和鼠标控制人物的移动 跳跃 转向 就和普通的3D游戏
  • 实用科研网站(自用)

    网站 网址 Papers With Code https paperswithcode com AMiner https www aminer cn Connected Papers https www connectedpapers co
  • Python3 生成器(generator)概念浅析

    引子 某次面试问候选人 Python 中生成器是什么 答曰 有 yield 关键字的函数 而在我印象中此种函数返回的值是生成器 而函数本身不是 如下 In 1 def get nums n for i in range n yield i
  • k互近邻算法 rerank

    建议读者手中有re ranking的代码 或者看过某个行人充实别的代码 一 re ranking大致流程 re ranking是一个图像检索问题 给定一个probe 要从图片集gallery中找出与它相似的图片 如 既然是检索问题 那么ra