// virtual GMatrix* GGraphCutTransducer::transduceInner(const GMatrix& features1, const GMatrix& labels1, const GMatrix& features2) { // Use k-NN to compute a distance metric with good scale factors for prediction GKNN knn; knn.setNeighborCount(m_neighborCount); //knn.setOptimizeScaleFactors(true); knn.train(features1, labels1); GRowDistanceScaled* pMetric = knn.metric(); // Merge the features into one dataset and build a kd-tree GMatrix both(features1.relation().clone()); GReleaseDataHolder hBoth(&both); both.reserve(features1.rows() + features2.rows()); for(size_t i = 0; i < features1.rows(); i++) both.takeRow((double*)features1[i]); for(size_t i = 0; i < features2.rows(); i++) both.takeRow((double*)features2[i]); GRowDistanceScaled metric2; GKdTree neighborFinder(&both, m_neighborCount, &metric2, false); GVec::copy(metric2.scaleFactors(), pMetric->scaleFactors(), features1.cols()); // Transduce GMatrix* pOut = new GMatrix(labels1.relation().clone()); Holder<GMatrix> hOut(pOut); pOut->newRows(features2.rows()); pOut->setAll(0); for(size_t lab = 0; lab < labels1.cols(); lab++) { // Use max-flow/min-cut graph-cut to separate out each label value int valueCount = (int)labels1.relation().valueCount(lab); for(int val = 1; val < valueCount; val++) { // Add neighborhood edges GGraphCut gc(features1.rows() + features2.rows() + 2); for(size_t i = 0; i < both.rows(); i++) { neighborFinder.neighbors(m_pNeighbors, m_pDistances, i); for(size_t j = 0; j < m_neighborCount; j++) { if(m_pNeighbors[j] >= both.rows()) continue; gc.addEdge(2 + i, 2 + m_pNeighbors[j], (float)(1.0 / std::max(sqrt(m_pDistances[j]), 1e-9))); // connect neighbors } } // Add source and sink edges for(size_t i = 0; i < features1.rows(); i++) { if((int)labels1[i][0] == val) gc.addEdge(0, 2 + i, 1e12f); // connect to source else gc.addEdge(1, 2 + i, 1e12f); // connect to sink } // Cut gc.cut(0, 1); // Label the unlabeled rows for(size_t i = 0; i < features2.rows(); i++) { if(gc.isSource(2 + features1.rows() + i)) pOut->row(i)[lab] = (double)val; } } } return hOut.release(); }
virtual void initVector(double* pVector) { GRowDistanceScaled* pMetric = m_pLearner->metric(); GVec::copy(pVector, pMetric->scaleFactors(), relation()->size()); }