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::LearnOMP() { CStaticGraphicalModel *pGrModel = this->GetStaticModel(); PNL_CHECK_IS_NULL_POINTER(pGrModel); PNL_CHECK_LEFT_BORDER(GetNumEv() - GetNumberProcEv() , 1); //omp_set_num_threads(2); int numberOfThreads = omp_get_num_procs(); //CParPearlInfEngine **pCurrentInfEng = new CParPearlInfEngine*[numberOfThreads]; CJtreeInfEngine **pCurrentInfEng = new CJtreeInfEngine*[numberOfThreads]; for (int i = 0; i < numberOfThreads; i++) pCurrentInfEng[i] = NULL; CFactor *parameter1 = NULL; int exit = 0; int numberOfParameters = pGrModel->GetNumberOfParameters(); int domainNodes; //int itsML = 0; // !!! float loglik = -FLT_MAX; float loglikOld = -FLT_MAX; float epsilon = GetPrecisionEM(); float stopExpression = epsilon + 1.0f; int iteration = 0; int ev; // to create additional factors CFactor **ppAllFactors = new CFactor*[numberOfParameters*numberOfThreads]; bool *was_updated = new bool[numberOfParameters*numberOfThreads]; int factor; #pragma omp parallel for private(factor) default(shared) for (factor = 0; factor < numberOfParameters; factor++) { ppAllFactors[factor] = pGrModel->GetFactor(factor); ppAllFactors[factor]->GetDistribFun()->ClearStatisticalData(); was_updated[factor] = false; for (int proc = 1; proc < numberOfThreads; proc++) { ppAllFactors[factor + proc * numberOfParameters] = ppAllFactors[factor]->Clone(); ppAllFactors[factor + proc * numberOfParameters]->GetDistribFun()-> ClearStatisticalData(); was_updated[factor + proc * numberOfParameters]= false; }; }; int* itsML = new int[numberOfThreads]; for (int delta = 0; delta < numberOfThreads; delta++) { itsML[delta] = 0; }; int start_ev, end_ev; do { iteration++; start_ev = GetNumberProcEv(); end_ev = GetNumEv(); #pragma omp parallel for schedule(dynamic) private(ev) for (ev = start_ev; ev < end_ev ; ev++) { CFactor *parameter = NULL; int DomainNodes_new; int bMaximize = 0; int bSumOnMixtureNode = 0; int infIsNeed = 0; int currentEvidNumber = ev; // !!! const CEvidence* pCurrentEvid = m_Vector_pEvidences[currentEvidNumber]; infIsNeed = !GetObsFlags(ev)->empty(); // !!! int Num_thread = omp_get_thread_num(); if (infIsNeed) { if (!pCurrentInfEng[Num_thread]) { pCurrentInfEng[Num_thread] = CJtreeInfEngine::Create( (const CStaticGraphicalModel *)pGrModel); } pCurrentInfEng[Num_thread]->EnterEvidence(pCurrentEvid, bMaximize, bSumOnMixtureNode); } for (DomainNodes_new = 0; DomainNodes_new < numberOfParameters; DomainNodes_new++) { parameter = ppAllFactors[DomainNodes_new + Num_thread * numberOfParameters]; if (infIsNeed) { int DomainSize; const int *domain; parameter->GetDomain(&DomainSize, &domain); if (IsDomainObserved(DomainSize, domain, currentEvidNumber)) { const CEvidence *pEvidences[] = { pCurrentEvid }; parameter->UpdateStatisticsML(pEvidences, 1); was_updated[DomainNodes_new+Num_thread*numberOfParameters]= true; } else { pCurrentInfEng[Num_thread]->MarginalNodes(domain, DomainSize, 1); const CPotential * pMargPot = pCurrentInfEng[Num_thread]->GetQueryJPD(); parameter ->UpdateStatisticsEM(pMargPot, pCurrentEvid); was_updated[DomainNodes_new+Num_thread*numberOfParameters]= true; } } else { const CEvidence *pEvidences[] = { pCurrentEvid }; parameter->UpdateStatisticsML(pEvidences, 1); was_updated[DomainNodes_new+Num_thread*numberOfParameters]= true; } } itsML[Num_thread] = itsML[Num_thread] || !infIsNeed; } // end of parallel for for (int delta = 1; delta < numberOfThreads; delta++) { itsML[0] = itsML[0] || itsML[delta]; }; //to join factors #pragma omp parallel for private(factor) default(shared) for (factor = 0; factor < numberOfParameters; factor++) { for (int proc = 1; proc < numberOfThreads; proc++) { if (was_updated[factor+proc*numberOfParameters]) { ppAllFactors[factor]->UpdateStatisticsML(ppAllFactors[factor + proc*numberOfParameters]); ppAllFactors[factor+proc*numberOfParameters]->GetDistribFun()-> ClearStatisticalData(); }; was_updated[factor+proc*numberOfParameters] = false; }; }; switch (pGrModel->GetModelType()) { case mtBNet: { loglikOld = loglik; loglik = 0.0f; for (domainNodes = 0; domainNodes < numberOfParameters; domainNodes++) { parameter1 = pGrModel->GetFactor(domainNodes); loglik += parameter1->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[0]; if (exit) { ClearStatisticData(); } m_critValue.push_back(loglik); for (int j = 0; j < numberOfThreads; j++) { delete pCurrentInfEng[j]; pCurrentInfEng[j] = NULL; } } while (exit); delete [] pCurrentInfEng; //”даление дополнительных факторов for (factor = numberOfParameters; factor < numberOfParameters * numberOfThreads; factor++) { delete ppAllFactors[factor]; }; delete[] ppAllFactors; delete[] was_updated; if (iteration > GetMaxIterEM()) { PNL_THROW(CNotConverged, "maximum number of iterations") } SetNumProcEv( GetNumEv() ); }
void CEMLearningEngine::LearnExtraCPDs(int nMaxFamily, pCPDVector* additionalCPDs, floatVector* additionalLLs) { CStaticGraphicalModel *pGrModel = this->GetStaticModel(); PNL_CHECK_IS_NULL_POINTER(pGrModel); PNL_CHECK_LEFT_BORDER(GetNumEv(), 1); int numberOfFactors = pGrModel->GetNumberOfFactors(); int numberOfAddFactors = additionalCPDs->size(); additionalLLs->resize(numberOfAddFactors); additionalLLs->clear(); m_vFamilyLogLik.resize(numberOfFactors); float loglik = 0.0f, ll; int i, ev; int iteration = 0; const CEvidence* pEv; CFactor *factor = NULL; int nnodes; const int * domain; bool bInfIsNeed; CInfEngine *pInfEng = m_pInfEngine; if (IsAllObserved()) { for (i = 0; i < numberOfFactors; i++) { factor = pGrModel->GetFactor(i); factor->UpdateStatisticsML(&m_Vector_pEvidences[GetNumberProcEv()], GetNumEv() - GetNumberProcEv()); } for( ev = 0; ev < GetNumEv() ; ev++) { pEv = m_Vector_pEvidences[ev]; for( i = 0; i < numberOfAddFactors; i++ ) { factor = static_cast<CFactor*>((*additionalCPDs)[i]); factor->UpdateStatisticsML( &pEv, 1 ); } } switch (pGrModel->GetModelType()) { case mtBNet: { for( i = 0; i<numberOfFactors; i++ ) { factor = pGrModel->GetFactor(i); ll = factor->ProcessingStatisticalData( GetNumEv()); m_vFamilyLogLik[i] = ll; loglik += ll; } for( i = 0; i < numberOfAddFactors; i++ ) { factor = static_cast<CFactor*>((*additionalCPDs)[i]); ll = factor->ProcessingStatisticalData( GetNumEv()); (*additionalLLs)[i] = ll; } break; } case mtMRF2: case mtMNet: { break; } default: { PNL_THROW(CBadConst, "model type" ) break; } } m_critValue.push_back(loglik); } else {
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() ); }
void CEMLearningEngine::Learn() { CStaticGraphicalModel *pGrModel = this->GetStaticModel(); PNL_CHECK_IS_NULL_POINTER(pGrModel); PNL_CHECK_LEFT_BORDER(GetNumEv() - GetNumberProcEv() , 1); CInfEngine *pInfEng = NULL; if (m_pInfEngine) { pInfEng = m_pInfEngine; } else { if (!m_bAllObserved) { pInfEng = CJtreeInfEngine::Create(pGrModel); m_pInfEngine = pInfEng; } } float loglik = 0.0f; int nFactors = pGrModel->GetNumberOfFactors(); const CEvidence *pEv; CFactor *pFactor; int iteration = 0; int ev; bool IsCastNeed = false; int i; for( i = 0; i < nFactors; i++ ) { pFactor = pGrModel->GetFactor(i); EDistributionType dt = pFactor->GetDistributionType(); if ( dt == dtSoftMax ) IsCastNeed = true; } float ** full_evid = NULL; if (IsCastNeed) { BuildFullEvidenceMatrix(&full_evid); } if (IsAllObserved()) { int i; float **evid = NULL; EDistributionType dt; CFactor *factor = NULL; for (i = 0; i < nFactors; i++) { factor = pGrModel->GetFactor(i); dt = factor->GetDistributionType(); if (dt != dtSoftMax) { factor->UpdateStatisticsML(&m_Vector_pEvidences[GetNumberProcEv()], GetNumEv() - GetNumberProcEv()); } else { intVector family; family.resize(0); pGrModel->GetGraph()->GetParents(i, &family); family.push_back(i); CSoftMaxCPD* SoftMaxFactor = static_cast<CSoftMaxCPD*>(factor); SoftMaxFactor->BuildCurrentEvidenceMatrix(&full_evid, &evid,family,m_Vector_pEvidences.size()); SoftMaxFactor->InitLearnData(); SoftMaxFactor->SetMaximizingMethod(m_MaximizingMethod); SoftMaxFactor->MaximumLikelihood(evid, m_Vector_pEvidences.size(), 0.00001f, 0.01f); SoftMaxFactor->CopyLearnDataToDistrib(); for (int k = 0; k < factor->GetDomainSize(); k++) { delete [] evid[k]; } delete [] evid; } } m_critValue.push_back(UpdateModel()); } else { bool bContinue; const CPotential * pot; /* bool IsCastNeed = false; int i; for( i = 0; i < nFactors; i++ ) { pFactor = pGrModel->GetFactor(i); EDistributionType dt = pFactor->GetDistributionType(); if ( dt == dtSoftMax ) IsCastNeed = true; } float ** full_evid; if (IsCastNeed) { BuildFullEvidenceMatrix(full_evid); }*/ do { ClearStatisticData(); iteration++; for( ev = GetNumberProcEv(); ev < GetNumEv() ; 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(); if ( (!(m_Vector_pEvidences[ev])->IsNodeObserved(i)) && (IsCastNeed) ) { Cast(pot, i, ev, &full_evid); } EDistributionType dt; dt = pFactor->GetDistributionType(); if ( !(dt == dtSoftMax) ) pFactor->UpdateStatisticsEM( /*pInfEng->GetQueryJPD */ pot, pEv ); } else { if ((pFactor->GetDistributionType()) != dtSoftMax) pFactor->UpdateStatisticsML( &pEv, 1 ); } } } int i; /* printf ("\n My Full Evidence Matrix"); for (i=0; i<nFactors; i++) { for (j=0; j<GetNumEv(); j++) { printf ("%f ", full_evid[i][j]); } printf("\n"); } */ float **evid = NULL; EDistributionType dt; CFactor *factor = NULL; // int i; for (i = 0; i < nFactors; i++) { factor = pGrModel->GetFactor(i); dt = factor->GetDistributionType(); if (dt == dtSoftMax) { intVector family; family.resize(0); pGrModel->GetGraph()->GetParents(i, &family); family.push_back(i); CSoftMaxCPD* SoftMaxFactor = static_cast<CSoftMaxCPD*>(factor); SoftMaxFactor->BuildCurrentEvidenceMatrix(&full_evid, &evid,family,m_Vector_pEvidences.size()); SoftMaxFactor->InitLearnData(); SoftMaxFactor->SetMaximizingMethod(m_MaximizingMethod); // SoftMaxFactor->MaximumLikelihood(evid, m_numberOfLastEvidences, SoftMaxFactor->MaximumLikelihood(evid, m_Vector_pEvidences.size(), 0.00001f, 0.01f); SoftMaxFactor->CopyLearnDataToDistrib(); for (int k = 0; k < factor->GetDomainSize(); k++) { delete [] evid[k]; } delete [] evid; } } 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() ); if (IsCastNeed) { int NumOfNodes = pGrModel->GetGraph()->GetNumberOfNodes(); for (i=0; i<NumOfNodes; i++) { delete [] full_evid[i]; } delete [] full_evid; } }