Ich bin neu in Caffe Framework und ich würde gerne Caffe verwenden, um das Training mit Multi-Label zu implementieren. Ich benutze zwei LMDB um Daten und Labels zu speichern. Die Daten LMDB haben die Dimension Nx1xHxW, während das Label LMDB die Dimension Nx1x1x3 hat. Labels sind Float-Daten.Multi-Etiketten mit zwei verschiedenen LMDB
Die Textdatei ist wie folgt:
5911 3
train/train_data/4224.bmp 13 0 12
train/train_data/3625.bmp 11 3 7
... ...
I C++ verwenden LMDB zu erstellen. Mein main.cpp:
#include <algorithm>
#include <fstream> // NOLINT(readability/streams)
#include <string>
#include <utility>
#include <vector>
#include <QImage>
#include "boost/scoped_ptr.hpp"
#include "gflags/gflags.h"
#include "glog/logging.h"
#include "caffe/proto/caffe.pb.h"
#include "caffe/util/db.hpp"
#include "caffe/util/format.hpp"
#include "caffe/util/rng.hpp"
#include <boost/filesystem.hpp>
#include <iomanip>
#include <iostream> // NOLINT(readability/streams)
#include <string>
#include "google/protobuf/message.h"
#include "caffe/common.hpp"
#include "caffe/proto/caffe.pb.h"
#include "caffe/util/format.hpp"
#ifndef CAFFE_TMP_DIR_RETRIES
#define CAFFE_TMP_DIR_RETRIES 100
#endif
using namespace caffe; // NOLINT(build/namespaces)
using std::pair;
using boost::scoped_ptr;
const char *dat_lab="/home/mul/caffe-master/examples/2D_3D/new/info/train.data";
string data_db="/home/mul/caffe-master/examples/2D_3D/new/2D_3D_data_leveldb";
string label_db="/home/mul/caffe-master/examples/2D_3D/new/2D_3D_label_leveldb";
string root="/home/mul/caffe-master/examples/2D_3D/new/";
string path;
int main()
{
//Create data DB
scoped_ptr<db::DB> dat_db(db::GetDB("leveldb"));
dat_db->Open(data_db, db::NEW);
scoped_ptr<db::Transaction> dat_txn(dat_db->NewTransaction());
//Create label DB
scoped_ptr<db::DB> lab_db(db::GetDB("leveldb"));
lab_db->Open(label_db, db::NEW);
scoped_ptr<db::Transaction> lab_txn(lab_db->NewTransaction());
//Storing to db
Datum dat_datum,lab_datum;
int count=0;
std::ifstream infile(dat_lab);
std::string filename;
const char *dataname;
int dataNum;
int labelcount;
QImage img;
infile>>dataNum>>labelcount;
LOG(INFO) << "A total of " << dataNum<< " images.";
for (int line_id = 0; line_id < dataNum; ++line_id)
{
infile>>filename;
path=root+filename;
dataname=path.c_str();
img.load(dataname);
dat_datum.set_channels(1);
dat_datum.set_height(img.height());
dat_datum.set_width(img.width());
dat_datum.clear_data();
dat_datum.clear_float_data();
int datum_channels = dat_datum.channels();
int datum_height = dat_datum.height();
int datum_width = dat_datum.width();
int datum_size = datum_channels * datum_height * datum_width;
std::string buffer(datum_size, ' ');
const uchar* ptr = img.bits();
int img_index = 0;
for (int h = 0; h < datum_height; ++h)
{
for (int w = 0; w < datum_width; ++w)
{
for (int c = 0; c < datum_channels; ++c)
{
int datum_index = (c * datum_height + h) * datum_width + w;
buffer[datum_index] = static_cast<char>(ptr[img_index++]);
}
}
}
dat_datum.set_data(buffer);
lab_datum.set_channels(labelcount);
lab_datum.set_height(1);
lab_datum.set_width(1);
lab_datum.clear_data();
lab_datum.clear_float_data();
for(int i=0;i<labelcount;++i)
{
float mid;
infile>>mid;
lab_datum.add_float_data(mid);
}
// sequential
string key_str = caffe::format_int(line_id, 8);
// Put in db
string out;
CHECK(dat_datum.SerializeToString(&out));
dat_txn->Put(key_str, out);
CHECK(lab_datum.SerializeToString(&out));
lab_txn->Put(key_str, out);
if (++count % 1000 == 0)
{
// Commit db
dat_txn->Commit();
dat_txn.reset(dat_db->NewTransaction());
lab_txn->Commit();
lab_txn.reset(lab_db->NewTransaction());
LOG(INFO) << "Processed " << count << " files.";
}
}
// write the last batch
if (count % 1000 != 0)
{
dat_txn->Commit();
lab_txn->Commit();
LOG(INFO) << "Processed " << count << " files.";
}
return 0;
}
Zwei LMDB können erfolgreich erstellt werden. Aber wenn ich Caffe verwende, um das Training mit zwei LMDB zu implementieren, ist das Ergebnis immer falsch. Die Verlustschicht ist EUCLIDEAN_LOSS und der Verlust kann nicht abfallen. Ich weiß nicht, ob der Code, der zwei LMDB erzeugen kann, falsch ist. Wer kann mir helfen ? Danke, was auch immer.
Warum verwenden Sie 'dat_datum.set_data (buffer)', um die Bilddaten zu setzen, während 'lab_datum.add_float_data (mid)' für die Etiketten verwendet wird? Ich habe keine Erfahrung mit 'Datum' C++ - Schnittstelle, aber ist es möglich, dass Einstellung' lab_datum.set_channels (labelcount) 'und dann' add_float_data' Methode die Größe der Daten ändern und legt schließlich die Label-Werte an Orten '3, 4, 5 'statt '0, 1, 2'? – Shai
anstelle von levelfb für die etiketten, warum erwägen sie nicht mit hdf5 eingang? Für ein Beispiel siehe [diese Antwort] (http://stackoverflow.com/a/31808324/1714410). – Shai
Diese Methode hat genügend Trainingsdaten, so dass der Speicher des Computers nicht alle Daten laden kann. Deshalb akzeptiere ich hdf5 nicht. Ich habe gerade dieses Problem gelöst und danke für Ihre Antwort. –