Wednesday, October 14, 2015

Bayesian regression example

This script is created to show a workflow of bayesian regression to fit a model to data. I created this html directly from ipython notebook, you can download the original notebook from Qingkai's Github.

In [1]:
%pylab inline
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import cm
Populating the interactive namespace from numpy and matplotlib

Create data and adding noise

We generate data based on the equation 2arctan(x/3), and add a gaussian noise to it. Assume this is our observed data with some noise in it, and we don't know how the data was generated, and want to use equation Aarctan(x/B) to model it, and find parameter A and B based on the data we obeserved.
In [2]:
#create some data and adding a white noise to the data
x = np.linspace(-10, 10, 100)
A = 2
B = 3
#We use the following equation to generate our data
y = A*np.arctan(x/B)

#adding the noise 
noise = np.random.normal(0,0.1,len(y))
y_observe = y + noise

plt.plot(x, y_observe, 'o')
plt.xlabel('X', fontsize = 16)
plt.ylabel('Y', fontsize = 16)
plt.show()

Grid search least square regression

Before we go further to use Bayesian approach, let's use a very common numerical way to solve this problem first - least square regression. To make the problem simple, I just use a grid search method to minimize the sum of squared residual between observed data and predicted data. Let's assume our parameter space for A and B range from 1 to 10, we calcuate the predicted value by using each parameter pair A and B, and calculate the sum of the residual to the observed data. We then can find the minimum of the sum of the residual square, and get the corresponding A and B as the parameters as the model that best fit the data.
In [3]:
A_space = np.arange(1, 10.25, 0.25)
B_space = np.arange(1, 10.25, 0.25)
residual_mat = np.zeros((len(A_space), len(B_space)))
#loop through parameter space, assume we know that A and B are ranging from 1 - 9
for i, A in enumerate(A_space):
    for j, B in enumerate(B_space):
        #estimate y
        y_est = A*np.arctan(x/B)
        sum_residual = sum((y_est - y_observe)**2)
        residual_mat[i, j] = sum_residual
        
#get the index of the smallest residual of all the models
ix_min = np.where(residual_mat == np.min(residual_mat))
A_est, B_est= A_space[ix_min[0][0]], B_space[ix_min[1][0]]
#plot the fitting line on the observed data
plt.plot(x, y_observe, 'o')
plt.plot(x, A_est*np.arctan(x/B_est), 'r', label = 'fitted line')
plt.xlabel('X', fontsize = 16)
plt.ylabel('Y', fontsize = 16)
plt.legend(fontsize = 16, loc = 2)
plt.title('The best model with parameter\n A = %.2f, and B = %.2f' %(A_est, B_est))
plt.show()
In [4]:
#visualize the space of the sum of squared residual
fig = plt.figure()
ax = Axes3D(fig)
X, Y = np.meshgrid(A_space, B_space)
ax.plot_surface(X, Y, residual_mat, rstride=1, cstride=1, cmap=cm.jet)
ax.set_xlabel('A', fontsize = 16)
ax.set_ylabel('B', fontsize = 16)
ax.set_zlabel('Residual^2 sum', fontsize = 16)
plt.title('The space of the sum of squared residual with minimum at\n A = %.2f, and B = %.2f' %(A_est, B_est))
plt.show()

Bayesian approach using MCMC

Even though we don't know what is A and B before hand, but my friend told me A should be around 2, and B should be around 3. How could we bring in this additional informaiton into our modeling? We can use Bayesian approach, and solve the problem from statistical point of view. We can think \(Y = f(X) + noise\), where f(X) is the true model we want to fit, and noise is comming from the measurements, \(X=[x_1, x_2, ..., x_N]\), and \(Y=[y_1, y_2, ..., y_N]\). For simplicity we treat noise as white noise, that is, noise fllow normal distribution noise~\(N(0, \sigma^2\)), assume we know the variance. Therefore, the predicting outcomes Y should be normally disbtributed with an expected value \(f(X_i)\), that is, \(Y_i\)~\(N(f(X_i)\), \(\sigma^2\)). This is to say, for each data point in observed data, it is normally distributed and centered at \(f(X_i)\). If we assume each of the observed data point is independent, we can then get the likelihood function as the multiply of each \(Y_i\)~\(N(f(X_i)\), \(\sigma^2\)), so \(Y\)~\(N(f(X)\), \(\sigma^2\)) (a gaussian multiply another gaussian is still a gaussian). If we stop here, and estimate the parameter A and B by maximize this likelyhood function, then this is MLE (Maximum Likelihood Estimation).
Now as we are very certain that A is around 2, B is around 3, so we can use a normal distribution to show our certainty. \(A\)~\(N(2, 0.01)\) and \(B\)~\(N(3, 0.01)\), that is we use a narrow gaussian (variance 0.01) to show we are quite certain that the parameter is centered around this mean value.
Then we can use Bayesian equation \(P(A, B|Y)=\frac{P(Y|A, B)P(A, B)}{P(Y)}\), where \(P(Y)=\int\int P(Y|A, B)P(A, B)dAdB\), and \(P(A, B) = P(A)P(B)\), since we can see the numerator is very easy to get, likelyhood function multiply prior, for current example, since they are all gaussian, so the numerator is also gaussian. But the denominator is a very ugly integral, not that easy to get. Since this denominator is used as a normalization factor to keep the posterior probability within [0, 1], it doesn't affect anything if we just want to know which A and B that maximize the posterior probability, this will be a MAP (Maximize A Posterior estimation). It is quite similar to MLE, differs just in which probability we try to maximize.
But if we want to get the posterior probability, we must figure out a way to solve the denominator! Here, MCMC (Markov Chain Monte Carlo) comes to save. It is a very elegant simulation procedure that is designed to get the posterior probability without solving the denominator. In this link, you can get a really nice intuition of the basic idea. Anyway, the following I will use MCMC to get an estimation of the posterior probability of both A and B (I assume we know the variance in the likelihood function, if we don't know the variance, we can add this paramter in, and estimate it as well).
In [5]:
from pymc import Model, Normal, HalfNormal
import pymc as pm
import corner
In [6]:
def myModel(x, y_observe): 
    # Priors for unknown model parameters
    #Note tau is the 1/sigma^2, e.g 1/σ^2
    A_prior = pm.distributions.Normal('A', mu = 2, tau = 100)
    B_prior = pm.distributions.Normal('B', mu = 3, tau = 100)
    
    #You can try different distributions on the variance of the noise
    #sigma = basic_model.HalfNormal('sigma', 1)
    #tau_prior = pm.distributions.Gamma("tau", alpha=0.001, beta=0.001)
    #Here I use sigma = 0.1
    tau_prior = 1.0/0.1**2
    
    # Expected value of outcome
    @pm.deterministic(plot=False)
    def f(x = x, A=A_prior, B=B_prior):
        return A*np.arctan(x/B)
    
    # Likelihood (sampling distribution) of observations
    Y_obs = pm.distributions.Normal('Y_obs', mu = f, tau = tau_prior, value = y_observe, observed=True)
    return locals()
In [7]:
#Here I also calculate MAP to get the best solution
model = pm.Model(myModel(x, y_observe))
map_ = pm.MAP(model)
map_.fit()
#print the MAP solution
print map_.A_prior.value, map_.B_prior.value

#Use MCMC to get the distribution of parameters
mcmc = pm.MCMC(myModel(x, y_observe))
mcmc.sample(iter=50000, burn=20000)
pm.Matplot.plot(mcmc)
#The trace is the series of the randm walk for each parameter, what we expect from this figure is no obvious trend. If the beginning of the run looks very different from the end, then the simulated Markov Chain is nowhere near stationarity and we need run longer.
#The Autocorrelation plot shows the cross-correlation of a signal with itself at different points in time. The x axis is time lag, and y is autocorrelation coefficient. What we are looking for is what lag the autocorrelations decrease to being not significantly different from zero. If autocorrelation is high, you will have to use a longer burn-in, and you will have to draw more samples after the burn-in to get a good estimate of the posterior distribution..Low autocorrelation means good exploration. Exploration and convergence are essentially the same thing. If a sampler explores well, then it will converge fast, and vice versa. Part of the confusion here is that the book does not explain the concept of convergence very well.
#Reference: http://stats.stackexchange.com/questions/116861/posterior-autocorrelation-in-pymc-how-to-interpret-it
1.9996140684 2.94570187909
 [-----------------100%-----------------] 50000 of 50000 complete in 4.1 secPlotting A
Plotting B

In [8]:
print mcmc.A_prior.summary()
print mcmc.B_prior.summary()
A:
 
Mean             SD               MC Error        95% HPD interval
------------------------------------------------------------------
2.001            0.019            0.001            [ 1.964  2.04 ]
 
 
Posterior quantiles:
 
|---------------|===============|===============|---------------|
1.963            1.988           2.001          2.014         2.039
 

B:
 
Mean             SD               MC Error        95% HPD interval
------------------------------------------------------------------
2.949            0.068            0.002            [ 2.812  3.079]
 
 
Posterior quantiles:
 
2.5             25              50              75             97.5
|---------------|===============|===============|---------------|
2.817            2.902           2.949          2.995         3.086
 

In [9]:
#plot the fitting
plt.plot(x, y_observe, 'o')
plt.plot(x, np.mean(mcmc.A_prior.trace())*np.arctan(x/np.mean(mcmc.B_prior.trace())), 'r', label = 'fitted line')
plt.xlabel('X', fontsize = 16)
plt.ylabel('Y', fontsize = 16)
plt.legend(fontsize = 16, loc = 2)
plt.show()
In [10]:
#let's plot the best solution with the true solution, you need corner as dependencies, e.g. sudo pip install corner
samples = array([mcmc.A_prior.trace(),mcmc.B_prior.trace()]).T
tmp = corner.corner(samples[:,:], labels=['A','B'], truths=[2, 3])

 

Thursday, October 1, 2015

How I begin machine learning

Today, one friend asked me about how to start to learn machine learning, I replied her the way I started and the resources I think is great, I listed here, hope it is also useful to others who want to learn machine learning. Machine learning as most of other discipline, is a matter of accumulation, so read more and exercise more, you will soon find machine learning is not that difficult, and fun to learn, good luck, and let me know if you have more questions. 

I started to learn Machine learning 2 or 3 years ago, here's how I learned it:

Programming:
Python and R are the most popular tools in data science, especially for small prototype project, so I learned python first, and now using python for all my stuff. R is really good too, especially for some statistical analysis, it may have better or easy ways to solve problem than python, but I just don't have time to learn R. So if you have time, learn both, otherwise, choose one, I recommend Python, after all, it is a general programming language that can do everything you want. 

Scala is another language I am learning, which is a functional programming language designed for scale up project (at least I think the name looks like scale ^)^), it is used in Apache Spark, which is one of the most popular framework for distributed computing, along with Hadoop, if you want to do data science, you'd better learn Spark for big data analysis. It has other api's, e.g. python, java, R, but scala is the best option if you are planning to use Spark in the future. 

Machine learning:
In the following I just put the resources I used to learn ML (also only good ones):

Online course:
(1) Learning from data, a very good course (and book too) for the basics from Caltech. It is a little theoretical than Ng's course on coursera, but it will give you a very nice foundation of machine learning.
(2) I guess Ng's machine learning course is the most popular one, and more practical, I think this is also the one you are talking about, it is a nice course as starting point, but he uses octave, which you will like if you use matlab. Anyway, after this course, you will only grab very shallow part of ML, if you go on youtube, Ng's video record from one semester's course, it has much more content than the coursera version, you can take it afterwards. 
(3) You also need good statistical background, which I didn't have when I started out, so I also took some statistical courses online, or you can read a related book. The one I took is Statistic One on coursera, which is kind of boring, but useful. 
(4) I also took Stanford's Introduction to statistical learning online, and read through the book, it is also a very good introduction course of ML
(5) Mining of massive datasets, another great course from Stanford, that covers more application of data science that used in industry. 

Books
My favorite part, I almost collected all popular machine learning books by now ^)^ But not read all of them ^)^
(1) Learning from data I talked above. 
(2) An introduction of statistical learning I talked above. You can use it while taking the class
(3) Machine learning by Tom Mitchell, very classical book, even though it is a bit outdated, it is still one of the best introduction book on ML
(4) Machine learning: An Algorithmic Perspective. A nice book focus on python implementation, I especially like the neural network chapter, very clear!
(5) Applied predictive model, one of my favorite, it covers a lot of stuff not in the above books but also very useful when you doing ML project.  
(6) All of statistics, a very nice and readable book to catch up with statistics. 
(7) Python Machine Learning, a very nice practical book if you want to quickly build models in python. 

After the above introduction books, you will have a very good working knowledge of machine learning, I then recommend to the two bible level books:
(8) Pattern Recognition and Machine learning. This is the most famous ML book, it is heavy on Bayesian point of view, even today, I haven't finish it from cover to cover, I only read the parts which I really interested, but it will take your ML skill to a higher level. 
(9) The elements of statistical learning. It is a great book too, but also very statistical ^)^ Both this book and the PRML book are not good for beginning ML, but improving your skills later.

Practice:
Like you said, the best way to learn machine learning is to work through easy project (but need to understand the underlying theory), so the following are the ones I think good for beginner:
(1) Kaggle definitely is a good place to play around, it has well defined questions and datasets, and also has the community to help you improve you skills when you ask questions. 
(2) UCI machine learning repository has many datasets you can try out
(3) My favorite machine learning lib is sklearn, go to browse their example gallery, and follow their tutorial, you will soon be able to apply it to various problems. 

Friday, May 22, 2015

Setup Hadoop using Sandbox

I am now learning Hadoop, and find the easiest way to setup the environment is to use Hortonworks Sandbox (I also tried to install everything using homebrew, and it took me much longer time to setup everything). I will just list the steps here to setup the environment, and hope this is something also useful to you.

Step 1 - install Sandbox and start it:
Download the Sandbox from here, I downloaded the one for VirtualBox (Mac & Windows). It is essentially setup a Linux server (RedHat) using Virtual Machine with all the needed package installed, e.g. Hadoop, Hive, pig, etc. Follow the instructions from the install guides pdf to start the Virtual Machine.

Step 2 - Login into the Linux server:
You can either use the provided GUI, or use SSH. I prefer working in terminal, so I use SSH.
$ssh root@127.0.0.1 -p 2222  #passwd: hadoop
If you want to put/get files from your local machine, then use the sftp:
$sftp -P 2222 root@127.0.0.1 #Note here the -P flag is upper case
To make things easier, just make alias in .bashrc file, then we can only type 'hssh' to login the server.
alias hssh='ssh root@127.0.0.1 -p 2222'
alias hsftp='sftp -P 2222 root@127.0.0.1'


Step 3 - SSH login without passwd
If you don't like to type the password every time you login, you can do the following:
(1) check if you already have .ssh folder in your home directory
     $ls -a ~/.ssh
(2) if you don't have the folder, then generate by using:
     $ssh-keygen
(3) Then put the generated key to the server.
    $scp -P 2222 ~/.ssh/id_rsa.pub root@127.0.0.1:~/.ssh/authorized_keys

Ok, now all set, and you can use it follow the Hortonworks tutorials.


Wednesday, May 13, 2015

Algorithms for the Ages

Top 10 algorithms in the 20th century

“Great algorithms are the poetry of computation,” says Francis Sullivan of the Institute for Defense Analyses' Center for Computing Sciences in Bowie, Maryland. He and Jack Dongarra of the University of Tennessee and Oak Ridge National Laboratory have put together a sampling that might have made Robert Frost beam with pride—had the poet been a computer jock. Their list of 10 algorithms having “the greatest influence on the development and practice of science and engineering in the 20th century” appears in the January/February issue of Computing in Science & Engineering. If you use a computer, some of these algorithms are no doubt crunching your data as you read this. The drum roll, please:
1946: The Metropolis Algorithm for Monte Carlo. Through the use of random processes, this algorithm offers an efficient way to stumble toward answers to problems that are too complicated to solve exactly.
1947: Simplex Method for Linear Programming. An elegant solution to a common problem in planning and decision-making.
1950: Krylov Subspace Iteration Method. A technique for rapidly solving the linear equations that abound in scientific computation.
1951: The Decompositional Approach to Matrix Computations. A suite of techniques for numerical linear algebra.
1957: The Fortran Optimizing Compiler. Turns high-level code into efficient computer-readable code.
1959: QR Algorithm for Computing Eigenvalues. Another crucial matrix operation made swift and practical.
1962: Quicksort Algorithms for Sorting. For the efficient handling of large databases.
1965: Fast Fourier Transform. Perhaps the most ubiquitous algorithm in use today, it breaks down waveforms (like sound) into periodic components.
1977: Integer Relation Detection. A fast method for spotting simple equations satisfied by collections of seemingly unrelated numbers.
1987: Fast Multipole Method. A breakthrough in dealing with the complexity of n-body calculations, applied in problems ranging from celestial mechanics to protein folding.
From: Random Samples, Science, page 799, February 4, 2000. 

Tuesday, May 12, 2015

Empirical Subspace Detection

After talked with the steps of the subspace detection algorithm in the previous blog, I read a paper on the Empirical subspace detection algorithm can be found here.

The idea of the Empirical subspace detection algorithm is this: After you have the design set (a matrix with the repeat waveforms that aligned on P wave), you don't need to calculate the SVD to find the orthogonal basis like the original subspace detection algorithm, instead you calculate the stacking of the waveforms in the design set, and the time derivative of the stacked waveform. The author of the paper found that the stacked waveform is similar to the first basis vector from the SVD, and the derivative of the stacked waveform is similar to the second basis vector. For the first one, it is quite easy to understand, the first basis contains the common features of all the waveforms, that is why it is mimic the stacking of the waveforms. But why the second basis vector is similar to the derivative of the stacked signal is not that easy to see. The author claims that the second singular vector represents information related to the variations produced by slight offsets in earthquake location of the design set earthquakes.

So this forms the empirical part of this algorithm: just use stacked waveform and the time derivative of the stacked waveform in the design set to represent the first two basis vector from the SVD (No need to calculate SVD in practice).

I went ahead to test this concept using some simulated signal, this is what I did:
(1) I generate a signal using Mexican hat wavelet, one pulse at a location to represent P wave, and the other pulse at a later location but with 2 times of the amplitude, then I add white noise in the background.
(2) I generate another 9 waveform based on the above signal but each shift the S wave a little step, (note: the first pulse are aligned to represent the P wave, and the second pulse shifted to represent the S wave shift due to the different location of the event), see the following figure as an example:
(3) I calculate the stacking of these signals, and the time derivative of the stacked signal.
(4) Then I compare the signal from step (3) with the first and second basis vector from the SVD.
(5) I plot the normalized comparison (scale the maximum amplitude to 1) in the following figures:

Conclusion: It does seem the author is correct that the stacked waveform, and the time derivative of the stacked waveform looks assemble the first two basis vector from SVD. For the derivative of the stacking, the S wave part matching with the second basis vector very well (similar results from the author's paper Fig. 4). I also tried different width of the pulse, you can find it in the code or the figures on my Github. Still I can not give a solid physical meaning why the time derivative of the stacking matches the 2nd basis vector. If you know the answer, please let me know ^)^

You can find my code to generate these figures here on my Github. The code will also generate results for different signal width of the Mexican hat wavelet to play with different frequency. Try it.

Acknowledgment: Thanks Taka for discussion, really helpful!