So I'm trying to understand the implementation of a function that plots the bivariate normal contours of two variables. Thought I'd post here since the question is primarily mathematical in nature and the code itself isn't too complicated.
The following code is given in one of the lectures of an online ML course:
def plot_contours(mu, cov, x1g, x2g, col):
rv = multivariate_normal(mean=mu, cov=cov)
z = np.zeros((len(x1g),len(x2g)))
for i in range(0,len(x1g)):
for j in range(0,len(x2g)):
z[j,i] = rv.logpdf([x1g[i], x2g[j]])
sign, logdet = np.linalg.slogdet(cov)
normalizer = -0.5 * (2 * np.log(6.28) + sign * logdet)
for offset in range(1,4):
plt.contour(x1g,x2g,z, levels=[normalizer - offset], colors=col, linewidths=2.0, linestyles='solid')
We specify a bivariate normal distribution with mean vector mu and covariance matrix cov. If $n_1=$len(x1g) and $n_2=$len(x2g), then we're looking to calculate the probability density at all points in $\{0,1,\ldots,n_1-1\}\times\{0,1,\ldots,n_2-1\}$.
My question is: if the purpose is to plot contours of the normal probability density, why do we use the logpdf function? The descriptions of the functions are here:
pdf(x, loc=0, scale=1) Probability density function.
logpdf(x, loc=0, scale=1) Log of the probability density function.
Any particular reason of using logpdf and then proceeding to calculate other stuff like the log of the determinant and a normalizing term? Couldn't we just have calculated the pdf like:
z[j,i] = rv.pdf([x1g[i], x2g[j]])
feed this into the contour function and be done with it?