C++ 十一月 07, 2022

fvecs及ivecs数据格式介绍和c读取代码

文章字数 785 阅读约需 5 mins 阅读次数 1000000

最近在做关于结构化及非结构化数据混合索引及搜索的工作,其中有一项挑战是根据论文中的数据集、标签集,自己得到真值集(不知道为啥论文没给出真值集),然后进行后续工作。

在此过程中,我需要知道真值集的存储格式——ivecs。

ivecs与fvecs格式

在常用的公开数据集中(如CrawlEnron),数据集文件、查询文件往往使用fvecs格式存储。而真值集(即查询的答案)文件使用ivecs格式存储。其实这两种格式十分相似。

fvecs

数据集、查询集采用fvecs格式,其实他们是完全相同的东西。在数据集中,存储的是所有向量,而查询集中,存储的同样是向量,只是向量数量会少一些。

fvecs采用二进制来存储,直接打开便是乱码。

下面用一张图来表示fvecs的大致格式:

每一“行”中,第一个数表示数据的维度dim,后面跟着的dim个数便是向量各维度的值。(注:fvecs中的f指float32)

因此,一“行”表示的便是一个向量。

那么行数是如何计算的呢?我们一般使用下面的式子:

line_num = filesize / (dim + 1 ) / 4

其中line_num是行数,filesize是文件字节数,dim+1指每个向量占用的数值个数,4指每4个字节存储一个数值。

ivecs

ivecs其实和fvecs的格式是一样的,只不过它存储的不是向量,而是每一条查询的答案。

就是说,ivecs里的每一“行”里,第一个数据是查询答案的数量n,后面n个数是答案向量的id。(注:ivecs中的i指int32)

cpp读取fvecs文件代码

先将下面的代码放入read.cpp,然后编译出read.exe

#include <fstream>
#include <vector>
#include<iostream>
using namespace std;
 
void load_ivecs_data(const char* filename,
                 std::vector<std::vector<float> >& results, unsigned &num, unsigned &dim) {
  std::ifstream in(filename, std::ios::binary);
  if (!in.is_open()) {
    std::cout << "open file error" << std::endl;
    exit(-1);
  }
  in.read((char *)&dim, 4);
  
  
  
  in.seekg(0, std::ios::end);
  std::ios::pos_type ss = in.tellg();
  size_t fsize = (size_t)ss;
  num = (unsigned)(fsize / (dim + 1) / 4);
  results.resize(num);
  for (unsigned i = 0; i < num; i++) results[i].resize(dim);

  in.seekg(0, std::ios::beg);
  for (size_t i = 0; i < num; i++) {
    in.seekg(4, std::ios::cur);
    in.read((char*)results[i].data(), dim * 4);
    
  }
  in.close();
}


int main(int argc, char** argv) {
  std::vector<std::vector<float> > true_load;
  unsigned dim, num;
  load_ivecs_data(argv[1], true_load, num, dim);
    std::cout << "result_num:"<< num << std::endl << "result dimension:" << dim << std::endl;
  for(size_t i = 0; i < num; i++) {
    for(size_t j = 0; j < dim; j++) {
      std::cout << true_load[i][j] << " ";
    }
    std::cout << std::endl;
  }
  std::cout << "result_num:"<< num << std::endl << "result dimension:" << dim << std::endl;
  return 0;
}

在read.exe所在目录下放置groundtruth数据集文件,然后在cmd中输入:

.\read.exe .\xzx_groundtruth

结果如下:

补档:python读取ivecs、fvecs代码

import sys
import numpy as np

def ivecs_read(fname):
    a = np.fromfile(fname, dtype='int32')
    d = a[0]
    return a.reshape(-1, d + 1)[:, 1:].copy()

def fvecs_read(fname):
    return ivecs_read(fname).view('float32')

dataset_path = sys.argv[1]
dataset = fvecs_read(dataset_path)

上一篇 :  
下一篇 :  
0%