def test(): ## Provided the weights for the stationary distribution and the exchangeable coefficients ## we use them to generate the true rate matrix and the sequences to get the averaged ## sufficient statistics for the sequences throughout a larger number of replications ## Based on the sufficient statistics and we fix the exchangeable coefficients to ## its true values, we use HMC to estimate the weights for the stationary distribution ## The rate matrix is an un-normalized version ## The correctness of HMC and ExpectedCompleteReversibleObjective has been tested ## The estimated stationary distribution 'stationaryDistEst' is very close to stationaryDist nStates = 4 nRep = 1000 seedNum = np.arange(0, nRep) np.random.seed(123) weights = np.random.uniform(0, 1, nStates) print(weights) exchangeCoef = np.array((1, 2, 3, 4, 5, 6)) ## get the rate matrix testRateMtx = ReversibleRateMtxPiAndExchangeGTR(nStates, weights, exchangeCoef) stationaryDist = testRateMtx.getStationaryDist() rateMtx = testRateMtx.getRateMtx() bt = 5.0 nSeq = 100 nInit = np.zeros(nStates) holdTimes = np.zeros(nStates) nTrans = np.zeros((nStates, nStates)) for j in range(nRep): ## do forward sampling seqList = generateFullPathUsingRateMtxAndStationaryDist(nSeq, nStates, seedNum[j], rateMtx, stationaryDist, bt) ## summarize the sufficient statistics ## extract first state from sequences firstStates = getFirstAndLastStateOfListOfSeq(seqList)['firstLastState'][:, 0] unique, counts = np.unique(firstStates, return_counts=True) nInitCount = np.asarray((unique, counts)).T nInit = nInit + nInitCount[:, 1] for i in range(nSeq): sequences = seqList[i] holdTimes = holdTimes + sequences['sojourn'] nTrans = nTrans + sequences['transitCount'] avgNTrans = nTrans / nRep avgHoldTimes = holdTimes / nRep avgNInit = nInit / nRep expectedCompleteReversibleObjective = ExpectedCompleteReversibleObjective(holdTimes=avgHoldTimes, nInit=avgNInit, nTrans=avgNTrans, kappa=1, exchangeCoef=exchangeCoef) prng = np.random.RandomState(1) hmc = HMC(40, 0.02, expectedCompleteReversibleObjective, expectedCompleteReversibleObjective) sample = prng.uniform(0, 1, nStates) samples = hmc.run(0, 5000, sample) avgWeights = np.sum(samples, axis=0) / samples.shape[0] stationaryDistEst = np.exp(avgWeights)/np.sum(np.exp(avgWeights)) print(weights) print(avgWeights) print(stationaryDist) print(stationaryDistEst)
def obtainSufficientStatisticsForChainGraphRateMtx(nStates, nRep=5000, bt=5.0, nSeq=100, SDOfBiWeights=0.5, bivariateDictionary=None): ## we generate the sufficient statistics for a large number of replications first ## and then we summarize the sufficient statistics for the forward sampler and ## then we use this data to run HMC and local BPS algorithms separately to see ## if we can obtain reasonable estimates of the exchangeable parameters seedNum = np.arange(0, nRep) if bivariateDictionary is None: bivariateDictionary = getHardCodedDictChainGraph(nStates) prng = RandomState(1234567890) stationaryWeights = prng.uniform(0, 1, nStates) bivariateWeights = prng.normal(0, SDOfBiWeights, int((nStates) * (nStates - 1) / 2)) testRateMtx = ReversibleRateMtxPiAndBinaryWeightsWithGraphicalStructure(nStates, stationaryWeights, bivariateWeights, bivariateDictionary) stationaryDist = testRateMtx.getStationaryDist() rateMatrix = testRateMtx.getRateMtx() nInit = np.zeros(nStates) holdTimes = np.zeros(nStates) nTrans = np.zeros((nStates, nStates)) for i in seedNum: seqList = generateFullPathUsingRateMtxAndStationaryDist(RandomState(i), nSeq, nStates, rateMatrix, stationaryDist, bt) ## summarize the sufficient statistics ## extract first state from sequences firstStates = getFirstAndLastStateOfListOfSeq(seqList)['firstLastState'][:, 0] unique, counts = np.unique(firstStates, return_counts=True) nInitCount = np.asarray((unique, counts)).T nInit = nInit + nInitCount[:, 1] for j in range(nSeq): sequences = seqList[j] holdTimes = holdTimes + sequences['sojourn'] nTrans = nTrans + sequences['transitCount'] print(i) avgNTrans = nTrans / nRep avgHoldTimes = holdTimes / nRep avgNInit = nInit / nRep result = {} result['stationaryWeights'] = stationaryWeights result['bivariateDictionary'] = bivariateDictionary result['bivariateWeights'] = bivariateWeights result['rateMatrix'] = rateMatrix result['stationaryDist'] = stationaryDist result['exchangeableCoef'] = testRateMtx.getExchangeCoef() result['transitCount'] = avgNTrans result['sojourn'] = avgHoldTimes result['nInit'] = avgNInit return result
print("The true rate matrix is ") print(rateMtx) #[[-0.78028091 0.01019415 0.63967359 0.13041317] # [ 0.06563807 -0.27952517 0.03614709 0.17774 ] # [ 1.02131772 0.00896336 -2.46060442 1.43032334] # [ 0.11767434 0.0249081 0.80833633 -0.95091876]] print("The true exchangeable parameters are ") trueExchangeCoef = testRateMtx.getExchangeCoef() print(trueExchangeCoef) ## generate data sequences of a CTMC with an un-normalized rate matrix bt = 5.0 nSeq = 5000 seqList = generateFullPathUsingRateMtxAndStationaryDist(nSeq, nStates, seed, rateMtx, stationaryDist, bt) ## initial guess of the parameters newSeed = 456 np.random.seed(456) initialWeights = stationaryWeights print(initialWeights) ## this is the weight at the 0th iteration #initialBinaryWeights = np.array((0.586, 0.876, -0.1884, 0.8487, 0.5998, -1.35819, # -1.521, -0.6138, -0.58865, 0.19012)) #print("The initial binary feature weights at 0th iteration are: ") # This is the weight after 250th iteration # initialBinaryWeights = np.array((-0.26843204, 0.36688318, -0.97301064, 0.91227563, 1.20215414, -1.69677469,-0.95141154, -0.59620609, 0.8609998, 0.54728876))
def testCalculate(): ## test the correctness of the code using numeric gradient check nStates = 6 nRep = 10000 seedNum = np.arange(0, nRep) np.random.seed(123) weights = np.random.uniform(0, 1, 18) print(weights) # delta = 0.000001 bivariateFeatDictionary = getHardCodedDict() weightsForPi = weights[0:nStates] weightsForBivariate = weights[nStates:len(weights)] ## get the rate matrix testRateMtx = ReversibleRateMtxPiAndBinaryWeightsWithGraphicalStructure(nStates, weightsForPi, weightsForBivariate, bivariateFeatDictionary) stationaryDist = testRateMtx.getStationaryDist() rateMtx = testRateMtx.getRateMtx() bt = 3.0 nSeq = 500 ## simulate the observation data first seqList = generateFullPathUsingRateMtxAndStationaryDist(RandomState(seedNum[0]), nSeq, nStates, rateMtx, stationaryDist, bt) ## get observed sequences at a finite number of time points dataGenerationRegime = DataGenerationRegime(nStates=nStates, bivariateFeatIndexDictionary=bivariateFeatDictionary, btLength=bt, nSeq=nSeq, stationaryWeights=weightsForPi, bivariateWeights=weightsForBivariate, interLength=0.5) ## summarize the sufficient statistics obsData = dataGenerationRegime.generatingSeqGivenRateMtxAndBtInterval(seqList) marginalResult = dataGenerationRegime.summaryFirstLastStatesArrayIntoMatrix(obsData, nStates) obsNInit0 = marginalResult['nInit'] ## get the marginal count from observations marginalCount = marginalResult['count'] ## extract first state from sequences ## Below are our actual observation sequences firstStates = getFirstAndLastStateOfListOfSeq(seqList)['firstLastState'][:, 0] unique, counts = np.unique(firstStates, return_counts=True) nInitCount = np.asarray((unique, counts)).T obsNInit = np.zeros(nStates) obsNInit = obsNInit + nInitCount[:, 1] print(obsNInit) ## it should be equal to obsNinit0 rateMtxExpectations = RateMtxExpectations(rateMtx, 0.5) marginalExpectations = rateMtxExpectations.expectationsWithMarginalCount(marginalCount) ## get expected holding time expectedHoldingTime = np.diag(marginalExpectations) ## get expected transition count expectedTransCount = deepcopy(marginalExpectations) np.fill_diagonal(expectedTransCount, 0) expectedCompleteObjectiveFromExptStat = ExpectedCompleteReversibleObjective(expectedHoldingTime, obsNInit, expectedTransCount, nBivariateFeatWeightsDictionary=bivariateFeatDictionary) expectedForwardResult = expectedCompleteObjectiveFromExptStat.calculate(weights, bivariateFeatDictionary) exptFuncValue = expectedForwardResult['value'] exptGradient = expectedForwardResult['gradient'] print(exptFuncValue) print(exptGradient) # nInit = np.zeros(nStates) # holdTimes = np.zeros(nStates) # nTrans = np.zeros((nStates, nStates)) # # for j in range(nRep): # # ## do forward sampling # seqList = generateFullPathUsingRateMtxAndStationaryDist(RandomState(seedNum[0]), nSeq, nStates, rateMtx, stationaryDist, bt) # # ## summarize the sufficient statistics # # ## extract first state from sequences # firstStates = getFirstAndLastStateOfListOfSeq(seqList)['firstLastState'][:, 0] # unique, counts = np.unique(firstStates, return_counts=True) # nInitCount = np.asarray((unique, counts)).T # nInit = nInit + nInitCount[:, 1] # # for i in range(nSeq): # sequences = seqList[i] # holdTimes = holdTimes + sequences['sojourn'] # nTrans = nTrans + sequences['transitCount'] # # avgNTrans = nTrans/nRep # avgHoldTimes = holdTimes/nRep # avgNInit = nInit/nRep T = 0.5 postSampler = EndPointSampler(rateMtx, T) pathStat2 = PathStatistics(nStates) nSegment = dataGenerationRegime.nPairSeq counter =0 for j in range(nRep): ## do posterior path sampling ## for each segment of the observed path for the time series, ## loop over each segment of the sequence for i in range(nSegment): ## loop over each sequences for k in range(len(seqList)): p2 = Path() startState = obsData[i][int(k)][0] endState = obsData[i][k][1] postSampler.sample(np.random.RandomState(counter), int(startState), int(endState), T, pathStat2, p2) counter = counter + 1 if j%10 == 0: print(j) m2 = pathStat2.getCountsAsSimpleMatrix() / nRep avgNInit = obsNInit avgNTrans = deepcopy(m2) np.fill_diagonal(avgNTrans, 0) avgHoldTimes = m2.diagonal() originalExpectedCompleteObjective = ExpectedCompleteReversibleObjective(avgHoldTimes, avgNInit, avgNTrans, nBivariateFeatWeightsDictionary=bivariateFeatDictionary) forwardResult = originalExpectedCompleteObjective.calculate(weights, bivariateFeatDictionary) funcValue = forwardResult['value'] gradient = forwardResult['gradient'] print(funcValue) print(gradient)