/// <summary> /// Reads the xml representation of an object form the xml input stream.<br> /// </summary> /// <param name="parser">XMLStreamReader the xml input stream</param> /// <example> /// mandelEllis.ReadXML(new XmlTextReader("mandelellis.xml")); /// </example> public void ReadXML(XmlTextReader xmlTextReader) { XDocument xdoc = XDocument.Load(xmlTextReader); XElement feature = xdoc.Element("feature"); if (feature == null) { throw new MissingFieldException("Could not find feature section - no GmmMe Loaded!"); } Matrix mean = new Matrix(0, 0); mean.ReadXML(xdoc, "mean"); Matrix covarMatrix = new Matrix(0, 0); covarMatrix.ReadXML(xdoc, "cov"); Matrix covarMatrixInv = new Matrix(0, 0); covarMatrixInv.ReadXML(xdoc, "icov"); this.gmmMe = new GmmMe(mean, covarMatrix, covarMatrixInv); xmlTextReader.Close(); }
/// <summary> /// Calculate the Kullback-Leibler (KL) distance between the two GmmMe. (Also /// known as relative entropy) To make the measure symmetric (ie. to obtain a /// divergence), the KL distance should be called twice, with exchanged /// parameters, and the result be added. /// Implementation according to the submission to the MIREX'05 by Mandel and Ellis. /// </summary> /// <param name="gmmMe1">ME features of song 1</param> /// <param name="gmmMe2">ME features of song 2</param> /// <returns>the KL distance from gmmMe1 to gmmMe2</returns> private float KullbackLeibler(GmmMe gmmMe1, GmmMe gmmMe2) { int dim = gmmMe1.covarMatrix.GetColumnDimension(); /// calculate the trace-term: Matrix tr1 = gmmMe2.covarMatrixInv.Times(gmmMe1.covarMatrix); Matrix tr2 = gmmMe1.covarMatrixInv.Times(gmmMe2.covarMatrix); Matrix sum = tr1.Plus(tr2); float trace = (float)sum.Trace(); /// "distance" between the two mean vectors: Matrix dist = gmmMe1.mean.Minus(gmmMe2.mean); /// calculate the second brace: Matrix secBra = gmmMe2.covarMatrixInv.Plus(gmmMe1.covarMatrixInv); Matrix tmp1 = dist.Transpose().Times(secBra); /// finally, the whole term: return(0.5f * (trace - 2 * dim + (float)tmp1.Times(dist).Get(0, 0))); }
public MandelEllis(GmmMe gmmMe) : this() { this.gmmMe = gmmMe; }
/// <summary> /// Reads the xml representation of an object form the xml input stream.<br> /// </summary> /// <param name="parser">XMLStreamReader the xml input stream</param> /// <example> /// mandelEllis.ReadXML(new XmlTextReader("mandelellis.xml")); /// </example> public void ReadXML(XmlTextReader xmlTextReader) { XDocument xdoc = XDocument.Load(xmlTextReader); XElement feature = xdoc.Element("feature"); if (feature == null) { throw new MissingFieldException("Could not find feature section - no GmmMe Loaded!"); } Matrix mean = new Matrix(0,0); mean.ReadXML(xdoc, "mean"); Matrix covarMatrix = new Matrix(0,0); covarMatrix.ReadXML(xdoc, "cov"); Matrix covarMatrixInv = new Matrix(0,0); covarMatrixInv.ReadXML(xdoc, "icov"); this.gmmMe = new GmmMe(mean, covarMatrix, covarMatrixInv); xmlTextReader.Close(); }
/// <summary> /// Calculate the Kullback-Leibler (KL) distance between the two GmmMe. (Also /// known as relative entropy) To make the measure symmetric (ie. to obtain a /// divergence), the KL distance should be called twice, with exchanged /// parameters, and the result be added. /// Implementation according to the submission to the MIREX'05 by Mandel and Ellis. /// </summary> /// <param name="gmmMe1">ME features of song 1</param> /// <param name="gmmMe2">ME features of song 2</param> /// <returns>the KL distance from gmmMe1 to gmmMe2</returns> private float KullbackLeibler(GmmMe gmmMe1, GmmMe gmmMe2) { int dim = gmmMe1.covarMatrix.GetColumnDimension(); /// calculate the trace-term: Matrix tr1 = gmmMe2.covarMatrixInv.Times(gmmMe1.covarMatrix); Matrix tr2 = gmmMe1.covarMatrixInv.Times(gmmMe2.covarMatrix); Matrix sum = tr1.Plus(tr2); float trace = (float)sum.Trace(); /// "distance" between the two mean vectors: Matrix dist = gmmMe1.mean.Minus(gmmMe2.mean); /// calculate the second brace: Matrix secBra = gmmMe2.covarMatrixInv.Plus(gmmMe1.covarMatrixInv); Matrix tmp1 = dist.Transpose().Times(secBra); /// finally, the whole term: return 0.5f * (trace - 2*dim + (float)tmp1.Times(dist).Get(0, 0)); }