mirror of
https://github.com/opencv/opencv.git
synced 2024-11-27 20:50:25 +08:00
Merge remote-tracking branch 'upstream/3.4' into merge-3.4
This commit is contained in:
commit
5c76f99fdd
@ -184,21 +184,9 @@ public:
|
||||
computeStrides(shape(inputs[0]), shape(outputs[0]));
|
||||
|
||||
#ifdef HAVE_OPENCL
|
||||
if (uorder.empty())
|
||||
{
|
||||
std::vector<int> orderVec(_order.begin(), _order.end());;
|
||||
Mat morder(1, orderVec.size(), CV_32SC1, &orderVec[0]);
|
||||
|
||||
std::vector<int> oldStrideVec(_oldStride.begin(), _oldStride.end());
|
||||
Mat mold_stride(1, _oldStride.size(), CV_32SC1, &oldStrideVec[0]);
|
||||
|
||||
std::vector<int> newStrideVec(_newStride.begin(), _newStride.end());
|
||||
Mat mnew_stride(1, newStrideVec.size(), CV_32SC1, &newStrideVec[0]);
|
||||
|
||||
morder.copyTo(uorder);
|
||||
mold_stride.copyTo(uold_stride);
|
||||
mnew_stride.copyTo(unew_stride);
|
||||
}
|
||||
uorder.release();
|
||||
uold_stride.release();
|
||||
unew_stride.release();
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -286,6 +274,22 @@ public:
|
||||
if (!_needsPermute)
|
||||
return false;
|
||||
|
||||
if (uorder.empty())
|
||||
{
|
||||
std::vector<int> orderVec(_order.begin(), _order.end());;
|
||||
Mat morder(1, orderVec.size(), CV_32SC1, &orderVec[0]);
|
||||
|
||||
std::vector<int> oldStrideVec(_oldStride.begin(), _oldStride.end());
|
||||
Mat mold_stride(1, _oldStride.size(), CV_32SC1, &oldStrideVec[0]);
|
||||
|
||||
std::vector<int> newStrideVec(_newStride.begin(), _newStride.end());
|
||||
Mat mnew_stride(1, newStrideVec.size(), CV_32SC1, &newStrideVec[0]);
|
||||
|
||||
morder.copyTo(uorder);
|
||||
mold_stride.copyTo(uold_stride);
|
||||
mnew_stride.copyTo(unew_stride);
|
||||
}
|
||||
|
||||
bool use_half = (inps.depth() == CV_16S);
|
||||
String opts = format("-DDtype=%s", use_half ? "half" : "float");
|
||||
for (size_t i = 0; i < inputs.size(); i++)
|
||||
|
@ -335,6 +335,10 @@ void ONNXImporter::populateNet(Net dstNet)
|
||||
{
|
||||
inpShape[j] = tensorShape.dim(j).dim_value();
|
||||
}
|
||||
if (!inpShape.empty())
|
||||
{
|
||||
inpShape[0] = std::max(inpShape[0], 1); // It's OK to have undetermined batch size
|
||||
}
|
||||
outShapes[valueInfoProto.name()] = inpShape;
|
||||
}
|
||||
|
||||
|
@ -2388,7 +2388,7 @@ TEST_P(ConvolutionEltwiseActivationFusion, Accuracy)
|
||||
if (eltwiseOp != "sum" && weightedEltwise)
|
||||
throw SkipTestException("weighted eltwise not supported");
|
||||
LayerParams eltwiseParams;
|
||||
TestLayerFusion::makeDefaultTestEltwiseLayer(eltwiseParams, eltwiseOp, false);
|
||||
TestLayerFusion::makeDefaultTestEltwiseLayer(eltwiseParams, eltwiseOp, weightedEltwise);
|
||||
|
||||
std::string actType = get<3>(GetParam());
|
||||
LayerParams activationParams;
|
||||
@ -2398,7 +2398,7 @@ TEST_P(ConvolutionEltwiseActivationFusion, Accuracy)
|
||||
Target targetId = get<1>(get<4>(GetParam()));
|
||||
|
||||
// bug: https://github.com/opencv/opencv/issues/17945
|
||||
if (eltwiseOp != "sum" && backendId == DNN_BACKEND_OPENCV && (targetId == DNN_TARGET_OPENCL || targetId == DNN_TARGET_OPENCL_FP16))
|
||||
if ((eltwiseOp != "sum" || weightedEltwise) && backendId == DNN_BACKEND_OPENCV && (targetId == DNN_TARGET_OPENCL || targetId == DNN_TARGET_OPENCL_FP16))
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_OPENCL);
|
||||
|
||||
// bug: https://github.com/opencv/opencv/issues/17953
|
||||
@ -2485,7 +2485,7 @@ TEST_P(ConvolutionActivationEltwiseFusion, Accuracy)
|
||||
if (eltwiseOp != "sum" && weightedEltwise)
|
||||
throw SkipTestException("weighted eltwise not supported");
|
||||
LayerParams eltwiseParams;
|
||||
TestLayerFusion::makeDefaultTestEltwiseLayer(eltwiseParams, eltwiseOp, false);
|
||||
TestLayerFusion::makeDefaultTestEltwiseLayer(eltwiseParams, eltwiseOp, weightedEltwise);
|
||||
|
||||
Backend backendId = get<0>(get<4>(GetParam()));
|
||||
Target targetId = get<1>(get<4>(GetParam()));
|
||||
|
@ -1294,6 +1294,15 @@ public:
|
||||
*/
|
||||
CV_WRAP virtual void getVotes(InputArray samples, OutputArray results, int flags) const = 0;
|
||||
|
||||
/** Returns the OOB error value, computed at the training stage when calcOOBError is set to true.
|
||||
* If this flag was set to false, 0 is returned. The OOB error is also scaled by sample weighting.
|
||||
*/
|
||||
#if CV_VERSION_MAJOR == 4
|
||||
CV_WRAP virtual double getOOBError() const { return 0; }
|
||||
#else
|
||||
/*CV_WRAP*/ virtual double getOOBError() const = 0;
|
||||
#endif
|
||||
|
||||
/** Creates the empty model.
|
||||
Use StatModel::train to train the model, StatModel::train to create and train the model,
|
||||
Algorithm::load to load the pre-trained model.
|
||||
|
@ -101,7 +101,7 @@ medianPartition( size_t* ofs, int a, int b, const float* vals )
|
||||
int i0 = a, i1 = (a+b)/2, i2 = b;
|
||||
float v0 = vals[ofs[i0]], v1 = vals[ofs[i1]], v2 = vals[ofs[i2]];
|
||||
int ip = v0 < v1 ? (v1 < v2 ? i1 : v0 < v2 ? i2 : i0) :
|
||||
v0 < v2 ? i0 : (v1 < v2 ? i2 : i1);
|
||||
v0 < v2 ? (v1 == v0 ? i2 : i0): (v1 < v2 ? i2 : i1);
|
||||
float pivot = vals[ofs[ip]];
|
||||
std::swap(ofs[ip], ofs[i2]);
|
||||
|
||||
@ -131,7 +131,6 @@ medianPartition( size_t* ofs, int a, int b, const float* vals )
|
||||
CV_Assert(vals[ofs[k]] >= pivot);
|
||||
more += vals[ofs[k]] > pivot;
|
||||
}
|
||||
CV_Assert(std::abs(more - less) <= 1);
|
||||
|
||||
return vals[ofs[middle]];
|
||||
}
|
||||
|
@ -381,36 +381,23 @@ public:
|
||||
Mat res, nr, d;
|
||||
if( _results.needed() )
|
||||
{
|
||||
_results.create(testcount, 1, CV_32F);
|
||||
res = _results.getMat();
|
||||
}
|
||||
if( _neighborResponses.needed() )
|
||||
{
|
||||
_neighborResponses.create(testcount, k, CV_32F);
|
||||
nr = _neighborResponses.getMat();
|
||||
}
|
||||
if( _dists.needed() )
|
||||
{
|
||||
_dists.create(testcount, k, CV_32F);
|
||||
d = _dists.getMat();
|
||||
}
|
||||
|
||||
for (int i=0; i<test_samples.rows; ++i)
|
||||
{
|
||||
Mat _res, _nr, _d;
|
||||
if (res.rows>i)
|
||||
{
|
||||
_res = res.row(i);
|
||||
}
|
||||
if (nr.rows>i)
|
||||
{
|
||||
_nr = nr.row(i);
|
||||
}
|
||||
if (d.rows>i)
|
||||
{
|
||||
_d = d.row(i);
|
||||
}
|
||||
tr.findNearest(test_samples.row(i), k, Emax, _res, _nr, _d, noArray());
|
||||
res.push_back(_res.t());
|
||||
_results.assign(res);
|
||||
}
|
||||
|
||||
return result; // currently always 0
|
||||
|
@ -216,13 +216,14 @@ public:
|
||||
sample = Mat( nallvars, 1, CV_32F, psamples + sstep0*w->sidx[j], sstep1*sizeof(psamples[0]) );
|
||||
|
||||
double val = predictTrees(Range(treeidx, treeidx+1), sample, predictFlags);
|
||||
double sample_weight = w->sample_weights[w->sidx[j]];
|
||||
if( !_isClassifier )
|
||||
{
|
||||
oobres[j] += val;
|
||||
oobcount[j]++;
|
||||
double true_val = w->ord_responses[w->sidx[j]];
|
||||
double a = oobres[j]/oobcount[j] - true_val;
|
||||
oobError += a*a;
|
||||
oobError += sample_weight * a*a;
|
||||
val = (val - true_val)/max_response;
|
||||
ncorrect_responses += std::exp( -val*val );
|
||||
}
|
||||
@ -237,7 +238,7 @@ public:
|
||||
if( votes[best_class] < votes[k] )
|
||||
best_class = k;
|
||||
int diff = best_class != w->cat_responses[w->sidx[j]];
|
||||
oobError += diff;
|
||||
oobError += sample_weight * diff;
|
||||
ncorrect_responses += diff == 0;
|
||||
}
|
||||
}
|
||||
@ -421,6 +422,10 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
double getOOBError() const {
|
||||
return oobError;
|
||||
}
|
||||
|
||||
RTreeParams rparams;
|
||||
double oobError;
|
||||
vector<float> varImportance;
|
||||
@ -500,6 +505,8 @@ public:
|
||||
const vector<Node>& getNodes() const CV_OVERRIDE { return impl.getNodes(); }
|
||||
const vector<Split>& getSplits() const CV_OVERRIDE { return impl.getSplits(); }
|
||||
const vector<int>& getSubsets() const CV_OVERRIDE { return impl.getSubsets(); }
|
||||
double getOOBError() const CV_OVERRIDE { return impl.getOOBError(); }
|
||||
|
||||
|
||||
DTreesImplForRTrees impl;
|
||||
};
|
||||
|
@ -37,18 +37,31 @@ TEST(ML_KNearest, accuracy)
|
||||
EXPECT_LE(err, 0.01f);
|
||||
}
|
||||
{
|
||||
// TODO: broken
|
||||
#if 0
|
||||
SCOPED_TRACE("KDTree");
|
||||
Mat bestLabels;
|
||||
Mat neighborIndexes;
|
||||
float err = 1000;
|
||||
Ptr<KNearest> knn = KNearest::create();
|
||||
knn->setAlgorithmType(KNearest::KDTREE);
|
||||
knn->train(trainData, ml::ROW_SAMPLE, trainLabels);
|
||||
knn->findNearest(testData, 4, bestLabels);
|
||||
knn->findNearest(testData, 4, neighborIndexes);
|
||||
Mat bestLabels;
|
||||
// The output of the KDTree are the neighbor indexes, not actual class labels
|
||||
// so we need to do some extra work to get actual predictions
|
||||
for(int row_num = 0; row_num < neighborIndexes.rows; ++row_num){
|
||||
vector<float> labels;
|
||||
for(int index = 0; index < neighborIndexes.row(row_num).cols; ++index) {
|
||||
labels.push_back(trainLabels.at<float>(neighborIndexes.row(row_num).at<int>(0, index) , 0));
|
||||
}
|
||||
// computing the mode of the output class predictions to determine overall prediction
|
||||
std::vector<int> histogram(3,0);
|
||||
for( int i=0; i<3; ++i )
|
||||
++histogram[ static_cast<int>(labels[i]) ];
|
||||
int bestLabel = static_cast<int>(std::max_element( histogram.begin(), histogram.end() ) - histogram.begin());
|
||||
bestLabels.push_back(bestLabel);
|
||||
}
|
||||
bestLabels.convertTo(bestLabels, testLabels.type());
|
||||
EXPECT_TRUE(calcErr( bestLabels, testLabels, sizes, err, true ));
|
||||
EXPECT_LE(err, 0.01f);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@ -74,4 +87,26 @@ TEST(ML_KNearest, regression_12347)
|
||||
EXPECT_EQ(2, zBestLabels.at<float>(1,0));
|
||||
}
|
||||
|
||||
TEST(ML_KNearest, bug_11877)
|
||||
{
|
||||
Mat trainData = (Mat_<float>(5,2) << 3, 3, 3, 3, 4, 4, 4, 4, 4, 4);
|
||||
Mat trainLabels = (Mat_<float>(5,1) << 0, 0, 1, 1, 1);
|
||||
|
||||
Ptr<KNearest> knnKdt = KNearest::create();
|
||||
knnKdt->setAlgorithmType(KNearest::KDTREE);
|
||||
knnKdt->setIsClassifier(true);
|
||||
|
||||
knnKdt->train(trainData, ml::ROW_SAMPLE, trainLabels);
|
||||
|
||||
Mat testData = (Mat_<float>(2,2) << 3.1, 3.1, 4, 4.1);
|
||||
Mat testLabels = (Mat_<int>(2,1) << 0, 1);
|
||||
Mat result;
|
||||
|
||||
knnKdt->findNearest(testData, 1, result);
|
||||
|
||||
EXPECT_EQ(1, int(result.at<int>(0, 0)));
|
||||
EXPECT_EQ(2, int(result.at<int>(1, 0)));
|
||||
EXPECT_EQ(0, trainLabels.at<int>(result.at<int>(0, 0), 0));
|
||||
}
|
||||
|
||||
}} // namespace
|
||||
|
@ -51,4 +51,50 @@ TEST(ML_RTrees, getVotes)
|
||||
EXPECT_EQ(result.at<float>(0, predicted_class), rt->predict(test));
|
||||
}
|
||||
|
||||
TEST(ML_RTrees, 11142_sample_weights_regression)
|
||||
{
|
||||
int n = 3;
|
||||
// RTrees for regression
|
||||
Ptr<ml::RTrees> rt = cv::ml::RTrees::create();
|
||||
//simple regression problem of x -> 2x
|
||||
Mat data = (Mat_<float>(n,1) << 1, 2, 3);
|
||||
Mat values = (Mat_<float>(n,1) << 2, 4, 6);
|
||||
Mat weights = (Mat_<float>(n, 1) << 10, 10, 10);
|
||||
|
||||
Ptr<TrainData> trainData = TrainData::create(data, ml::ROW_SAMPLE, values);
|
||||
rt->train(trainData);
|
||||
double error_without_weights = round(rt->getOOBError());
|
||||
rt->clear();
|
||||
Ptr<TrainData> trainDataWithWeights = TrainData::create(data, ml::ROW_SAMPLE, values, Mat(), Mat(), weights );
|
||||
rt->train(trainDataWithWeights);
|
||||
double error_with_weights = round(rt->getOOBError());
|
||||
// error with weights should be larger than error without weights
|
||||
EXPECT_GE(error_with_weights, error_without_weights);
|
||||
}
|
||||
|
||||
TEST(ML_RTrees, 11142_sample_weights_classification)
|
||||
{
|
||||
int n = 12;
|
||||
// RTrees for classification
|
||||
Ptr<ml::RTrees> rt = cv::ml::RTrees::create();
|
||||
|
||||
Mat data(n, 4, CV_32F);
|
||||
randu(data, 0, 10);
|
||||
Mat labels = (Mat_<int>(n,1) << 0,0,0,0, 1,1,1,1, 2,2,2,2);
|
||||
Mat weights = (Mat_<float>(n, 1) << 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10);
|
||||
|
||||
rt->train(data, ml::ROW_SAMPLE, labels);
|
||||
rt->clear();
|
||||
double error_without_weights = round(rt->getOOBError());
|
||||
Ptr<TrainData> trainDataWithWeights = TrainData::create(data, ml::ROW_SAMPLE, labels, Mat(), Mat(), weights );
|
||||
rt->train(data, ml::ROW_SAMPLE, labels);
|
||||
double error_with_weights = round(rt->getOOBError());
|
||||
std::cout << error_without_weights << std::endl;
|
||||
std::cout << error_with_weights << std::endl;
|
||||
// error with weights should be larger than error without weights
|
||||
EXPECT_GE(error_with_weights, error_without_weights);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}} // namespace
|
||||
|
Loading…
Reference in New Issue
Block a user