Assignment 2 for Course 1MS041¶
Make sure you pass the # ... Test cells and
submit your solution notebook in the corresponding assignment on the course website. You can submit multiple times before the deadline and your highest score will be used.
A courier company operates a fleet of delivery trucks that make deliveries to different parts of the city. The trucks are equipped with GPS tracking devices that record the location of each truck at regular intervals. The locations are divided into three regions: downtown, the suburbs, and the countryside. The following table shows the probabilities of a truck transitioning between these regions at each time step:
| Current region | Probability of transitioning to downtown | Probability of transitioning to the suburbs | Probability of transitioning to the countryside |
|---|---|---|---|
| Downtown | 0.3 | 0.4 | 0.3 |
| Suburbs | 0.2 | 0.5 | 0.3 |
| Countryside | 0.4 | 0.3 | 0.3 |
- If a truck is currently in the suburbs, what is the probability that it will be in the downtown region after two time steps? [1.5p]
- If a truck is currently in the suburbs, what is the probability that it will be in the downtown region the first time after two time steps? [1.5p]
- Is this Markov chain irreducible? [1.5p]
- What is the stationary distribution? [1.5p]
- Advanced question: What is the expected number of steps until the first time one enters the downtown region having started in the suburbs region. Hint: to get within 1 decimal point, it is enough to compute the probabilities for hitting times below 30. [2p]
# Part 1
# Fill in the answer to part 1 below as a decimal number
problem1_p1 = XXX
# Part 2
# Fill in the answer to part 2 below as a decimal number
problem1_p2 = XXX
# Part 3
# Fill in the answer to part 3 below as a boolean
problem1_irreducible = True/False
# Part 4
# Fill in the answer to part 4 below
# the answer should be a numpy array of length 3
# make sure that the entries sums to 1!
problem1_stationary = XXX
# Part 5
# Fill in the answer to part 5 below
# That is, the expected number of steps as a decimal number
problem1_ET = XXX
Use the Multi-dimensional Constrained Optimisation example (in 07-Optimization.ipynb) to numerically find the MLe for the mean and variance parameter based on normallySimulatedDataSamples, an array obtained by a specific simulation of $30$ IID samples from the $Normal(10,2)$ random variable.
Recall that $Normal(\mu, \sigma^2)$ RV has the probability density function given by:
$$ f(x ;\mu, \sigma) = \displaystyle\frac{1}{\sigma\sqrt{2\pi}}\exp\left(\frac{-1}{2\sigma^2}(x-\mu)^2\right) $$
The two parameters, $\mu \in \mathbb{R} := (-\infty,\infty)$ and $\sigma \in (0,\infty)$, are sometimes referred to as the location and scale parameters.
You know that the log likelihood function for $n$ IID samples from a Normal RV with parameters $\mu$ and $\sigma$ simply follows from $\sum_{i=1}^n \log(f(x_i; \mu,\sigma))$, based on the IID assumption.
NOTE: When setting bounding boxes for $\mu$ and $\sigma$ try to start with some guesses like $[-20,20]$ and $[0.1,5.0]$ and make it larger if the solution is at the boundary. Making the left bounding-point for $\sigma$ too close to $0.0$ will cause division by zero Warnings. Other numerical instabilities can happen in such iterative numerical solutions to the MLe. You need to be patient and learn by trial-and-error. You will see the mathematical theory in more details in a future course in scientific computing/optimisation. So don't worry too much now except learning to use it for our problems.
import numpy as np
from scipy import optimize
# do NOT change the next three lines
np.random.seed(123456) # set seed
# simulate 30 IID samples drawn from Normal(10,2)RV
normallySimulatedDataSamples = np.random.normal(10,2,30)
# define the negative log likelihoo function you want to minimise by editing XXX
def negLogLklOfIIDNormalSamples(parameters):
'''return the -log(likelihood) of normallySimulatedDataSamples with mean and var parameters'''
mu_param=parameters[0]
sigma_param=parameters[1]
XXX
XXX # add more or less lines as you need
return XXX
# you should only change XXX below and not anything else
parameter_bounding_box=((XXX, XXX), (XXX, XXX)) # specify the constraints for each parameter - some guess work...
initial_arguments = np.array([XXX, XXX]) # point in 2D to initialise the minimize algorithm
result_problem2_opt = optimize.minimize(XXX, initial_arguments, bounds=parameter_bounding_box, XXX)
# call the minimize method above finally! you need to play a bit to get initial conditions and bounding box ok
result_problem2_opt
Derive the maximum likelihood estimate for $n$ IID samples from a random variable with the following probability density function: $$ f(x; \lambda) = \frac{1}{24} \lambda^5 x^4 \exp(-\lambda x), \qquad \text{ where, } \lambda>0, x > 0 $$
You can solve the MLe by hand (using pencil paper or using key-strokes). Present your solution as the return value of a function called def MLeForAssignment2Problem3(x), where x is a list of $n$ input data points.
# do not change the name of the function, just replace XXX with the appropriate expressions for the MLe
def MLeForAssignment2Problem3(x):
'''write comment of what this function does'''
XXX
XXX
return XXX
Random variable generation and transformation¶
The purpose of this problem is to show that you can implement your own sampler, this will be built in the following three steps:
- [2p] Implement a Linear Congruential Generator where you tested out a good combination (a large $M$ with $a,b$ satisfying the Hull-Dobell (Thm 6.8)) of parameters. Follow the instructions in the code block.
- [2p] Using a generator construct random numbers from the uniform $[0,1]$ distribution.
- [4p] Using a uniform $[0,1]$ random generator, generate samples from
$$p_0(x) = \frac{\pi}{2}|\sin(2\pi x)|, \quad x \in [0,1] \enspace .$$
Using the Accept-Reject sampler (Algorithm 1 in TFDS notes) with sampling density given by the uniform $[0,1]$ distribution.
def problem4_LCG(size=None, seed = 0):
"""
A linear congruential generator that generates pseudo random numbers according to size.
Parameters
-------------
size : an integer denoting how many samples should be produced
seed : the starting point of the LCG, i.e. u0 in the notes.
Returns
-------------
out : a list of the pseudo random numbers
"""
XXX
return XXX
def problem4_uniform(generator=None, period = 1, size=None, seed=0):
"""
Takes a generator and produces samples from the uniform [0,1] distribution according
to size.
Parameters
-------------
generator : a function of type generator(size,seed) and produces the same result as problem1_LCG, i.e. pseudo random numbers in the range {0,1,...,period-1}
period : the period of the generator
seed : the seed to be used in the generator provided
size : an integer denoting how many samples should be produced
Returns
--------------
out : a list of the uniform pseudo random numbers
"""
XXX
return XXX
def problem4_accept_reject(uniformGenerator=None, n_iterations=None, seed=0):
"""
Takes a generator that produces uniform pseudo random [0,1] numbers
and produces samples from (pi/2)*abs(sin(x*2*pi)) using an Accept-Reject
sampler with the uniform distribution as the proposal distribution.
Runs n_iterations
Parameters
-------------
generator : a function of the type generator(size,seed) that produces uniform pseudo random
numbers from [0,1]
seed : the seed to be used in the generator provided
n_iterations : an integer denoting how many attempts should be made in the accept-reject sampler
Returns
--------------
out : a list of the pseudo random numbers with the specified distribution
"""
XXX
return XXX
Local Test for Assignment 2, PROBLEM 4¶
Evaluate cell below to make sure your answer is valid. You should not modify anything in the cell below when evaluating it to do a local test of your solution. You may need to include and evaluate code snippets from lecture notebooks in cells above to make the local test work correctly sometimes (see error messages for clues). This is meant to help you become efficient at recalling materials covered in lectures that relate to this problem. Such local tests will generally not be available in the exam.
# If you managed to solve all three parts you can test the following code to see if it runs
# you have to change the period to match your LCG though, this is marked as XXX.
# It is a very good idea to check these things using the histogram function in sagemath
# try with a larger number of samples, up to 10000 should run
print("LCG output: %s" % problem4_LCG(size=10, seed = 1))
period = XXX
print("Uniform sampler %s" % problem4_uniform(generator=problem4_LCG, period = period, size=10, seed=1))
uniform_sampler = lambda size,seed: problem4_uniform(generator=problem4_LCG, period = period, size=size, seed=seed)
print("Accept-Reject sampler %s" % problem4_accept_reject(uniformGenerator = uniform_sampler,n_iterations=20,seed=1))
# If however you did not manage to implement either part 1 or part 2 but still want to check part 3, you can run the code below
def testUniformGenerator(size,seed):
import random
random.seed(seed)
return [random.uniform(0,1) for s in range(size)]
print("Accept-Reject sampler %s" % problem4_accept_reject(uniformGenerator=testUniformGenerator, n_iterations=20, seed=1))