void CBayesLearningEngine::Learn() { if(!m_pGrModel) { PNL_THROW( CNULLPointer, "no graphical model") } CStaticGraphicalModel *grmodel = this->GetStaticModel(); CFactor *factor = NULL; int numberOfFactors = grmodel->GetNumberOfFactors(); int domainNodes; if(m_numberOfLearnedEvidences == m_numberOfAllEvidences) { PNL_THROW(COutOfRange, "number of unlearned evidences must be positive") } int currentEvidNumber; const CEvidence* pCurrentEvid; //below code is intended to work on tabular CPD and gaussian CPD //later we will generalize it for other distribution types if ((grmodel->GetFactor(0))->GetDistributionType() == dtTabular) { for( int ev = m_numberOfLearnedEvidences; ev < m_numberOfAllEvidences; ev++) { currentEvidNumber = ev; pCurrentEvid = m_Vector_pEvidences[currentEvidNumber]; if( !pCurrentEvid) { PNL_THROW(CNULLPointer, "evidence") } for( domainNodes = 0; domainNodes < numberOfFactors; domainNodes++ ) { factor = grmodel->GetFactor( domainNodes ); int DomainSize; const int *domain; factor->GetDomain( &DomainSize, &domain ); const CEvidence *pEvidences[] = { pCurrentEvid }; CTabularDistribFun* pDistribFun = (CTabularDistribFun*)(factor->GetDistribFun()); pDistribFun->BayesUpdateFactor(pEvidences, 1, domain); } } } else { for( domainNodes = 0; domainNodes < numberOfFactors; domainNodes++ )
void CParEMLearningEngine::Learn() { CStaticGraphicalModel *pGrModel = this->GetStaticModel(); PNL_CHECK_IS_NULL_POINTER(pGrModel); PNL_CHECK_LEFT_BORDER(GetNumEv() - GetNumberProcEv() , 1); CJtreeInfEngine *pCurrentInfEng = NULL; CFactor *parameter = NULL; int exit = 0; int numberOfParameters = pGrModel->GetNumberOfParameters(); int domainNodes; int infIsNeed = 0; int itsML = 0; // !!! float loglik = -FLT_MAX; float loglikOld = -FLT_MAX; float epsilon = GetPrecisionEM(); float stopExpression = epsilon + 1.0f; int iteration = 0; int currentEvidNumber; int bMaximize = 0; int bSumOnMixtureNode = 0; const CEvidence* pCurrentEvid; int start_mpi, finish_mpi; int NumberOfProcesses, MyRank; int numSelfEvidences; MPI_Comm_size(MPI_COMM_WORLD, &NumberOfProcesses); MPI_Comm_rank(MPI_COMM_WORLD, &MyRank); int d = 0; do { iteration++; numSelfEvidences = (GetNumEv() - GetNumberProcEv()) / NumberOfProcesses; start_mpi = GetNumberProcEv() + numSelfEvidences * MyRank; // !!! if (MyRank < NumberOfProcesses - 1) finish_mpi = start_mpi + numSelfEvidences; // !!! else finish_mpi = GetNumEv(); // !!! for(int ev = start_mpi; ev < finish_mpi; ev++) { infIsNeed = 0; currentEvidNumber = ev; // !!! pCurrentEvid = m_Vector_pEvidences[currentEvidNumber]; if( !pCurrentEvid) { PNL_THROW(CNULLPointer, "evidence") } infIsNeed = !GetObsFlags(ev)->empty(); // !!! if(infIsNeed) { // create inference engine if(!pCurrentInfEng) { pCurrentInfEng = CJtreeInfEngine::Create(pGrModel); } pCurrentInfEng->EnterEvidence(pCurrentEvid, bMaximize, bSumOnMixtureNode); } for(domainNodes = 0; domainNodes < numberOfParameters; domainNodes++) { parameter = pGrModel->GetFactor(domainNodes); if(infIsNeed) { int DomainSize; const int *domain; parameter->GetDomain(&DomainSize, &domain); if (IsDomainObserved(DomainSize, domain, currentEvidNumber)) { const CEvidence *pEvidences[] = { pCurrentEvid }; parameter->UpdateStatisticsML(pEvidences, 1); } else { pCurrentInfEng->MarginalNodes(domain, DomainSize, 1); const CPotential * pMargPot = pCurrentInfEng->GetQueryJPD(); parameter ->UpdateStatisticsEM(pMargPot, pCurrentEvid); } } else { const CEvidence *pEvidences[] = { pCurrentEvid }; parameter->UpdateStatisticsML(pEvidences, 1); } } itsML = itsML || !infIsNeed; } for(domainNodes = 0; domainNodes < numberOfParameters; domainNodes++ ) { parameter = pGrModel->GetFactor(domainNodes); CNumericDenseMatrix<float> *matForSending; int matDim; const int *pMatRanges; int dataLength; const float *pDataForSending; matForSending = static_cast<CNumericDenseMatrix<float>*> ((parameter->GetDistribFun())->GetStatisticalMatrix(stMatTable)); matForSending->GetRanges(&matDim, &pMatRanges); matForSending->GetRawData(&dataLength, &pDataForSending); float *pDataRecv = new float[dataLength]; float *pDataRecv_copy = new float[dataLength]; MPI_Status status; MPI_Allreduce((void*)pDataForSending, pDataRecv, dataLength, MPI_FLOAT, MPI_SUM, MPI_COMM_WORLD); CNumericDenseMatrix<float> *RecvMatrix = static_cast<CNumericDenseMatrix<float>*> (parameter->GetDistribFun()->GetStatisticalMatrix(stMatTable)); int dataLength_new; float *pData_new; RecvMatrix->GetRawData(&dataLength_new, (const float**)(&pData_new)); for(int t=0;t<dataLength_new;t++) pData_new[t]=pDataRecv[t]; } switch (pGrModel->GetModelType()) { case mtBNet: { loglikOld = loglik; loglik = 0.0f; for(domainNodes = 0; domainNodes < numberOfParameters; domainNodes++) { parameter = pGrModel->GetFactor(domainNodes); loglik += parameter->ProcessingStatisticalData(m_numberOfAllEvidences); } break; } case mtMRF2: case mtMNet: { loglikOld = loglik; loglik = _LearnPotentials(); break; } default: { PNL_THROW(CBadConst, "model type") break; } } stopExpression = float(fabs(2 * (loglikOld - loglik) / (loglikOld + loglik))); exit = ((stopExpression > epsilon) && (iteration <= GetMaxIterEM())) && !itsML; if(exit) { ClearStatisticData(); } delete pCurrentInfEng; pCurrentInfEng = NULL; }while(exit); if(iteration > GetMaxIterEM()) { PNL_THROW(CNotConverged, "maximum number of iterations") } SetNumProcEv( GetNumEv() ); }
void CParEMLearningEngine::LearnContMPI() { CStaticGraphicalModel *pGrModel = this->GetStaticModel(); PNL_CHECK_IS_NULL_POINTER(pGrModel); PNL_CHECK_LEFT_BORDER(GetNumEv() - GetNumberProcEv() , 1); CInfEngine *pInfEng = NULL; pInfEng = CJtreeInfEngine::Create(pGrModel); float loglik = 0.0f; int domainNodes; CFactor *parameter = NULL; int numberOfParameters = pGrModel->GetNumberOfParameters(); int nFactors = pGrModel->GetNumberOfFactors(); const CEvidence *pEv; CFactor *pFactor; int iteration = 0; int ev; int i,numSelfEvidences,NumberOfProcesses, MyRank; int start_mpi, finish_mpi; MPI_Comm_size(MPI_COMM_WORLD, &NumberOfProcesses); MPI_Comm_rank(MPI_COMM_WORLD, &MyRank); if (IsAllObserved()) { int i; float **evid = NULL; EDistributionType dt; CFactor *factor = NULL; for (i = 0; i < nFactors; i++) { factor = pGrModel->GetFactor(i); factor->UpdateStatisticsML(&m_Vector_pEvidences[GetNumberProcEv()], GetNumEv() - GetNumberProcEv()); } m_critValue.push_back(UpdateModel()); } else { bool bContinue; const CPotential * pot; do { ClearStatisticData(); iteration++; numSelfEvidences = (GetNumEv() - GetNumberProcEv()) / NumberOfProcesses; start_mpi = GetNumberProcEv() + numSelfEvidences * MyRank; if (MyRank < NumberOfProcesses - 1) finish_mpi = start_mpi + numSelfEvidences; else finish_mpi = GetNumEv(); for(int ev = start_mpi; ev < finish_mpi; ev++) { bool bInfIsNeed = !GetObsFlags(ev)->empty(); pEv = m_Vector_pEvidences[ev]; if( bInfIsNeed ) { pInfEng->EnterEvidence(pEv, 0, 0); } int i; for( i = 0; i < nFactors; i++ ) { pFactor = pGrModel->GetFactor(i); int nnodes; const int * domain; pFactor->GetDomain( &nnodes, &domain ); if( bInfIsNeed && !IsDomainObserved(nnodes, domain, ev ) ) { pInfEng->MarginalNodes( domain, nnodes, 1 ); pot = pInfEng->GetQueryJPD(); pFactor->UpdateStatisticsEM( /*pInfEng->GetQueryJPD */ pot, pEv ); } else { pFactor->UpdateStatisticsML( &pEv, 1 ); } } } for(domainNodes = 0; domainNodes < numberOfParameters; domainNodes++ ) { parameter = pGrModel->GetFactor(domainNodes); C2DNumericDenseMatrix<float> *matMeanForSending; C2DNumericDenseMatrix<float> *matCovForSending; int dataLengthM,dataLengthC; const float *pMeanDataForSending; const float *pCovDataForSending; matMeanForSending = static_cast<C2DNumericDenseMatrix<float>*> ((parameter->GetDistribFun())->GetStatisticalMatrix(stMatMu)); matMeanForSending->GetRawData(&dataLengthM, &pMeanDataForSending); matCovForSending = static_cast<C2DNumericDenseMatrix<float>*> ((parameter->GetDistribFun())->GetStatisticalMatrix(stMatSigma)); matCovForSending->GetRawData(&dataLengthC, &pCovDataForSending); float *pMeanDataRecv = new float[dataLengthM]; float *pCovDataRecv = new float[dataLengthC]; MPI_Status status; MPI_Allreduce((void*)pMeanDataForSending, pMeanDataRecv, dataLengthM, MPI_FLOAT, MPI_SUM, MPI_COMM_WORLD); MPI_Allreduce((void*)pCovDataForSending, pCovDataRecv, dataLengthC, MPI_FLOAT, MPI_SUM, MPI_COMM_WORLD); memcpy((void*)pMeanDataForSending,pMeanDataRecv,dataLengthM*sizeof(float)); memcpy((void*)pCovDataForSending,pCovDataRecv,dataLengthC*sizeof(float)); } loglik = UpdateModel(); if( GetMaxIterEM() != 1) { bool flag = iteration == 1 ? true : (fabs(2*(m_critValue.back()-loglik)/(m_critValue.back() + loglik)) > GetPrecisionEM() ); bContinue = GetMaxIterEM() > iteration && flag; } else { bContinue = false; } m_critValue.push_back(loglik); }while(bContinue); } SetNumProcEv( GetNumEv() ); }
CExInfEngine< INF_ENGINE, MODEL, FLAV, FALLBACK_ENGINE1, FALLBACK_ENGINE2 >::CExInfEngine( CStaticGraphicalModel const *gm ) : CInfEngine( itEx, gm ), evidence_mine( false ), maximize( 0 ), MPE_ev( 0 ), query_JPD( 0 ), graphical_model( gm ) { int i, j, k; intVector dom; intVector conv; CFactor *fac; PNL_MAKE_LOCAL( CGraph *, gr, gm, GetGraph() ); PNL_MAKE_LOCAL( int, sz, gr, GetNumberOfNodes() ); gr->GetConnectivityComponents( &decomposition ); for ( i = decomposition.size(); i--; ) { std::sort( decomposition[i].begin(), decomposition[i].end() ); } if ( PNL_IS_EXINFENGINEFLAVOUR_UNSORTED( FLAV ) ) { gr->GetTopologicalOrder( &conv ); } orig2comp.resize( sz ); orig2idx.resize( sz ); for ( k = 2; k--; ) { for ( i = decomposition.size(); i--; ) { for ( j = decomposition[i].size(); j--; ) { orig2comp[decomposition[i][j]] = i; orig2idx[decomposition[i][j]] = j; } } if ( PNL_IS_EXINFENGINEFLAVOUR_UNSORTED( FLAV ) && k ) { for ( i = sz; i--; ) { decomposition[orig2comp[conv[i]]][orig2idx[conv[i]]] = i; } } else { break; } } graphs.resize( decomposition.size() ); models.resize( decomposition.size() ); engines.resize( decomposition.size() ); for ( i = decomposition.size(); i--; ) { graphs[i] = gr->ExtractSubgraph( decomposition[i] ); #if 0 std::cout << "graph " << i << std::endl; graphs[i]->Dump(); #endif } node_types.resize( decomposition.size() ); node_assoc.resize( decomposition.size() ); for ( i = 0, k = 0; i < decomposition.size(); ++i ) { node_types[i].resize( decomposition[i].size() ); node_assoc[i].resize( decomposition[i].size() ); for ( j = 0; j < decomposition[i].size(); ++j ) { node_types[i][j] = *gm->GetNodeType( decomposition[i][j] ); node_assoc[i][j] = j; } } for ( i = decomposition.size(); i--; ) { models[i] = MODEL::Create( decomposition[i].size(), node_types[i], node_assoc[i], graphs[i] ); } for ( i = 0; i < gm->GetNumberOfFactors(); ++i ) { fac = gm->GetFactor( i ); fac->GetDomain( &dom ); #if 0 std::cout << "Ex received orig factor" << std::endl; fac->GetDistribFun()->Dump(); #endif k = orig2comp[dom[0]]; for ( j = dom.size(); j--; ) { dom[j] = orig2idx[dom[j]]; } fac = CFactor::CopyWithNewDomain( fac, dom, models[k]->GetModelDomain() ); #if 0 std::cout << "Ex mangled it to" << std::endl; fac->GetDistribFun()->Dump(); #endif models[k]->AttachFactor( fac ); } for ( i = decomposition.size(); i--; ) { switch ( decomposition[i].size() ) { case 1: engines[i] = FALLBACK_ENGINE1::Create( models[i] ); continue; case 2: engines[i] = FALLBACK_ENGINE2::Create( models[i] ); continue; default: engines[i] = INF_ENGINE::Create( models[i] ); } } }
float CMlLearningEngine::_LearnPotentials() { int iteration = 1; float log_lik = 0.0f; CStaticGraphicalModel *grmodel = this->GetStaticModel(); CFactor *parameter = NULL; float epsilon = m_precisionIPF; const CPotential *joint_prob = NULL; CPotential *clique_jpd = NULL; CMatrix<float> *itogMatrix; CInfEngine *m_pInfEngine = CNaiveInfEngine::Create(grmodel); intVector obsNodes(0); valueVector obsValues(0); CEvidence *emptyEvidence = CEvidence::Create(grmodel->GetModelDomain(), obsNodes, obsValues); m_pInfEngine -> EnterEvidence( emptyEvidence ); int querySize = grmodel->GetNumberOfNodes(); int *query; query = new int [querySize]; int i; for( i = 0; i < querySize; i++ ) { query[i] = i; } m_pInfEngine -> MarginalNodes( query, querySize ); joint_prob = m_pInfEngine->GetQueryJPD(); CPotential *itog_joint_prob = static_cast<CPotential *>(joint_prob ->Marginalize(query, querySize)); int DomainSize; const int *domain; potsPVector learn_factors; CPotential *tmp_factor; for (i = 0; i < grmodel -> GetNumberOfFactors(); i++) { factor = grmodel -> GetFactor(i); factor -> GetDomain( &DomainSize, &domain ); CDistribFun *correspData= factor -> GetDistribFun(); CMatrix<float> *learnMatrix = correspData -> GetStatisticalMatrix(stMatTable); CPotential *factor = CTabularPotential::Create( domain, DomainSize, parameter->GetModelDomain()); learn_factors.push_back(factor); learn_factors[i] -> AttachMatrix(learnMatrix->NormalizeAll(), matTable); } int data_length; float *old_itog_data = NULL; const float *itog_data; delete [] query; int convergence = 0; while( !convergence && (iteration <= m_maxIterIPF)) { iteration++; itogMatrix = (itog_joint_prob->GetDistribFun()) -> GetMatrix(matTable); static_cast<CNumericDenseMatrix<float>*>(itogMatrix)-> GetRawData(&data_length, &itog_data); old_itog_data = new float[data_length]; for( i = 0; i < data_length; i++) { old_itog_data[i] = itog_data[i]; } for( int clique = 0; clique < grmodel->GetNumberOfFactors(); clique++) { factor = grmodel -> GetFactor(clique); factor -> GetDomain( &DomainSize, &domain ); clique_jpd = static_cast<CPotential *> (itog_joint_prob -> Marginalize( domain, DomainSize )); tmp_factor = itog_joint_prob -> Multiply(learn_factors[clique]); delete (itog_joint_prob); itog_joint_prob = tmp_factor; tmp_factor = itog_joint_prob -> Divide(clique_jpd); delete (itog_joint_prob); delete (clique_jpd); itog_joint_prob = tmp_factor; } itogMatrix = (itog_joint_prob->GetDistribFun()) -> GetMatrix(matTable); static_cast<CNumericDenseMatrix<float>*>(itogMatrix)-> GetRawData(&data_length, &itog_data); convergence = true; for (int j = 0; j < data_length; j++) { if( fabs( itog_data[j] - old_itog_data[j] ) > epsilon) { convergence = false; break; } } delete []old_itog_data; } if(iteration > m_maxIterIPF) { PNL_THROW(CNotConverged, "maximum number of iterations for IPF procedure") } for(int clique = 0; clique < grmodel -> GetNumberOfFactors(); clique++) { CMatrix<float> *matrix = NULL; factor = grmodel -> GetFactor(clique); int DomainSize; const int *domain; int data_length; const float *data; factor -> GetDomain( &DomainSize, &domain ); matrix = itog_joint_prob->Marginalize( domain, DomainSize ) ->GetDistribFun()-> GetMatrix( matTable ); static_cast<CNumericDenseMatrix<float>*>(matrix)->GetRawData(&data_length, &data); CNumericDenseMatrix<float>* matLearn = static_cast<CNumericDenseMatrix<float>*>( parameter->GetDistribFun()->GetStatisticalMatrix(stMatTable)); for(int offset = 0; offset < data_length; offset++) { float prob = float( ( data[offset] < FLT_EPSILON ) ? -FLT_MAX : log( data[offset] ) ); log_lik += matLearn->GetElementByOffset(offset)*prob - m_Vector_pEvidences.size(); } factor ->AttachMatrix(matrix, matTable); delete (learn_factors[clique]); } delete (itog_joint_prob); learn_factors.clear(); return log_lik; }