private boolean EM(int iters)
    {
    	// p(z), size: K
        double[] Pz = new double[this.K];

        // p(d|z), size: K x M
        double[][] Pd_z = new double[this.K][this.M];

        // p(w|z), size: K x V
        double[][] Pw_z = new double[this.K][this.V];

        // p(z|d,w), size: K x M x doc.size()
        double[][][] Pz_dw = new double[this.K][this.M][];

         // L: log-likelihood value
         double L = -1;

         // run EM algorithm
         this.init(Pz, Pd_z, Pw_z, Pz_dw);
         for (int it = 0; it < iters; it++)
         {
         	 // E-step
        	 if (!this.Estep(Pz, Pd_z, Pw_z, Pz_dw))
        	 {
        		 System.out.println("EM,  in E-step");
             }

             // M-step
             if (!this.Mstep(Pz_dw, Pw_z, Pd_z, Pz))
             {
            	 System.out.println("EM, in M-step");
             }

             L = calcLoglikelihood(Pz, Pd_z, Pw_z);
             System.out.println("[" + it + "]" + "\tlikelihood: " + L);
         }
                
         //print result
         for (int m = 0; m < this.M; m++)
         {
        	 double norm = 0.0;
        	 for (int z = 0; z < this.K; z++) {
        		 norm += Pd_z[z][m];
             }
        	 if (norm <= 0.0) norm = 1.0;
        	 for (int z = 0; z < this.K; z++) {
        		 System.out.format("%10.4f", Pd_z[z][m]/norm);
             }
             System.out.println();
        } 
        return false;
    }