Merge branch 'ProtoNN-dev' of github.com:Microsoft/EdgeML into ProtoNN-dev

This commit is contained in:
Aditya Kusupati 2017-11-15 23:42:34 +05:30
Родитель 89da7e92c1 31eaf47a6a
Коммит 0eea0cf96c
11 изменённых файлов: 235 добавлений и 211 удалений

Просмотреть файл

@ -21,7 +21,7 @@ int main(int argc, char **argv) {
assert(sizeof(MKL_INT) == sizeof(Eigen::Index) && "MKL BLAS routines are called directly on data of an Eigen matrix. Hence, the index sizes should match.");
ProtoNN::ProtoNNPredictor predictor(argc, (const char**)argv);
ProtoNN::ProtoNNPredictor::ResultStruct res;
EdgeML::ResultStruct res;
res = predictor.test();

Просмотреть файл

Просмотреть файл

@ -7,7 +7,7 @@ COMMON_INCLUDE_DIR=../common
IFLAGS= -I ../../eigen/ -I $(COMMON_INCLUDE_DIR) -I$(MKL_ROOT)/include
PARAMETER_SPARSITY_FLAGS = -DSPARSE_LABEL #-DSPARSE_Z #-DSPARSE_B #-DSPARSE_W
PARAMETER_SPARSITY_FLAGS = -DSPARSE_LABEL_PROTONN #-DSPARSE_Z_PROTONN #-DSPARSE_B_PROTONN #-DSPARSE_W_PROTONN
PROTONN_FLAGS = -DL2 $(PARAMETER_SPARSITY_FLAGS)
CFLAGS += $(PROTONN_FLAGS)

Просмотреть файл

@ -5,6 +5,7 @@
#define __PROTONN_H__
#include "Data.h"
#include "metrics.h"
namespace EdgeML
{
@ -14,25 +15,25 @@ namespace EdgeML
// Should the model parameters and labels be represented as sparse or dense?
//
#ifdef SPARSE_Z
#ifdef SPARSE_Z_PROTONN
#define ZMatType SparseMatrixuf
#else
#define ZMatType MatrixXuf
#endif
#ifdef SPARSE_W
#ifdef SPARSE_W_PROTONN
#define WMatType SparseMatrixuf
#else
#define WMatType MatrixXuf
#endif
#ifdef SPARSE_B
#ifdef SPARSE_B_PROTONN
#define BMatType SparseMatrixuf
#else
#define BMatType MatrixXuf
#endif
#ifdef SPARSE_LABEL
#ifdef SPARSE_LABEL_PROTONN
#define LabelMatType SparseMatrixuf
#else
#define LabelMatType MatrixXuf
@ -223,7 +224,7 @@ namespace EdgeML
Data testData;
FP_TYPE* dataPoint; // for scoreSparseDataPoint
#ifdef SPARSE_Z
#ifdef SPARSE_Z_PROTONN
// for mkl csc_mv call
char matdescra[6] = { 'G', 'X', 'X', 'C', 'X', 'X' }; // 'X' means unused
char transa = 'n';
@ -239,18 +240,6 @@ namespace EdgeML
void createOutputDirs();
public:
struct ResultStruct {
ProblemFormat problemType;
FP_TYPE accuracy;
FP_TYPE precision1;
FP_TYPE precision3;
FP_TYPE precision5;
ResultStruct();
inline void scaleAndAdd(ResultStruct& a, FP_TYPE scale);
inline void scale(FP_TYPE scale);
};
// Use this consutrctor when loading model from binary stream.
// For this you need to have exported a binary stream model from the trainer.
ProtoNNPredictor(
@ -291,20 +280,10 @@ namespace EdgeML
ResultStruct testPointWise();
ResultStruct test();
ResultStruct test();
void saveTopKScores(std::string filename="", int topk=5);
ResultStruct evaluate(
const MatrixXuf& Yscores,
const LabelMatType& Y);
void getTopKScoresBatch(
const MatrixXuf& Yscores,
MatrixXuf& topKIndices,
MatrixXuf& topKScores,
int k = 5);
void saveTopKScores(std::string filename = "", int k = 5);
void normalize();
};
}

Просмотреть файл

@ -35,7 +35,7 @@ namespace EdgeML
const MatrixXuf& WX,
const FP_TYPE& gamma,
const EdgeML::ProblemFormat& problemType,
EdgeML::ProtoNN::ProtoNNPredictor::ResultStruct& res,
EdgeML::ResultStruct& res,
FP_TYPE* const stats);
//
@ -51,7 +51,7 @@ namespace EdgeML
void accuracy(
const ZMatType& Z, const LabelMatType& Y, const MatrixXuf& D,
const EdgeML::ProblemFormat& problemType,
EdgeML::ProtoNN::ProtoNNPredictor::ResultStruct& res);
EdgeML::ResultStruct& res);
//

Просмотреть файл

@ -59,7 +59,7 @@ size_t ProtoNNModel::modelStat()
{
size_t offset = 0;
offset += sizeof(hyperParams);
#ifdef SPARSE_Z
#ifdef SPARSE_Z_PROTONN
offset += sizeof(bool);
offset += sizeof(Eigen::Index);
Eigen::Index nnz = params.Z.outerIndexPtr()[params.Z.cols()]
@ -92,7 +92,7 @@ void ProtoNNModel::exportModel(
memcpy(toModel + offset, (void *)&hyperParams, sizeof(hyperParams));
offset += sizeof(hyperParams);
#ifdef SPARSE_Z
#ifdef SPARSE_Z_PROTONN
memcpy(toModel + offset, (void *)&isZSparse, sizeof(bool));
offset += sizeof(bool);
offset += sizeof(Eigen::Index);
@ -125,7 +125,7 @@ void ProtoNNModel::importModel(const size_t numBytes, const char *const fromMode
params.resizeParamsFromHyperParams(hyperParams, false); // No need to set to zero.
bool isZSparse(true);
#ifdef SPARSE_Z
#ifdef SPARSE_Z_PROTONN
#else
memcpy((void *)&isZSparse, fromModel + offset, sizeof(bool));
offset += sizeof(bool);

Просмотреть файл

@ -9,37 +9,6 @@
using namespace EdgeML;
using namespace EdgeML::ProtoNN;
ProtoNNPredictor::ResultStruct::ResultStruct()
:
problemType(undefinedProblem),
accuracy(0),
precision1(0),
precision3(0),
precision5(0)
{}
inline void ProtoNNPredictor::ResultStruct::scaleAndAdd(ProtoNNPredictor::ResultStruct& a, FP_TYPE scale)
{
if ((problemType == undefinedProblem) && (a.problemType != undefinedProblem))
problemType = a.problemType;
assert(problemType == a.problemType);
accuracy += scale * a.accuracy;
precision1 += scale * a.precision1;
precision3 += scale * a.precision3;
precision5 += scale * a.precision5;
}
inline void ProtoNNPredictor::ResultStruct::scale(FP_TYPE scale)
{
accuracy *= scale;
precision1 *= scale;
precision3 *= scale;
precision5 *= scale;
}
ProtoNNPredictor::ProtoNNPredictor(
const int& argc,
const char ** argv)
@ -111,7 +80,7 @@ ProtoNNPredictor::ProtoNNPredictor(
dataPoint = new FP_TYPE[model.hyperParams.D];
}
#ifdef SPARSE_Z
#ifdef SPARSE_Z_PROTONN
ZRows = model.params.Z.rows();
ZCols = model.params.Z.cols();
alpha = 1.0;
@ -140,7 +109,7 @@ ProtoNNPredictor::ProtoNNPredictor(
dataPoint = new FP_TYPE[model.hyperParams.D];
#ifdef SPARSE_Z
#ifdef SPARSE_Z_PROTONN
ZRows = model.params.Z.rows();
ZCols = model.params.Z.cols();
alpha = 1.0;
@ -329,7 +298,7 @@ void ProtoNNPredictor::scoreDenseDataPoint(
RBF();
// mm(scoresMat, model.params.Z, CblasNoTrans, D, CblasTrans, 1.0, 0.0L);
#ifdef SPARSE_Z
#ifdef SPARSE_Z_PROTONN
cscmv(&transa,
&ZRows, &ZCols,
&alpha, matdescra, model.params.Z.valuePtr(),
@ -368,7 +337,7 @@ void ProtoNNPredictor::scoreSparseDataPoint(
RBF();
// mm(scoresMat, model.params.Z, CblasNoTrans, D, CblasTrans, 1.0, 0.0L);
#ifdef SPARSE_Z
#ifdef SPARSE_Z_PROTONN
cscmv(&transa,
&ZRows, &ZCols,
&alpha, matdescra, model.params.Z.valuePtr(),
@ -430,13 +399,13 @@ void ProtoNNPredictor::normalize()
}
}
ProtoNNPredictor::ResultStruct ProtoNNPredictor::test()
EdgeML::ResultStruct ProtoNNPredictor::test()
{
if(batchSize == 0) return testPointWise();
else return testBatchWise();
}
ProtoNNPredictor::ResultStruct ProtoNNPredictor::testBatchWise()
EdgeML::ResultStruct ProtoNNPredictor::testBatchWise()
{
dataCount_t n;
@ -446,14 +415,14 @@ ProtoNNPredictor::ResultStruct ProtoNNPredictor::testBatchWise()
dataCount_t nBatches = (n + batchSize - 1)/ batchSize;
ProtoNNPredictor::ResultStruct res, tempRes;
EdgeML::ResultStruct res, tempRes;
for (dataCount_t i = 0; i < nBatches; ++i) {
Eigen::Index startIdx = i * batchSize;
dataCount_t curBatchSize = (batchSize < n - startIdx)? batchSize : n - startIdx;
MatrixXuf Yscores = MatrixXuf::Zero(model.hyperParams.l, curBatchSize);
scoreBatch(Yscores, startIdx, curBatchSize);
tempRes = evaluate(Yscores, testData.Ytest.middleCols(startIdx, curBatchSize));
tempRes = evaluate(Yscores, testData.Ytest.middleCols(startIdx, curBatchSize), model.hyperParams.problemType);
res.scaleAndAdd(tempRes, curBatchSize);
}
@ -461,7 +430,7 @@ ProtoNNPredictor::ResultStruct ProtoNNPredictor::testBatchWise()
return res;
}
ProtoNNPredictor::ResultStruct ProtoNNPredictor::testPointWise()
EdgeML::ResultStruct ProtoNNPredictor::testPointWise()
{
dataCount_t n;
FP_TYPE *scores, *featureValues;
@ -473,14 +442,14 @@ ProtoNNPredictor::ResultStruct ProtoNNPredictor::testPointWise()
scores = new FP_TYPE[model.hyperParams.l];
Map<MatrixXuf> Yscores(scores, model.hyperParams.l, 1);
ProtoNNPredictor::ResultStruct res, tempRes;
EdgeML::ResultStruct res, tempRes;
for (dataCount_t i = 0; i < n; ++i) {
scoreSparseDataPoint(scores,
(const FP_TYPE*) testData.Xtest.valuePtr() + testData.Xtest.outerIndexPtr()[i],
(const featureCount_t*) testData.Xtest.innerIndexPtr() + testData.Xtest.outerIndexPtr()[i],
(featureCount_t) testData.Xtest.outerIndexPtr()[i + 1] - testData.Xtest.outerIndexPtr()[i]);
tempRes = evaluate(Yscores, testData.Ytest.middleCols(i, 1));
tempRes = evaluate(Yscores, testData.Ytest.middleCols(i, 1), model.hyperParams.problemType);
res.scaleAndAdd(tempRes, 1);
}
res.scale(1/(FP_TYPE)n);
@ -490,139 +459,20 @@ ProtoNNPredictor::ResultStruct ProtoNNPredictor::testPointWise()
return res;
}
// computes accuracy for binary/multiclass datasets, and prec1, prec3, prec5 for multilabel datasets
ProtoNNPredictor::ResultStruct ProtoNNPredictor::evaluate(
const MatrixXuf& Yscores,
const LabelMatType& Y)
{
assert(Yscores.cols() == Y.cols());
assert(Yscores.rows() == Y.rows());
MatrixXuf Ytrue(Y);
MatrixXuf Ypred = Yscores;
FP_TYPE acc = 0;
FP_TYPE prec1 = 0;
FP_TYPE prec3 = 0;
FP_TYPE prec5 = 0;
ProblemFormat problemType = model.hyperParams.problemType;
ProtoNNPredictor::ResultStruct res;
res.problemType = problemType;
if (problemType == EdgeML::ProblemFormat::binary || problemType == EdgeML::ProblemFormat::multiclass) {
dataCount_t Ytrue_, Ypred_;
for (Eigen::Index i = 0; i < Ytrue.cols(); ++i) {
Ytrue.col(i).maxCoeff(&Ytrue_);
Ypred.col(i).maxCoeff(&Ypred_);
if (Ytrue_ == Ypred_)
acc += 1;
}
assert(Y.cols() != 0);
res.accuracy = acc = safeDiv(acc, (FP_TYPE)Y.cols());
}
else if (problemType == EdgeML::ProblemFormat::multilabel) {
const labelCount_t k = 5;
assert(k * Ypred.cols() < 3e9);
std::vector<labelCount_t> topInd(k * Ypred.cols());
pfor(Eigen::Index i = 0; i < Ytrue.cols(); ++i) {
for (Eigen::Index j = 0; j < Ytrue.rows(); ++j) {
FP_TYPE val = Ypred(j, i);
if (j >= k && (val < Ypred(topInd[i*k + (k - 1)], i)))
continue;
size_t top = std::min(j, (Eigen::Index)k - 1);
while (top > 0 && (Ypred(topInd[i*k + (top - 1)], i) < val)) {
topInd[i*k + (top)] = topInd[i*k + (top - 1)];
top--;
}
topInd[i*k + top] = j;
}
}
assert(k >= 5);
for (Eigen::Index i = 0; i < Ytrue.cols(); ++i) {
for (labelCount_t j = 0; j < 1; ++j) {
if (Ytrue(topInd[i*k + j], i) == 1)
prec1++;
}
for (labelCount_t j = 0; j < 3; ++j) {
if (Ytrue(topInd[i*k + j], i) == 1)
prec3++;
}
for (labelCount_t j = 0; j < 5; ++j) {
if (Ytrue(topInd[i*k + j], i) == 1)
prec5++;
}
}
dataCount_t totalCount = Y.cols();
assert(totalCount != 0);
res.precision1 = (prec1 /= (FP_TYPE)totalCount);
res.precision3 = (prec3 /= ((FP_TYPE)totalCount)*3);
res.precision5 = (prec5 /= ((FP_TYPE)totalCount)*5);
}
return res;
}
void ProtoNNPredictor::getTopKScoresBatch(
const MatrixXuf& Yscores,
MatrixXuf& topKindices,
MatrixXuf& topKscores,
int k)
{
dataCount_t totalCount = Yscores.cols();
dataCount_t totalLabels = Yscores.rows();
if (k < 1)
k = 5;
if (totalLabels < k)
k = totalLabels;
topKindices = MatrixXuf::Zero(k, totalCount);
topKscores = MatrixXuf::Zero(k, totalCount);
pfor(Eigen::Index i = 0; i < Yscores.cols(); ++i) {
for (Eigen::Index j = 0; j < Yscores.rows(); ++j) {
FP_TYPE val = Yscores(j, i);
if (j >= k && (val < Yscores(topKindices(k-1, i), i)))
continue;
size_t top = std::min(j, (Eigen::Index)k - 1);
while (top > 0 && (Yscores(topKindices(top-1, i), i) < val)) {
topKindices(top, i) = topKindices(top - 1, i);
top--;
}
topKindices(top, i) = j;
}
}
pfor(Eigen::Index i = 0; i < topKindices.cols(); ++i)
for (Eigen::Index j = 0; j < topKindices.rows(); ++j)
topKscores(j, i) = Yscores(topKindices(j, i), i);
}
void ProtoNNPredictor::saveTopKScores(std::string filename, int topk)
{
dataCount_t tempBatchSize = batchSize;
if(tempBatchSize == 0) tempBatchSize = 1;
dataCount_t n;
n = testData.Xtest.cols();
const dataCount_t n = testData.Ytest.cols();
assert(n > 0);
if (topk < 1)
topk = 5;
if (filename.empty())
filename = outDir + "/detailedPrediction";
filename = outDir + "/detailedPrediction";
LOG_INFO("Attempting to open the following file for detailed prediction output: " + filename);
std::ofstream outfile(filename);
assert(outfile.is_open());
@ -636,7 +486,7 @@ void ProtoNNPredictor::saveTopKScores(std::string filename, int topk)
getTopKScoresBatch(Yscores, topKindices, topKscores, topk);
for (Eigen::Index j = 0; j < topKindices.cols(); j++) {
for (LabelMatType::InnerIterator it(testData.Ytest, i*tempBatchSize+j); it; ++it)
for (SparseMatrixuf::InnerIterator it(testData.Ytest, i*tempBatchSize+j); it; ++it)
outfile << it.row() << ", ";
for (Eigen::Index k = 0; k < topKindices.rows(); k++) {
outfile << topKindices(k, j) << ":" << topKscores(k, j) << " ";
@ -647,5 +497,3 @@ void ProtoNNPredictor::saveTopKScores(std::string filename, int topk)
outfile.close();
}

Просмотреть файл

@ -339,7 +339,7 @@ void ProtoNNTrainer::initializeModel()
for (labelCount_t i = 0; i < model.hyperParams.m; ++i) {
dataCount_t prot = rand() % data.Xtrain.cols();
model.params.B.col(i) = model.params.W * data.Xtrain.col(prot);
#ifdef SPARSE_Z
#ifdef SPARSE_Z_PROTONN
model.params.Z.col(i) = data.trainLabel.col(prot).sparseView();
#else
model.params.Z.col(i) = data.trainLabel.col(prot);
@ -353,7 +353,7 @@ void ProtoNNTrainer::initializeModel()
MatrixXuf WX = MatrixXuf::Zero(model.params.W.rows(), data.Xtrain.cols());
mm(WX, model.params.W, CblasNoTrans, data.Xtrain, CblasNoTrans, 1.0, 0.0L);
#ifdef SPARSE_Z
#ifdef SPARSE_Z_PROTONN
MatrixXuf Z = model.params.Z;
assert(model.params.B.cols() % data.Ytrain.rows() == 0);
kmeansLabelwise(data.Ytrain, WX, model.params.B, Z,
@ -379,7 +379,7 @@ void ProtoNNTrainer::initializeModel()
SparseMatrixuf YTrainSub(data.Ytrain.rows(), numRand);
randPick(WX, WXSub);
randPick(data.Ytrain, YTrainSub);
#ifdef SPARSE_Z
#ifdef SPARSE_Z_PROTONN
MatrixXuf Z = model.params.Z;
kmeansOverall(YTrainSub, WXSub, model.params.B, Z);
model.params.Z = Z.sparseView();
@ -388,7 +388,7 @@ void ProtoNNTrainer::initializeModel()
#endif
#else
#ifdef SPARSE_Z
#ifdef SPARSE_Z_PROTONN
MatrixXuf Z = model.params.Z;
kmeansOverall(data.Ytrain, WX, model.params.B, Z);
model.params.Z = Z.sparseView();

Просмотреть файл

@ -9,8 +9,10 @@ IFLAGS= -I ../../eigen/ -I$(MKL_ROOT)/include
COMMON_INCLUDES = logger.h timer.h \
blas_routines.h par_utils.h \
mmaped.h utils.h \
goldfoil.h Data.h
COMMON_OBJS = logger.o timer.o blas_routines.o par_utils.o mmaped.o utils.o goldfoil.o Data.o
goldfoil.h Data.h \
metrics.h
COMMON_OBJS = logger.o timer.o blas_routines.o par_utils.o mmaped.o utils.o goldfoil.o Data.o metrics.o
COMMON_LIB = ../../libcommon.so
@ -44,6 +46,9 @@ utils.o: utils.cpp $(COMMON_INCLUDES)
goldfoil.o: goldfoil.cpp $(COMMON_INCLUDES)
$(CC) -c -o $@ $(IFLAGS) $(CFLAGS) $<
metrics.o: metrics.cpp $(COMMON_INCLUDES)
$(CC) -c -o $@ $(IFLAGS) $(CFLAGS) $<
.PHONY: clean cleanest

154
src/common/metrics.cpp Normal file
Просмотреть файл

@ -0,0 +1,154 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
#include "metrics.h"
using namespace EdgeML;
EdgeML::ResultStruct::ResultStruct()
:
problemType(undefinedProblem),
accuracy(0),
precision1(0),
precision3(0),
precision5(0)
{}
void EdgeML::ResultStruct::scaleAndAdd(ResultStruct& results, FP_TYPE scale)
{
if ((problemType == undefinedProblem) && (results.problemType != undefinedProblem))
problemType = results.problemType;
assert(problemType == results.problemType);
accuracy += scale * results.accuracy;
precision1 += scale * results.precision1;
precision3 += scale * results.precision3;
precision5 += scale * results.precision5;
}
void EdgeML::ResultStruct::scale(FP_TYPE scale)
{
accuracy *= scale;
precision1 *= scale;
precision3 *= scale;
precision5 *= scale;
}
// computes accuracy for binary/multiclass datasets, and prec1, prec3, prec5 for multilabel datasets
EdgeML::ResultStruct EdgeML::evaluate(
const MatrixXuf& Yscores,
const SparseMatrixuf& Y,
const ProblemFormat problemType)
{
assert(Yscores.cols() == Y.cols());
assert(Yscores.rows() == Y.rows());
MatrixXuf Ytrue(Y);
MatrixXuf Ypred = Yscores;
FP_TYPE acc = 0;
FP_TYPE prec1 = 0;
FP_TYPE prec3 = 0;
FP_TYPE prec5 = 0;
EdgeML::ResultStruct res;
res.problemType = problemType;
if (problemType == EdgeML::ProblemFormat::binary || problemType == EdgeML::ProblemFormat::multiclass) {
dataCount_t Ytrue_, Ypred_;
for (Eigen::Index i = 0; i < Ytrue.cols(); ++i) {
Ytrue.col(i).maxCoeff(&Ytrue_);
Ypred.col(i).maxCoeff(&Ypred_);
if (Ytrue_ == Ypred_)
acc += 1;
}
assert(Y.cols() != 0);
res.accuracy = acc = safeDiv(acc, (FP_TYPE)Y.cols());
}
else if (problemType == EdgeML::ProblemFormat::multilabel) {
const labelCount_t k = 5;
assert(k * Ypred.cols() < 3e9);
std::vector<labelCount_t> topInd(k * Ypred.cols());
pfor(Eigen::Index i = 0; i < Ytrue.cols(); ++i) {
for (Eigen::Index j = 0; j < Ytrue.rows(); ++j) {
FP_TYPE val = Ypred(j, i);
if (j >= k && (val < Ypred(topInd[i*k + (k - 1)], i)))
continue;
size_t top = std::min(j, (Eigen::Index)k - 1);
while (top > 0 && (Ypred(topInd[i*k + (top - 1)], i) < val)) {
topInd[i*k + (top)] = topInd[i*k + (top - 1)];
top--;
}
topInd[i*k + top] = j;
}
}
assert(k >= 5);
for (Eigen::Index i = 0; i < Ytrue.cols(); ++i) {
for (labelCount_t j = 0; j < 1; ++j) {
if (Ytrue(topInd[i*k + j], i) == 1)
prec1++;
}
for (labelCount_t j = 0; j < 3; ++j) {
if (Ytrue(topInd[i*k + j], i) == 1)
prec3++;
}
for (labelCount_t j = 0; j < 5; ++j) {
if (Ytrue(topInd[i*k + j], i) == 1)
prec5++;
}
}
dataCount_t totalCount = Y.cols();
assert(totalCount != 0);
res.precision1 = (prec1 /= (FP_TYPE)totalCount);
res.precision3 = (prec3 /= ((FP_TYPE)totalCount)*3);
res.precision5 = (prec5 /= ((FP_TYPE)totalCount)*5);
}
return res;
}
void EdgeML::getTopKScoresBatch(
const MatrixXuf& Yscores,
MatrixXuf& topKindices,
MatrixXuf& topKscores,
int k)
{
dataCount_t totalCount = Yscores.cols();
dataCount_t totalLabels = Yscores.rows();
if (k < 1)
k = 5;
if (totalLabels < k)
k = totalLabels;
topKindices = MatrixXuf::Zero(k, totalCount);
topKscores = MatrixXuf::Zero(k, totalCount);
pfor(Eigen::Index i = 0; i < Yscores.cols(); ++i) {
for (Eigen::Index j = 0; j < Yscores.rows(); ++j) {
FP_TYPE val = Yscores(j, i);
if (j >= k && (val < Yscores(topKindices(k-1, i), i)))
continue;
size_t top = std::min(j, (Eigen::Index)k - 1);
while (top > 0 && (Yscores(topKindices(top-1, i), i) < val)) {
topKindices(top, i) = topKindices(top - 1, i);
top--;
}
topKindices(top, i) = j;
}
}
pfor(Eigen::Index i = 0; i < topKindices.cols(); ++i)
for (Eigen::Index j = 0; j < topKindices.rows(); ++j)
topKscores(j, i) = Yscores(topKindices(j, i), i);
}

38
src/common/metrics.h Normal file
Просмотреть файл

@ -0,0 +1,38 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
#ifndef __METRICS_H__
#define __METRICS_H__
#include "Data.h"
#include "utils.h"
namespace EdgeML
{
struct ResultStruct {
ProblemFormat problemType;
FP_TYPE accuracy;
FP_TYPE precision1;
FP_TYPE precision3;
FP_TYPE precision5;
ResultStruct();
void scaleAndAdd(ResultStruct& a, FP_TYPE scale);
void scale(FP_TYPE scale);
};
ResultStruct evaluate(
const MatrixXuf& Yscores,
const SparseMatrixuf& Y,
const ProblemFormat problemType);
void getTopKScoresBatch(
const MatrixXuf& Yscores,
MatrixXuf& topKIndices,
MatrixXuf& topKScores,
int k = 5);
};
#endif