# Scenario A - Noise Level Variation (multiple runs for init mode)

In this scenario the noise level on a generated dataset is varied in three steps: low/medium/high,
the rest of the parameters in the dataset is kept constant.

The model used in the inference of the parameters is formulated as follows:

\begin{equation}
\large y = f(x) = \sum\limits_{m=1}^M \big[A_m \cdot e^{-\frac{(x-\mu_m)^2}{2\cdot\sigma_m^2}}\big] + \epsilon
\end{equation}

This file runs a series of runs for a single sampler init mode. It does not store the traces or plots, only the summary statistics are stored.

```python
%matplotlib inline
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import pymc3 as pm
import arviz as az

#az.style.use('arviz-darkgrid')

print('Running on PyMC3 v{}'.format(pm.__version__))
```

## Import local modules

```python
import datetime
import os
import sys
sys.path.append('../../modules')
import datagen as dg
import models as mdl
import results as res
import figures as fig
import settings as cnf
```

## Local configuration

```python
# output for results and images
out_path      = './output_mruns_lognormal_adapt'
file_basename = out_path + '/scenario_noise'

# if dir does not exist, create it
if not os.path.exists(out_path):
    os.makedirs(out_path)

conf = {}

# scenario name
conf['scenario'] = 'noise variation'

# initialization method for sampler ('jitter+adapt_diag'/'advi+adapt_diag'/'adapt_diag')
conf['init_mode'] = 'adapt_diag'

# probabilistic model (priors)
conf['prior_model'] = 'lognormal'

# provide peak positions to the model as testvalues ('yes'/'no')
conf['peak_info'] = 'yes'

# absolute peak shift (e.g. 2%(4), 5%(10) or 10%(20) of X-min.)
conf['peak_shift'] = 0.0

# dataset directory
conf['dataset_dir'] = './input_datasets'

# number of runs over the dataset
conf['nruns'] = 1

# number of cores to run
conf['ncores'] = 2

# number of samples per chain
conf['nsamples'] = 2000
```

```python
conf
```

## Save configuration

```python
cnf.save(out_path, conf)
```

# Generate data and plot

```python
# list of wavelengths (x-values)
xval = [i for i in range(200, 400, 2)]

ldata  = []
lpeaks = []

# number of spectra per noise level
nsets  = 10

# noise level is 1%, 2% and 5% of the minimal signal amplitude
noise_levels = [0.05, 0.10, 0.25]

# total number of datasets
tsets = nsets * len(noise_levels)

# load pre-generated datasets from disk
ldata, lpeaks, _ = dg.data_load(tsets, conf['dataset_dir'])

# add peakshift
lpeaks = dg.add_peakshift(lpeaks, conf['peak_shift'])
```

```python
# plot datasets
#fig.plot_datasets(ldata, lpeaks, dims=(int(tsets/2),2), figure_size=(12,int(tsets*(1.8))),
#                                                    savefig='yes', fname=file_basename)
```

# Initialize models and run inference

```python
# convert pandas data to numpy arrays
x_val = np.array(xval, dtype='float32')

# store dataset y-values in list
cols = ldata[0].columns
y_val = [ldata[i][cols].values for i in range(len(ldata))]
```

```python
# initialize models and run inference
models = []
traces = []

for r in range(conf['nruns']):
    print("running loop {0}/{1} over datasets".format(r+1,conf['nruns']))
    for i in range(len(ldata)):
        if conf['peak_info'] == 'yes':
            plist = lpeaks[i].flatten()
            plist.sort()
            model_g = mdl.model_pvoigt(xvalues=x_val, observations=y_val[i], npeaks=3,
                                      mu_peaks=plist, pmodel=conf['prior_model'])
        else:
            model_g = mdl.model_pvoigt(xvalues=x_val, observations=y_val[i], npeaks=3,
                                      pmodel=conf['prior_model'])
        models.append(model_g)

        with model_g:
            print("({0}:{1}) running inference on dataset #{2}/{3}".format(r+1,conf['nruns'],i+1,len(ldata)))
            trace_g = pm.sample(conf['nsamples'], init=conf['init_mode'], cores=conf['ncores'])
            traces.append(trace_g)
```

# Model visualization

```python
pm.model_to_graphviz(models[0])
```

```python
# save model figure as image
img = pm.model_to_graphviz(models[0])
img.render(filename=file_basename + '_model', format='png');
```

# Collect results and save

```python
# posterior predictive traces
ppc = [pm.sample_posterior_predictive(traces[i], samples=500, model=models[i]) for i in range(len(traces))]
```

```python
varnames = ['amp', 'mu', 'sigma', 'epsilon']
nruns = conf['nruns']

# total dataset y-values, noise and run number list
ly_val = [val for run in range(nruns) for idx, val in enumerate(y_val)]
lnoise = [nl for run in range(nruns) for nl in noise_levels for i in range(nsets)]
lruns = ['{0}'.format(run+1) for run in range(nruns) for i in range(tsets)]

# collect the results and display
df = res.get_results_summary(varnames, traces, ppc, ly_val, epsilon_real=lnoise, runlist=lruns)
df
```

```python
# save results to .csv
df.to_csv(file_basename + '.csv', index=False)
```

```python
cnf.close(out_path)
```


## Jupyter notebook illustrating  commands required to use Python 2.7 modules.  Reproduces Fig 3 in Physical Review E Article:

###Motion Blur Filtering: A Statistical Approach for Extracting  Confinement Forces & Diffusivity from a Single Blurred Trajectory

#####Author: Chris Calderon

Copyright 2015 Ursa Analytics, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0

### Cell below loads the required modules and packages

```python
%matplotlib inline
#command above avoids using the "dreaded" pylab flag when launching ipython (always put magic command above as first arg to ipynb file)

#load some standard scientific computing and plotting modules (code tested using Python 2.7.10, Scipy 0.15.1, and Matplotlib 1.4.3)
import numpy as np
import scipy.optimize as spo
import matplotlib.font_manager as font_manager
import matplotlib.pyplot as plt
####################################

#finally load custom modules provided with this repo
import findBerglundVersionOfMA1 #this module builds off of Berglund's 2010 PRE parameterization (atypical MA1 formulation)
import MotionBlurFilter
import Ursa_IPyNBpltWrapper

```

    <module 'findBerglundVersionOfMA1' from 'findBerglundVersionOfMA1.pyc'>

##Now that required modules packages are loaded, set parameters for simulating "Blurred" OU trajectories.  Specific mixed continuous/discrete model:

\begin{align}
dr_t = & ({v}-{\kappa} r_t)dt + \sqrt{2 D}dB_t \\
\psi_{t_i} = & \frac{1}{t_E}\int_{t_{i}-t_E}^{t_i} r_s ds + \epsilon^{\mathrm{loc}}_{t_i}
\end{align}

###In above equations, parameter vector specifying model is: $\theta = (\kappa,D,\sigma_{\mathrm{loc}},v)$

###Statistically exact discretization of above for uniform time spacing  $\delta$  (non-uniform $\delta$ requires time dependent vectors and matrices below):

\begin{align}
r_{t_{i+1}} = & A + F r_{t_{i}} + \eta_{t_i} \\
\psi_{t_i} = & H_A + H_Fr_{t_{i-1}} + \epsilon^{\mathrm{loc}}_{t_i} + \epsilon^{\mathrm{mblur}}_{t_i} \\
\epsilon^{\mathrm{loc}}_{t_i} + & \epsilon^{\mathrm{mblur}}_{t_i} \sim  \mathcal{N}(0,R_i) \\
\eta_i \sim & \mathcal{N}(0,Q) \\
t_{i-1} = & t_{i}-t_E \\
 C = & cov(\epsilon^{\mathrm{mblur}}_{t_i},\eta_{t_{i-1}}) \ne 0
\end{align}

####Note:  Kalman Filter (KF) and Motion Blur Filter (MBF) codes estimate $\sqrt(2D)$ directly as "thermal noise" parameter

```python
#set parameters determining state dynamics
kappa = 1. # units: [1/s]
v = 2. #units [microns/s]
D = .01 #units [microns^2/s]
twoDsqrt = np.sqrt(D*2.) #filter codes provided (KF and MBF) estimate square root of 2D directly.

#parmeters determining trajectory length, uniform spacing in time, and number of trajectories to analyze
#(Note: code is setup up to extract MLE on trajectorywise basis [trajectories not pooled])
T = 400 #length of each trajectory
delta = 25./1000. #spacing between observations.  code can be readily modified to handle non-uniform time spacing
Ntraj = 20 #number of trajectories to simulate and obtain MLE estimate (for quick illustration, can set to 1)
#(recommended to use notebook in small simulations and plots and write "production" script from modules provided)

#set parameters determining time dependent localization noise
#to simulate constant measurement noise just set sigF=sigB
sigF=30. #final localization in nm (state assumed to be in microns)
sigB=30. #initial localization in nm (state assumed to be in microns)

#set parameters for time dependent localization noise (simple exponential growth)
decay = -np.log(sigB/sigF)/T

Tsub = 100 #Parameter "numerically integrating" blur integral.  Exact OU process realized in simulations below,
#however "Tsub" parameter used to empirically simulate blur.  This is done to demonstrate that closed-form
#"blur" expressions derived in technical report are consistent with time integrated / averaged
#data (avoids potential self fulfilling prophecy issues).  As mentioned in paper, camera readout and other nuances
#of optical microscopy likely to manifest before this dicretization errors crops up.

```

###Cells below simulates "blurred" trajectories based on parameters defined above.  MLE, summary statistics of parameter distribution, and sample plots reproducing figure data also shown.

```python
np.random.seed(0) #set seed to allow reproducible graphs and data compared to results presented in paper
myoptmeth='nelder-mead' #set optimization for MLE search (recommended to use nelder-mead due to highly nonlinear nature of MLE)

res1=[];res2=[];res3=[]; #variables for storing MLE parameters computed over Ntraj trajectory simulations
#res1 stores directed diffusion result (obtained using modified Berglund 2010 approach adding in constant velocity)
#res2 stores the Motion Blur Filter estimates
#res3 stores the classic KF estimates

for i in range(Ntraj):

    #print progress bar
    print '\n','^'*100
    print 'Iteration ', i , '  ', '&'*50
    print '^'*100 ,'\n\n'

    #setup storage for noise input (used for time varying and constant localization simulations)
    locNoiseNonStat=[];locNoiseNonStatMag=[]

    #setup vector providing true (possibly) nonstationary noise magnitude
    for t in range(T):
        noisemag = sigF*np.exp(-decay*(T-t))
        locNoiseNonStatMag.append(noisemag)
        locNoiseNonStat.append(np.random.randn(1)*noisemag/1000.)

    locNoiseNonStat = np.array(locNoiseNonStat) #cast list for processing
    locNoiseNonStatMag =  np.array(locNoiseNonStatMag) #cast list for processing

    #bias the intial guess from the known simulated truth above; motion blur MLE should converge to "offset" below in large T limit
    offset = 15./1000.
    locNoiseNonStatMagGuess = (locNoiseNonStatMag/1000. - offset) #input a biased "cramer rao type" guess in microns
    pars=(kappa,twoDsqrt, offset,v)

###Done setting up time dependent measurement noise input and noise realization ##############
    #now simulate one trajectory of process
    xrawfull,xrawsampled,xblur   = MotionBlurFilter.simTimeIntegratedOUdeltaICvel(pars,delta,Tsub,1,T)
    #output "xrawsampled" and "xblur" above gives T samples of trajectory;  former gives exact position at t_i
    #and latter gives "motion blurred" observation (using Tsub observations and assuming uniform continuous illumination)

    print "True Pars",pars #print true data generating process (DGP) parameters

    ymeas=xblur+locNoiseNonStat #add measurement noise to "perfectly blurred" trajectory

    MA=findBerglundVersionOfMA1.CostFuncMA1Diff(ymeas,delta) #initiate instance of class object finding Berglund parameters
    #note this esimator attemps to find \theta = (sqrtD, \sigma_loca, v) [KF and MBF code attempts to find sqrt(2D) and Bergrlund
    #code provide attempts to find sqrt(D)]

    XtrueMA= np.array([pars[1]/np.sqrt(2),pars[2],pars[3]]) #set the true parameters based on the known simulation parameters

    #seed MA1 search with low quality estimate of truth based on true known DGP parameter (multiple truth by factor of 1/2).
    res = spo.minimize(MA.evalCostFuncVel, XtrueMA/2., method='nelder-mead',options={'xtol': 1e-5, 'disp': False})

    #store and print result
    res1.append(res.x)
    print 'MA res',res.x[0]*np.sqrt(2),res.x[1],res.x[-1]
    print '-'*100

    #use crude estimate of mean reversion parameter.  see Calderon, PRE (2013)
    kappa1 = np.log(np.sum(ymeas[1:]*ymeas[0:-1])/(np.sum(ymeas[0:-1]**2)-T*res.x[1]**2))/-delta

    #set initial parameter guess for filter guess
    parsIG=np.array([np.abs(kappa1),res.x[0]*np.sqrt(2),res.x[1],res.x[-1]]) #in practice, if reliable "StaticErrorEstSeq" provided, set offset par IG to zero.
    print 'parsIG for filters',parsIG

#   intitialize class object for filters of interest. setup code allowing for time varying noise to illustrate
#   the call sequence.  note: if optional "StaticErrorEstSeq" not defined, constant effective localization noise estimated.
    BlurF = MotionBlurFilter.ModifiedKalmanFilter1DwithCrossCorr(ymeas,delta,StaticErrorEstSeq=locNoiseNonStatMagGuess)
    KF = MotionBlurFilter.ClassicKalmanFilter(ymeas,delta,StaticErrorEstSeq=locNoiseNonStatMagGuess) #run side by side comparison of Rfixed and Rvarying

#   run KF MLE search (optmizatiion search for innovation MLE) with time varying or time constant noise
    resKF = spo.minimize(KF.evalCostFunc,parsIG, method=myoptmeth)
    print 'KF result:', resKF
    res3.append(resKF.x)

#     parsIG2=np.array(np.hstack((np.array([resKF.x[0],res.x[0]*np.sqrt(2),.00]),resKF.x[-1])))
    parsIG2=parsIG #set initial parameter for motion blur filter
    #(if comparing output, use same IG for both filters;  for produciton recommended to utilize KF drift pars for "warmer start")
    print 'parsIG for Motion Blur filter',parsIG2

#   run Motion Blur Filter search (optmizatiion search for innovation MLE) with time varying or time constant noise
    resBlur = spo.minimize(BlurF.evalCostFunc,parsIG2, method=myoptmeth)
    res2.append(resBlur.x)
    print 'Motion Blur result:',resBlur

    print '*'*100
    print 'True DGP',pars

#   store relevant statistics and filter estimates evaluated at MLE
#   below "xfilt" corresponds to filtered state estimate
#          "pit"  corresponds to PIT or generalized residual sequence evaluated at MLE
#          "Shist" correspond to variance of innovation sequence evaluated at MLE
#   suffix "2" after variable is used only to distinguish quantities computed with KF and MBF
    loglike,xfilt,pit,Shist =KF.KFfilterOU1d(resKF.x)
    loglike2,xfilt2,pit2,Shist2 =BlurF.KFfilterOU1d(resBlur.x)
    print '%'*100

    print 'run simple diagnostic check',np.std(pit),np.std(pit2)
    print 'correctly specied large sample PIT sequence should have std of uniform r.v. on [0,1] =',np.sqrt(1/12.)

#Box below outputs results of Ntraj optimizations

```

    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    Iteration  0    &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

    True Pars (1.0, 0.1414213562373095, 0.015, 2.0)
    MA res 0.175907307177 0.0286451845584 0.196276811177
    ----------------------------------------------------------------------------------------------------
    parsIG for filters [ 0.05840048  0.17590731  0.02864518  0.19627681]
    KF result:   status: 0
        nfev: 259
     success: True
         fun: -1.7816118189996721
           x: array([ 0.88321288,  0.13219046,  0.01378807,  1.761304  ])
     message: 'Optimization terminated successfully.'
         nit: 150
    parsIG for Motion Blur filter [ 0.05840048  0.17590731  0.02864518  0.19627681]
    Motion Blur result:   status: 0
        nfev: 332
     success: True
         fun: -1.7820111214180372
           x: array([ 0.88762266,  0.13191369,  0.015036  ,  1.76942183])
     message: 'Optimization terminated successfully.'
         nit: 197
    ****************************************************************************************************
    True DGP (1.0, 0.1414213562373095, 0.015, 2.0)
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    run simple diagnostic check 0.285613315409 0.285481381802
    correctly specied large sample PIT sequence should have std of uniform r.v. on [0,1] = 0.288675134595

    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    Iteration  1    &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

    True Pars (1.0, 0.1414213562373095, 0.015, 2.0)
    MA res 0.180275080116 0.0280898751699 0.206053907965
    ----------------------------------------------------------------------------------------------------
    parsIG for filters [ 0.0636527   0.18027508  0.02808988  0.20605391]
    KF result:   status: 0
        nfev: 315
     success: True
         fun: -1.8018405358423837
           x: array([ 1.06838838,  0.12047352,  0.01432375,  2.11645113])
     message: 'Optimization terminated successfully.'
         nit: 186
    parsIG for Motion Blur filter [ 0.0636527   0.18027508  0.02808988  0.20605391]
    Motion Blur result:   status: 0
        nfev: 291
     success: True
         fun: -1.8027395409237803
           x: array([ 1.07665046,  0.11978065,  0.01536691,  2.13169498])
     message: 'Optimization terminated successfully.'
         nit: 168
    ****************************************************************************************************
    True DGP (1.0, 0.1414213562373095, 0.015, 2.0)
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    run simple diagnostic check 0.291401742297 0.291449935183
    correctly specied large sample PIT sequence should have std of uniform r.v. on [0,1] = 0.288675134595

    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    Iteration  2    &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

    True Pars (1.0, 0.1414213562373095, 0.015, 2.0)
    MA res 0.193412787309 0.0282994208113 0.207220724622
    ----------------------------------------------------------------------------------------------------
    parsIG for filters [ 0.05363553  0.19341279  0.02829942  0.20722072]
    KF result:   status: 0
        nfev: 331
     success: True
         fun: -1.7657439109280539
           x: array([ 0.96648687,  0.13027198,  0.01475058,  2.06001836])
     message: 'Optimization terminated successfully.'
         nit: 193
    parsIG for Motion Blur filter [ 0.05363553  0.19341279  0.02829942  0.20722072]
    Motion Blur result:   status: 0
        nfev: 364
     success: True
         fun: -1.7663072942584879
           x: array([ 0.97167261,  0.12972404,  0.01594395,  2.07033799])
     message: 'Optimization terminated successfully.'
         nit: 216
    ****************************************************************************************************
    True DGP (1.0, 0.1414213562373095, 0.015, 2.0)
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    run simple diagnostic check 0.288479380977 0.288368470363
    correctly specied large sample PIT sequence should have std of uniform r.v. on [0,1] = 0.288675134595

    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    Iteration  3    &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

    True Pars (1.0, 0.1414213562373095, 0.015, 2.0)
    MA res 0.187074141668 0.02790284586 0.200641311879
    ----------------------------------------------------------------------------------------------------
    parsIG for filters [ 0.04950885  0.18707414  0.02790285  0.20064131]
    KF result:   status: 0
        nfev: 286
     success: True
         fun: -1.7950980130734999
           x: array([ 0.95222337,  0.12305581,  0.0142633 ,  2.01230926])
     message: 'Optimization terminated successfully.'
         nit: 166
    parsIG for Motion Blur filter [ 0.04950885  0.18707414  0.02790285  0.20064131]
    Motion Blur result:   status: 0
        nfev: 318
     success: True
         fun: -1.7959151217527227
           x: array([ 0.95836817,  0.12249424,  0.01534194,  2.02440771])
     message: 'Optimization terminated successfully.'
         nit: 190
    ****************************************************************************************************
    True DGP (1.0, 0.1414213562373095, 0.015, 2.0)
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    run simple diagnostic check 0.28765452627 0.287690639899
    correctly specied large sample PIT sequence should have std of uniform r.v. on [0,1] = 0.288675134595

    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    Iteration  4    &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

    True Pars (1.0, 0.1414213562373095, 0.015, 2.0)
    MA res 0.178419903459 0.0278526230763 0.188761089053
    ----------------------------------------------------------------------------------------------------
    parsIG for filters [ 0.05226267  0.1784199   0.02785262  0.18876109]
    KF result:   status: 0
        nfev: 337
     success: True
         fun: -1.8348428972788715
           x: array([ 1.12689466,  0.10663008,  0.01446761,  2.19069464])
     message: 'Optimization terminated successfully.'
         nit: 203
    parsIG for Motion Blur filter [ 0.05226267  0.1784199   0.02785262  0.18876109]
    Motion Blur result:   status: 0
        nfev: 367
     success: True
         fun: -1.8360135448587829
           x: array([ 1.13539293,  0.10574436,  0.01529597,  2.20629983])
     message: 'Optimization terminated successfully.'
         nit: 219
    ****************************************************************************************************
    True DGP (1.0, 0.1414213562373095, 0.015, 2.0)
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    run simple diagnostic check 0.293458821959 0.293328559322
    correctly specied large sample PIT sequence should have std of uniform r.v. on [0,1] = 0.288675134595

    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    Iteration  5    &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

    True Pars (1.0, 0.1414213562373095, 0.015, 2.0)
    MA res 0.186280027776 0.0293925583954 0.180174070797
    ----------------------------------------------------------------------------------------------------
    parsIG for filters [ 0.04696911  0.18628003  0.02939256  0.18017407]
    KF result:   status: 0
        nfev: 329
     success: True
         fun: -1.7711341943067758
           x: array([ 1.14266335,  0.11730292,  0.01602799,  2.21670929])
     message: 'Optimization terminated successfully.'
         nit: 197
    parsIG for Motion Blur filter [ 0.04696911  0.18628003  0.02939256  0.18017407]
    Motion Blur result:   status: 0
        nfev: 264
     success: True
         fun: -1.7721927897784893
           x: array([ 1.15171076,  0.11645313,  0.0169724 ,  2.23336651])
     message: 'Optimization terminated successfully.'
         nit: 156
    ****************************************************************************************************
    True DGP (1.0, 0.1414213562373095, 0.015, 2.0)
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    run simple diagnostic check 0.288996936979 0.289043131259
    correctly specied large sample PIT sequence should have std of uniform r.v. on [0,1] = 0.288675134595

    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    Iteration  6    &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

    True Pars (1.0, 0.1414213562373095, 0.015, 2.0)
    MA res 0.184095772425 0.0275236589229 0.21329626156
    ----------------------------------------------------------------------------------------------------
    parsIG for filters [ 0.06584774  0.18409577  0.02752366  0.21329626]
    KF result:   status: 0
        nfev: 255
     success: True
         fun: -1.7784511245601069
           x: array([ 0.83040854,  0.13843115,  0.01318085,  1.71173949])
     message: 'Optimization terminated successfully.'
         nit: 148
    parsIG for Motion Blur filter [ 0.06584774  0.18409577  0.02752366  0.21329626]
    Motion Blur result:   status: 0
        nfev: 245
     success: True
         fun: -1.7788429246239732
           x: array([ 0.8348035 ,  0.13813615,  0.01457631,  1.71996066])
     message: 'Optimization terminated successfully.'
         nit: 148
    ****************************************************************************************************
    True DGP (1.0, 0.1414213562373095, 0.015, 2.0)
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    run simple diagnostic check 0.286036281475 0.286014703043
    correctly specied large sample PIT sequence should have std of uniform r.v. on [0,1] = 0.288675134595

    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    Iteration  7    &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

    True Pars (1.0, 0.1414213562373095, 0.015, 2.0)
    MA res 0.173703884015 0.0279647007169 0.179916722204
    ----------------------------------------------------------------------------------------------------
    parsIG for filters [ 0.04910047  0.17370388  0.0279647   0.17991672]
    KF result:   status: 0
        nfev: 299
     success: True
         fun: -1.819354535407057
           x: array([ 0.91544121,  0.10844909,  0.01479815,  1.83256298])
     message: 'Optimization terminated successfully.'
         nit: 178
    parsIG for Motion Blur filter [ 0.04910047  0.17370388  0.0279647   0.17991672]
    Motion Blur result:   status: 0
        nfev: 277
     success: True
         fun: -1.8199109810934644
           x: array([ 0.91989023,  0.10792052,  0.0156346 ,  1.84092257])
     message: 'Optimization terminated successfully.'
         nit: 163
    ****************************************************************************************************
    True DGP (1.0, 0.1414213562373095, 0.015, 2.0)
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    run simple diagnostic check 0.289694854082 0.289631512406
    correctly specied large sample PIT sequence should have std of uniform r.v. on [0,1] = 0.288675134595

    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    Iteration  8    &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

    True Pars (1.0, 0.1414213562373095, 0.015, 2.0)
    MA res 0.188215597178 0.0269994088316 0.216667997164
    ----------------------------------------------------------------------------------------------------
    parsIG for filters [ 0.06422321  0.1882156   0.02699941  0.216668  ]
    KF result:   status: 0
        nfev: 265
     success: True
         fun: -1.7932492982747963
           x: array([ 0.94576666,  0.13863911,  0.01257289,  1.96197588])
     message: 'Optimization terminated successfully.'
         nit: 159
    parsIG for Motion Blur filter [ 0.06422321  0.1882156   0.02699941  0.216668  ]
    Motion Blur result:   status: 0
        nfev: 356
     success: True
         fun: -1.793787957850205
           x: array([ 0.95159787,  0.13825233,  0.01400534,  1.97310477])
     message: 'Optimization terminated successfully.'
         nit: 212
    ****************************************************************************************************
    True DGP (1.0, 0.1414213562373095, 0.015, 2.0)
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    run simple diagnostic check 0.286814497063 0.286791636248
    correctly specied large sample PIT sequence should have std of uniform r.v. on [0,1] = 0.288675134595

    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    Iteration  9    &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

    True Pars (1.0, 0.1414213562373095, 0.015, 2.0)
    MA res 0.179609600041 0.030135398726 0.206122359837
    ----------------------------------------------------------------------------------------------------
    parsIG for filters [ 0.05733093  0.1796096   0.0301354   0.20612236]
    KF result:   status: 0
        nfev: 329
     success: True
         fun: -1.7542946186397506
           x: array([ 0.90577464,  0.12218299,  0.01610827,  1.89101766])
     message: 'Optimization terminated successfully.'
         nit: 198
    parsIG for Motion Blur filter [ 0.05733093  0.1796096   0.0301354   0.20612236]
    Motion Blur result:   status: 0
        nfev: 305
     success: True
         fun: -1.7549470719605487
           x: array([ 0.91123791,  0.12180469,  0.01710078,  1.90155201])
     message: 'Optimization terminated successfully.'
         nit: 180
    ****************************************************************************************************
    True DGP (1.0, 0.1414213562373095, 0.015, 2.0)
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    run simple diagnostic check 0.292213041023 0.29215551921
    correctly specied large sample PIT sequence should have std of uniform r.v. on [0,1] = 0.288675134595

    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    Iteration  10    &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

    True Pars (1.0, 0.1414213562373095, 0.015, 2.0)
    MA res 0.194900445992 0.0283714116274 0.205820756514
    ----------------------------------------------------------------------------------------------------
    parsIG for filters [ 0.0590164   0.19490045  0.02837141  0.20582076]
    KF result:   status: 0
        nfev: 328
     success: True
         fun: -1.7525821894420677
           x: array([ 1.0647229 ,  0.14388608,  0.01384812,  2.14976121])
     message: 'Optimization terminated successfully.'
         nit: 193
    parsIG for Motion Blur filter [ 0.0590164   0.19490045  0.02837141  0.20582076]
    Motion Blur result:   status: 0
        nfev: 316
     success: True
         fun: -1.7532432748105589
           x: array([ 1.07257618,  0.14340374,  0.01532623,  2.16457573])
     message: 'Optimization terminated successfully.'
         nit: 187
    ****************************************************************************************************
    True DGP (1.0, 0.1414213562373095, 0.015, 2.0)
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    run simple diagnostic check 0.28829640342 0.288308540313
    correctly specied large sample PIT sequence should have std of uniform r.v. on [0,1] = 0.288675134595

    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    Iteration  11    &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

    True Pars (1.0, 0.1414213562373095, 0.015, 2.0)
    MA res 0.197334942057 0.0290480614739 0.199004552797
    ----------------------------------------------------------------------------------------------------
    parsIG for filters [ 0.05919837  0.19733494  0.02904806  0.19900455]
    KF result:   status: 0
        nfev: 409
     success: True
         fun: -1.7459830489424366
           x: array([ 1.25650871,  0.14116223,  0.01457918,  2.49654596])
     message: 'Optimization terminated successfully.'
         nit: 240
    parsIG for Motion Blur filter [ 0.05919837  0.19733494  0.02904806  0.19900455]
    Motion Blur result:   status: 0
        nfev: 280
     success: True
         fun: -1.746986461108919
           x: array([ 1.2684877 ,  0.1405289 ,  0.01597022,  2.519055  ])
     message: 'Optimization terminated successfully.'
         nit: 164
    ****************************************************************************************************
    True DGP (1.0, 0.1414213562373095, 0.015, 2.0)
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    run simple diagnostic check 0.288754955165 0.288719360422
    correctly specied large sample PIT sequence should have std of uniform r.v. on [0,1] = 0.288675134595

    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    Iteration  12    &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

    True Pars (1.0, 0.1414213562373095, 0.015, 2.0)
    MA res 0.193917779937 0.0318583407875 0.225408115617
    ----------------------------------------------------------------------------------------------------
    parsIG for filters [ 0.07115509  0.19391778  0.03185834  0.22540812]
    KF result:   status: 0
        nfev: 241
     success: True
         fun: -1.6707425509809044
           x: array([ 0.89667894,  0.14400119,  0.01758656,  1.85653446])
     message: 'Optimization terminated successfully.'
         nit: 143
    parsIG for Motion Blur filter [ 0.07115509  0.19391778  0.03185834  0.22540812]
    Motion Blur result:   status: 0
        nfev: 275
     success: True
         fun: -1.6713130272545018
           x: array([ 0.9030943 ,  0.14360298,  0.01889992,  1.86861869])
     message: 'Optimization terminated successfully.'
         nit: 164
    ****************************************************************************************************
    True DGP (1.0, 0.1414213562373095, 0.015, 2.0)
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    run simple diagnostic check 0.291513384799 0.291525556841
    correctly specied large sample PIT sequence should have std of uniform r.v. on [0,1] = 0.288675134595

    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    Iteration  13    &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

    True Pars (1.0, 0.1414213562373095, 0.015, 2.0)
    MA res 0.189613568266 0.0270429289772 0.205770106527
    ----------------------------------------------------------------------------------------------------
    parsIG for filters [ 0.06021629  0.18961357  0.02704293  0.20577011]
    KF result:   status: 0
        nfev: 301
     success: True
         fun: -1.7938974338279612
           x: array([ 1.00674634,  0.13555701,  0.0129385 ,  2.01148602])
     message: 'Optimization terminated successfully.'
         nit: 178
    parsIG for Motion Blur filter [ 0.06021629  0.18961357  0.02704293  0.20577011]
    Motion Blur result:   status: 0
        nfev: 401
     success: True
         fun: -1.7944560004444496
           x: array([ 1.01285176,  0.13510527,  0.0142972 ,  2.02282412])
     message: 'Optimization terminated successfully.'
         nit: 237
    ****************************************************************************************************
    True DGP (1.0, 0.1414213562373095, 0.015, 2.0)
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    run simple diagnostic check 0.292981807175 0.292953038738
    correctly specied large sample PIT sequence should have std of uniform r.v. on [0,1] = 0.288675134595

    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    Iteration  14    &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

    True Pars (1.0, 0.1414213562373095, 0.015, 2.0)
    MA res 0.194330340556 0.0288702933224 0.199792254314
    ----------------------------------------------------------------------------------------------------
    parsIG for filters [ 0.05698324  0.19433034  0.02887029  0.19979225]
    KF result:   status: 0
        nfev: 297
     success: True
         fun: -1.7649921120067014
           x: array([ 1.30710326,  0.1347985 ,  0.01447312,  2.59080402])
     message: 'Optimization terminated successfully.'
         nit: 175
    parsIG for Motion Blur filter [ 0.05698324  0.19433034  0.02887029  0.19979225]
    Motion Blur result:   status: 0
        nfev: 296
     success: True
         fun: -1.7663656487863773
           x: array([ 1.32167031,  0.13397275,  0.01575428,  2.61815275])
     message: 'Optimization terminated successfully.'
         nit: 181
    ****************************************************************************************************
    True DGP (1.0, 0.1414213562373095, 0.015, 2.0)
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    run simple diagnostic check 0.282963569253 0.283246496977
    correctly specied large sample PIT sequence should have std of uniform r.v. on [0,1] = 0.288675134595

    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    Iteration  15    &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

    True Pars (1.0, 0.1414213562373095, 0.015, 2.0)
    MA res 0.199466126155 0.0270517479867 0.189480681513
    ----------------------------------------------------------------------------------------------------
    parsIG for filters [ 0.05250734  0.19946613  0.02705175  0.18948068]
    KF result:   status: 0
        nfev: 284
     success: True
         fun: -1.7815960663061923
           x: array([ 1.23927392,  0.14201206,  0.01286312,  2.42660898])
     message: 'Optimization terminated successfully.'
         nit: 168
    parsIG for Motion Blur filter [ 0.05250734  0.19946613  0.02705175  0.18948068]
    Motion Blur result:   status: 0
        nfev: 337
     success: True
         fun: -1.7825488249738688
           x: array([ 1.25042906,  0.14134119,  0.01435858,  2.44731256])
     message: 'Optimization terminated successfully.'
         nit: 199
    ****************************************************************************************************
    True DGP (1.0, 0.1414213562373095, 0.015, 2.0)
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    run simple diagnostic check 0.286652721106 0.286726183977
    correctly specied large sample PIT sequence should have std of uniform r.v. on [0,1] = 0.288675134595

    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    Iteration  16    &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

    True Pars (1.0, 0.1414213562373095, 0.015, 2.0)
    MA res 0.181770781739 0.0299852505464 0.204829006816
    ----------------------------------------------------------------------------------------------------
    parsIG for filters [ 0.06361031  0.18177078  0.02998525  0.20482901]
    KF result:   status: 0
        nfev: 281
     success: True
         fun: -1.7394700657355295
           x: array([ 0.9036258 ,  0.12509471,  0.01645436,  1.79985445])
     message: 'Optimization terminated successfully.'
         nit: 167
    parsIG for Motion Blur filter [ 0.06361031  0.18177078  0.02998525  0.20482901]
    Motion Blur result:   status: 0
        nfev: 290
     success: True
         fun: -1.7399846909498822
           x: array([ 0.90879913,  0.12458333,  0.01749916,  1.80930691])
     message: 'Optimization terminated successfully.'
         nit: 174
    ****************************************************************************************************
    True DGP (1.0, 0.1414213562373095, 0.015, 2.0)
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    run simple diagnostic check 0.288502426997 0.288499032876
    correctly specied large sample PIT sequence should have std of uniform r.v. on [0,1] = 0.288675134595

    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    Iteration  17    &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

    True Pars (1.0, 0.1414213562373095, 0.015, 2.0)
    MA res 0.210896574385 0.0249763436522 0.184601696119
    ----------------------------------------------------------------------------------------------------
    parsIG for filters [ 0.04467303  0.21089657  0.02497634  0.1846017 ]
    KF result:   status: 0
        nfev: 274
     success: True
         fun: -1.7764986370199787
           x: array([ 1.01321982,  0.16901656,  0.00958725,  2.06463929])
     message: 'Optimization terminated successfully.'
         nit: 158
    parsIG for Motion Blur filter [ 0.04467303  0.21089657  0.02497634  0.1846017 ]
    Motion Blur result:   status: 0
        nfev: 318
     success: True
         fun: -1.7769121211717924
           x: array([ 1.01930224,  0.16871457,  0.0119127 ,  2.07633927])
     message: 'Optimization terminated successfully.'
         nit: 188
    ****************************************************************************************************
    True DGP (1.0, 0.1414213562373095, 0.015, 2.0)
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    run simple diagnostic check 0.292483784038 0.292426308881
    correctly specied large sample PIT sequence should have std of uniform r.v. on [0,1] = 0.288675134595

    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    Iteration  18    &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

    True Pars (1.0, 0.1414213562373095, 0.015, 2.0)
    MA res 0.182308544841 0.0269785365972 0.193720665184
    ----------------------------------------------------------------------------------------------------
    parsIG for filters [ 0.05850637  0.18230854  0.02697854  0.19372067]
    KF result:   status: 0
        nfev: 308
     success: True
         fun: -1.8181279429756163
           x: array([ 1.04727541,  0.12265195,  0.01338526,  2.05958426])
     message: 'Optimization terminated successfully.'
         nit: 180
    parsIG for Motion Blur filter [ 0.05850637  0.18230854  0.02697854  0.19372067]
    Motion Blur result:   status: 0
        nfev: 343
     success: True
         fun: -1.8188199057631909
           x: array([ 1.05403159,  0.12206421,  0.01449626,  2.07202637])
     message: 'Optimization terminated successfully.'
         nit: 200
    ****************************************************************************************************
    True DGP (1.0, 0.1414213562373095, 0.015, 2.0)
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    run simple diagnostic check 0.290090782068 0.289964968298
    correctly specied large sample PIT sequence should have std of uniform r.v. on [0,1] = 0.288675134595

    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    Iteration  19    &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

    True Pars (1.0, 0.1414213562373095, 0.015, 2.0)
    MA res 0.209075624778 0.0269907020043 0.199816557616
    ----------------------------------------------------------------------------------------------------
    parsIG for filters [ 0.05044755  0.20907562  0.0269907   0.19981656]
    KF result:   status: 0
        nfev: 295
     success: True
         fun: -1.7467132433806367
           x: array([ 1.06907685,  0.1641132 ,  0.01166758,  2.19272865])
     message: 'Optimization terminated successfully.'
         nit: 180
    parsIG for Motion Blur filter [ 0.05044755  0.20907562  0.0269907   0.19981656]
    Motion Blur result:   status: 0
        nfev: 357
     success: True
         fun: -1.7472847913697027
           x: array([ 1.0767594 ,  0.1637405 ,  0.01370832,  2.2075416 ])
     message: 'Optimization terminated successfully.'
         nit: 219
    ****************************************************************************************************
    True DGP (1.0, 0.1414213562373095, 0.015, 2.0)
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    run simple diagnostic check 0.292555792722 0.29247798074
    correctly specied large sample PIT sequence should have std of uniform r.v. on [0,1] = 0.288675134595

```python
#Summarize the results of the above Ntraj simulations (increase Ntraj to get more precise MLE par distributions)
#
#this block is useful for when one wishes to explore statistical MLE performance under different parameters and
#sampling conditions

resSUM=np.array(res2)
print 'Blur medians',np.median(resSUM[:,0]),np.median(resSUM[:,1]),np.median(resSUM[:,2]),np.median(resSUM[:,3])
print 'means',np.mean(resSUM[:,0]),np.mean(resSUM[:,1]),np.mean(resSUM[:,2]),np.mean(resSUM[:,3])
print 'std',np.std(resSUM[:,0]),np.std(resSUM[:,1]),np.std(resSUM[:,2]),np.std(resSUM[:,3])

print '^'*100 ,'\n\n'

resSUM=np.array(res3)
print 'KF medians',np.median(resSUM[:,0]),np.median(resSUM[:,1]),np.median(resSUM[:,2]),np.median(resSUM[:,3])
print 'means',np.mean(resSUM[:,0]),np.mean(resSUM[:,1]),np.mean(resSUM[:,2]),np.mean(resSUM[:,3])
print 'std',np.std(resSUM[:,0]),np.std(resSUM[:,1]),np.std(resSUM[:,2]),np.std(resSUM[:,3])

print '*'*100
print 'True DGP Parameters',pars
```

    Blur medians 1.01607699998 0.132943219858 0.0153340832695 2.07118218241
    means 1.03434743784 0.132464061743 0.0153748525719 2.08384109425
    std 0.132913117729 0.0156196678532 0.00147863475233 0.238072307324
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

    KF medians 1.00998307772 0.133494482257 0.0142935210055 2.05980130726
    means 1.02707462651 0.132996029723 0.0140832244426 2.07016649811
    std 0.130381692882 0.0155220233256 0.00173124482052 0.23337518562
    ****************************************************************************************************
    True DGP Parameters (1.0, 0.1414213562373095, 0.015, 2.0)

### Now plot results shown in Technical Report Figure in Notebook Title

```python
#setup trajectory and MSD plot in shared x-axis plot
fig,ax,axTop,pltPars = Ursa_IPyNBpltWrapper.sharedXPltSetup(axisfontsize='22',legendfontsize='18')

#setup grid for blur and fully sampled state time grid
t1=np.arange(xrawsampled.shape[0])
t1sub = np.arange(xrawfull.shape[0])/float(Tsub)
t2=(t1+.5)*delta #evaluate at midpoint as well
t1=(t1+1)*delta #xrawsampled is at endpoint (done to keep xblur and xrawsampled same size)

ix = 0
neongreen=[51/255., 214/255., 51/255.]
axTop.plot(t2,ymeas[:,ix],'-', label='Meas. Pos.',color=neongreen,linewidth=3)
vKF=[];vB=[];vTrue=[]; #store velocity information evaluated at truth and filtered/MLE estimates
vB.append(-xfilt2*resBlur.x[0]+resBlur.x[-1])
vKF.append(-xfilt*resKF.x[0]+resKF.x[-1])
vTrue.append(-xrawsampled[:,ix]*pars[0]+pars[-1])

#tweak graph limits and appearance
axTop.yaxis.set_ticks(np.arange(0,4.,1.))

#adjust font on axis font
Ursa_IPyNBpltWrapper.xyLabels(axTop,pltPars,xlabel='',ylabel='') #adjust font style and size in main plot

#setup "time lag" grid to use in MSD computation
tlag = np.arange(1,T,10)
tlag,MSD = findBerglundVersionOfMA1.MSD(ymeas,tlag) #evaluate MSD at tlag obs points above
tlag = tlag*delta #evalute magntidue of time lag for plotting

ax.plot(tlag,MSD,'-',linewidth=3)
print pars,resBlur.x
L = np.sqrt(6*(twoDsqrt)**2/kappa)
# ax.plot(tlag,np.ones(len(MSD))*(L**2/6.),'r--',linewidth=5,label='Exact MSD Plateau')
print L*1000

#print the MSD estimate using the last 3/4 of MSD [not unreasonable given shape, but
#usually MSD truncation is typically quite heuristic with the "lag cutoff"; this adds additional error on top of time aggregation ]
print 'MSD mean', np.mean(np.array(MSD[25:]))

#tweak graph limits and appearance

ax.set_xlim([0,10])
ax.xaxis.set_ticks(np.arange(0,12,2))
ax.set_ylim([-.1,6.2])
ax.yaxis.set_ticks(np.arange(1,7.,2.))
ax.set_ylim([-.1,3.])
ax.yaxis.set_ticks(np.arange(0,3.,1.))

Ursa_IPyNBpltWrapper.xyLabels(ax,pltPars,xlabel='',ylabel='') #adjust font style and size in main plot (Helvetica default)

# fig.savefig('Fig3_MSDandTraj' + '.png',dpi=600)
```

```python
systemTemp = 310 #[specify Temp in Kelvin]
kT = 1.38064852e-23*1e12*1e6*systemTemp #k_B*T in units of pN*micron at specified temperature

#recall from code and note at beginnig of this document:
#       force in MBF and KF estimates sqrt(2D), but Einstein relation assumes fric = D/kT.  rescale for this fact here.
forceScaleTrue = kT/(twoDsqrt**2)*2.
forceScaleKF = kT/(resKF.x[1]**2)*2.
forceScaleBerglund = kT/(res.x[0]**2) #this estimator estimates sqrt(D), so no factor of two needed
forceScaleBlur = kT/(resBlur.x[1]**2)*2.

fig,ax,pltPars = Ursa_IPyNBpltWrapper.basicPltSetup(axisfontsize='22') #standard plot
vNaive=(ymeas[1:]-ymeas[:-1])/delta

orange=[255/255.,153/255.,51/255.]

ax.plot(t1,np.array(vTrue[0])*forceScaleTrue,'-',linewidth=2,color='c',label='True Force = $F(t)$')
ax.plot(t1,vB[0]*forceScaleBlur,'k--',linewidth=3,label='MBF MLE Force = $\hat{F}(t)$')
ax.plot(t1,np.ones(t1.shape)*res.x[-1]*forceScaleBerglund,'r:',linewidth=3,label='Berglund MLE Force = $\hat{F}$')

#lgd = ax.legend(loc='upper right', fancybox=True, framealpha=0.5,ncol=1,numpoints=1,prop=pltPars['leg_prop'],labelspacing=.1)
#Note call above requires some OS specific tweaks.  this font adjustment has been removed, but the data displayed is identitical
lgd = ax.legend(loc='upper right', fancybox=True, framealpha=0.5,ncol=1,numpoints=1,labelspacing=.1)

Ursa_IPyNBpltWrapper.xyLabels(ax,pltPars,xlabel='',ylabel='') #adjust font style and size in main plot (Helvetica default)

#save plot
# fig.savefig('Fig3_ForceTraj' + '.png',dpi=600)
```

###Now plot info from example appearing in Supp. Mat.

```python
fig,ax,pltPars = Ursa_IPyNBpltWrapper.basicPltSetup(axisfontsize='22') #standard plot
vNaive=(ymeas[1:]-ymeas[:-1])/delta #compute the naive FD estimate

orange=[255/255.,153/255.,51/255.]
ax.plot(t1,vTrue[0],'-',linewidth=2,color=orange,label='True Velocity = $v - \kappa r_t$')
ax.plot(t1,vB[0],'k--',linewidth=3,label='MBF MLE = $\hat{v} - \hat{\kappa} r_{t|t}$')
ax.plot(t1,np.ones(t1.shape)*res.x[-1],'r:',linewidth=3,label='Berglund MLE = $\hat{v}$')

#set limits for velocity plot
ax.set_xlim([0,10])
ax.xaxis.set_ticks(np.arange(0,12,2))
ax.set_ylim([-1.,2.5])
ax.yaxis.set_ticks(np.arange(-1,3.,.5))

lgd = ax.legend(loc='upper right', fancybox=True, framealpha=0.5,ncol=1,numpoints=1,labelspacing=.1)
Ursa_IPyNBpltWrapper.xyLabels(ax,pltPars,xlabel='',ylabel='') #adjust font style and size in main plot (Helvetica default)

# ax.plot(vNaive,'-',color=grey,linewidth=.5)
# fig.savefig('Fig3_VelTraj' + '.png',dpi=600)
```

```python
#now plot the finite difference estimate of velocity to show problems with attempting to take simple "time limits"
#of a nondifferentiable stochastic process (e.g., any SDE driven by Brownian motion)

fig,ax,pltPars = Ursa_IPyNBpltWrapper.basicPltSetup(axisfontsize='22') #standard plot
grey = (148/255., 148/255., 156/255.) #set custom RGB color
ax.plot(t1[1:],vNaive,'-',linewidth=1,label='$(r_{t} - r_{t-1})/\delta$',color=grey)
ax.plot(t1,np.ones(t1.shape)*res.x[-1],'r-',linewidth=4,label='Berglund MLE = $\hat{v}$')
ax.plot(t1,np.ones(t1.shape)*np.mean(vNaive),'b--',linewidth=3,label='Time Avg. $(r_{t} - r_{t-1})/\delta$')
ax.set_xlim([0,10])
ax.xaxis.set_ticks(np.arange(0,12,2))
ax.set_ylim([-14.,10])
ax.yaxis.set_ticks(np.arange(-12,12.,3))

lgd = ax.legend(loc='lower right', fancybox=True, framealpha=0.5,ncol=1,numpoints=1,labelspacing=.1)
Ursa_IPyNBpltWrapper.xyLabels(ax,pltPars,xlabel='',ylabel='') #adjust font style and size in main plot (Helvetica default)
fig.savefig('Fig3_VelFD' + '.png',dpi=600)
```


```python
%matplotlib inline
```

高级专题: 做动态决策 和 Bi-LSTM CRF
======================================================

动态Vs静态深度学习工具包
--------------------------------------------

Pytorch 是一种 *动态* 神经网络工具箱。动态工具包的另一个例子是 `Dynet <https://github.com/clab/dynet>`__
(我提到这一点，因为Pytorch和Dynet是相似的。 如果您在Dynet中看到一个示例，它可能会帮助您在Python中实现它)。
相反的是 *静态* 工具包，包括Theano、Keras、TensorFlow等。其核心区别是:

* 在静态工具箱中，您只定义一次计算图，编译它，然后将实例流入它。
* 在动态工具箱中，为 *每个实例* 定义一个计算图。它从来不被编译，并且是实时执行的。

如果没有丰富的经验，就很难理解其中的不同之处。一个例子是假设我们想要构建一个深层成分解析器(deep constituent parser)。
假设我们的模型大致包括以下步骤：

* 我们自底向上构建树
* 标记根节点 (句子的单子)
* 从那里，使用神经网络和单词的嵌入，以找到形成成分的组合。
  每当您形成一个新的成分时，都要使用某种技术来获得该成分的嵌入。
  在这种情况下，我们的网络体系结构将完全依赖于输入语句。在“The green cat scratched the wall”这个句子中，在模型的某一点上，
  我们希望组合跨度(span) $(i,j,r) = (1, 3, \text{NP})$ (即NP成分跨越单词1到单词3，在本例中是"The green cat")。

然而，另一个句子可能是"Somewhere, the big fat cat scratched the wall" 。在这个句子中，我们要在某一点上形成成分 $(2, 4, NP)$ 。
我们想要形成的成分将取决于实例。如果我们只编译一次计算图，就像在静态工具箱中一样，那么编程这个深层成分解析器的逻辑将是非常困难或不可能的。
然而，在动态工具箱中，并不只有一个预定义的计算图。每个实例都可以有一个新的计算图，所以这根本就不是个问题。

动态工具包还具有更易于调试的优点，而且代码更类似于宿主语言(host language)(我的意思是，与Keras或Theano相比，
Pytorch和Dynet看起来更像真正的Python代码)。

Bi-LSTM 条件随机场(CRFs)的讨论
-------------------------------------------

对于本节，我们将看到一个完整的，复杂的例子：用于命名实体(named-entity)识别的Bi-LSTM条件随机场。上面的LSTM标记器对于词性标注来说通常是足够的，
但是像CRF这样的序列模型对于在NER上的强大性能来说是非常重要的。假设你熟悉条件随机场(CRF)。虽然这个名字听起来很吓人，所有的模型都是CRF，
只是LSTM为这些CRF模型提供了特征。不过，这仍然是一个高级模型，比本教程中的任何早期模型都要复杂得多。
如果你想跳过它，那也很好。看你是否准备好了，看看你能不能:

-  Write the recurrence for the viterbi variable at step i for tag k.
-  Modify the above recurrence to compute the forward variables instead.
-  Modify again the above recurrence to compute the forward variables in
   log-space (hint: log-sum-exp)

如果你能做这三件事，你应该能够理解下面的代码。回想一下CRF咋样计算条件概率的。让 $y$ 是标记序列，$x$ 是单词的输入序列。然后我们计算

\begin{align}P(y|x) = \frac{\exp{(\text{Score}(x, y)})}{\sum_{y'} \exp{(\text{Score}(x, y')})}\end{align}

其中，分数是通过定义一些 log potentials $\log \psi_i(x,y)$ 来确定的，这样就有下式：

\begin{align}\text{Score}(x,y) = \sum_i \log \psi_i(x,y)\end{align}

要使分区函数(partition function)易于处理，the potentials 必须只考虑局部特征。

在Bi-LSTM CRF中，我们定义了两种势(potentials)：发射势(emission)和跃迁势(transition)。
在索引 $i$ 处单词的emission来自Bi-LSTM在第 $i$ 步的隐藏状态。
transition scores 存储在一个 $|T|x|T|$ 矩阵 $\textbf{P}$ 中，其中 $T$ 是标记集(tag set)。
在我的实现中，$\textbf{P}_{j,k}$ 是从标记 $k$ 跃迁到标记 $j$ 的得分。因此:

\begin{align}\text{Score}(x,y) = \sum_i \log \psi_\text{EMIT}(y_i \rightarrow x_i) + \log \psi_\text{TRANS}(y_{i-1} \rightarrow y_i)\end{align}

\begin{align}= \sum_i h_i[y_i] + \textbf{P}_{y_i, y_{i-1}}\end{align}

其中在第二个表达式中, 我们认为标签被分配了唯一的非负索引。

如果你觉得上面的讨论过于简单, 你可以查看 `这个 <http://www.cs.columbia.edu/%7Emcollins/crf.pdf>`__
来自 Michael Collins 所写的关于 CRFs 的内容。

实现笔记
--------------------

下面的例子实现了对数空间中的前向算法来计算分区函数(partition function)，并实现了Viterbi算法来解码。
反向传播将自动为我们计算梯度。我们不需要手工做任何事。

这里的实现并没有进行优化。如果您了解正在发生的事情，您可能很快就会看到，
前向算法中的下一个标记的迭代其实更适合在一个大操作中完成的。
我想要代码更易读，所以并没有将其放在大操作中。
如果您想要进行相关的更改，可以将这个标记器(tagger)用于实际任务。

```python
# Author: Robert Guthrie

import torch
import torch.autograd as autograd
import torch.nn as nn
import torch.optim as optim

torch.manual_seed(1)
```

辅助函数使代码更具可读性。

```python
def argmax(vec):
    # return the argmax as a python int
    _, idx = torch.max(vec, 1)
    return idx.item()

def prepare_sequence(seq, to_ix):
    idxs = [to_ix[w] for w in seq]
    return torch.tensor(idxs, dtype=torch.long)

# Compute log sum exp in a numerically stable way for the forward algorithm
def log_sum_exp(vec):
    max_score = vec[0, argmax(vec)]
    max_score_broadcast = max_score.view(1, -1).expand(1, vec.size()[1])
    return max_score + \
        torch.log(torch.sum(torch.exp(vec - max_score_broadcast)))
```

创建模型

```python
class BiLSTM_CRF(nn.Module):

    def __init__(self, vocab_size, tag_to_ix, embedding_dim, hidden_dim):
        super(BiLSTM_CRF, self).__init__()
        self.embedding_dim = embedding_dim
        self.hidden_dim = hidden_dim
        self.vocab_size = vocab_size
        self.tag_to_ix = tag_to_ix
        self.tagset_size = len(tag_to_ix)

        self.word_embeds = nn.Embedding(vocab_size, embedding_dim)
        self.lstm = nn.LSTM(embedding_dim, hidden_dim // 2,
                            num_layers=1, bidirectional=True)

        # Maps the output of the LSTM into tag space.
        self.hidden2tag = nn.Linear(hidden_dim, self.tagset_size)

        # Matrix of transition parameters.  Entry i,j is the score of
        # transitioning *to* i *from* j.
        self.transitions = nn.Parameter(
            torch.randn(self.tagset_size, self.tagset_size))

        # These two statements enforce the constraint that we never transfer
        # to the start tag and we never transfer from the stop tag
        self.transitions.data[tag_to_ix[START_TAG], :] = -10000
        self.transitions.data[:, tag_to_ix[STOP_TAG]] = -10000

        self.hidden = self.init_hidden()

    def init_hidden(self):
        return (torch.randn(2, 1, self.hidden_dim // 2),
                torch.randn(2, 1, self.hidden_dim // 2))

    def _forward_alg(self, feats):
        # Do the forward algorithm to compute the partition function
        init_alphas = torch.full((1, self.tagset_size), -10000.)
        # START_TAG has all of the score.
        init_alphas[0][self.tag_to_ix[START_TAG]] = 0.

        # Wrap in a variable so that we will get automatic backprop
        forward_var = init_alphas

        # Iterate through the sentence
        for feat in feats:
            alphas_t = []  # The forward tensors at this timestep
            for next_tag in range(self.tagset_size):
                # broadcast the emission score: it is the same regardless of
                # the previous tag
                emit_score = feat[next_tag].view(
                    1, -1).expand(1, self.tagset_size)
                # the ith entry of trans_score is the score of transitioning to
                # next_tag from i
                trans_score = self.transitions[next_tag].view(1, -1)
                # The ith entry of next_tag_var is the value for the
                # edge (i -> next_tag) before we do log-sum-exp
                next_tag_var = forward_var + trans_score + emit_score
                # The forward variable for this tag is log-sum-exp of all the
                # scores.
                alphas_t.append(log_sum_exp(next_tag_var).view(1))
            forward_var = torch.cat(alphas_t).view(1, -1)
        terminal_var = forward_var + self.transitions[self.tag_to_ix[STOP_TAG]]
        alpha = log_sum_exp(terminal_var)
        return alpha

    def _get_lstm_features(self, sentence):
        self.hidden = self.init_hidden()
        embeds = self.word_embeds(sentence).view(len(sentence), 1, -1)
        lstm_out, self.hidden = self.lstm(embeds, self.hidden)
        lstm_out = lstm_out.view(len(sentence), self.hidden_dim)
        lstm_feats = self.hidden2tag(lstm_out)
        return lstm_feats

    def _score_sentence(self, feats, tags):
        # Gives the score of a provided tag sequence
        score = torch.zeros(1)
        tags = torch.cat([torch.tensor([self.tag_to_ix[START_TAG]], dtype=torch.long), tags])
        for i, feat in enumerate(feats):
            score = score + \
                self.transitions[tags[i + 1], tags[i]] + feat[tags[i + 1]]
        score = score + self.transitions[self.tag_to_ix[STOP_TAG], tags[-1]]
        return score

    def _viterbi_decode(self, feats):
        backpointers = []

        # Initialize the viterbi variables in log space
        init_vvars = torch.full((1, self.tagset_size), -10000.)
        init_vvars[0][self.tag_to_ix[START_TAG]] = 0

        # forward_var at step i holds the viterbi variables for step i-1
        forward_var = init_vvars
        for feat in feats:
            bptrs_t = []  # holds the backpointers for this step
            viterbivars_t = []  # holds the viterbi variables for this step

            for next_tag in range(self.tagset_size):
                # next_tag_var[i] holds the viterbi variable for tag i at the
                # previous step, plus the score of transitioning
                # from tag i to next_tag.
                # We don't include the emission scores here because the max
                # does not depend on them (we add them in below)
                next_tag_var = forward_var + self.transitions[next_tag]
                best_tag_id = argmax(next_tag_var)
                bptrs_t.append(best_tag_id)
                viterbivars_t.append(next_tag_var[0][best_tag_id].view(1))
            # Now add in the emission scores, and assign forward_var to the set
            # of viterbi variables we just computed
            forward_var = (torch.cat(viterbivars_t) + feat).view(1, -1)
            backpointers.append(bptrs_t)

        # Transition to STOP_TAG
        terminal_var = forward_var + self.transitions[self.tag_to_ix[STOP_TAG]]
        best_tag_id = argmax(terminal_var)
        path_score = terminal_var[0][best_tag_id]

        # Follow the back pointers to decode the best path.
        best_path = [best_tag_id]
        for bptrs_t in reversed(backpointers):
            best_tag_id = bptrs_t[best_tag_id]
            best_path.append(best_tag_id)
        # Pop off the start tag (we dont want to return that to the caller)
        start = best_path.pop()
        assert start == self.tag_to_ix[START_TAG]  # Sanity check
        best_path.reverse()
        return path_score, best_path

    def neg_log_likelihood(self, sentence, tags):
        feats = self._get_lstm_features(sentence)
        forward_score = self._forward_alg(feats)
        gold_score = self._score_sentence(feats, tags)
        return forward_score - gold_score

    def forward(self, sentence):  # dont confuse this with _forward_alg above.
        # Get the emission scores from the BiLSTM
        lstm_feats = self._get_lstm_features(sentence)

        # Find the best path, given the features.
        score, tag_seq = self._viterbi_decode(lstm_feats)
        return score, tag_seq
```

运行训练

```python
START_TAG = "<START>"
STOP_TAG = "<STOP>"
EMBEDDING_DIM = 5
HIDDEN_DIM = 4

# Make up some training data
training_data = [(
    "the wall street journal reported today that apple corporation made money".split(),
    "B I I I O O O B I O O".split()
), (
    "georgia tech is a university in georgia".split(),
    "B I O O O O B".split()
)]

word_to_ix = {}
for sentence, tags in training_data:
    for word in sentence:
        if word not in word_to_ix:
            word_to_ix[word] = len(word_to_ix)

tag_to_ix = {"B": 0, "I": 1, "O": 2, START_TAG: 3, STOP_TAG: 4}

model = BiLSTM_CRF(len(word_to_ix), tag_to_ix, EMBEDDING_DIM, HIDDEN_DIM)
optimizer = optim.SGD(model.parameters(), lr=0.01, weight_decay=1e-4)

# Check predictions before training
with torch.no_grad():
    precheck_sent = prepare_sequence(training_data[0][0], word_to_ix)
    precheck_tags = torch.tensor([tag_to_ix[t] for t in training_data[0][1]], dtype=torch.long)
    print(model(precheck_sent))

# Make sure prepare_sequence from earlier in the LSTM section is loaded
for epoch in range(
        300):  # again, normally you would NOT do 300 epochs, it is toy data
    for sentence, tags in training_data:
        # Step 1. Remember that Pytorch accumulates gradients.
        # We need to clear them out before each instance
        model.zero_grad()

        # Step 2. Get our inputs ready for the network, that is,
        # turn them into Tensors of word indices.
        sentence_in = prepare_sequence(sentence, word_to_ix)
        targets = torch.tensor([tag_to_ix[t] for t in tags], dtype=torch.long)

        # Step 3. Run our forward pass.
        loss = model.neg_log_likelihood(sentence_in, targets)

        # Step 4. Compute the loss, gradients, and update the parameters by
        # calling optimizer.step()
        loss.backward()
        optimizer.step()

# Check predictions after training
with torch.no_grad():
    precheck_sent = prepare_sequence(training_data[0][0], word_to_ix)
    print(model(precheck_sent))
# We got it!
```

练习: 一个用于判别标记的新的损失函数
--------------------------------------------------------

在解码时，我们没有必要创建一个计算图，因为我们不会从viterbi路径分数反向传播。
既然我们有它，试着训练标记器，其中损失函数是viterbi路径分数和gold-standard路径分数之间的差异。
应该清楚的是，这个函数是非负的，当预测的标记序列是正确的标记序列时是0。
这本质上是结构化感知器(*structured perceptron*)。

这个修改应该是短的，因为Viterbi和 score\_sentence 已经实现了。这是计算图的形状取决于训练实例的一个例子。
虽然我还没有尝试在静态工具箱中实现这一点，我认为这是可能的，但却要复杂得多。

选择一些真实数据并作比较!


```python
import numpy as np
import pandas as pd
import linearsolve as ls
import matplotlib.pyplot as plt
plt.style.use('classic')
%matplotlib inline
```

# Class 19: Optimal Monetary Policy in the New-Keynesian Model

In this notebook, we will derive and compute the optimal monetary policy response to exogenous shocks in the new-Keynesian model.

## The New-Keynesian Model

Consider the New-Keynesian model without a specification for monetary policy:

\begin{align}
y_t & = E_t y_{t+1}  - \left( r_{t} - \bar{r}\right) + g_t\\
i_{t} & = r_{t} + E_t \pi_{t+1}\\
\pi_t & = \beta E_t\pi_{t+1}  + \kappa y_t+ u_t,
\end{align}

where $\bar{y}$ and $\pi^T$ have been set to zero. We can interpret $y$ as the output gap (log difference of output from steady state). The system above has three equations, but four endogenous variables: $y_t$, $\pi_t$, $i_t$, and $r_t$ ($u_t$ and $g_t$ are exogenous to the system). Previously, we closed the model by assuming a *rule* for monetary that specified the nominal interest rate as a linear function of inflation and output. Here we will derive optimal monetary policy.

## The Optimization Problem

Suppose that the central bank has preferences over inflation and output in period $t$ is represented by the *loss function*:

\begin{align}
L\left(\pi_t, y_t\right) & = \frac{1}{2}\bigg[\pi_t^2 + \lambda y_t^2\bigg].
\end{align}

The loss function reflects the degree of disutility that the central bank incurs when inflation and the output gap are different from zero. $\lambda$ denotes the weight that the central bank places on output fluctuations. If $\lambda =0$, then central bank cares only about inflation stabilization. A value for $\lambda>0$ means that the central bank wants to stabilize output and inflation. In the US, the Fed is required by law to promote inflation *and* employment stability and so $\lambda>0$ would make sense for a model of the Fed's decisionmaking.

The unconstrained minimum of $L$ is obtained at $\pi_t= 0$ and $y_t = 0$. But often this is not feasible given the constraints of the model. To see why, note that the new-Keynesian Phillips curve imposes a constraint on the feasible combinations of output and inflation. Therefore, the central bank's optimization problem is to solve:

\begin{align}
\min_{\pi, y} \frac{1}{2}\bigg[\pi^2 + \lambda y^2\bigg]
\end{align}

subject to:

\begin{align}
\pi & = \beta \pi' + \kappa y + u
\end{align}

where time subscripts have been dropped. $\pi'$ means expected inflation next period.

The problem can be recast as an unconstrained optimization problem by substituting the Phillips curve into the loss function to eliminate inflation:

\begin{align}
\min_{y} \frac{1}{2}\bigg[\left(\beta \pi' + \kappa y + u\right)^2 + \lambda y^2\bigg]
\end{align}

The first-order condition with respect to $y$ is:

\begin{align}
\kappa \underbrace{\left(\beta \pi' + \kappa y + u\right)}_{\pi} + \lambda y & = 0
\end{align}

or:

\begin{align}
\pi & = -\frac{\lambda}{\kappa}y
\end{align}

Since the central bank solves the same problem in each period, we have the final equation for the system given in the first section:

\begin{align}
\boxed{\pi_t  = -\frac{\lambda}{\kappa}y_t}
\end{align}

This equation expresses the optimal outcome of monetary policy. It should maintain a fixed proportional relationship between output and inflation that depends only on $\lambda$ and $\kappa$. Given this equation, the optimal setting of the nominal interest rate is determined by the IS and Fisher equations.

## Exogenous Shocks and Parameters

As usual, the variables $g_t$ and $u_t$ represent exogenous shocks to aggregate demand and inflation. They follow AR(1) processes:

\begin{align}
g_{t+1} & = \rho_g g_{t} + \epsilon^g_{t+1}\\
u_{t+1} & = \rho_u u_{t} + \epsilon^u_{t+1}.
\end{align}

We will use the following parameterization in the simulations below:

| $$\beta$$ | $$\bar{r}$$    | $$\kappa$$ | $$\rho_g$$ | $$\rho_u$$ | $$\lambda$$ |
|-----------|----------------|------------|------------|------------|-------------|
| 0.995     | $$-\log\beta$$ | 0.25       | 0.5        | 0.5        | 0.1         |

I have assumed a value of 0.1 for $\lambda$, the weight on ouput in the loss function. This value is in the range of estimates for the Fed's loss function.

```python
# Create a variable called 'parameters' that stores the model parameter values (except lambda) in a Pandas Series. PROVIDED
parameters = pd.Series({'beta':0.995,'r_bar':-np.log(0.995),'kappa':0.25,'rho_g':0.5,'rho_u':0.5})

# Add the value for lambda as 'lam' to 'parameters'
parameters['lam'] = 0.1

# Create variable called 'var_names' that stores the variable names in a list with state variables ordered first. PROVIDED
var_names = ['g','u','y','pi','i','r']

# Create variable called 'shock_names' that stores an exogenous shock name for each state variable. PROVIDED
shock_names = ['e_g','e_u']

# Define a function that evaluates the equilibrium conditions of the model solved for zero. PROVIDED
def equilibrium_equations(variables_forward,variables_current,parameters):

    # Parameters. PROVIDED
    p = parameters

    # Current variables. PROVIDED
    cur = variables_current

    # Forward variables. PROVIDED
    fwd = variables_forward

    # IS equation. PROVIDED
    is_equation = fwd.y - (cur.r -p.r_bar) + cur.g - cur.y

    # Fisher_equation. PROVIDED
    fisher_equation = cur.r + fwd.pi - cur.i

    # Monetary policy. Variable name: 'monetary_policy'
    monetary_policy = p.lam*cur.y  + p.kappa*cur.pi

    # Phillips curve. PROVIDED
    phillips_curve = p.beta*fwd.pi + p.kappa*cur.y + cur.u - cur.pi

    # Demand process. PROVIDED
    demand_process = p.rho_g*cur.g - fwd.g

    # Inflation process. PROVIDED
    inflation_process = p.rho_u*cur.u - fwd.u

    # Stack equilibrium conditions into a numpy array. PROVIDED
    return np.array([is_equation,fisher_equation,monetary_policy,phillips_curve,demand_process,inflation_process])

# Initialize the model into a variable named 'nk_model'. PROVIDED
nk_model = ls.model(equations = equilibrium_equations,n_states=2,var_names=var_names,shock_names=shock_names,parameters = parameters)

# Compute the steady state numerically using .compute_ss() method of nk_model. PROVIDED
nk_model.compute_ss([0,0,0,0.01,0.01,0.01])

# Find the log-linear approximation around the non-stochastic steady state and solve using .approximate_and_solve() method of nk_model
# set argumement 'log_linear' to False because the model is already log-linear.
nk_model.approximate_and_solve(log_linear = False)
```

## Optimal Responses to Shocks

Compute a 21 period impulse responses of the model's variables to a 0.01 unit shock to the exogenous component of  demand ($g_t$) and a 0.01/4 unit shock to the exogenous component of inflation ($u_t$) in period 5.

```python
# Compute the desired impulse responses
nk_model.impulse(shocks=[0.01,0.01/4],T=21,t0=5)
```

### Demand Shocks

Plot the impulse responses of output and inflation to the demand shock. Multiply output by 100 and multiply inflation by 400 (to annualize the values).

```python
# Create figure. PROVIDED
fig = plt.figure(figsize=(12,4))

# Create left subplot. PROVIDED
ax1 = fig.add_subplot(1,2,1)
# Create right subplot. PROVIDED
ax2 = fig.add_subplot(1,2,2)

# Left subplot title. PROVIDED
ax1.set_title('Output $y_t$')
# Right subplot title. PROVIDED
ax2.set_title('Inflation $\pi_t$')

# Left subplot y-axis label. PROVIDED
ax1.set_ylabel('Percent')
# Right subplot y-axis label. PROVIDED
ax2.set_ylabel('Percent')

# Plot output on left axis
ax1.plot(nk_model.irs['e_g']['y']*100,lw=4)

# Plot inflation on right axis
ax2.plot(nk_model.irs['e_g']['pi']*400,lw=4)
```

Apparently optimal policy entails perfectly offsetting demand shocks so that output and inflation are perfectly stabilized. This is because there is no tradeoff in stabilizing output versus inflation in the face of a demand shock.

### Inflation Shocks

Plot the impulse responses of output and inflation to the inflation shock. Multiply output by 100 and multiply inflation by 400.

```python
# Create figure. PROVIDED
fig = plt.figure(figsize=(12,4))

# Create left subplot. PROVIDED
ax1 = fig.add_subplot(1,2,1)
# Create right subplot. PROVIDED
ax2 = fig.add_subplot(1,2,2)

# Left subplot title. PROVIDED
ax1.set_title('Output $y_t$')
# Right subplot title. PROVIDED
ax2.set_title('Inflation $\pi_t$')

# Left subplot y-axis label. PROVIDED
ax1.set_ylabel('Percent')
# Right subplot y-axis label. PROVIDED
ax2.set_ylabel('Percent')

# Plot output on left axis
ax1.plot(nk_model.irs['e_u']['y']*100,lw=4)

# Plot inflation on right axis
ax2.plot(nk_model.irs['e_u']['pi']*400,lw=4)

```

The Phillips curve implies that there *is* a tradeoff in stabilizing output versus inflation in the face of an inflation shock. The optimal policy is to allow inflation to rise and to allow output to fall so that the full force of the shock does not fall on inflation.

## Stochastic Simulation with Optimal Monetary Policy

Now we simulate how would output and inflation evolve if monetary policy were set optimally. Specifically, construct a 201 period stochastic simulation with the seed for the random number generator set to 126. Note that the shock covariance matrix for the model is:

\begin{align}
\text{Covariance matrix} & = \left[\begin{array}{cc}\sigma_g^2 & 0\\ 0 & \sigma_u^2\end{array}\right]
\end{align}

Use the following values for $\sigma_g$ and $\sigma_u$ in the simulation:

| $$\sigma_g$$ | $$\sigma_u$$ |
|--------------|--------------|
| 0.015        | 0.003        |

```python
# Define variable 'sig_g' equal to the the standard deviation of sigma_g
sig_g = 0.015

# Define variable 'sig_u' equal to the the standard deviation of sigma_u
sig_u = 0.003

# Compute simulation
nk_model.stoch_sim(cov_mat = [[sig_g**2,0],[0,sig_u**2]],T=201,seed=126)
```

Plot the simulated values of output and inflation.

```python
# Create figure. PROVIDED
fig = plt.figure(figsize=(12,4))
# Create subplot. PROVIDED
ax = fig.add_subplot(1,1,1)
# Add plot title. PROVIDED
ax.set_title('Output and inflation under optimal monetary policy')
# y-axis label. PROVIDED
ax.set_ylabel('Percent')

# Plot output
(nk_model.simulated['y']*100).plot(lw=2,label='output')

# Plot inflation
(nk_model.simulated['pi']*400).plot(lw=2,label='inflation')

# Construct legend. PROVIDED
ax.legend(loc='center left', bbox_to_anchor=(1, 0.5))

# Add grid
ax.grid()
```

Compute the correlations of output and inflation under optimal monetary policy.

```python
# Correlations of output and inflation
nk_model.simulated[['y','pi']].corr()
```

      y
      pi

      y
      1.0
      -1.0

      pi
      -1.0
      1.0

By requiring that output be proportional to inflation, the optimal monetary policy implies perfect negative correlation between output and inflation. All demand shocks are neutralized.


```python
import numpy as np
import matplotlib.pyplot as plt
#import pandas as pd
```

```python
import torch
import torchvision
import torch.nn as nn
import torch.nn.functional as F
from torch.autograd import Variable
from torchvision import datasets, transforms, models
from torch import optim
from torch.utils.data import DataLoader
```

```python
datapath="../datasets/fashion_mnist/"
```

```python
n_epochs = 10
learning_rate = 0.01
batch_size = 64
```

```python
def dataset_labels(i):
    return ["T-shirt/top", "Trouser", "Pullover", "Dress", "Coat", "Sandal", "Shirt", "Sneaker", "Bag", "Ankle boot"][i]
```

```python
training_set = datasets.FashionMNIST(root=datapath, download=False, train=True, transform=transforms.ToTensor())
test_set = datasets.FashionMNIST(root=datapath, download=False, train=False, transform=transforms.ToTensor())

training_loader = torch.utils.data.DataLoader(training_set, batch_size=batch_size, shuffle=True, num_workers=2)
test_loader = torch.utils.data.DataLoader(test_set, batch_size=batch_size, shuffle=True, num_workers=2)

n_training_samples, img_width, img_height = training_set.train_data.shape
```

#### Plot to check how images look like

```python
rand_idxs = np.random.randint(n_training_samples, size=9)
f, a = plt.subplots(nrows=3, ncols=3, figsize=(10, 5))

for i in range(9):
    X = training_set.train_data[rand_idxs[i]]
    Y = training_set.train_labels[rand_idxs[i]]

    r, c = i //3, i%3
    a[r][c].set_title(dataset_labels(Y))
    a[r][c].axis("off")
    a[r][c].imshow(X.numpy())

plt.draw()
```

### Simple CNN model for Fashion MNIST dataset

#### Use GPU if available

```python
use_gpu=False
if torch.cuda.is_available():
    use_gpu=True
```

### Dimensions of the image after convolution and pooling
We use the formulae:
1. For Convolution:
$$\begin{align}
W_{out} = \dfrac{(W_{in} - F + 2P)}{S} + 1 \newline
H_{out} = \dfrac{(H_{in} - F + 2P)}{S} + 1 \newline
\end{align}$$

For Pooling:
    $$\begin{align}
    W_{out} = \dfrac{W_{in} - F}{S} + 1 \newline
    H_{out} = \dfrac{H_{in} - F}{S} + 1 \newline
    \end{align}$$

    where we assume the filter is square shaped  and the dilation etc are set to default values.

```python
class simpleCNN(nn.Module):
    def __init__(self):
        super(simpleCNN, self).__init__()
        self.convlayer1 = nn.Conv2d(in_channels=1, out_channels=10, kernel_size=5)
        self.convlayer2 = nn.Conv2d(in_channels=10, out_channels=20, kernel_size=3)
        self.poollayer1 = nn.MaxPool2d(kernel_size=2)
        self.convlayer3 = nn.Conv2d(in_channels=20, out_channels=30, kernel_size=3)
        self.ReLU = nn.ReLU()

        self.fc1 = nn.Linear( 30*4*4, 20) # 4*4 is the shape of the final image
        self.fc2 = nn.Linear(20, 10)

    def forward(self, x):
        x = self.ReLU(self.convlayer1(x))
        x = self.ReLU(self.convlayer2(x))
        x = self.poollayer1(x)
        x = self.ReLU(self.convlayer3(x))
        x = self.poollayer1(x)
        x = x.view(-1, 30*4*4)
        x = self.ReLU( self.fc1(x))
        x = self.fc2(x)

        return x

print(simpleCNN())
```

    simpleCNN(
      (convlayer1): Conv2d(1, 10, kernel_size=(5, 5), stride=(1, 1))
      (convlayer2): Conv2d(10, 20, kernel_size=(3, 3), stride=(1, 1))
      (poollayer1): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
      (convlayer3): Conv2d(20, 30, kernel_size=(3, 3), stride=(1, 1))
      (ReLU): ReLU()
      (fc1): Linear(in_features=480, out_features=20, bias=True)
      (fc2): Linear(in_features=20, out_features=10, bias=True)
    )

### Initialize the CNN, Loss criterion, and optimizer

```python
fmnistCNN = simpleCNN()
if use_gpu:
    #fmnistCNN = fmnistCNN.cuda()
    fmnistCNN.cuda()
lossfn = nn.CrossEntropyLoss() #Cross Entropy loss since this is a classification problem
#optimizer = optim.Adam(fmnistCNN.parameters() , lr=learning_rate)
optimizer = optim.Adam(fmnistCNN.parameters(), lr=learning_rate)
scheduler = optim.lr_scheduler.ExponentialLR(optimizer, gamma=0.1)
```

```python
curr_iter=0
for epoch in range(n_epochs*2):
    #print("Current epoch : {0}".format(epoch+1))
    #print("--" * 10)
    curr_loss = 0.0

    for (images, labels) in training_loader:
        images = images.cuda()
        labels = labels.cuda()
        images = Variable(images)
        labels = Variable(labels)

        optimizer.zero_grad()
        outputs = fmnistCNN(images)

        loss = lossfn(outputs, labels)
        loss.backward()

        optimizer.step()
        scheduler.step()
        curr_iter += 1
        curr_loss += loss.item()

        if curr_iter%1000 == 0:
            print("Current epoch {}: Training loss {:.3f}".format(epoch+1, curr_loss/1000))
            #print("For iteration number {0}, loss is: {1}".format(curr_iter, loss))
            #print("Training loss: %.3f \n" %(curr_loss/1000))
            curr_loss = 0.0

print("--"*20)
print("Finished Training")
```

    Current epoch 2: Training loss 0.021
    Current epoch 3: Training loss 0.041
    Current epoch 4: Training loss 0.064
    Current epoch 5: Training loss 0.085
    Current epoch 6: Training loss 0.106
    Current epoch 7: Training loss 0.126
    Current epoch 8: Training loss 0.147
    Current epoch 9: Training loss 0.170
    Current epoch 10: Training loss 0.190
    Current epoch 11: Training loss 0.209
    Current epoch 12: Training loss 0.231
    Current epoch 13: Training loss 0.252
    Current epoch 14: Training loss 0.272
    Current epoch 15: Training loss 0.296
    Current epoch 16: Training loss 0.316
    Current epoch 18: Training loss 0.019
    Current epoch 19: Training loss 0.040
    Current epoch 20: Training loss 0.061
    ----------------------------------------
    Finished Training

#### Use model.eval() for testing/inference

```python
fmnistCNN.eval()
```

    simpleCNN(
      (convlayer1): Conv2d(1, 10, kernel_size=(5, 5), stride=(1, 1))
      (convlayer2): Conv2d(10, 20, kernel_size=(3, 3), stride=(1, 1))
      (poollayer1): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
      (convlayer3): Conv2d(20, 30, kernel_size=(3, 3), stride=(1, 1))
      (ReLU): ReLU()
      (fc1): Linear(in_features=480, out_features=20, bias=True)
      (fc2): Linear(in_features=20, out_features=10, bias=True)
    )

```python
correct = 0
total = 0
```

```python
for imgs, labels in test_loader:
    imgs = imgs.cuda()
    imgs = Variable(imgs)

    labels = labels.cuda()
    #labels = Variable(labels)
    preds = fmnistCNN(imgs)

    _,predicted = torch.max(preds.data ,1)
    total += labels.size(0)
    correct += (predicted == labels).sum().item()

print("Validation accuracy is: %.4f" %( 100* correct/total))
```

    Validation accuracy is: 86.5600

```python

```