【问题标题】:extract features to a text file将特征提取到文本文件
【发布时间】:2015-12-29 01:15:35
【问题描述】:

按照步骤 http://caffe.berkeleyvision.org/gathered/examples/feature_extraction.html 在训练后从新图像中提取特征,

你最终会得到一个 data.mdb 文件。

我更喜欢将功能写入 txt 文件,以便轻松操作它。

我做了一些谷歌搜索并找到了一些代码,但没有工作。此外,生成的 data.mdb 文件在 mac 上使用 mdb opener 应用程序打开时,根本不显示任何表格。

是否有一种简单的方法可以将提取的特征写入文本文件,或者有一种简单的方法来操作 mdb 文件,以便我们检查每张图像的实际值?

【问题讨论】:

    标签: neural-network caffe lmdb


    【解决方案1】:

    Caffe 的 c++ 接口提供了一些 lmdb 功能来读取数据,然后将其写回。

    您可以使用look yourself 了解 LMDBDataLayer 如何执行其读取操作,然后将其用作参考来编写程序来操作/写入文本来自 LMDB 数据库的数据。

    【讨论】:

      【解决方案2】:

      我不知道你是否已经想出了如何解决这个问题,但这是我最近发现的方法。

      我是 Caffe 的新手,我发现很难理解整个 Caffe 的架构。我只是想要一种快速的方法来从 Caffe 的 CNN 中提取特征并在以后对其进行操作。此外,我在 OSX 上工作并且没有从源代码安装 Caffe。我通过'port'安装它,安装似乎不完整。所以我在另一台正确安装了 Caffe 的机器上运行 Caffe 的“feature_extractor”,并将输出文件复制到我的机器上以进一步处理。

      为此,您必须在计算机上安装 LMDB 和 Google 的 Protobuf。您必须将 C/C++ 程序与 liblmdb 和 libprotobuf 链接。

      我按照 Caffe 的教程将 AlexNet 的“fc7”层的输出保存到 LMDB 格式的文件中。然后我写了一个简单的 C/C++ 程序来阅读它。这可以使用以下代码完成:

      #include <fstream>
      #include <iostream>
      #include <lmdb.h>
      
      using namespace std;
      
      int main( int argc, char *argv[] )
      {
          if( argc!=2 )
          {
              cerr<< "Error"<< endl
                  << "Usage : "<< argv[0]<< " mdb_dirname"<< endl;
              return 0;
          }
          char *mdb_dirname     = argv[1];
      
          int rc;
          MDB_env *env;
          MDB_dbi dbi;
          MDB_val key, data;
          MDB_txn *txn;
          MDB_cursor *cursor;
          char sval[32];
      
          rc = mdb_env_create(&env);
          rc = mdb_env_open(env, mdb_dirname, 0, 0664);
          rc = mdb_txn_begin(env, NULL, 0, &txn);
          rc = mdb_open(txn, NULL, 0, &dbi);
          rc = mdb_cursor_open(txn, dbi, &cursor);
      
          key.mv_size  = sizeof(int);
          key.mv_data  = sval;
          data.mv_size = sizeof(sval);
          data.mv_data = sval;
      
          while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_NEXT)) == 0)
          {
              printf("key: %p %d %.*s, data: %p %d  %.*s\n",
                     key.mv_data,  (int) key.mv_size,  (int) key.mv_size,  (char *) key.mv_data,
                     data.mv_data, (int) data.mv_size, (int) data.mv_size, (char *) data.mv_data);
          }
          mdb_cursor_close(cursor);
          mdb_txn_abort(txn);
      
          mdb_close(env, dbi);
          mdb_env_close(env);
      
          return 0;
      }
      

      “mdb_dirname”是“feature_extractor”创建的目录。它包含“data.mdb”和“lock.mdb”。

      注意到我也是 LMDB 的新手。我并没有真正理解上面的每一行代码。但是,我确实工作:)

      如果您处理 LMDB 文件,您可能会发现“key.mv_data”确实是您示例的索引。所以“data.mv_data”应该包含这个例子的特征向量。我查看了 Caffe 的 feature_extractor 的源代码,发现字符串 ‘data.mv_data’ 是从 ‘Datum’ 对象的序列化中获得的。这个 Datum 确实是使用 Google 的 Protocol Buffer 或 Protobuf 构建的。你可能会在 Caffe 目录的某个地方找到“caffe.proto”。此 .proto 文件由编译器“protoc”处理并生成必须包含在您的项目中的“caffe.pb.h”和“caffe.pb.cc”。如果找不到,就是这个样子

      syntax = "proto2";
      
      package caffe;
      
      message Datum {
        optional int32 channels = 1;
        optional int32 height = 2;
        optional int32 width = 3;
        // the actual image data, in bytes
        optional bytes data = 4;
        optional int32 label = 5;
        // Optionally, the datum could also hold float data.
        repeated float float_data = 6;
        // If true data contains an encoded image that need to be decoded
        optional bool encoded = 7 [default = false];
      }
      

      然后你可以将'data.mv_data'转换成特征向量

          while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_NEXT)) == 0)
          {
              string str( (char*)data.mv_data, (int)data.mv_size );
      
              datum.ParseFromString( str ); 
      
              if( datum.float_data_size()>0 )
              {
                  // datum.float_data_size() is the dimension of the feature vectors
                  for( int i = 0; i < datum.float_data_size(); i++ )
                  {
                      float f = datum.float_data(i);
                      // do something
                  }
              }
          }
      

      当我构建上面的代码时,有很多链接错误,例如未定义的引用……以及与 Protobuf 相关的其他内容。如果您遇到同样的问题,我找到的解决方案是将程序链接到 libprotobuf.a 而不是简单的 -llmdb(静态链接而不是动态链接)。

      另一个小问题是我分配给'feature_extractor'处理的文件中每个示例的标签丢失了。我不知道为什么。所以我只是把这些标签放到一个单独的文件中,并沿着 LMDB 文件处理它。例如,如果要输出 LIBSVM 文件:

          int c = 0;
          while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_NEXT)) == 0)
          {
              string str( (char*)data.mv_data, (int)data.mv_size );
              datum.ParseFromString( str ); 
              if( datum.float_data_size()>0 )
              {
                  cout<< label[c]<< " ";
                  for( int i = 0; i < datum.float_data_size(); i++ )
                  {
                      float f = datum.float_data(i);
                      cout<< (i+1)<< ":"<< f<< " ";
                  }
                  cout<< endl;
                  c++;
              }
          }
      

      祝你好运。

      【讨论】:

        猜你喜欢
        • 2019-04-28
        • 2011-07-25
        • 2013-02-26
        • 1970-01-01
        • 1970-01-01
        • 2012-06-20
        • 2015-05-21
        • 2019-04-09
        • 2016-09-12
        相关资源
        最近更新 更多